PrivateEvent
API v1 · stable

Documentation développeurs

Recevez et répondez aux demandes de privatisation directement depuis votre CRM via notre API REST authentifiée par token.

URL de base

Toutes les requêtes utilisent HTTPS et acceptent / retournent du JSON.

https://privateevent.mesprojets.org/api/v1

Authentification

L'API utilise des tokens Bearer personnels (Laravel Sanctum). Chaque token est rattaché à un compte propriétaire de lieu et lui donne accès uniquement aux ressources de ses lieux.

⚠️ Génération de token

Pour obtenir un token API pour votre lieu, contactez infos@mesprojets.org en précisant le nom de votre lieu. Le token vous sera transmis par canal sécurisé. Une UI de self-service sera disponible prochainement.

Utilisation

Ajoutez le header Authorization: Bearer <token> à chaque requête.

Exemple — vérifier votre identité

# Request curl -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ https://privateevent.mesprojets.org/api/v1/me # Response 200 OK { "user": { "id": 2, "name": "Marc Dupont", "email": "marc@hotel-tour-eiffel.test", "role": "venue_owner" }, "venues": [ {"id": 1, "name": "Le Belvédère", "slug": "le-belvedere-...", "status": "active"} ] }

Endpoints

Tous les endpoints sont scopés à vos lieux : vous ne voyez que les demandes envoyées à un lieu dont vous êtes propriétaire.

GET /api/v1/solicitations

Lister les demandes reçues

Retourne une liste paginée des sollicitations envoyées à vos lieux. Triées par sent_at décroissant.

Query parameters

ParamTypeDescription
statusstringFiltre : sent · viewed · replied · declined
pageintNuméro de page (50 résultats par page)

Exemple

curl -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ "https://privateevent.mesprojets.org/api/v1/solicitations?status=sent"
GET /api/v1/solicitations/{id}

Détail d'une demande

Récupère toutes les infos d'une demande : événement, contact, entreprise, proposition envoyée (s'il y en a). Marque automatiquement la demande comme « vue » au premier appel.

Exemple de réponse

{ "data": { "id": 4, "status": "viewed", "sent_at": "2026-05-11T10:46:09+00:00", "viewed_at": "2026-05-11T10:55:22+00:00", "venue": { "id": 1, "name": "Le Belvédère", "city": "Paris", "capacity_min": 10, "capacity_max": 60 }, "booking_request": { "id": 2, "event_date": "2026-06-10", "start_time": "19:00", "end_time": "23:00", "persons": 50, "budget": {"type": "per_person", "amount": 75, "currency": "EUR"}, "event_types": ["cocktail"], "message": "...", "company": {"name": "TestCorp SAS", "siret": null}, "contact": {"name": "Pierre Test", "email": "...", "phone": "..."} }, "proposal": null, "urls": { "self": "https://privateevent.mesprojets.org/api/v1/solicitations/4", "create_proposal": "https://privateevent.mesprojets.org/api/v1/solicitations/4/proposal", "decline": "https://privateevent.mesprojets.org/api/v1/solicitations/4/decline" } } }
POST /api/v1/solicitations/{id}/proposal

Envoyer un devis

Crée une proposition pour une demande. Le client est automatiquement notifié par email avec un lien magique vers son espace.

Body parameters

FieldTypeRequisDescription
messagestringouiCorps du devis (10 à 5000 caractères)
total_priceintegernonMontant total en euros (entier)
attachments[]file[]nonJusqu'à 5 PDF, 10 MB par fichier (multipart/form-data)

Exemple JSON simple

curl -X POST \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{"message":"Nous pouvons accueillir votre événement, voici notre proposition.","total_price":3325}' \ https://privateevent.mesprojets.org/api/v1/solicitations/4/proposal # Response 201 Created {"data":{"id":2,"message":"...","total_price":3325,"source":"api","created_at":"..."}}

Exemple avec PDF

curl -X POST \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ -F "message=Devis détaillé en pièce jointe." \ -F "total_price=4500" \ -F "attachments[]=@devis.pdf" \ https://privateevent.mesprojets.org/api/v1/solicitations/4/proposal

Codes d'erreur spécifiques

  • 403 — Cette sollicitation n'est pas accessible avec votre token
  • 409 — Une proposition existe déjà OU la demande a été déclinée
  • 422 — Erreur de validation (message trop court, etc.)
POST /api/v1/solicitations/{id}/decline

Décliner une demande

Marque la demande comme déclinée. Aucun body requis.

curl -X POST \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Accept: application/json" \ https://privateevent.mesprojets.org/api/v1/solicitations/4/decline

Webhooks entrants

Configurez une URL pour recevoir en temps réel les nouvelles demandes de devis dans votre CRM, sans avoir à polling l'API.

Configuration

  1. Connectez-vous à votre espace lieu
  2. Menu Webhooks APICréer un webhook
  3. Renseignez l'URL HTTPS qui recevra les notifications
  4. Notez le signing secret généré aléatoirement (vous en aurez besoin pour vérifier les signatures)

Format des requêtes

Chaque event est envoyé en POST sur votre URL avec :

  • Content-Type: application/json
  • User-Agent: PrivateEvent-Webhooks/1.0
  • X-PrivateEvent-Event: solicitation.created
  • X-PrivateEvent-Signature: sha256=<hmac>
  • X-PrivateEvent-Delivery-Id: <uuid>

Payload exemple

{ "event": "solicitation.created", "occurred_at": "2026-05-11T10:46:09+00:00", "data": { "solicitation": { "id": 4, "status": "sent", "sent_at": "2026-05-11T10:46:09+00:00", "urls": { "self": "...", "create_proposal": "...", "decline": "..." } }, "venue": {"id": 1, "name": "Le Belvédère", "slug": "...", "city": "Paris"}, "booking_request": { "id": 2, "event_date": "2026-06-10", "start_time": "19:00", "end_time": "23:00", "persons": 50, "budget": {"type": "per_person", "amount": 75}, "event_types": ["cocktail"], "message": "...", "company": {"name": "TestCorp SAS", "siret": null}, "contact": {"name": "Pierre Test", "email": "...", "phone": "..."} } } }

Vérification de la signature

La signature est un HMAC-SHA256 du body raw avec votre signing secret. Vérifiez-la systématiquement pour vous protéger contre les requêtes falsifiées.

PHP

// Récupérer le body brut $body = file_get_contents('php://input'); $signature = $_SERVER['HTTP_X_PRIVATEEVENT_SIGNATURE'] ?? ''; $expected = 'sha256=' . hash_hmac('sha256', $body, YOUR_SIGNING_SECRET); if (! hash_equals($expected, $signature)) { http_response_code(401); exit('Invalid signature'); } $payload = json_decode($body, true); // Traiter $payload...

Node.js (Express)

const crypto = require('crypto'); app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => { const sig = req.header('X-PrivateEvent-Signature') || ''; const expected = 'sha256=' + crypto .createHmac('sha256', YOUR_SIGNING_SECRET) .update(req.body) .digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) { return res.status(401).send('Invalid signature'); } const payload = JSON.parse(req.body.toString()); // Traiter payload... res.status(200).send('ok'); });

Python (Flask)

import hmac, hashlib from flask import request, abort @app.route('/webhook', methods=['POST']) def webhook(): body = request.get_data() sig = request.headers.get('X-PrivateEvent-Signature', '') expected = 'sha256=' + hmac.new( YOUR_SIGNING_SECRET.encode(), body, hashlib.sha256 ).hexdigest() if not hmac.compare_digest(sig, expected): abort(401) payload = request.get_json() # Traiter payload... return 'ok', 200

Retry policy

En cas de non-réponse 2xx, on retente jusqu'à 5 fois avec un backoff exponentiel : 10s, 60s, 5min, 15min, 1h. Votre endpoint doit répondre 200 OK rapidement (sous 10 secondes) — délégez le traitement asynchrone si nécessaire.

Rate limits & bonnes pratiques

  • 60 requêtes par minute et par token. Au-delà : réponse 429 Too Many Requests.
  • Préférez les webhooks au polling pour être notifié en temps réel.
  • Pas de batch endpoint pour l'instant : une proposition par appel.
  • Idempotence : un même solicitation_id ne peut recevoir qu'une seule proposition. Retentez si vous obtenez 409.

Support

Question d'intégration ou bug API ?

infos@mesprojets.org
Réponse sous 24h ouvré.