{"openapi":"3.0.0","paths":{"/api/v1/health":{"get":{"operationId":"HealthController_check_v1","parameters":[],"responses":{"200":{"description":"Service opérationnel"}},"summary":"État de l'API et de sa base de données","tags":["Système"]}},"/api/v1/auth/signup":{"post":{"operationId":"AuthController_signup_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignUpDto"}}}},"responses":{"201":{"description":""}},"summary":"Créer un compte développeur (et son premier membre, propriétaire)","tags":["Authentification"]}},"/api/v1/auth/login":{"post":{"operationId":"AuthController_loginMember_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}}},"responses":{"200":{"description":""}},"summary":"Ouvrir une session","tags":["Authentification"]}},"/api/v1/auth/me":{"get":{"operationId":"AuthController_me_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Membre connecté","tags":["Authentification"]}},"/api/v1/auth/logout":{"post":{"operationId":"AuthController_logoutMember_v1","parameters":[],"responses":{"204":{"description":""}},"security":[{"session":[]}],"summary":"Fermer la session","tags":["Authentification"]}},"/api/v1/apps":{"post":{"operationId":"AppsController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Créer une application (avec ses environnements sandbox et production)","tags":["Applications"]},"get":{"operationId":"AppsController_list_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Lister les applications du compte","tags":["Applications"]}},"/api/v1/apps/{appId}/keys":{"post":{"operationId":"AppsController_createApiKey_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyDto"}}}},"responses":{"201":{"description":""}},"security":[{"session":[]}],"summary":"Générer une clé API. Le secret n’est affiché qu’une seule fois.","tags":["Applications"]},"get":{"operationId":"AppsController_listApiKeys_v1","parameters":[{"name":"appId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Lister les clés d'une application (sans secret)","tags":["Applications"]}},"/api/v1/apps/{appId}/keys/{keyId}":{"delete":{"operationId":"AppsController_revoke_v1","parameters":[{"name":"keyId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"session":[]}],"summary":"Révoquer une clé API","tags":["Applications"]}},"/api/v1/connected-businesses":{"post":{"operationId":"ConnectionsController_createBusiness_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConnectedBusinessDto"}}}},"responses":{"201":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Enregistrer une entreprise cliente (propriétaire futur d’un compte WhatsApp Business)","tags":["Connexions WhatsApp"],"x-required-scopes":["connections:manage"]},"get":{"operationId":"ConnectionsController_listBusinesses_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Lister les entreprises de l'environnement de la clé","tags":["Connexions WhatsApp"],"x-required-scopes":["connections:read"]}},"/api/v1/connected-businesses/{businessId}/waba-connections":{"post":{"operationId":"ConnectionsController_completeSignup_v1","parameters":[{"name":"businessId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteSignupDto"}}}},"responses":{"201":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Terminer l'Embedded Signup : connecter le compte et le numéro WhatsApp Business","tags":["Connexions WhatsApp"],"x-required-scopes":["connections:manage"]}},"/api/v1/connected-businesses/{businessId}/phone-numbers":{"get":{"operationId":"ConnectionsController_listNumbers_v1","parameters":[{"name":"businessId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Comptes et numéros connectés d'une entreprise","tags":["Connexions WhatsApp"],"x-required-scopes":["connections:read"]}},"/api/v1/messages":{"post":{"operationId":"MessagesController_create_v1","parameters":[{"name":"Idempotency-Key","in":"header","description":"Rejouer la même requête avec la même clé ne renvoie jamais le message deux fois.","required":false,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageDto"}}}},"responses":{"202":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Envoyer un message (accepté immédiatement, envoyé de façon asynchrone)","tags":["Messages"],"x-required-scopes":["messages:send"]},"get":{"operationId":"MessagesController_history_v1","parameters":[{"name":"phoneNumberId","required":false,"in":"query","description":"Identifiant du numéro d'envoi (champ `id` d'un numéro, renvoyé par /connected-businesses/{id}/phone-numbers).","schema":{"type":"string"}},{"name":"direction","required":false,"in":"query","description":"Filtrer par sens : `inbound` (reçus) ou `outbound` (envoyés).","schema":{"type":"string","enum":["inbound","outbound"]}},{"name":"status","required":false,"in":"query","description":"Filtrer par statut : queued, sent, delivered, read, failed ou received.","schema":{"type":"string","enum":["queued","sent","delivered","read","failed","received"]}},{"name":"limit","required":false,"in":"query","description":"Nombre d'éléments par page, de 1 à 100.","schema":{"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Valeur `nextCursor` de la page précédente","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Historique des messages (paginé, plus récents d’abord)","tags":["Messages"],"x-required-scopes":["messages:read"]}},"/api/v1/messages/{id}":{"get":{"operationId":"MessagesController_one_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Statut d'un message","tags":["Messages"],"x-required-scopes":["messages:read"]}},"/api/v1/sandbox/simulate/inbound-message":{"post":{"operationId":"SandboxController_inbound_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulateInboundDto"}}}},"responses":{"201":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Simuler un message reçu d’un client (clé sandbox uniquement). Déclenche le webhook `message.received`.","tags":["Bac à sable"],"x-required-scopes":["messages:send"]}},"/api/v1/sandbox/simulate/message-status":{"post":{"operationId":"SandboxController_status_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulateStatusDto"}}}},"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Faire avancer le statut d’un message sortant (clé sandbox uniquement). Déclenche le webhook correspondant.","tags":["Bac à sable"],"x-required-scopes":["messages:send"]}},"/api/v1/waba-connections/{wabaConnectionId}/templates":{"post":{"operationId":"TemplatesController_create_v1","parameters":[{"name":"wabaConnectionId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTemplateDto"}}}},"responses":{"201":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Soumettre un template à la revue de Meta","tags":["Templates"],"x-required-scopes":["templates:manage"]},"get":{"operationId":"TemplatesController_list_v1","parameters":[{"name":"wabaConnectionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Templates du compte WhatsApp et leur statut de revue","tags":["Templates"],"x-required-scopes":["templates:manage"]}},"/api/v1/waba-connections/{wabaConnectionId}/templates/sync":{"post":{"operationId":"TemplatesController_sync_v1","parameters":[{"name":"wabaConnectionId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Synchroniser les statuts depuis Meta","tags":["Templates"],"x-required-scopes":["templates:manage"]}},"/api/v1/waba-connections/{wabaConnectionId}/templates/{name}":{"delete":{"operationId":"TemplatesController_remove_v1","parameters":[{"name":"wabaConnectionId","required":true,"in":"path","schema":{"type":"string"}},{"name":"name","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Supprimer un template (toutes ses langues)","tags":["Templates"],"x-required-scopes":["templates:manage"]}},"/api/v1/webhook-endpoints":{"post":{"operationId":"WebhooksController_create_v1","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEndpointDto"}}}},"responses":{"201":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Déclarer une destination de webhook. Le secret de signature n’est affiché qu’une fois.","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]},"get":{"operationId":"WebhooksController_list_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Lister les destinations","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/webhook-endpoints/{id}":{"get":{"operationId":"WebhooksController_get_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Détail d’une destination","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]},"patch":{"operationId":"WebhooksController_update_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEndpointDto"}}}},"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Modifier l’URL, les événements, ou désactiver/réactiver","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]},"delete":{"operationId":"WebhooksController_remove_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"204":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Supprimer une destination (ses livraisons passées sont conservées jusqu’à la fin de la rétention)","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/webhook-endpoints/{id}/rotate-secret":{"post":{"operationId":"WebhooksController_rotate_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Générer un nouveau secret de signature (l’ancien cesse de fonctionner)","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/webhook-endpoints/{id}/test":{"post":{"operationId":"WebhooksController_test_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Vérifier la destination : envoie un événement de test signé et renvoie la réponse","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/webhook-deliveries":{"get":{"operationId":"WebhooksController_history_v1","parameters":[{"name":"endpointId","required":false,"in":"query","description":"Filtrer sur une destination.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"Filtrer par statut de livraison : pending, succeeded ou failed.","schema":{"type":"string","enum":["pending","succeeded","failed"]}},{"name":"limit","required":false,"in":"query","description":"Nombre d'éléments par page, de 1 à 100.","schema":{"maximum":100,"default":25,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Valeur `nextCursor` de la page précédente, pour obtenir la suite.","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Historique des livraisons (paginé)","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/webhook-deliveries/{id}":{"get":{"operationId":"WebhooksController_delivery_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Détail d’une livraison, avec chaque tentative","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/webhook-deliveries/{id}/replay":{"post":{"operationId":"WebhooksController_replay_v1","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"202":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Rejouer l’événement vers la même destination","tags":["Webhooks"],"x-required-scopes":["webhooks:manage"]}},"/api/v1/usage":{"get":{"description":"Le coût Meta est une ESTIMATION calculée avec la grille tarifaire configurée ; `unpricedMessages` compte les messages facturables sans tarif configuré. Les frais BrefPoint sont séparés et jamais ajoutés au coût Meta.","operationId":"BillingController_usage_v1","parameters":[{"name":"from","required":false,"in":"query","description":"Début (inclus), ISO 8601. Défaut : début du mois en cours (UTC)","schema":{"format":"date-time","type":"string"}},{"name":"to","required":false,"in":"query","description":"Fin (exclue), ISO 8601","schema":{"format":"date-time","type":"string"}},{"name":"groupBy","required":false,"in":"query","description":"Regroupement : `day` (défaut), `category`, `country` ou `phone_number`.","schema":{"default":"day","type":"string","enum":["day","category","country","phone_number"]}}],"responses":{"200":{"description":""}},"security":[{"api-key":[]},{"session":[]}],"summary":"Consommation par jour, catégorie, pays ou numéro","tags":["Usage et facturation"],"x-required-scopes":["usage:read"]}},"/api/v1/billing/overview":{"get":{"operationId":"BillingController_overview_v1","parameters":[],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Plan, consommation de la période et limites (portail)","tags":["Usage et facturation"]}},"/api/v1/platform":{"get":{"operationId":"BillingController_platform_v1","parameters":[],"responses":{"200":{"description":""}},"summary":"Identité commerciale et légale de la plateforme (publique)","tags":["Usage et facturation"]}},"/api/v1/logs/requests":{"get":{"operationId":"LogsController_requests_v1","parameters":[{"name":"environmentId","required":false,"in":"query","description":"Filtrer sur un environnement.","schema":{"type":"string"}},{"name":"status","required":false,"in":"query","description":"`success` (statut < 400) ou `error` (statut ≥ 400).","schema":{"type":"string","enum":["success","error"]}},{"name":"method","required":false,"in":"query","description":"Filtrer par méthode HTTP (GET, POST…).","schema":{"type":"string"}},{"name":"route","required":false,"in":"query","description":"Filtre sur le chemin (ex. /messages)","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Nombre d'éléments par page, de 1 à 200 (50 par défaut).","schema":{"maximum":200,"default":50,"type":"number"}},{"name":"cursor","required":false,"in":"query","description":"Valeur `nextCursor` de la page précédente, pour obtenir la suite.","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"session":[]}],"summary":"Journal des appels API du compte (méthode, route, statut, durée, code d'erreur, requestId)","tags":["Journaux"]}}},"info":{"title":"Bref Point Inbox API","description":"One API. Every conversation.\n\nBusiness messaging infrastructure for developers.\n\nBref Point Inbox est un produit indépendant de l'écosystème Bref Point. Il n'est ni édité, ni approuvé par Meta.","version":"1","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Clé API : pk_…"},"session":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Session du portail : ses_…"}},"schemas":{"SignUpDto":{"type":"object","properties":{"accountName":{"type":"string","description":"Nom de votre société ou équipe : il désigne votre compte (2 à 120 caractères).","example":"Acme Software"},"email":{"type":"string","description":"Adresse e-mail du membre. Elle sert d'identifiant de connexion et doit être unique.","example":"dev@acme.com"},"password":{"type":"string","description":"Mot de passe : 10 caractères au minimum.","minLength":10}},"required":["accountName","email","password"]},"LoginDto":{"type":"object","properties":{"email":{"type":"string","description":"Adresse e-mail du membre. Elle sert d'identifiant de connexion et doit être unique."},"password":{"type":"string","description":"Mot de passe : 10 caractères au minimum."}},"required":["email","password"]},"CreateAppDto":{"type":"object","properties":{"name":{"type":"string","description":"Nom affiché dans la console (2 à 80 caractères). Unique dans votre compte pour une application.","example":"Mon CRM"}},"required":["name"]},"CreateApiKeyDto":{"type":"object","properties":{"name":{"type":"string","description":"Nom affiché dans la console (2 à 80 caractères). Unique dans votre compte pour une application.","example":"Production backend"},"environment":{"type":"string","description":"Environnement de la clé : `sandbox` pour tester, `production` pour envoyer à de vrais destinataires.","enum":["sandbox","production"]},"scopes":{"type":"array","description":"Droits de la clé. Une clé ne peut faire que ce qu'on lui accorde. Valeurs : messages:send, messages:read, templates:manage, webhooks:manage, connections:read, connections:manage, usage:read.","items":{"type":"string","enum":["messages:send","messages:read","templates:manage","webhooks:manage","connections:read","connections:manage","usage:read"]}}},"required":["name","environment","scopes"]},"CreateConnectedBusinessDto":{"type":"object","properties":{"name":{"type":"string","description":"Nom de l'entreprise de votre client (2 à 120 caractères).","example":"Cabinet Dentaire Zokem"},"externalRef":{"type":"string","description":"Votre propre identifiant de ce client"}},"required":["name"]},"CompleteSignupDto":{"type":"object","properties":{"code":{"type":"string","description":"Code renvoyé par l'Embedded Signup (usage unique, bref)"},"wabaId":{"type":"string","description":"Identifiant du compte WhatsApp Business (WABA) renvoyé par l'inscription intégrée. Chiffres uniquement.","example":"102290129340398"},"phoneNumberId":{"type":"string","description":"Identifiant du numéro WhatsApp renvoyé par l'inscription intégrée. Chiffres uniquement.","example":"106540352242922"},"mode":{"type":"string","description":"`cloud_api` (défaut), ou `coexistence` si le client garde l'application WhatsApp Business sur son téléphone.","enum":["cloud_api","coexistence"]}},"required":["code","wabaId","phoneNumberId"]},"SendMessageDto":{"type":"object","properties":{"phoneNumberId":{"type":"string","description":"Identifiant du numéro (renvoyé par /connected-businesses/:id/phone-numbers)"},"to":{"type":"string","example":"+237600000000","description":"Destinataire, format international"},"type":{"type":"string","description":"Type de message : text, template, image, video, audio, document ou location.","enum":["text","template","image","document","video","audio","location"]},"text":{"type":"object","description":"Pour `type: text` : `{ body, previewUrl? }`. Le corps fait 1 à 4096 caractères. Exige une conversation ouverte (fenêtre de 24 h).","example":{"body":"Bonjour !"}},"template":{"type":"object","description":"Pour `type: template` : `{ name, language, components? }`. Le template doit être approuvé par Meta.","example":{"name":"rappel_rdv","language":"fr","components":[]}},"image":{"type":"object","description":"Pour `type: image` : `{ link | id, caption? }`. `link` est une URL https publique, `id` un média déjà hébergé par Meta.","example":{"link":"https://exemple.com/photo.jpg","caption":"Légende"}},"video":{"type":"object","description":"Pour `type: video` : `{ link | id, caption? }`."},"audio":{"type":"object","description":"Pour `type: audio` : `{ link | id }`."},"document":{"type":"object","description":"Pour `type: document` : `{ link | id, caption?, filename? }`."},"location":{"type":"object","description":"Pour `type: location` : `{ latitude, longitude, name?, address? }`.","example":{"latitude":4.05,"longitude":9.7,"name":"Cabinet"}}},"required":["phoneNumberId","to","type"]},"SimulateInboundDto":{"type":"object","properties":{"phoneNumberId":{"type":"string","description":"Identifiant d'un numéro de l'environnement sandbox."},"from":{"type":"string","description":"Numéro de l'expéditeur simulé, format international avec « + ».","example":"+237600000000"},"text":{"type":"string","description":"Texte du message simulé.","example":"Bonjour, je voudrais un rendez-vous"}},"required":["phoneNumberId","from","text"]},"SimulateStatusDto":{"type":"object","properties":{"messageId":{"type":"string","description":"Identifiant d'un message sortant de l'environnement sandbox."},"status":{"type":"string","description":"Nouveau statut : sent, delivered, read ou failed. Un statut ne recule jamais, comme chez Meta.","enum":["sent","delivered","read","failed"]}},"required":["messageId","status"]},"CreateTemplateDto":{"type":"object","properties":{"name":{"type":"string","description":"Nom du template : minuscules, chiffres et underscores (ex. rappel_rdv).","example":"rappel_rdv"},"language":{"type":"string","description":"Code de langue : `fr`, `en`, `en_US`…","example":"fr"},"category":{"type":"string","description":"Catégorie Meta : MARKETING, UTILITY ou AUTHENTICATION. Elle détermine la tarification chez Meta.","enum":["MARKETING","UTILITY","AUTHENTICATION"]},"components":{"example":[{"type":"BODY","text":"Bonjour {{1}}, votre rendez-vous est confirmé."}],"description":"Composants au format Meta","type":"array","items":{"type":"string"}}},"required":["name","language","category","components"]},"CreateEndpointDto":{"type":"object","properties":{"url":{"type":"string","description":"URL https de votre récepteur. Les adresses http, localhost et réseau privé sont refusées.","example":"https://api.exemple.com/webhooks/inbox"},"events":{"example":["message.received","message.delivered"],"description":"`*` pour tout recevoir","type":"array","items":{"type":"string"}}},"required":["url","events"]},"UpdateEndpointDto":{"type":"object","properties":{"url":{"type":"string","description":"URL https de votre récepteur. Les adresses http, localhost et réseau privé sont refusées."},"events":{"description":"Événements reçus : `*` pour tout, ou une liste parmi message.received, message.sent, message.delivered, message.read, message.failed, template.status_updated.","type":"array","items":{"type":"string"}},"enabled":{"type":"boolean","description":"false = désactiver, true = réactiver (remet le compteur d’échecs à zéro)"}}}}}}