Skip to content

Holds et sessions ​

Le problème

Trois jetons circulent — sessionToken, holdToken, eventId — et il n'est pas évident de savoir lequel va où, qui pose les holds, ni ce qui se passe à l'expiration. Cette page répond à ces trois questions.

Les trois jetons ​

JetonProduit parVit oùSert à
sessionTokensessions.create() ou le widgetNavigateurIdentifier la session widget, appeler /api/widget/**
holdTokensessions.create() ou le widgetServeurConfirmer, libérer, prolonger les sièges du panier
eventIdRésolution du slugLes deuxCibler l'événement

Le holdToken ne va pas au navigateur

C'est lui qui autorise book() et release(). Exposé côté client, il permettrait de manipuler le panier d'un autre. Créez la session côté serveur, envoyez le sessionToken à la page, gardez le holdToken.

Si le widget crée lui-même la session, vous récupérez les deux jetons dans onReady. Dans ce cas, remontez immédiatement le holdToken à votre serveur et n'en gardez pas de copie côté page.

Qui pose les holds ​

ScénarioQui bloqueComment
L'utilisateur clique un siège dans le widgetLe widgetAutomatique, à chaque sélection
Vente au guichet depuis votre back-officeVousholds.hold(eventId, seats, holdToken)
Quota réservé à un partenaireVousholds.changeStatus(eventId, seats, 'hold')
Import d'une billetterie externeVousholds.book(...) directement

Désélectionner un siège dans le widget retire son hold. Vous n'avez rien à faire pour ce cas.

Durée de vie ​

La durée d'un hold est un réglage de workspace : back-office → Paramètres → Durée de hold. Elle s'applique à tous les holds, ceux du widget comme les vôtres.

Chaque hold() renvoie la durée effective :

ts
const hold = await client.holds.hold(eventId, ['A-1'], holdToken);

hold.expiresAt;         // Date — quand le siège redevient libre
hold.durationSeconds;   // number — la durée configurée
php
$hold = $client->holds->hold($eventId, ['A-1'], $holdToken);

$hold->expiresAt;         // DateTimeImmutable
$hold->durationSeconds;   // int

Servez-vous de expiresAt pour afficher un compte à rebours : un utilisateur qui voit « il vous reste 7:30 pour finaliser » abandonne moins qu'un utilisateur surpris par une place perdue.

Prolonger ​

Un tunnel de paiement plus long que la durée de hold ? Rafraîchissez la session avant la redirection :

ts
const renewed = await client.sessions.refresh(sessionToken);
renewed.expiresIn;   // nouvelle durée, en secondes
php
$renewed = $client->sessions->refresh($sessionToken);
$renewed->expiresIn;   // nouvelle durée, en secondes

Alternative : reposer un hold() sur les mêmes sièges avec le même holdToken, ce qui repart de zéro.

Ce qui se passe à l'expiration ​

Les sièges repassent en available, silencieusement. Il n'y a ni webhook ni notification — c'est à votre application de le constater.

Deux conséquences pratiques :

Avant de confirmer, ne présumez rien. Un book() sur un hold expiré échoue en 409 si quelqu'un a pris la place entre-temps, avec le message One or more seats are not available. C'est le cas nominal, à traiter — voir Brancher un paiement.

Faites le ménage dans vos commandes. Une tâche périodique qui repasse les commandes en_attente trop anciennes en expiree évite d'accumuler des paniers fantômes de votre côté.

Vérifier l'état réel ​

En cas de doute, la source de vérité est l'événement :

ts
const map = await client.events.listSeats(eventId, ['A-1', 'A-2']);

map.held();               // ['A-1']  → hold encore actif
map.available();          // ['A-2']  → hold expiré ou jamais posé
map.isAvailable('A-2');   // true
php
$map = $client->events->listSeats($eventId, ['A-1', 'A-2']);

$map->held();               // ['A-1']
$map->available();          // ['A-2']
$map->isAvailable('A-2');   // true

Passer la liste des sièges en second argument évite de rapatrier une salle entière pour vérifier deux places.

Erreurs fréquentes ​

SymptômeCauseCorrectif
book() renvoie 409 alors que l'utilisateur avait bien sélectionnéHold expiré pendant le paiementRembourser, prévenir, proposer de nouvelles places
Les sièges restent bloqués après un abandonAucun release() appeléLibérer sur la route d'annulation du PSP
holdToken invalideSession expirée ou jeton d'une autre sessionRecréer une session
Deux onglets, deux paniersDeux sessions distinctes, holds séparésRattacher la session Mitoera à la session applicative

À retenir ​

sessionTokenNavigateur
holdTokenServeur, jamais exposé
Le widget pose les holdsAutomatiquement, à la sélection
DuréeRéglage de workspace, lisible dans hold.durationSeconds
ExpirationSilencieuse, sans notification
Vérificationevents.listSeats() fait foi

API, SDK et widget de plans de salle.