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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.