Skip to content

Démarrage rapide ​

Ce guide part d'un compte vide et arrive à une réservation encaissée. Comptez une trentaine de minutes. Chaque étape est autonome et donne le code exact à exécuter.

Le fil rouge : vendre des places pour un concert du 12 mars dans la salle Olympia.

Avant de commencer

Vous avez besoin d'un compte sur bo.mitoera.com et d'un terminal. Tout ce qui suit fonctionne aussi en mode sandbox, sans conséquence sur vos données de production — c'est même recommandé pour un premier essai.

Étape 1 — Récupérer ses clés API ​

Dans le back-office, ouvrez Clés API et créez deux clés :

CléFormatOù l'utiliser
Clé secrète (backoffice)pk_xxxxxxxx:sk_xxxxxxxxServeur uniquement
Clé publiquepk_live_xxxxxxxx (prod) · pk_test_xxxxxxxx (sandbox)Front-end, dans le widget

Ne publiez jamais la clé secrète

Elle donne un accès complet en écriture à votre workspace. Elle ne doit jamais apparaître dans du code envoyé au navigateur, ni dans un dépôt Git. Stockez-la en variable d'environnement.

Le détail des deux types de clés est sur la page Clés API.

Étape 2 — Installer le SDK ​

Vous pouvez tout faire en HTTP brut, mais le SDK évite d'écrire l'authentification et le parsing à la main.

bash
npm install @mitoera/sdk
bash
composer require mitoera/php-sdk:^1.0
bash
# Rien à installer : cURL ou fetch suffisent.
# Voir la référence API : /api/

Versions

mitoera/php-sdk est en v1.0.1, @mitoera/sdk en 0.1.0 — ce dernier étant en 0.x, épinglez-le si votre chaîne de build ne le fait pas. Les deux sont sous licence MIT et sans dépendance de production.

Initialisez ensuite le client avec votre clé secrète :

ts
import { MitoeraClient } from '@mitoera/sdk';

const client = new MitoeraClient({
  keyId:  process.env.MITOERA_KEY_ID,   // pk_xxxxxxxx
  secret: process.env.MITOERA_SECRET,   // sk_xxxxxxxx
});
php
use Mitoera\Sdk\MitoeraClient;

$client = new MitoeraClient([
    'keyId'  => getenv('MITOERA_KEY_ID'),   // pk_xxxxxxxx
    'secret' => getenv('MITOERA_SECRET'),   // sk_xxxxxxxx
]);

Étape 3 — Créer le plan de salle ​

Un plan naît vide, puis on lui ajoute ses sièges.

ts
const chart = await client.charts.create('Salle Olympia');
console.log(chart.id); // 01926a3f-1234-7abc-8def-000000000001
php
$chart = $client->charts->create('Salle Olympia');
echo $chart->id; // 01926a3f-1234-7abc-8def-000000000001
bash
curl -X POST https://api.mitoera.com/api/charts \
  -u pk_xxxxxxxx:sk_xxxxxxxx \
  -H 'Content-Type: application/json' \
  -d '{"name":"Salle Olympia"}'

Dessinez ensuite la salle. Deux voies :

  • Le back-office — ouvrez le plan et placez rangées et sièges à la souris. C'est la voie recommandée pour démarrer.
  • L'éditeur embarqué — le même éditeur, dans une iframe de votre propre back-office, si vos utilisateurs doivent dessiner leurs salles eux-mêmes.

Gardez l'id du plan sous la main : c'est votre chartId.

Étape 4 — Publier le plan ​

Un plan draft n'est pas utilisable par un événement. Il faut le publier.

ts
await client.charts.publish(chartId);
php
$client->charts->publish($chartId);
bash
curl -X POST https://api.mitoera.com/api/charts/CHART_ID/publish \
  -u pk_xxxxxxxx:sk_xxxxxxxx

Toute modification ultérieure repasse pendingChanges à true : les changements existent, mais les événements continuent d'utiliser la dernière version publiée jusqu'à ce que vous republiiez.

Étape 5 — Créer l'événement ​

L'événement, c'est la date. Il porte un identifier textuel unique, bien plus pratique qu'un UUID dans vos URLs.

ts
const event = await client.events.create(
  'Concert 12 mars',   // title
  'concert-12-mars',   // identifier (slug unique)
  chartId,             // plan associé
);
php
$event = $client->events->create(
    'Concert 12 mars',   // title
    'concert-12-mars',   // identifier (slug unique)
    $chartId,            // plan associé
);
bash
curl -X POST https://api.mitoera.com/api/events \
  -u pk_xxxxxxxx:sk_xxxxxxxx \
  -H 'Content-Type: application/json' \
  -d '{"title":"Concert 12 mars","identifier":"concert-12-mars","chartId":"CHART_ID"}'

Si vous aviez créé l'événement sans plan, associez-le après coup avec linkChart(eventId, chartId).

Étape 6 — Ouvrir une session côté serveur ​

Avant d'afficher la page de réservation, votre back-end crée une session. Elle matérialise le panier et produit les jetons nécessaires.

ts
const session = await client.sessions.create(event.id);

// À transmettre à la page :
session.sessionToken;  // pour le widget
session.holdToken;     // à garder côté serveur pour confirmer plus tard
session.expiresIn;     // durée de vie, en secondes
php
$session = $client->sessions->create($event->id);

// À transmettre à la page :
$session->sessionToken;  // pour le widget
$session->holdToken;     // à garder côté serveur pour confirmer plus tard
$session->expiresIn;     // durée de vie, en secondes

Session obligatoire ?

Non. Le widget sait créer sa propre session à partir de la clé publique, et vous récupérez alors les jetons dans le callback onReady. Créer la session côté serveur vous donne simplement la main dessus dès le départ — c'est plus confortable dès que le paiement entre en jeu.

Étape 7 — Afficher le plan sur votre page ​

La version la plus courte, sans bundler, avec la clé publique :

html
<div id="mitoera-chart" style="width:100%;height:600px"></div>

<script src="https://bo.mitoera.com/mitoera-widget.js"></script>
<script>
  const chart = new Mitoera.SeatingChart({
    divId:        'mitoera-chart',
    workspaceKey: 'pk_live_xxxxxxxx',
    event:        'concert-12-mars',   // slug ou UUID

    onReady: ({ sessionToken, holdToken, eventId }) => {
      console.log('Widget prêt', eventId);
    },
    onSelectionChange: (seats) => {
      document.querySelector('#total').textContent = `${seats.length} siège(s)`;
    },
    onCheckout: (seats) => {
      // L'utilisateur a cliqué « Valider » → on part vers le paiement
      demarrerPaiement(seats.map(s => s.seatKey));
    },
  });

  chart.render();
</script>

Avec un bundler (Vue, React, Svelte…), c'est le même objet importé depuis le SDK :

ts
import { SeatingChart } from '@mitoera/sdk/browser';

À ce stade, votre page affiche le plan, les sièges se sélectionnent et se bloquent automatiquement. Voir SeatingChart pour les options complètes.

Étape 8 — Confirmer la réservation après paiement ​

Le paiement encaissé, votre serveur transforme le hold en réservation ferme. C'est la seule étape qui rend les sièges définitivement vendus.

ts
const book = await client.holds.book(
  eventId,
  ['A-1', 'A-2'],      // seatKeys sélectionnés
  session.holdToken,
);

book.bookedSeats; // ['A-1', 'A-2']
book.bookedAt;    // Date
php
$book = $client->holds->book(
    $eventId,
    ['A-1', 'A-2'],      // seatKeys sélectionnés
    $session->holdToken,
);

$book->bookedSeats; // ['A-1', 'A-2']
$book->bookedAt;    // DateTimeImmutable
bash
curl -X POST https://api.mitoera.com/api/events/EVENT_ID/book \
  -u pk_xxxxxxxx:sk_xxxxxxxx \
  -H 'Content-Type: application/json' \
  -d '{"seatKeys":["A-1","A-2"],"holdToken":"hld_9f2c…"}'

Et si l'utilisateur abandonne, libérez explicitement plutôt que d'attendre l'expiration :

ts
await client.holds.release(eventId, ['A-1', 'A-2'], session.holdToken);
php
$client->holds->release($eventId, ['A-1', 'A-2'], $session->holdToken);

Étape 9 — Vérifier l'état des sièges ​

Pour contrôler le résultat, demandez la carte des statuts de l'événement :

ts
const map = await client.events.listSeats(eventId);

map.booked();            // ['A-1', 'A-2']
map.available().length;  // sièges encore vendables
map.isAvailable('A-3');  // true
php
$map = $client->events->listSeats($eventId);

$map->booked();            // ['A-1', 'A-2']
count($map->available());  // sièges encore vendables
$map->isAvailable('A-3');  // true
bash
curl https://api.mitoera.com/api/events/EVENT_ID/seats \
  -u pk_xxxxxxxx:sk_xxxxxxxx

Récapitulatif ​

┌ Serveur (clé secrète) ─────────────────────────────────────┐
│  1. charts.create → dessin → charts.publish                │
│  2. events.create(title, identifier, chartId)              │
│  3. sessions.create(eventId) → sessionToken + holdToken    │
└────────────────────────────────────────────────────────────┘
              │ sessionToken
              ▼
┌ Navigateur (clé publique) ─────────────────────────────────┐
│  4. new SeatingChart({ divId, workspaceKey, event })       │
│     → sélection utilisateur → hold automatique             │
│     → onCheckout(seats)                                    │
└────────────────────────────────────────────────────────────┘
              │ seatKeys
              ▼
┌ Serveur (clé secrète) ─────────────────────────────────────┐
│  5. paiement encaissé                                      │
│  6. holds.book(eventId, seatKeys, holdToken)               │
│     ou holds.release(...) si abandon                       │
└────────────────────────────────────────────────────────────┘

Et ensuite ​

API, SDK et widget de plans de salle.