Référence de l'API
Chaque route que sert l'API, qui peut l'appeler, et comment fonctionnent la connexion, les permissions, les espaces de travail, les réservations, les paiements, les erreurs, les listes et les limites.
Pour le pack Full Stack
URL de base et format des réponses
Chaque route est servie sous le préfixe /api. En local, l'URL de base est http://localhost:8000/api. Sur un serveur, c'est l'adresse de votre API suivie de /api, la même valeur que lisent les deux frontends dans NEXT_PUBLIC_API_BASE_URL (Variables d'environnement). Les images sont servies hors du préfixe, sur /media/….
Les routes du site sont publiques ou prennent le jeton d'un participant ; celles du tableau de bord exigent le jeton bearer d'un membre de l'équipe, et la plupart aussi une permission. Les corps de requête sont en JSON, sauf pour les envois de fichiers. Chaque réponse arrive dans la même enveloppe :
{
"success": true,
"data": { },
"message": ""
}data contient le résultat. message est une courte phrase que certaines écritures renseignent, dans la langue de la requête, et vide sinon. L'argent est un nombre entier d'unités mineures avec sa currency (price_minor: 2000 vaut 20,00), et chaque date est une chaîne ISO en UTC ; chaque événement porte aussi son time_zone.
La vérification de santé ne demande aucun jeton :
curl http://localhost:8000/api/health{"success":true,"data":{"status":"ok","database":"up"},"message":""}Quand la base de données ne peut pas être lue, elle répond quand même 200, avec "status":"degraded" et "database":"down". La vérification de santé de l'image Docker lit ce champ.
Erreurs
Un échec garde l'enveloppe, avec success: false et le statut HTTP :
{
"success": false,
"data": null,
"message": "…",
"errors": { "email": ["…"] },
"code": "SEAT_UNAVAILABLE",
"details": { "seats": ["A12"] }
}messageest une phrase dans la langue de la requête.errorsapparaît lors d'un échec de validation, avec les problèmes par champ, indexés par le chemin envoyé par le client (commetitle.enouattendee.email).- Un champ inconnu dans un corps est refusé avec
400, eterrorsle nomme. L'inscription, par exemple, ne prend que les champs listés ci-dessous. codeetdetailsapparaissent là où un écran réagit à un refus en particulier :SEAT_UNAVAILABLEavec les places prises,HOLD_EXPIRED,SOLD_OUT,ALREADY_ADMITTEDavec la première admission,VERSION_CONFLICT,NOT_READYavec ce qui manque,COOLDOWNavecretry_afteren secondes.- Une route protégée sans jeton, ou avec un jeton expiré, répond
401; un jeton sans la permission répond403. - Une requête au-delà d'une limite répond
429.
En-têtes
| En-tête | Envoyé avec | Ce qu'il porte |
|---|---|---|
Authorization: Bearer … | Routes de l'équipe et des participants | Le jeton de POST /api/auth/login (équipe) ou de POST /api/customer-auth/login (participant). Les deux types ne sont pas interchangeables |
X-Workspace-Id | Routes de l'équipe | L'espace de travail visé par la requête. Un espace auquel le membre n'appartient pas est ignoré, et le sien est utilisé |
X-Hold-Token | Une réservation et le paiement qui en découle | Le secret de la réservation, renvoyé une seule fois à sa création |
X-Order-Token | Routes de commande d'un invité | Le secret de la commande, renvoyé une seule fois par POST /api/checkout. Les commandes d'un participant connecté n'exigent que son jeton |
Idempotency-Key | POST /api/holds, POST /api/checkout, POST /api/admin/orders/:reference/refunds | Un UUID créé à l'ouverture du formulaire. Une nouvelle tentative avec la même clé et le même corps renvoie la première réponse au lieu de faire le travail deux fois ; sans clé, la requête est refusée |
Accept-Language | N'importe quelle route | ar pour des messages en arabe ; toute autre valeur répond en anglais |
Les textes d'événement, de lieu et de type de billet portent les deux langues sous la forme { "en": "…", "ar": "…" } quoi que dise Accept-Language, et le client en choisit une, en retombant sur l'anglais quand l'arabe est vide.
Listes et pagination
{ "data": [ ], "page": 1, "limit": 10, "total": 36, "totalPages": 4 }- La plupart des listes se paginent avec
pageetlimit, au plus 100 par page : 9 événements par page sur le site, 10 événements, lieux et participants et 8 commandes par page dans le tableau de bord par défaut. Plusieurs renvoient aussi descountspar onglet ou statut. - Les listes de l'équipe, des rôles et des paramètres du site se paginent avec
pageetpage_count, et les demandes avecpageetpage_size(10 par défaut, 50 au plus). - Les listes du tableau de bord arrivent les plus récemment modifiées d'abord, avec l'identifiant comme départage, si bien que la pagination est stable. Le catalogue du site arrive les plus proches d'abord.
- Les filtres de la liste de l'équipe (
email,name,phone) se combinent : une ligne doit correspondre à chacun de ceux donnés.namecorrespond au prénom, au nom, à l'identifiant ou au nom complet.
Connexion
Se connecter comme membre de l'équipe
Terminalcurl -X POST http://localhost:8000/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email":"YOUR_EMAIL","password":"YOUR_PASSWORD"}'Utilisez l'un des comptes du tableau de bord de Installation, ou le vôtre.
data.access_tokenest le jeton, avectoken_typeBeareret le membre de l'équipe avec ses rôles et permissions. Le jeton dureJWT_EXPIRATION,7dpar défaut, etexpires_inindique cette valeur telle qu'écrite.GET /api/auth/merenvoie le membre connecté avec ses rôles et permissions.Appeler une route protégée
Terminalcurl http://localhost:8000/api/admin/orders \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "X-Workspace-Id: 1"
- Un e-mail inconnu et un mauvais mot de passe répondent tous deux
401avec le même message. - Dix connexions échouées depuis une même adresse en 15 minutes donnent
429jusqu'à ce que le plus ancien échec ait 15 minutes (RATE_LIMIT_LOGIN). Les connexions réussies ne sont pas comptées. Les connexions de l'équipe et des participants sont comptées séparément. - Les comptes d'équipe viennent des données d'exemple ou de la page Équipe ; il n'y a pas d'inscription pour l'équipe. Un client se déconnecte en oubliant son jeton.
GET /api/admin/workspace/membershipsliste les espaces de travail auxquels le membre appartient, les siens en premier. Envoyez l'identifiant de celui choisi dansX-Workspace-Id.
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
POST | /api/auth/login | N'importe qui | Connexion de l'équipe : email, password |
GET | /api/auth/me | N'importe quel membre de l'équipe connecté | Le membre de l'équipe connecté, ses rôles et permissions |
GET | /api/admin/workspace/memberships | N'importe quel membre de l'équipe connecté | Les espaces de travail du membre, pour le sélecteur de la barre de navigation |
Permissions
Les routes de l'équipe vérifient une permission nommée <area>.<action>. Un membre détient chaque permission de chaque rôle qu'il a, et le rôle est le même dans chaque espace de travail auquel il appartient. Les 29 permissions et les quatre rôles d'exemple (Propriétaire, Gestionnaire, Finance, Contrôle des billets) sont listés dans Équipe, rôles et espaces de travail.
Événements, lieux et organisateurs sur le site
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/public/events | N'importe qui | Les événements publics à venir, les plus proches d'abord. q (titre, résumé, lieu, ville ou organisateur), category, city, venue et organiser (slugs), from et to (YYYY-MM-DD), page, limit. Les brouillons, les événements non listés et ceux qui sont terminés sont exclus |
GET | /api/public/events/cities | N'importe qui | Les villes avec des événements à venir et combien chacune en compte, pour le filtre de ville |
GET | /api/public/events/:slug | N'importe qui | Un événement en entier : description, programme, le lieu avec son adresse, son accessibilité, ses transports et sa position, le code de session, et les types de billets avec prix, frais, places restantes et limite par commande. Un événement annulé répond avec status: cancelled |
GET | /api/public/sessions/:code/availability | N'importe qui | La disponibilité en direct pour le plan des places : l'horloge du serveur, hold_seconds, max_per_order, les frais, les types de billets, le plan de places publié (ou null pour l'entrée libre) et chaque place comme available, held, sold ou unavailable |
GET | /api/public/categories | N'importe qui | Les catégories d'événements |
GET | /api/public/organisers | N'importe qui | Les organisateurs |
GET | /api/public/organisers/:slug | N'importe qui | Un organisateur avec jusqu'à 24 de ses événements à venir et leur total |
GET | /api/public/venues | N'importe qui | Les lieux, avec leurs événements à venir et leurs places |
GET | /api/public/venues/:slug | N'importe qui | Un lieu, avec son plan de places publié |
GET | /api/public/settings | N'importe qui | Ce dont le site a besoin pour fixer le prix et l'heure d'un achat : le nom de l'espace de travail, currency, fee_bps (les frais de réservation que le participant paie sur chaque billet, 300 vaut 3 %), hold_seconds, max_per_order, time_zone, support_email, payment_methods et mail_simulated (vrai tant que les e-mails sont écrits dans le journal de l'API) |
GET | /api/settings/public | N'importe qui | Le site_name, le contact_email et le contact_city du site |
Les recettes de l'organisateur ne font jamais partie d'une réponse publique.
Comptes de participants
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
POST | /api/customer-auth/register | N'importe qui | Inscription : first_name, last_name, email, password (8 à 72 caractères avec une lettre et un chiffre), terms_accepted (true), et en option role (attendee ou organiser, jamais lu). Tout autre champ répond 400 en le nommant. Répond 201, connecté aussitôt, et envoie un code à six chiffres |
POST | /api/customer-auth/login | N'importe qui | Connexion du participant : email, password, et remember pour un jeton de 30 jours au lieu d'un jour |
POST | /api/customer-auth/logout | N'importe qui | Répond { signed_out: true } ; les jetons n'ont pas d'état, le client oublie donc sa copie |
POST | /api/customer-auth/forgot-password | N'importe qui | email. Envoie un lien de réinitialisation valable une heure quand le compte existe, et répond de la même façon dans les deux cas |
POST | /api/customer-auth/reset-password | N'importe qui | token (issu du lien) et le nouveau password. Un lien expiré ou déjà utilisé répond 400 avec TOKEN_EXPIRED |
POST | /api/customer-auth/verify-email | Un participant connecté | code, les six chiffres de l'e-mail, valables 24 heures. Les commandes achetées avec cette adresse en tant qu'invité rejoignent le compte |
POST | /api/customer-auth/resend-verification | Un participant connecté | Envoie un nouveau code ; une fois par minute au plus (429 avec COOLDOWN et retry_after) |
GET | /api/me | Un participant connecté | Le profil du participant |
PATCH | /api/me | Un participant connecté | Modifie first_name, last_name, email, marketing_emails ou reminder_emails |
GET | /api/me/saved | Un participant connecté | Les événements enregistrés, sous forme de cartes |
GET | /api/me/saved/slugs | Un participant connecté | Seulement les slugs des événements enregistrés, pour les boutons en forme de cœur |
PUT | /api/me/saved/:slug | Un participant connecté | Enregistrer un événement |
DELETE | /api/me/saved/:slug | Un participant connecté | Retirer un événement des enregistrés |
GET | /api/me/tickets | Un participant connecté | Les billets du participant en upcoming et past, une carte par commande |
GET | /api/me/tickets/:reference | Un participant connecté | Les billets d'une commande, avec les codes QR et les liens de téléchargement |
GET | /api/me/orders | Un participant connecté | Les commandes du participant |
GET | /api/me/orders/:reference | Un participant connecté | Le reçu d'une commande, avec sa chronologie |
L'inscription est limitée à 10 par adresse en 10 minutes, et les demandes de réinitialisation du mot de passe à 5. Tant qu'aucune clé d'e-mail n'est définie, les codes et liens sont écrits dans le journal de l'API, et mail_simulated l'indique.
Réservations et paiement
Un achat se fait en deux appels : réserver les places, puis payer à partir de la réservation. Les deux fonctionnent pour un invité et pour un participant connecté, dont le jeton est lu quand il est envoyé.
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
POST | /api/holds | N'importe qui | Réservez { session_code, seats: ["A12", "B12"] } pour des places réservées, ou { session_code, ticket_type_id, quantity } pour une entrée libre, de 1 à 8 à la fois. Exige Idempotency-Key. Répond 201 avec la réservation, son expires_at et l'horloge du serveur, et son token, affiché une seule fois |
GET | /api/holds/:id | Le propriétaire de la réservation, avec X-Hold-Token | Lire la réservation |
PATCH | /api/holds/:id | Le propriétaire de la réservation, avec X-Hold-Token | Remplacer la sélection ; l'échéance ne bouge pas |
DELETE | /api/holds/:id | Le propriétaire de la réservation, avec X-Hold-Token | Libérer les places maintenant |
GET | /api/checkout/methods | N'importe qui | Les moyens de paiement proposés, chacun avec provider et live |
POST | /api/checkout | Le propriétaire de la réservation, avec X-Hold-Token | hold_id, attendee (first_name, last_name, email), provider (stripe, paypal ou simulated) et terms_accepted. Exige Idempotency-Key. Répond 201 avec order_reference, status, redirect_url et access_token, le secret de la commande, affiché une seule fois. L'Accept-Language de la requête (ar, sinon en) est conservé sur la commande comme locale, la langue de chaque e-mail la concernant |
- Une réservation dure la durée de réservation de l'espace de travail (
hold_seconds, dix minutes dans les données d'exemple), comptée sur l'horloge du serveur. Passé ce délai, la réservation répond410avecHOLD_EXPIREDet les places sont de nouveau libres. - Une place que quelqu'un d'autre a réservée ou achetée répond
409avecSEAT_UNAVAILABLEet les places dansdetails.seats; un type de billet complet répondSOLD_OUT; plus que la limite par commande répondTOO_MANY. - Envoyez le navigateur vers
redirect_url: la page propre de Stripe ou de PayPal, ou la page du simulateur du site. Les données de carte ne sont jamais envoyées à cette API. - Une réservation dont le total est 0 n'a pas besoin de
provider: la commande est confirmée aussitôt avec le fournisseurfreeet le statutpaid, etredirect_urlest sa page de confirmation.
Commandes, fichiers de billets et paiements
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/orders/:reference/status | Le participant de la commande, ou un invité avec X-Order-Token | status (pending_payment, paid, payment_failed, expired, payment_review, partially_refunded, refunded), le fournisseur et l'horloge du serveur, pour la page qui attend le paiement |
GET | /api/orders/:reference/receipt | Le participant de la commande, ou un invité avec X-Order-Token | La commande avec son événement, son lieu, ses billets (chaque billet payé avec son code QR), l'état de l'e-mail de billets et les liens downloads signés |
POST | /api/orders/:reference/resend-email | Le participant de la commande, ou un invité avec X-Order-Token | Renvoie les billets à l'adresse de la commande, dans la langue de l'Accept-Language de la requête. Répond 202, ou 429 avec COOLDOWN dans la minute suivant le dernier |
GET | /api/orders/:reference/tickets.pdf | Toute personne qui détient le lien signé | Tous les billets de la commande dans un seul PDF |
GET | /api/orders/:reference/calendar.ics | Toute personne qui détient le lien signé | L'événement sous forme de fichier de calendrier |
GET | /api/tickets/:reference/pdf | Toute personne qui détient le lien signé | Un billet en PDF |
GET | /api/payments/return/paypal | N'importe qui | PayPal envoie l'acheteur ici : l'API capture le paiement et redirige vers la page d'attente du site (ou sa page d'annulation) |
POST | /api/payments/simulated/:reference/complete | La page du simulateur, avec le jeton de la commande | token et outcome (pay, fail ou cancel). Répond 404 chaque fois que le simulateur n'est pas proposé |
POST | /api/webhooks/:provider | Stripe ou PayPal | stripe ou paypal. La signature est vérifiée avec STRIPE_WEBHOOK_SECRET ou PAYPAL_WEBHOOK_ID ; une signature absente ou erronée répond 401. Chaque événement n'est traité qu'une fois, quel que soit le nombre d'envois |
- Les liens de téléchargement sont signés avec
expetsiget valables 30 minutes à partir du reçu qui les a créés ; un lien périmé répond404, et relire le reçu en crée de nouveaux. Ils sont construits à partir dePUBLIC_API_URL. - Les billets sont émis une fois que le fournisseur confirme le paiement, par son webhook, par le retour de PayPal, ou par le simulateur. Stripe envoie
checkout.session.completed,checkout.session.async_payment_succeeded,checkout.session.async_payment_failedetrefund.updated; PayPalPAYMENT.CAPTURE.COMPLETED,PAYMENT.CAPTURE.DENIEDetPAYMENT.CAPTURE.REFUNDED. - Le simulateur est proposé tant qu'aucune clé Stripe ou PayPal de production n'est définie ;
PAYMENTS_SIMULATOR=onouoffremplace ce choix.
Le formulaire de contact
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
POST | /api/leads | N'importe qui | name, email, subject (general, tickets, organisers, scale, press), message (10 à 2000 caractères) et client_token (un UUID v4). Répond 201 avec { id, received_at } |
- Un
client_tokenrépété renvoie le reçu du premier envoi au lieu d'en stocker un second. - Un champ
companyrempli est traité comme un robot : la réponse paraît identique, et rien n'est stocké. - Chaque adresse peut en envoyer cinq en dix minutes ; le suivant répond
429.
Événements
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admin/events | Équipe avec events.view | Les événements avec des counts par onglet. tab (all, published, draft, ended), q, category, status, venue (identifiant), from, to, sort (starts_at, sinon dernière modification), order (asc, desc), page, limit |
GET | /api/admin/events/:id | Équipe avec events.view | Un événement pour l'éditeur, avec sa liste de contrôle readiness, sa version et le début et la fin en heure locale |
POST | /api/admin/events | Équipe avec events.edit | Créer un brouillon : title, summary, description (chacun en, ar), category (slug), venue_id, color (pink, yellow, teal, blue), admission_mode (reserved, general), visibility (public, unlisted), starts_local, ends_local, time_zone, agenda et ticket_types (title, price_minor, capacity, et en option description, max_per_order, status), en option slug |
PATCH | /api/admin/events/:id | Équipe avec events.edit | Enregistrer les mêmes champs avec la version chargée par l'éditeur. Un enregistrement plus récent répond 409 avec VERSION_CONFLICT ; le prix d'un type de billet vendu est verrouillé (PRICE_LOCKED) |
POST | /api/admin/events/:id/publish | Équipe avec events.publish | Mettre un brouillon en vente. Un brouillon qui n'est pas prêt répond 400 avec NOT_READY et ce qui manque |
POST | /api/admin/events/:id/unpublish | Équipe avec events.publish | Retour en brouillon : les ventes s'arrêtent et les réservations sont libérées, les billets déjà vendus restent valables |
POST | /api/admin/events/:id/cancel | Équipe avec events.publish | { confirm }, le slug de l'événement saisi en toutes lettres. Les ventes et l'entrée s'arrêtent, et le titulaire de chaque commande payée reçoit un e-mail. Les remboursements se font ensuite commande par commande |
POST | /api/admin/events/:id/duplicate | Équipe avec events.edit | Un nouveau brouillon avec les mêmes détails et types de billets, et aucune vente |
POST | /api/admin/events/:id/archive | Équipe avec events.publish | Archiver un brouillon, ou un événement terminé ou annulé |
GET | /api/admin/events/:id/attendees | Équipe avec events.view | Les billets de l'événement avec titulaire, place, type, statut et heure d'entrée. q, status (admitted, not_admitted, void), page, limit |
Lieux et plans de salle
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admin/venues | Équipe avec venues.view | Les lieux. q, city, page, limit |
GET | /api/admin/venues/map | Équipe avec venues.view | Le repère de chaque lieu pour la carte |
GET | /api/admin/venues/:id | Équipe avec venues.view | Un lieu avec ses plans |
POST | /api/admin/venues | Équipe avec venues.edit | Ajouter un lieu : name (en, ar), address, city, time_zone, capacity, accessibility (en, ar), et en option slug, transit, location (latitude, longitude) |
PATCH | /api/admin/venues/:id | Équipe avec venues.edit | Modifier n'importe lequel de ces champs |
GET | /api/admin/venues/:id/layouts | Équipe avec venues.view | Les versions de plan du lieu |
GET | /api/admin/venues/:id/layouts/:version | Équipe avec venues.view | Une version avec ses places |
POST | /api/admin/venues/:id/layouts | Équipe avec venues.edit | Démarrer un nouveau brouillon |
PATCH | /api/admin/venues/:id/layouts/:version | Équipe avec venues.edit | Enregistrer le brouillon : rows (1 à 40), seats_per_row (1 à 60), aisles_after (jusqu'à 6), seats (label, et en option accessible, companion, disabled, price_tier de 0 à 9) et loaded_at. Un brouillon enregistré depuis par quelqu'un d'autre répond 409 avec VERSION_CONFLICT |
POST | /api/admin/venues/:id/layouts/:version/publish | Équipe avec venues.edit | { acknowledged: true }. Publie le brouillon comme plan du lieu ; les places déjà vendues gardent la version sur laquelle elles ont été vendues. Un plan vide, ou avec plus de places que la capacité du lieu (OVER_CAPACITY), est refusé |
Commandes, billets et remboursements
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admin/orders | Équipe avec orders.view | Les commandes avec des counts par statut. status (paid, pending_payment, refunded, payment_failed, payment_review), event (slug), provider (stripe, paypal, simulated, free), q (référence, e-mail ou nom), from, to, page, limit |
GET | /api/admin/orders/events | Équipe avec orders.view | Chaque événement qui a des commandes, pour le filtre de la page des commandes |
GET | /api/admin/orders/:reference | Équipe avec orders.view | Une commande : billets, remboursements, la chronologie du paiement, un lien vers elle dans le tableau de bord du fournisseur, et sa version |
GET | /api/admin/orders/:reference/refund-preview | Équipe avec refunds.create | Ce que renverrait le remboursement de ?tickets=TKT-1042-2,…, billet par billet |
POST | /api/admin/orders/:reference/refunds | Équipe avec refunds.create | Rembourser des billets entiers : tickets (1 à 8 références), reason (customer_request, event_cancelled, duplicate_order, event_changed, other), acknowledged (true) et order_version. Exige Idempotency-Key. Répond 202 avec le remboursement pending |
POST | /api/admin/refunds/:id/retry | Équipe avec refunds.create | Renvoyer un remboursement échoué au fournisseur |
POST | /api/admin/refunds/:id/restore | Équipe avec refunds.create | Clore définitivement un remboursement échoué ; ses billets sont de nouveau valables |
POST | /api/admin/tickets/:reference/reissue | Équipe avec tickets.manage | Un nouveau code QR pour un billet valide ; l'ancien code cesse de fonctionner à l'entrée |
POST | /api/admin/tickets/:reference/void | Équipe avec tickets.manage | Annuler un billet gratuit. Un billet payé répond 409 avec USE_REFUND : il est remboursé à la place |
Ses billets sont suspendus (refund_pending) dès que le remboursement est demandé, si bien que l'entrée les refuse. Le remboursement se règle quand le fournisseur le confirme, quelques secondes plus tard pour le simulateur : les billets sont alors annulés et leurs places repartent en vente. Un remboursement échoué les garde suspendus jusqu'à ce qu'il soit relancé, ou rétabli, ce qui les rend de nouveau valables. Relisez la commande pour voir où elle en est.
Contrôle des billets à l'entrée
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admin/check-in/sessions | Équipe avec checkin.scan | Les sessions que ce membre peut scanner, à partir d'hier, avec les nombres d'admis et d'attendus et si les portes sont ouvertes |
GET | /api/admin/check-in/sessions/:code/summary | Équipe avec checkin.scan | Admis, attendus, restants, et les alertes en attente |
GET | /api/admin/check-in/sessions/:code/scans | Équipe avec checkin.scan | Les scans récents, chacun admitted, eligible, duplicate, wrong_session, void ou not_found |
POST | /api/admin/check-in/sessions/:code/acknowledge | Équipe avec checkin.scan | Marquer les alertes de la session comme vues |
POST | /api/admin/check-in/validate | Équipe avec checkin.scan | session_code et code : ce que la caméra a lu, ou une référence de billet saisie comme TKT-1042-1. Indique si le billet peut entrer, sans l'admettre |
POST | /api/admin/check-in/admit | Équipe avec checkin.scan | Pareil avec client_request_id (un UUID), et admet le billet. Un billet déjà entré répond 409 avec ALREADY_ADMITTED, quand et par qui ; WRONG_SESSION et TICKET_VOID sont aussi refusés |
GET | /api/admin/session-staff | Équipe avec admins.edit | Quels membres du contrôle des billets sont attribués à quelles sessions |
PUT | /api/admin/session-staff/:code | Équipe avec admins.edit | Définir l'équipe d'entrée d'une session : admin_ids, séparés par des virgules |
Les membres qui peuvent modifier ou publier des événements accèdent à toutes les sessions ; les autres seulement à celles qui leur sont attribuées, et une autre répond 403. Chaque membre peut faire 120 contrôles par minute.
Vue d'ensemble, rapports et exports
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admin/overview | Équipe avec overview.view | La vue d'ensemble : totaux, la série des ventes, les ventes par événement, fournisseur et catégorie, l'entrée en direct, les prochains événements et ce qui demande de l'attention. range (last_7_days, last_30_days, this_month, all), last_30_days par défaut |
GET | /api/admin/reports | Équipe avec reports.view | Les mêmes chiffres de ventes, pour range, ou from et to, et en option un event |
POST | /api/admin/reports/export | Équipe avec reports.export | Démarrer un CSV : kind (orders, sales, attendees) et des filters optionnels. Répond 202 avec son id |
GET | /api/admin/reports/exports/:id | Équipe avec reports.export | Où en est l'export ; une fois prêt, son download_url |
GET | /api/admin/reports/exports/:id/download | Toute personne qui détient le token du lien | Le fichier CSV. Le lien fonctionne une heure et n'est affiché qu'une fois |
Les fichiers CSV sont écrits dans EXPORT_DIR en arrière-plan, et le lien de téléchargement est construit à partir de PUBLIC_API_URL.
Espace de travail, paiements et paramètres du site
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admin/workspace | Équipe avec settings.view | L'espace de travail : nom, e-mail de support, devise, fuseau horaire, frais de réservation (fee_bps), hold_seconds et max_per_order (lecture seule : ce sont des colonnes alimentées par back-end/src/database/seeders/data/settings.json), et notification_settings, les réglages de la cloche de notifications de l'équipe |
PATCH | /api/admin/workspace | Équipe avec settings.edit | Modifier name, support_email, currency (USD, EUR, GBP, AED, SAR), time_zone, fee_bps (0 à 2000, centièmes de pourcent ; le participant les paie toujours au paiement) ou notification_settings (order_paid, refund_requested, checkin_alerts), avec la version chargée. La devise se verrouille dès que l'espace de travail a vendu (CURRENCY_LOCKED). Tout autre champ, fee_payer, hold_seconds et max_per_order compris, répond 400 |
GET | /api/admin/payment-providers | Équipe avec settings.view | Les configured, live et offered de chaque fournisseur. Les clés restent dans le .env de l'API et ne sont jamais renvoyées |
GET | /api/settings | Équipe avec settings.view | Chaque paramètre du site. search, category, page, page_count |
GET | /api/settings/:key | Équipe avec settings.view | Un paramètre par sa clé |
PATCH | /api/settings/:key | Équipe avec settings.edit | Modifier la valeur d'un paramètre |
DELETE | /api/settings/:key | Équipe avec settings.edit | Supprimer un paramètre |
Équipe et rôles
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/admins | Équipe avec admins.view | L'équipe de l'espace de travail. email, name, phone (tous ceux donnés doivent correspondre), page, page_count |
GET | /api/admins/statistics | Équipe avec admins.view | Les décomptes pour la liste de l'équipe |
GET | /api/admins/:id | Équipe avec admins.view | Un membre, par identifiant ou nom d'utilisateur |
POST | /api/admins | Équipe avec admins.create | Ajouter un membre : first_name, last_name, email, password et password_confirmation (6 caractères ou plus), en option phone |
PATCH | /api/admins/:id | Équipe avec admins.edit | Modifier un membre |
PATCH | /api/admins/:id/roles | Équipe avec admins.assign_roles | Définir les rôles d'un membre : role_ids |
DELETE | /api/admins/:id | Équipe avec admins.delete | Retirer un membre de l'espace de travail courant. Le compte lui-même n'est supprimé que si c'était son dernier espace de travail ; data.removed répond workspace ou account. Se retirer soi-même répond 403 avec REMOVE_SELF, et retirer le dernier propriétaire de l'espace de travail 409 avec LAST_OWNER |
PATCH | /api/admins/profile | N'importe quel membre de l'équipe connecté | Modifier les propres first_name, last_name, email, phone, profile_picture ou country_id du membre connecté. Un password ou des role_ids dans le corps répondent 400 : le mot de passe a sa propre route |
PATCH | /api/admins/profile/password | N'importe quel membre de l'équipe connecté | Changer le propre mot de passe du membre connecté : current_password, password, password_confirmation |
GET | /api/roles | Équipe avec roles.view | Les rôles. name, guard_name, created_from, created_to, page, page_count |
GET | /api/roles/statistics | Équipe avec roles.view | Les nombres pour la liste des rôles |
GET | /api/roles/select | Équipe avec roles.view | L'identifiant et le nom de chaque rôle, pour un sélecteur |
GET | /api/roles/permissions | Équipe avec roles.view | Toutes les permissions, groupées par domaine |
GET | /api/roles/:id | Équipe avec roles.view | Un rôle avec ses permissions |
POST | /api/roles | Équipe avec roles.create | Ajouter un rôle : name |
PUT | /api/roles/:id | Équipe avec roles.edit | Renommer un rôle : name |
POST | /api/roles/:id/permissions | Équipe avec roles.assign_permissions | Définir les permissions d'un rôle, par nom |
DELETE | /api/roles/:id | Équipe avec roles.delete | Supprimer un rôle |
Demandes, notifications et fichiers envoyés
| Méthode | Chemin | Qui peut l'appeler | Rôle |
|---|---|---|---|
GET | /api/leads | Équipe avec leads.view | Les demandes du formulaire de contact, avec des décomptes par statut. status, q, received_within_days, page, page_size |
GET | /api/leads/:id | Équipe avec leads.view | Une demande |
PATCH | /api/leads/:id | Équipe avec leads.edit | Définir status (new, contacted, closed), notes ou assigned_admin_id |
GET | /api/notifications | N'importe quel membre de l'équipe connecté | Les 30 notifications les plus récentes du membre connecté |
PATCH | /api/notifications/read-all | N'importe quel membre de l'équipe connecté | Toutes les marquer comme lues |
PATCH | /api/notifications/:id/read | N'importe quel membre de l'équipe connecté | En marquer une comme lue |
DELETE | /api/notifications/:id | N'importe quel membre de l'équipe connecté | En supprimer une |
POST | /api/helpers/upload | N'importe quel membre de l'équipe connecté | Stocker un fichier (multipart file, avec path pour le dossier, for pour le préréglage de taille comme venue, cover, logo ou profile, et type). Les photos sont réencodées, sur 1 920 pixels de large au plus ; les vidéos sont acceptées en MP4, WebM, MOV ou M4V ; 150 Mo au plus. Répond avec les adresses du fichier stocké |
Les notifications couvrent les commandes payées, les demandes de remboursement, les alertes d'entrée, les nouvelles demandes et les concepts de lieux terminés, et sont conservées 30 jours. Un envoi de fichier n'a pas de permission propre : ce que devient le fichier est vérifié par la route qui l'enregistre. Les fichiers vont dans le bucket R2 quand ses cinq variables sont définies, et dans MEDIA_UPLOAD_DIR sinon.
Limites par adresse
| Route | Limite | Variable |
|---|---|---|
POST /api/auth/login, POST /api/customer-auth/login | 10 connexions échouées par 15 minutes, chacune comptée à part | RATE_LIMIT_LOGIN |
POST /api/customer-auth/register | 10 par 10 minutes | Aucune |
POST /api/customer-auth/forgot-password | 5 par 10 minutes | Aucune |
POST /api/leads | 5 par 10 minutes | Aucune |
POST /api/admin/check-in/validate, /admit | 120 par minute et par membre de l'équipe | Aucune |
POST /api/customer-auth/resend-verification, POST /api/orders/:reference/resend-email | Une fois par minute | Aucune |
Une requête au-delà d'une limite répond 429. Les compteurs vivent dans la mémoire de l'API : un redémarrage les efface. Derrière un reverse proxy, définissez TRUST_PROXY pour que chaque visiteur soit compté sur sa propre adresse.
Assistant IA d'événements et ses conversations
Inclus avec votre achat. Connectez-vous pour le lire, ou ouvrez-le dans votre téléchargement.
La route de streaming de l'assistant, sa liste de modèles, l'approbation des brouillons et les conversations enregistrées.
Studio de lieux
Inclus avec votre achat. Connectez-vous pour le lire, ou ouvrez-le dans votre téléchargement.
Les routes du studio : les générations et les concepts enregistrés sur un lieu.
Serveur MCP
Inclus avec votre achat. Connectez-vous pour le lire, ou ouvrez-le dans votre téléchargement.
L'endpoint MCP pour les agents de code et la façon dont il est autorisé.
Mises à jour en direct via WebSocket
Inclus avec votre achat. Connectez-vous pour le lire, ou ouvrez-le dans votre téléchargement.
Les namespaces Socket.IO qu'écoute le tableau de bord, leurs événements et la façon dont une connexion est autorisée.
Routes du mode démo
Inclus avec votre achat. Connectez-vous pour le lire, ou ouvrez-le dans votre téléchargement.
Les routes qui n'existent que pour un build de démo publique.