Skip to content

omniticket/billetweb

Omniticket's Billetweb, under any PHP host: an organizer's events with their rates, sessions and places left, the attendees of an event (incrementally, as Billetweb asks), and a ticket's barcode checked at the door - read only, through Billetweb's API v1.

Floor
Provider · Omniticket
Version
1.x
Conformance suite
not wired
Verified for real
Verified in part
Licence
MIT
composer require omniticket/billetweb:1.x-dev

Billetweb for omnisense/omniticket: an organizer's events, their rates and places left, their sessions, their attendees, and a ticket code checked - through Billetweb's API v1 (https://www.billetweb.fr/bo/api.php, its OpenAPI description at https://www.billetweb.fr/api/openapi.json), the key in an HTTP Basic header. Reading only.

Operation Billetweb API v1
events() GET /api/events (past=1 with a query's past)
event($id) GET /api/events?id=&past=1, GET /api/event/{id}/avail?past=1, GET /api/event/{id}/tickets
attendees($id, $since) GET /api/event/{id}/attendees?disabled=1 (last_update with $since)
check($id, $code) GET /api/event/{id}/attendees?barcode=&disabled=1

The check POST endpoint, which marks a ticket as scanned, is not used. No PHP client of Billetweb's API was found to reuse (Billetweb publishes the OpenAPI description only).

Installation

composer require omniticket/billetweb symfony/http-client

Requires PHP 8.2, omnisense/omniticket (1.x) and symfony/http-client-contracts (^3.0): the application gives the HTTP client to BilletwebFactory's constructor.

Credentials

The API user and key of Billetweb's back office ("API"). A key is read-only or read and write, possibly restricted to some events: read-only is all this package needs.

Options

Option Type Default Required
user string - yes the API user
key string - yes the API key
timezone string Europe/Paris no the zone Billetweb's dates are in: it gives local times without one
currency string EUR no the currency of its prices: its answers do not name it
url string https://www.billetweb.fr no

Capabilities

Contract Supported
EventCatalogInterface yes
AttendeeListInterface yes, incremental (last_update)
TicketCheckInterface yes, a lookup by barcode

capabilities(): catalog, attendees, check, incremental and widget true; terms https://www.billetweb.fr/bo/api.php; limits: attendee functions 10 calls a minute; fair use, monitored: keep the data on your side and read attendees incrementally; abuse may suspend the key.

Behaviour

Events. Each line: id, name, start and end in timezone, place as the venue, shop as both the purchase URL and the widget URL (the module Billetweb's own embedding code frames). A listed event has no availability: its status is Ended when its end (else start) is past, else Unknown.

One event. Three calls. The availability lines by type: event (the whole event, and its status), ticket (per rate), session (each session: id, start, end, name, location). Places: avail (-1 is no limit), quota (a negative one ignored), total_sales (else sales). The rates: id, name, price in units of currency, the ticket's availability, start_time and end_time as the sale period, category. Status: ended by date, else sold out when nothing remains, else on sale when Billetweb says available, else unknown.

Attendees. One call, cancelled and refunded tickets included (disabled=1). Each: id, barcode as the code, firstname, name, email, ticket as the rate, order_id, order_session, product_download as the ticket URL. Status: disabled - cancelled when its order was paid, else refunded; used 1 (scanned) or 2 (gone out) - checked in, used_date as when; used 3 (expired) - cancelled; order not paid - pending; else valid.

Check. One lookup by barcode, the first attendee holding the exact code decides. Nothing throttles the calls: an application checking more than 10 tickets a minute keeps the attendee list itself (attendees() then Check::among()).

Example

The core's installation page runs this provider on recorded answers. With the account's key:

<?php

require __DIR__.'/vendor/autoload.php';

use Omniticket\Billetweb\BilletwebFactory;
use Omniticket\Registry;
use Symfony\Component\HttpClient\HttpClient;

$registry = new Registry([new BilletwebFactory(HttpClient::create(['timeout' => 15]))], [
    'box_office' => ['factory' => 'billetweb', 'options' => ['user' => getenv('BILLETWEB_USER'), 'key' => getenv('BILLETWEB_KEY')]],
]);

$event = $registry->catalog('box_office')->event('1235');
foreach ($event->sessions as $session) {
    echo $session->start?->format('d/m H:i'), ' ', $session->availability->remaining ?? '?', " left\n";
}

$since = new \DateTimeImmutable('-1 hour');
foreach ($registry->attendees('box_office')->attendees('1235', $since) as $attendee) {
    echo $attendee->name(), ' ', $attendee->status->value, "\n";
}

Not run live (no account).

Errors

  • 401, 403: InvalidKeyException (Billetweb refused the credentials (401) for the events: invalid key); 404: NotFoundException; another status of 400 or more, or an answer that is not JSON: ProviderException, the status as its code.
  • An event Billetweb does not list: NotFoundException (Billetweb has no event "<id>".).
  • A network failure: UnreachableException.

Verified, and not

Tests/BilletwebProviderTest.php, against the examples of Billetweb's OpenAPI description as published (read on 2026-10-24): events, one event whole (rates, sessions, places left, "no limit"), attendees with last_update, checks valid, already used, refunded and unknown, a refused key; BareTest. Green in the family's harness on 2026-10-26. Not run live: no Billetweb account was used.

Responsibility

This package is an independent, unofficial client, affiliated with Billetweb in no way. Whoever runs it keeps Billetweb's API rules (billetweb.fr/bo/api.php: 10 attendee calls a minute, fair use); see the README.

Propose a change docs/index.md