Référence Edge Functions
Batlr expose plusieurs edge functions Supabase hébergées à https://kgcligweyslnqatoirah.supabase.co/functions/v1/. Cette page documente celles utiles aux intégrateurs.
Auth
La plupart des endpoints publics utilisent l'anon key (visible dans le code du widget). Les endpoints sensibles (charge, refund, invite) nécessitent un JWT staff dans le header Authorization: Bearer <token>.
booking-widget
Sert le widget en XHTML (utilisé par Supabase Storage qui rewrite text/html).
GET /functions/v1/booking-widget?restaurant_id={UUID}
Response : XHTML complet du widget (alternative à https://www.batlr.app/widget.html?restaurant_id=...).
Préférer le hosting Vercel (
batlr.app) pour les intégrations standard. Cet endpoint sert de fallback CSP-safe.
send-booking-confirmation
Envoie email + SMS de confirmation, lien de paiement, statut, annulation, demande d'avis.
POST /functions/v1/send-booking-confirmation
Content-Type: application/json
{
"restaurant_id": "UUID",
"guest_name": "Marie Dupont",
"guest_email": "marie@exemple.fr",
"guest_phone": "+33612345678",
"date": "2026-04-20",
"time": "19:30",
"party_size": 4,
"source": "app",
"status": "confirmed",
"send_email": true,
"send_sms": true,
"payment_link": "https://...",
"payment_mode": "card_hold",
"reservation_id": "UUID",
"customer_id": "UUID",
"cancellation_reason": null,
"review_link": null,
"confirm_url": null
}
Auth : anon key.
Effets : envoi via Resend (email) et Twilio (SMS) selon les toggles, log dans communication_events.
Quota SMS : vérifié via RPC get_sms_quota (fallback email si épuisé).
send-reminders
Envoi de rappels (mode auto via cron OU mode forcé par staff).
Mode auto (cron interne)
POST /functions/v1/send-reminders
Pas de body. Scanne tous les restaurants avec reminder_enabled = true, identifie les réservations dues, envoie selon les timings configurés.
Mode forcé (manuel par staff)
POST /functions/v1/send-reminders
Authorization: Bearer <staff JWT>
Content-Type: application/json
{
"force": true,
"reservation_id": "UUID",
"restaurant_id": "UUID",
"send_email": true,
"send_sms": true
}
send-review-requests
Envoi de demandes d'avis post-visite (cron toutes les 30 min).
POST /functions/v1/send-review-requests
Auth : service role (interne). Sélectionne les réservations Terminées éligibles selon les critères :
- Réservation > délai configuré
- Client a ≥ N visites
- Pas de demande envoyée dans les X jours (cooldown)
- Email valide
send-waitlist-notification
Notifications liste d'attente.
POST /functions/v1/send-waitlist-notification
Content-Type: application/json
{
"entry_id": "UUID",
"restaurant_id": "UUID",
"notification_type": "joined" | "spot_available" | "your_turn",
"send_email": true,
"send_sms": true
}
Auth : anon key.
stripe-checkout
Orchestration paiement Stripe (SetupIntent et PaymentIntent).
POST /functions/v1/stripe-checkout
Content-Type: application/json
{
"action": "get_config" | "create_setup_intent" | "confirm_setup" | "create_payment_intent" | "confirm_payment" | "complete_session",
"reservation_id": "UUID",
"restaurant_id": "UUID",
"amount_cents": 5000,
"metadata": { ... }
}
Auth : anon (widget) ou staff JWT (links).
Actions
| Action | Effet |
|---|---|
get_config | Retourne publishable_key + connected_account_id Stripe |
create_setup_intent | Crée un SetupIntent (mode card hold) |
confirm_setup | Confirme le SetupIntent + sauve stripe_payment_method_id sur la résa |
create_payment_intent | Crée un PaymentIntent (mode prépaiement) |
confirm_payment | Confirme le PaymentIntent + marque payée |
complete_session | Endpoint legacy de finalisation |
stripe-charge
Débit d'une carte sauvegardée (no-show ou annulation tardive).
POST /functions/v1/stripe-charge
Authorization: Bearer <staff JWT>
Content-Type: application/json
{
"reservation_id": "UUID",
"restaurant_id": "UUID",
"reason": "no_show" | "late_cancellation"
}
Auth : staff requis. Charge le stripe_payment_method_id de la réservation.
stripe-refund
Remboursement total ou partiel.
POST /functions/v1/stripe-refund
Authorization: Bearer <staff JWT>
Content-Type: application/json
{
"reservation_id": "UUID",
"restaurant_id": "UUID",
"amount_cents": 2500
}
amount_cents optionnel — omis = remboursement total.
stripe-connect
Onboarding Stripe Express (création / refresh du lien d'onboarding).
POST /functions/v1/stripe-connect
Authorization: Bearer <staff JWT>
Content-Type: application/json
{
"action": "create_account_link" | "create_login_link" | "disconnect",
"restaurant_id": "UUID"
}
stripe-webhook
Webhook entrant Stripe (signé HMAC-SHA256). Reçoit charge.succeeded, setup_intent.succeeded, charge.refunded, charge.failed.
POST /functions/v1/stripe-webhook
Stripe-Signature: <hmac>
N'appelez pas cet endpoint manuellement — il est appelé par Stripe.
reconfirm-reservation
Action depuis la page de reconfirmation client (/rc?token=...).
POST /functions/v1/reconfirm-reservation
Content-Type: application/json
{
"token": "string",
"action": "confirm" | "decline"
}
Auth : token-based. Met à jour reservations.reconfirmation_status.
verify-email
Vérification d'email staff.
POST /functions/v1/verify-email
Content-Type: application/json
{
"action": "verify",
"token": "string"
}
Réponses :
200 + { success: true }— vérifié410— lien expiré
invite-manager, delete-team-member
Gestion d'équipe (admin/manager only).
POST /functions/v1/invite-manager
Authorization: Bearer <staff JWT>
Content-Type: application/json
{
"restaurant_id": "UUID",
"email": "...",
"role": "Manager"
}
POST /functions/v1/delete-team-member
Authorization: Bearer <staff JWT>
Content-Type: application/json
{
"restaurant_id": "UUID",
"team_member_id": "UUID"
}
apple-webhook
Webhook Apple Server-to-Server Notifications V2 (StoreKit). Vérification JWS via jose@5.
POST /functions/v1/apple-webhook
Appelé uniquement par Apple. Met à jour les statuts d'abonnement Pro.
Codes d'erreur communs
| HTTP | Sens |
|---|---|
| 400 | Bad request — payload manquant ou invalide |
| 401 | Unauthorized — JWT manquant ou invalide |
| 403 | Forbidden — JWT valide mais rôle insuffisant |
| 404 | Not found — restaurant/réservation introuvable |
| 410 | Gone — token expiré |
| 429 | Too many requests — rate limit |
| 500 | Server error — contactez le support avec l'ID de requête |
Rate limits
- Endpoints publics (anon) — 60 req/min par IP
- Endpoints staff (JWT) — 300 req/min par utilisateur
- Webhooks Stripe / Apple — pas de limite, validés par signature