StudEvent
API · v1

Démarrer

  • Introduction
  • Authentification
  • Erreurs
  • Pagination

Core API

  • Événements
  • Checkout
  • Commandes
  • Billets
  • Scan

Webhooks

  • Concept
  • Signature & vérif
  • Types d'événements
  • Gérer les endpoints

SDK & exemples

  • Lister tes events
  • Tunnel d'achat

Pour les IA

  • Claude / Cursor / Windsurf
  • llms.txt & full
  • OpenAPI spec
  • Changelog
Besoin d'aide ?
dev@studevent-app.com
v1 · stable

StudEvent API

L'API publique de StudEvent permet à ton BDE d'intégrer la billetterie directement sur son site : afficher tes événements, vendre des places, valider des billets, recevoir des notifications temps réel.

Base URL
https://studevent-app.com/api/v1
Auth
Bearer sk_live_…
Format
JSON · UTF-8

Toutes les requêtes utilisent HTTPS et retournent du JSON. L'API est versionnée via le préfixe /v1. Les ruptures de compatibilité ouvriront une nouvelle version — la v1 restera servie sans changement.

Authentification

Toutes les requêtes doivent porter un header Authorization avec une clé API créée depuis ton dashboard Paramètres → API & Webhooks. Chaque clé est rattachée à ton organisation et porte un ensemble de scopes qui limitent ce qu'elle peut faire.

curl https://studevent-app.com/api/v1/events \
  -H "Authorization: Bearer sk_live_XXXXXXXXXXXXXXXXXXXXXXXX"

Scopes disponibles

ChampTypeDescription
events:readstringLecture des événements & tarifs publiés.
orders:readstringLecture des commandes (statut, total, billets).
tickets:readstringLecture des billets émis.
tickets:writestringMarquer un billet comme scanné (point d’entrée custom).
checkout:writestringCréer un checkout — démarrer un paiement Stripe.
webhooks:managestringCRUD sur les endpoints webhooks via l’API.
⚠️ Stocke tes clés côté serveur uniquement. Une clé sk_live_… exposée dans du JavaScript public donne accès à toutes les commandes et billets de ton BDE.

Erreurs

L'API retourne des codes HTTP standards. Les erreurs renvoient un objet JSON avec un type machine-friendly et un message humain.

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "error": {
    "type": "invalid_api_key",
    "message": "Unknown or revoked API key."
  }
}
ChampTypeDescription
400invalid_requestParamètres manquants ou invalides.
401authentication_required / invalid_api_keyHeader Authorization absent ou clé inconnue.
403permission_denied / insufficient_scopeLa clé n’a pas le scope requis pour cette action.
404resource_not_foundLa ressource ciblée n’existe pas dans ton organisation.
429rate_limitedLimite de débit atteinte — réessaie après le délai indiqué.
500internal_errorErreur côté serveur StudEvent — réessaie ou contacte-nous.

Pagination

Les endpoints de liste retournent { object: "list", data: [...], has_more, next_cursor }. Pour récupérer la page suivante, repasse next_cursor dans le paramètre cursor.

# Première page
curl "https://studevent-app.com/api/v1/events?limit=20" -H "Authorization: Bearer $KEY"

# Page suivante
curl "https://studevent-app.com/api/v1/events?limit=20&cursor=2026-05-22T10:14:32Z" \
  -H "Authorization: Bearer $KEY"

Événements

Objets publics — la base pour afficher ta billetterie sur ton site.

Lister les événements

GET/v1/eventsscope: events:read
ChampTypeDescription
statusstring?draft, published (défaut), closed, archived.
limitint?1 à 100, défaut 20.
cursorstring?ISO timestamp, retourné via next_cursor.
curl "https://studevent-app.com/api/v1/events?limit=10" \
  -H "Authorization: Bearer $STUDEVENT_KEY"

Récupérer un événement

GET/v1/events/{id_or_slug}scope: events:read

Renvoie l'événement avec ses ticket_types inline (tarif, quota, disponibilité). Accepte soit l'UUID, soit le slug.

curl https://studevent-app.com/api/v1/events/gala-2026 \
  -H "Authorization: Bearer $STUDEVENT_KEY"

Checkout

Crée une commande en statut pending et reçois l'URL Stripe vers laquelle rediriger l'acheteur. Une fois le paiement validé, le billet est émis automatiquement par notre webhook Stripe et l'événement order.paid est envoyé à tes endpoints souscrits.

POST/v1/checkout/sessionsscope: checkout:write
ChampTypeDescription
event_idrequiredstringUUID de l’événement publié.
ticket_type_idrequiredstringUUID du tarif choisi.
emailrequiredstringEmail de l’acheteur (le billet y sera envoyé).
first_namerequiredstringPrénom du porteur.
last_namerequiredstringNom du porteur.
responsesobject?Map des réponses au formulaire custom (clé → valeur).
curl -X POST https://studevent-app.com/api/v1/checkout/sessions \
  -H "Authorization: Bearer $STUDEVENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "a1b2c3d4-…",
    "ticket_type_id": "tt_…",
    "email": "leo@example.com",
    "first_name": "Léo",
    "last_name": "Martin",
    "responses": { "promo_id": "2027", "campus_id": "lyon" }
  }'

Commandes

GET/v1/orders/{ref}scope: orders:read

Accepte un display_ref (O-2026-XXXXXXXX) ou un UUID. Renvoie la commande avec ses tickets émis inline.

curl https://studevent-app.com/api/v1/orders/O-2026-X4F8K2QM \
  -H "Authorization: Bearer $STUDEVENT_KEY"

Billets

GET/v1/tickets/{ref}scope: tickets:read

Récupère un billet par display_ref (T-2026-XXXXXXXX) ou UUID.

Scan

Endpoint server-to-server pour valider un billet à l'entrée — utile si tu construis ton propre point de contrôle (tourniquet, app native, etc.). Pour le scanner web standard, utilise l'interface dashboard intégrée.

POST/v1/tickets/{ref}/scanscope: tickets:write
ChampTypeDescription
qrstring?QR payload brut — si fourni, la signature HMAC est vérifiée.
gate_idstring?UUID de la porte/zone, pour les statistiques.
device_idstring?Identifiant libre du device scanner.
curl -X POST https://studevent-app.com/api/v1/tickets/T-2026-XFXPBBC5/scan \
  -H "Authorization: Bearer $STUDEVENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"gate_id": "porte-A", "device_id": "ipad-01"}'

Webhooks

Les webhooks permettent à ton site BDE de recevoir des notifications en temps réel quand quelque chose se passe sur StudEvent : un billet vient d'être payé, un participant vient de passer à l'entrée, une commande a été remboursée. Tu configures un ou plusieurs endpoints HTTPS, et StudEvent y envoie des requêtes POST JSON signées.

Vérifier la signature

Chaque requête webhook porte un header studevent-signature au format t=<timestamp>,v1=<hex_hmac>. Le HMAC est calculé sur la chaîne `${timestamp}.${rawBody}` avec ton signing_secret.

import crypto from "node:crypto";

export function verify(req, body) {
  const header = req.headers["studevent-signature"] ?? "";
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", process.env.STUDEVENT_WEBHOOK_SECRET)
    .update(`${parts.t}.${body}`)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(parts.v1, "hex"),
  );
}
Rejette toute requête où |now − t| > 300s pour empêcher les attaques par rejeu.

Types d'événements

ChampTypeDescription
order.paideventUne commande est passée à status=paid. Le billet a été émis.
order.refundedeventLa commande a été remboursée par le BDE.
ticket.createdeventUn nouveau billet a été émis (juste avant order.paid).
ticket.scannedeventUn billet est passé à l’entrée (premier scan valide).
refund.createdeventAudit du remboursement effectué — qui, quand, raison.

Format du payload

POST https://mon-bde.fr/api/studevent-webhook
Headers:
  studevent-signature: t=1748044819,v1=abc123…
  studevent-event: order.paid
  Content-Type: application/json

{
  "id": "evt_8KqLm2",
  "type": "order.paid",
  "created": 1748044819,
  "data": {
    "order_id": "o_…",
    "order_ref": "O-2026-X4F8K2QM",
    "event_id": "a1b2c3d4-…",
    "email": "leo@example.com",
    "total_cents": 4500,
    "currency": "eur"
  }
}

Gérer les endpoints

Gérables soit depuis ton dashboard (Paramètres → API & Webhooks), soit via l'API avec le scope webhooks:manage.

GET/v1/webhook_endpointsscope: webhooks:manage
POST/v1/webhook_endpointsscope: webhooks:manage
DELETE/v1/webhook_endpoints/{id}scope: webhooks:manage
curl -X POST https://studevent-app.com/api/v1/webhook_endpoints \
  -H "Authorization: Bearer $STUDEVENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://mon-bde.fr/api/studevent-webhook",
    "enabled_events": ["order.paid", "ticket.scanned", "refund.created"],
    "description": "Sync vers notre intranet"
  }'

⚠️ Le signing_secret n'est visible qu'une seule fois à la création.

Exemple : afficher tes events sur ton site

Quelques lignes côté serveur sur ton site BDE :

export const revalidate = 60;

export default async function EventsPage() {
  const res = await fetch("https://studevent-app.com/api/v1/events?limit=20", {
    headers: { Authorization: `Bearer ${process.env.STUDEVENT_KEY}` },
    next: { revalidate: 60 },
  });
  const { data: events } = await res.json();

  return (
    <ul>
      {events.map((e) => (
        <li key={e.id}>
          <a href={`/events/${e.slug}`}>{e.name}</a>
          <span>{new Date(e.starts_at).toLocaleDateString("fr-FR")}</span>
        </li>
      ))}
    </ul>
  );
}

Exemple : tunnel d'achat sur ton site

Affiche ton propre formulaire sur ton site, et appelle /v1/checkout/sessions pour rediriger vers Stripe. Le billet sera émis automatiquement et l'événement order.paid arrivera sur ton webhook.

export async function POST(req) {
  const form = await req.formData();
  const res = await fetch("https://studevent-app.com/api/v1/checkout/sessions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.STUDEVENT_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      event_id: form.get("event_id"),
      ticket_type_id: form.get("ticket_type_id"),
      email: form.get("email"),
      first_name: form.get("first_name"),
      last_name: form.get("last_name"),
    }),
  });
  if (!res.ok) {
    const err = await res.json();
    return Response.json(err, { status: res.status });
  }
  const { url } = await res.json();
  return Response.redirect(url, 303);
}

Pour les IA — MCP server

StudEvent fournit un serveur MCP officiel (@studevent/mcp) qui expose tous les endpoints v1 comme tools utilisables directement depuis Claude Desktop, Cursor, Windsurf, Codex, ou tout client MCP compatible. Tu peux par exemple demander à Claude « liste mes events publiés », « crée un checkout pour Léo sur le gala », ou « combien de billets scannés ce soir ? ».

Configuration Claude Desktop

Édite ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) ou %APPDATA%\Claude\claude_desktop_config.json (Windows) :

{
  "mcpServers": {
    "studevent": {
      "command": "npx",
      "args": ["-y", "@studevent/mcp"],
      "env": { "STUDEVENT_API_KEY": "sk_live_XXXXXXXXXXXXXXXXXXXXXXXX" }
    }
  }
}

Configuration Cursor

Édite ~/.cursor/mcp.json (même format que Claude Desktop). Cursor redémarrera le serveur MCP automatiquement.

Configuration Windsurf

Édite ~/.codeium/windsurf/mcp_config.json (même format). Active la fonction MCP dans les paramètres Cascade.

Tools disponibles

ChampTypeDescription
list_eventsevents:readListe les events publiés.
get_eventevents:readDétail event + ticket_types.
create_checkout_sessioncheckout:writeCrée une commande + URL Stripe.
get_orderorders:readRécupère une commande par ref.
get_tickettickets:readRécupère un billet par ref.
scan_tickettickets:writeValide un billet à l’entrée.
list_webhook_endpointswebhooks:manageListe les endpoints webhooks.
create_webhook_endpointwebhooks:manageCrée un endpoint.
delete_webhook_endpointwebhooks:manageSupprime un endpoint.
Le serveur MCP utilise ta clé API standard — les scopes de la clé limitent ce que l'IA pourra faire. Crée une clé dédiée « Claude Desktop » avec les scopes strictement nécessaires.

llms.txt — contexte pour LLM

StudEvent expose deux fichiers au standard llms.txt pour donner du contexte aux LLM sans navigation web :

/llms.txt
Résumé court — overview + index des routes.
/llms-full.txt
Doc complète aplatie — colle-la dans un prompt comme contexte.
# Colle la doc dans un prompt
curl https://studevent-app.com/llms-full.txt | pbcopy

# Ou donne juste l'URL à ton IA — la plupart savent fetcher
echo "Voici la doc StudEvent: https://studevent-app.com/llms-full.txt"

OpenAPI spec

La spec OpenAPI 3.1 est servie à /api/v1/openapi.json (CORS ouvert). Utilise-la pour :

  • Codex / Cursor / Copilot — partage l'URL pour qu'ils comprennent les types et endpoints.
  • Postman / Insomnia / Hoppscotch — Import → URL → tous les endpoints sont prêts à tester.
  • Code-gen — openapi-typescript, hey-api, openapi-generator, etc. pour générer un client typé.
# Génère un client TS typé
npx openapi-typescript https://studevent-app.com/api/v1/openapi.json \
  -o ./src/lib/studevent.d.ts

Changelog

ChampTypeDescription
2026-05-23v1.0Sortie de l’API publique : events, checkout, orders, tickets, scan, webhooks.

Prêt à intégrer ?

Crée ta première clé depuis Paramètres → API & Webhooks. Toute question : dev@studevent-app.com.