API BilletWeb — Référence complète
Plateforme : BilletWeb.fr — billetterie en ligne Compte : Parc de la Luge (user=268537) Dernière mise à jour : 29/05/2026
1. Authentification
L'API BilletWeb utilise une authentification par query parameters (pas de token Bearer).
user=<user_id>
key=<api_key>
version=1
L'API key se trouve dans le compte BilletWeb : Réglages → Outils → API.
⚠️ Pas de JSON-RPC, pas de REST auth standard — clé en query string.
2. Endpoints
2.1 Lister les événements
GET https://www.billetweb.fr/api/user/events
?user=<user_id>
&key=<api_key>
&version=1
Retourne la liste des événements du compte.
Réponse :
[
{
"id": 1350897,
"name": "Parc de la Luge - Billetterie",
"date_start": "2026-01-01",
"date_end": "2026-12-31",
"status": "active"
}
]
2.2 Lister les participants
GET https://www.billetweb.fr/api/event/{event_id}/attendees
?user=<user_id>
&key=<api_key>
&version=1
&since=<YYYY-MM-DD HH:MM:SS>
Paramètres :
| Paramètre | Description |
|---|---|
event_id |
ID de l'événement BilletWeb |
since |
Optionnel — filtre les ventes après cette date (format YYYY-MM-DD HH:MM:SS) |
ticket_id |
Optionnel — filtre par type de billet |
Réponse (tableau de participants) :
[
{
"id": "12345678",
"barcode": "6743097169",
"ref": "BW-XXXXXX",
"ticket": "Luge - Forfait 4 tours",
"ticket_id": 12345,
"name": "Jean Dupont",
"email": "jean@email.com",
"used": "0",
"date": "2026-05-15 10:30:00",
"price": "11.00",
"event_id": "1350897"
}
]
Champs importants :
| Champ | Type | Description |
|---|---|---|
id |
string | ID unique de la commande (référence de commande) |
barcode |
string | Code barre unique (servira de lien entre BilletWeb et Odoo) |
ref |
string | Référence BilletWeb (format BW-XXXXXX) |
ticket |
string | Nom du billet |
ticket_id |
int | ID du type de billet |
name |
string | Nom du participant |
email |
string | Email du participant |
used |
string |
"0" = pas encore composté, "1" = déjà utilisé |
date |
string | Date d'achat |
price |
string | Prix payé |
event_id |
string | ID de l'événement |
2.3 Composter un billet (check)
POST https://www.billetweb.fr/api/event/{event_id}/check
?user=<user_id>
&key=<api_key>
&version=1
Body: {"code": "6743097169"}
Comportement :
- Valide que le billet existe et n'a pas déjà été utilisé
-
Composte le billet (le marque comme
used=1) - Idempotent ? Non — une fois composté, un deuxième appel échoue
Réponse succès :
{"success": true, "message": "Billet composté avec succès"}
Réponse erreur (billet déjà utilisé) :
{"error": "Ce billet a déjà été utilisé"}
3. Événements du Parc de la Luge
| ID BilletWeb | Nom | Événement Odoo |
|---|---|---|
1350897 |
Parc de la Luge - Billetterie | Event ID 1 |
1353693 |
BON CADEAU | Event ID 2 |
4. Mapping produits (18 billets)
| Intitulé BilletWeb | Code barre Odoo |
|---|---|
| Journée Luge illimitée | BW-LUGE-JOUR |
| Luge - Forfait 4 tours | BW-LUGE-4T |
| Luge - Forfait 6 tours | BW-LUGE-6T |
| Luge - Forfait 10 tours | BW-LUGE-10T |
| Luge - Forfait 12 tours | BW-LUGE-12T |
| Poney | BW-PONEY |
| Mon ticket Promo | BW-PROMO |
| OFFRE LIMITÉE - SPÉCIALE TRIBU | BW-LUGE-TRIBU |
| Tir à l'arc - 20 min | BW-TIR-20 |
| Tir à l'arc - 40 min | BW-TIR-40 |
| Kids électrique - 10 min | BW-KIDS-E10 |
| Trottinettes ETT - 20 min | BW-TROTT-20 |
| Bon cadeau Luge 4 tours | BW-CADEAU-LUGE4 |
| Bon cadeau Luge 3 tours | BW-CADEAU-LUGE3 |
| Bon cadeau Poney | BW-CADEAU-PONEY |
| Bon cadeau Kids électrique | BW-CADEAU-KIDS |
| Bon cadeau Tir à l'arc 20 min | BW-CADEAU-TIR20 |
| Bon cadeau Trottinettes ETT | BW-CADEAU-TROTT |
5. Architecture de synchronisation
┌─────────────┐ ┌──────────────┐ ┌──────────────┐
│ BilletWeb │◄────│ n8n.n8n-1 │────►│ Sync Server │
│ (API REST) │ │ (orchestre) │ │ (Python) │
└─────────────┘ └──────┬───────┘ └──────┬────────┘
│ │
│ Schedule: 15 min │ POST /sync
│ ▼
│ ┌────────────────┐
│ │ sync_billetweb │
│ │ (Python) │
│ └───────┬────────┘
│ │
│ ▼
│ ┌────────────────┐
└──────────►│ Odoo Online │
│ (JSON-RPC) │
└────────────────┘
Composants
| Service | Technologie | Port | Accès |
|---|---|---|---|
| n8n | n8n v2.21.7 Docker | 5678 | https://n8n.delgard.cloud |
| Sync Server | Python 3.12-slim | 8855 | Interne (Docker network) |
| Traefik | Reverse proxy | 80/443 | Let's Encrypt |
Flux de sync (script sync_billetweb.py)
1. 🔒 Charger tous les barcodes Odoo existants (anti-doublon)
2. 🌐 GET BilletWeb /api/event/{id}/attendees (2 events)
3. Pour chaque attendee nouveau :
a. Trouver/créer client (res.partner)
b. Trouver produit (product.product par barcode BW-*)
c. Trouver/créer commande (sale.order)
d. Créer ligne (sale.order.line)
e. Créer inscription (event.registration)
f. Lier ligne → inscription
4. 📊 Résultat : "X nouveaux importés"
6. Webhook de compostage (Odoo → BilletWeb)
Quand un billet est scanné au PDV Odoo (state: open → done), un webhook composte le billet BilletWeb.
Odoo (Automated Action)
│ POST webhook
▼
n8n Webhook Trigger
│ POST /webhook/billetweb-compost
▼
BilletWeb API
│ POST /api/event/{id}/check
▼
Billet composté ✅
Webhook URL
https://n8n.delgard.cloud/webhook/billetweb-compost
Payload attendu
{
"event_id": 1350897,
"barcode": "6743097169",
"name": "Jean Dupont",
"state": "done"
}
Configuration Odoo (Automated Action)
- Activer le mode développeur
- Technique → Automatisation → Règles d'automatisation → Créer
-
Modèle :
event.registration -
Déclencheur : « Lors de la mise à jour » + champ
state - Action : « Envoyer une notification webhook »
-
URL :
https://n8n.delgard.cloud/webhook/billetweb-compost -
Headers :
Content-Type: application/json -
Champs :
barcode,name,state,event_id
Test manuel
curl -X POST https://n8n.delgard.cloud/webhook/billetweb-compost \
-H "Content-Type: application/json" \
-d '{"event_id": 1350897, "barcode": "6743097169", "name": "Test", "state": "done"}'
# → {"message":"Workflow was started"}
7. Pièges et bonnes pratiques
Import initial : respecter le champ used
BilletWeb used
|
État réel | Odoo state correct |
|---|---|---|
"0" |
Pas encore venu | open |
"1" |
Déjà composté | done |
⚠️ Ne pas tout mettre en
donepar défaut — l'import initial du 26/05 avait ce bug.
Correction post-import :
# Repasser en "open" les billets used=0
bw_unused = {a['barcode'] for a in bw_attendees if a['used'] == '0'}
to_open = odoo_call("event.registration", "search_read",
[["barcode", "in", list(bw_unused)], ["state", "=", "done"]])
odoo_call("event.registration", "write",
[[r['id'] for r in to_open], {"state": "open"}])
# Repasser en "done" les billets used=1
bw_used = {a['barcode'] for a in bw_attendees if a['used'] == '1'}
to_done = odoo_call("event.registration", "search_read",
[["barcode", "in", list(bw_used)], ["state", "=", "open"]])
odoo_call("event.registration", "write",
[[r['id'] for r in to_done], {"state": "done"}])
Anti-doublon : cache vs Odoo direct
- Toujours requêter Odoo directement pour la liste des barcodes existants
- Ne pas se fier uniquement au fichier cache (
sync_cache.json) — il peut être vidé - Le cache est une optimisation, pas une source de vérité
Commandes multi-tickets
Ne pas bloquer la création d'une commande si client_order_ref existe déjà :
# ✅ Réutiliser la commande existante
existing_so = odoo_call("sale.order", "search_read",
[[["client_order_ref", "=", ref]]], {"fields": ["id"]})
if existing_so:
so = existing_so[0]["id"] # Ajouter des lignes à la commande existante
else:
so = odoo_call("sale.order", "create", [{...}]) # Créer nouvelle commande
Rate limiting BilletWeb
L'API BilletWeb n'a pas de limite documentée, mais espacer les appels d'au moins 1 seconde en cas de bulk.
8. Maintenance
Sync manuelle
docker exec n8n-sync-server-1 python3 /app/sync_billetweb.py
Réinitialiser le cache anti-doublon
docker exec n8n-sync-server-1 rm -f /root/.hermes/scripts/sync_cache.json
# Prochaine sync : recharge TOUS les barcodes depuis Odoo
Logs
docker logs n8n-n8n-1 --tail 50
docker logs n8n-sync-server-1 --tail 50
docker exec n8n-sync-server-1 cat /tmp/sync_result.json
Workflows n8n
| Nom | ID | Status |
|---|---|---|
| BilletWeb → Odoo Sync | n4r0JG3BvHKi9nmC |
✅ Actif (toutes les 15 min) |
| Compost BilletWeb (webhook) | V1TCykwcoSWlBHyX |
✅ Actif |
9. Fichiers associés
| Fichier | Emplacement |
|---|---|
| sync_billetweb.py (Docker) | /docker/n8n-gdkj/sync-server/sync_billetweb.py |
| sync_billetweb.py (host) | /root/.hermes/scripts/sync_billetweb.py |
| server.py (sync-server) | /docker/n8n-gdkj/sync-server/server.py |
| docker-compose n8n | /docker/n8n-gdkj/docker-compose.yml |
| Workflow n8n (export) | /root/workspace/n8n/workflow-billetweb-odoo.json |
| Architecture doc | /root/workspace/n8n/ARCHITECTURE.md |