Aller au contenu
Passavo
Menu

Construisez votre propre intégration

Votre catalogue, vos places libres, vos commandes, vos billets et vos scans, un autre programme peut aussi les récupérer, et il peut créer lui-même des commandes. Voici comment — d’abord en clair, ensuite avec le code.

Adresse de base
https://passavo.eu/api/v1
Version actuelle
2026-09-20
La description elle-même
openapi.json

Qu’est-ce qu’une API, et vous en faut-il une ?

Une API est une porte à l’arrière de votre compte. Là où vous cliquez dans votre écran de gestion, un programme peut passer par cette porte pour lire vos données ou y écrire — sans personne devant un écran.

Vous n’en avez besoin que pour faire ce que l’écran de gestion ne fait pas : des chiffres dans votre propre système, des places sur votre propre site, des billets depuis une caisse que vous avez déjà. Si vous pouvez le cliquer, cliquer va plus vite.

Celui qui construit cette intégration — votre webmaster, votre logiciel comptable, quelqu’un qui sait programmer — a besoin de deux choses : l’adresse ci-dessous et une clé que vous créez vous-même.

Ce que vous pouvez construire

Les places libres sur votre site

Montrez sur votre page d’accueil quelles visites ont encore de la place cette semaine, dans votre mise en page, avec des chiffres justes à l’instant même.

Alimenter votre comptabilité

Laissez votre comptable ou votre logiciel récupérer lui-même les ventes du mois passé, au lieu d’envoyer un export chaque mois.

Un écran à l’entrée

Une tablette dans le hall qui affiche le créneau qui commence et le nombre de places encore libres. Un appel par minute suffit.

Vendre depuis votre propre système

Créez une commande depuis le programme que vous utilisez déjà, envoyez un lien de paiement à l’acheteur et apprenez par webhook qu’il a payé.

L’API fait partie de la formule Pro

Vous créez les clés dans Paramètres → Accès API. Cet écran apparaît dans votre menu dès que votre organisation est sur cette formule ; vous changez de formule vous-même dans votre écran de gestion, sous Abonnement.

Voir les formules →

D’abord essayer sans risque

À côté d’une clé normale (pv_live_), vous pouvez créer une clé de test (pv_test_). Elle travaille avec votre vrai catalogue, vos vrais créneaux et votre vraie capacité, et peut aussi créer des commandes. Une telle commande de test ne passe jamais par un prestataire de paiement — une page de test simule le paiement —, ne compte pas dans votre chiffre d’affaires et est supprimée après 24 heures. D’ici là, elle bloque de vraies places : travaillez de préférence avec un produit créé à cet effet. Ce qui sort du bac à sable, comme gérer les webhooks, nous le refusons à une clé de test avec le code sandbox.

Démarrage rapide en cinq étapes

De rien du tout à une intégration qui sait qu’un paiement est arrivé. Chaque étape prend des minutes, pas des jours.

  1. Créez une clé

    Ouvrez Paramètres → Accès API dans votre écran de gestion et créez une clé avec les seuls droits dont vous avez besoin. Le jeton complet n’apparaît qu’une fois ; conservez-le comme un mot de passe.

  2. Faites votre premier appel

    Demandez GET /me avec votre clé dans l’en-tête Authorization. Vous recevez votre organisation, votre formule et les droits de la clé. Si cela marche, le reste marchera aussi.

  3. Créez une commande

    Envoyez les lignes à vendre vers POST /orders, avec une Idempotency-Key — elle est obligatoire ici. Si la connexion casse en chemin, le même appel répété ne crée pas une deuxième commande. Le champ reserved_until indique jusqu’à quand les places vous sont réservées.

  4. Envoyez l’acheteur vers le lien de paiement

    Demandez le lien de paiement avec POST /orders/{id}/checkout, en indiquant l’adresse où l’acheteur arrive après avoir payé. Envoyez l’acheteur vers ce lien, ou affichez-le dans votre propre page. Le paiement passe par le prestataire que vous avez déjà relié ; dès qu’il est reçu, les billets sont créés et envoyés.

  5. Laissez un webhook vous prévenir

    Préparez une adresse sur votre site et enregistrez-la. Dès qu’un paiement, une annulation ou un scan a lieu, vous le recevez là — sans devoir demander sans cesse s’il s’est passé quelque chose.

curl

curl "https://passavo.eu/api/v1/me" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/me');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/me', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/me", headers=headers)
data = response.json()["data"]

Authentification

Chaque requête porte votre clé comme jeton bearer. Une clé appartient à une seule organisation : cette organisation est le monde entier de la requête, et vous ne pouvez jamais y lire par mégarde les données de quelqu’un d’autre.

Authorization: Bearer pv_live_YOUR_API_KEY

Une clé normale commence par pv_live_, une clé bac à sable par pv_test_. Ce préfixe n’est pas un secret mais une aide : qui le voit dans un journal sait aussitôt d’où il vient.

Le jeton complet n’existe qu’un instant, à la création. Ensuite nous n’en gardons qu’une empreinte irréversible (sha256). Perdu veut donc dire perdu : révoquez la clé et créez-en une nouvelle.

Droits

Une clé sans droits ne peut rien. C’est volontairement l’inverse de ce qu’on attendrait : ces clés sont distribuées par des clients à des outils tiers, et là, la valeur par défaut doit être « rien » et pas « tout ».

read
Tout consulter : vos lieux, produits, prix, places libres, réductions, bons cadeaux et abonnements, ainsi que vos commandes, billets, acheteurs et les scans à l’entrée.
write
Créer des commandes, les faire régler, les annuler et les rembourser ; annuler ou renvoyer des billets ; enregistrer l’entrée des visiteurs ; émettre des bons cadeaux et des abonnements.
webhooks
Gérer vos propres destinations de webhooks.
external_payment
Marquer comme payée une commande qui coûte de l’argent sans prestataire de paiement, par exemple après un virement ou un paiement en espèces (POST /orders/{id}/mark-paid). Un droit à part, à côté de write, pour ne le donner qu’à une caisse ou une comptabilité que vous gérez vous-même. Confirmer une commande à zéro euro se fait aussi sans lui.

Quand quelque chose ne va pas

Chaque erreur a la même forme, avec un code fixé et un texte traduit. Lisez le code et pas le texte : le texte peut être réécrit, le code jamais.

{
  "error": {
    "code": "validation_failed",
    "message": "…",
    "details": {}
  }
}
Code Statut Quand
unauthenticated 401 Clé absente, inconnue, révoquée ou expirée.
forbidden 403 La clé est valable, mais n’a pas le droit de faire ceci.
plan_required 403 La formule de cette organisation ne comprend pas l’API.
sandbox 403 Une clé de test tente une action hors du bac à sable, comme gérer les webhooks.
not_found 404 N’existe pas, ou n’existe pas dans cette organisation.
validation_failed 422 La demande elle-même est fausse : filtre inconnu, date invalide.
rate_limited 429 Trop d’appels en une minute.
conflict 409 La même Idempotency-Key a déjà servi pour autre chose.
server_error 500 Quelque chose a mal tourné de notre côté.
slot_unavailable 409 Le créneau est complet, a déjà commencé ou est inconnu, ou aucun n’a été choisi alors que le produit en demande un.
sold_out 409 Le produit est épuisé ou n'est plus en vente.
discount_invalid 422 Le code de réduction n'existe pas, est épuisé ou ne s'applique pas ici.
payment_provider_missing 409 L'organisation n'a pas de prestataire de paiement relié.
not_cancellable 409 La commande ne peut pas être annulée dans son état actuel.
not_refundable 409 Il n’y a (plus) rien à rembourser sur cette commande, ou elle a été payée en dehors du prestataire de paiement.
check_in_duplicate 409 Ce code a déjà été enregistré à l'entrée.
check_in_invalid 404 Ce code est inconnu.
check_in_wrong_day 409 Ce code est valable, mais pas aujourd'hui.
check_in_cancelled 409 Ce code appartient à un billet annulé ou remboursé.

Une ligne d’une autre organisation renvoie toujours not_found, jamais un message disant que vous n’y avez pas accès. Si cette différence était visible, n’importe qui muni d’une clé valable pourrait deviner combien de produits a le voisin en parcourant les numéros.

Pagination, tri et filtres

Les listes arrivent page par page. Vous ne demandez pas la page trois mais ce qui vient après la page précédente : la réponse porte un curseur que vous renvoyez pour lire la suite. Ainsi une liste ne saute jamais de lignes quand quelque chose s’ajoute en cours de route.

Paramètre Ce que ça fait
page[size] Combien de lignes par page ; 25 par défaut, 100 au maximum.
page[cursor] Le next_cursor de la réponse précédente. S’il est vide, c’était la dernière page.
sort Sur quoi trier. Un tiret devant inverse l’ordre.
filter[…] Filtrer sur un champ que l’endpoint autorise.
include Inclure des relations dans la même réponse, séparées par des virgules.

Un paramètre que l’endpoint ne connaît pas est une erreur, pas un silence. Qui se trompe dans le nom d’un filtre doit l’apprendre — et pas récupérer sans le savoir la liste entière sans filtre.

Il n’y a volontairement pas de total dans la réponse : sur des dizaines de milliers de lignes, ce comptage coûte plus cher que la page elle-même.

{
  "data": [ … ],
  "meta": { "next_cursor": "…" }
}

Envoyer deux fois, exécuter une fois

Joignez une Idempotency-Key à chaque appel qui crée ou modifie quelque chose — une chaîne unique et aléatoire. Si le même appel revient avec la même clé, vous recevez exactement la même réponse sans que rien ne se produise une seconde fois. Pour POST /orders, elle est obligatoire.

Idempotency-Key: 6f1c0b4a-6b2f-4a1b-9c7e-1f2d3e4a5b6c

La même clé avec un contenu différent donne conflict et rien ne se passe. Une clé conservée vit 24 heures, et vaut par organisation.

Versions

La version est dans le chemin (/api/v1) et ne change qu’en cas de rupture ; une deuxième version tourne alors à côté et pas à travers. Chaque petit ajout est daté dans l’en-tête Passavo-Version, aujourd’hui 2026-09-20.

Ce qui peut s’ajouter dans cette version : un champ, un endpoint, une nouvelle valeur de tri ou de filtre, un nouveau code d’erreur. Construisez donc votre intégration pour qu’un champ inconnu ne la renverse pas.

Ce qui n’arrive jamais dans cette version : supprimer ou renommer un champ, changer un type, donner un autre sens à un code, ou rendre un paramètre obligatoire.

Limite de débit

Une clé peut faire 120 appels par minute. La limite vaut par clé et non par adresse, pour que deux clients derrière le même hébergeur ne se gênent pas.

Chaque réponse indique où vous en êtes dans X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. Au-delà, vous recevez rate_limited avec un Retry-After ; attendez simplement ce nombre de secondes.

Exemples de code

La même requête en quatre langages, par groupe d’endpoints. Remplacez YOUR_API_KEY par votre propre clé — et ne la mettez jamais dans du code qu’un visiteur peut télécharger.

Compte

Qui suis-je et que puis-je faire.

GET /api/v1/me

curl

curl "https://passavo.eu/api/v1/me" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/me');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/me', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/me", headers=headers)
data = response.json()["data"]

Catalogue

Sites, produits et tarifs.

GET /api/v1/events

curl

curl "https://passavo.eu/api/v1/events" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/events');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/events', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/events", headers=headers)
data = response.json()["data"]

Disponibilité

Créneaux et places disponibles.

GET /api/v1/products/{id}/slots

curl

curl "https://passavo.eu/api/v1/products/12/slots" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/products/12/slots');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/products/12/slots', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/products/12/slots", headers=headers)
data = response.json()["data"]

Vente

Réductions, bons cadeaux et abonnements annuels.

GET /api/v1/discounts

curl

curl "https://passavo.eu/api/v1/discounts" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/discounts');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/discounts', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/discounts", headers=headers)
data = response.json()["data"]

Commandes

Créer, payer, annuler et rembourser des commandes.

GET /api/v1/orders

curl

curl "https://passavo.eu/api/v1/orders" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/orders');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/orders', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/orders", headers=headers)
data = response.json()["data"]

Billets

Consulter, annuler et renvoyer des billets.

GET /api/v1/tickets

curl

curl "https://passavo.eu/api/v1/tickets" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/tickets');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/tickets', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/tickets", headers=headers)
data = response.json()["data"]

Entrée

L'enregistrement à l'entrée.

GET /api/v1/check-ins

curl

curl "https://passavo.eu/api/v1/check-ins" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/check-ins');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/check-ins', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/check-ins", headers=headers)
data = response.json()["data"]

Clients

Les acheteurs, résumés à partir des commandes.

GET /api/v1/customers

curl

curl "https://passavo.eu/api/v1/customers" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/customers');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/customers', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/customers", headers=headers)
data = response.json()["data"]

Méta

La description de l'API elle-même.

GET /api/v1/openapi.json

curl

curl "https://passavo.eu/api/v1/openapi.json" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->get('https://passavo.eu/api/v1/openapi.json');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/openapi.json', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json"}
response = requests.get("https://passavo.eu/api/v1/openapi.json", headers=headers)
data = response.json()["data"]

Webhooks

Messages que nous envoyons vers votre serveur.

GET /api/v1/webhook-deliveries

curl

curl "https://passavo.eu/api/v1/webhook-deliveries" \
  -H "Authorization: Bearer pv_live_YOUR_API_KEY" \
  -H "Accept: application/json"

PHP

use Illuminate\Support\Facades\Http;

$response = Http::acceptJson()
    ->withToken('pv_live_YOUR_API_KEY')
    ->get('https://passavo.eu/api/v1/webhook-deliveries');

$data = $response->json('data');

JavaScript

const response = await fetch('https://passavo.eu/api/v1/webhook-deliveries', {
  method: 'GET',
  headers: {
    Accept: 'application/json',
    Authorization: 'Bearer pv_live_YOUR_API_KEY',
  },
});

const { data } = await response.json();

Python

import requests

headers = {"Accept": "application/json", "Authorization": "Bearer pv_live_YOUR_API_KEY"}
response = requests.get("https://passavo.eu/api/v1/webhook-deliveries", headers=headers)
data = response.json()["data"]

Webhooks

Un webhook est l’inverse d’un appel : au lieu de demander sans cesse si le paiement est arrivé, nous envoyons un message à une adresse à vous dès que cela se produit. Cela évite des milliers d’appels par jour et vous le savez aussitôt plutôt qu’au passage suivant.

Vous gérez vos destinations dans votre écran de gestion sous Paramètres → Accès API, onglet Webhooks, ou via l’API avec une clé qui porte le droit webhooks. Chaque destination a son propre secret ; il vous sert à vérifier qu’un message vient bien de nous.

Vérifier la signature

Chaque message porte l’en-tête Passavo-Signature sous la forme t=<unix>,v1=<hmac-sha256>. t est le moment où nous avons signé ; v1 est un HMAC-SHA256 avec le secret de cette destination sur l’horodatage, un point et le corps brut. Recalculez-le et comparez en temps constant — une comparaison ordinaire trahit par sa durée combien de caractères étaient justes. Refusez aussi un message dont t s’écarte de plus de 300 secondes de votre propre horloge : ainsi personne ne peut rejouer plus tard un message intercepté.

Vérifiez sur le corps BRUT, avant que votre framework n’en fasse du json. Reconstruire le json remet les clés dans un autre ordre et plus aucune signature ne correspond.

curl

# De handtekening narekenen vanaf de opdrachtregel.
# T is de waarde van t= uit de header Passavo-Signature,
# het resultaat hoort gelijk te zijn aan de waarde van v1=.
printf '%s.%s' "$T" "$BODY" | openssl dgst -sha256 -hmac "$SECRET"

PHP

// De RUWE body, niet $request->all().
$body = $request->getContent();

// "t=1758355200,v1=9f86d0…" uit elkaar halen.
$delen = [];
foreach (explode(',', (string) $request->header('Passavo-Signature')) as $stuk) {
    [$sleutel, $waarde] = array_pad(explode('=', trim($stuk), 2), 2, '');
    $delen[$sleutel] = $waarde;
}

$t = $delen['t'] ?? '';
$verwacht = hash_hmac('sha256', $t . '.' . $body, $secret);

// hash_equals vergelijkt in constante tijd; de tijdstempel
// houdt een opgevangen bericht tegen dat later opnieuw komt.
if (! ctype_digit($t) || abs(time() - (int) $t) > 300 || ! hash_equals($verwacht, $delen['v1'] ?? '')) {
    abort(400);
}

JavaScript

import { createHmac, timingSafeEqual } from 'node:crypto';

// rawBody: de ruwe body als string, bv. via express.raw().
const header = request.headers['passavo-signature'] ?? '';
const delen = Object.fromEntries(header.split(',').map((s) => s.trim().split('=', 2)));

const verwacht = createHmac('sha256', secret).update(delen.t + '.' + rawBody).digest('hex');
const gekregen = delen.v1 ?? '';

const vers = /^\d+$/.test(delen.t ?? '')
  && Math.abs(Date.now() / 1000 - Number(delen.t)) <= 300;
const geldig = vers
  && verwacht.length === gekregen.length
  && timingSafeEqual(Buffer.from(verwacht), Buffer.from(gekregen));

Python

import hashlib, hmac, time

# raw_body: de ruwe body als bytes, bv. request.get_data() in Flask.
header = request.headers.get("Passavo-Signature", "")
delen = dict(stuk.strip().split("=", 1) for stuk in header.split(",") if "=" in stuk)
t = delen.get("t", "")

verwacht = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()

# compare_digest vergelijkt in constante tijd.
geldig = (t.isdigit()
          and abs(time.time() - int(t)) <= 300
          and hmac.compare_digest(verwacht, delen.get("v1", "")))

La liste complète des événements et de leur contenu se trouve dans la référence. →

Ce qui change

Chaque changement qui mérite d’être signalé reçoit une nouvelle version datée. Si votre intégration reste sur une date ancienne, elle continue de fonctionner — la date dit seulement contre quel comportement elle a été construite.

  1. 2026-09-20

    La première version

    Des clés avec droits, un bac à sable, un format de réponse unique et une pagination par curseur. En lecture : votre organisation, vos lieux, produits, créneaux, événements, réductions, bons cadeaux et abonnements, commandes, billets, acheteurs et scans. En écriture : créer, régler, annuler et rembourser des commandes, annuler des billets, enregistrer des entrées, émettre des bons cadeaux et des abonnements. Et des webhooks sortants, signés par destination.