{"openapi":"3.1.0","info":{"title":"Blueticked API","version":"1.0.0","description":"Multi-channel messaging (WhatsApp, SMS, email), templates, flows, campaigns, per-recipient documents and webhooks for South African businesses.\n\nOne send endpoint (`POST /v1/messages`) covers all three channels — see the request examples for the WhatsApp template, SMS, and email shapes.\n\nAuthenticate every request with `Authorization: Bearer blu_live_...` (or `blu_test_...` for the sandbox).\nSend an `Idempotency-Key` header on POSTs to make retries safe.\n\n## Test mode\n\nKeys prefixed `blu_test_` are sandbox keys: sends never reach providers,\nnever bill, and have their delivery lifecycle simulated (queued → sent →\ndelivered → read, ~5s per step). Webhook deliveries fire with `\"test\": true`.\n\nDeterministic magic numbers:\n\n| Number | Behaviour |\n|---|---|\n| +27800000001 | Always delivers (any other number behaves the same) |\n| +27800000002 | Fails at the send step with `recipient_unreachable` |\n| +27800000003 | Delivers, then fires a simulated `message.received` reply |\n\n## Error codes\n\n| Code | Meaning |\n|---|---|\n| `unauthorized` | Missing key, revoked key, or malformed Authorization header. |\n| `forbidden` | The API key exists but does not have the required scope. |\n| `not_found` | The requested contact, template, message or campaign does not exist. |\n| `validation_failed` | The request shape is valid JSON but fails business validation. |\n| `rate_limited` | The workspace or key exceeded a rate limit. |\n| `idempotency_conflict` | The same Idempotency-Key was reused with a different body. |\n| `method_not_allowed` | The endpoint does not support the attempted HTTP method. |\n| `channel_unavailable` | The requested provider channel is disconnected or not ready. |\n| `queue_unavailable` | The send queue is not configured, so live sends cannot be accepted. |\n| `insufficient_balance` | The prepaid wallet does not have enough available credit for the requested send. |\n| `document_invalid` | The document parameter is malformed: url must be https and filename at most 240 characters. |\n| `document_required` | The template has a DOCUMENT header; pass document: { url, filename }. |\n| `document_not_applicable` | A document was supplied but the template has no DOCUMENT header (or the send is not a template send). |\n| `document_source_invalid` | The campaign document_source is malformed; check mode, field_key, filename_template and missing_policy. |\n| `document_source_required` | The campaign template has a DOCUMENT header; pass a document_source. |\n| `document_source_not_applicable` | A document_source was supplied but the campaign is neither an email campaign nor a WhatsApp template with a DOCUMENT header. |\n| `internal_error` | Blueticked accepted the request but hit an internal failure. |\n\n## Intentionally outside the API\n\nOrganization and member management, billing, API-key management, and channel\nconnection (Embedded Signup) are dashboard-only by design — they are\nauthentication and account-security surfaces, not integration surfaces.\nEverything else a workspace can do has a v1 endpoint."},"servers":[{"url":"https://app.blueticked.com"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"blu_live or blu_test"}},"schemas":{"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"type":"boolean","enum":[false],"example":false},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","enum":["unauthorized","forbidden","not_found","validation_failed","rate_limited","idempotency_conflict","method_not_allowed","channel_unavailable","queue_unavailable","insufficient_balance","document_invalid","document_required","document_not_applicable","document_source_invalid","document_source_required","document_source_not_applicable","internal_error"],"description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable explanation."},"details":{"description":"Optional structured validation detail."}}},"request_id":{"type":"string","example":"req_abc123"}}}}},"paths":{"/api/v1/messages":{"post":{"operationId":"send-message","summary":"Send one message","description":"Send one WhatsApp template, SMS, or email message to an existing contact.\n\nWhatsApp outbound messages must use an approved template.\n\nPass business_id for managed-business scoping; pass channel_id when you need to send from a specific WhatsApp number.\n\nIf channel_id is omitted for a WhatsApp template, Blueticked uses the number attached to that approved template.\n\nUse Idempotency-Key on write calls to avoid duplicate sends.\n\nThe contact must already exist in the workspace.\n\nSend a customer statement (template with PDF): Send a WhatsApp template that has a DOCUMENT header, attaching a per-recipient PDF by URL.\n\nSend an SMS: Send a plain-text SMS to an existing contact. SMS uses a free-form body (no template).\n\nSend an email: Send a transactional email to an existing contact, with an optional subject line and reply-to.\n\nSend a marketing email (HTML + cc/bcc): Send a marketing email with your own HTML body, rendered inside the branded shell with the required compliance footer; cc/bcc supported.\n\nValidate one message: Validate auth, contact lookup, channel readiness, template variables and opt-outs without sending.","tags":["messages"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"channel_id":{"type":"string","example":"11111111-1111-4111-9111-111111111111"},"channel":{"type":"string","enum":["whatsapp","sms","email"],"example":"whatsapp"},"to":{"type":"object","properties":{"phone":{"type":"string","example":"+27821234567"}}},"template_id":{"type":"string","example":"1f2f3f4f-0000-4000-9000-abcdef123456"},"template_variables":{"type":"object","properties":{"1":{"type":"string","example":"Sam"},"2":{"type":"string","example":"#1001"}}},"document":{"type":"object","properties":{"url":{"type":"string","example":"https://files.example.com/statements/acct-1001.pdf"},"filename":{"type":"string","example":"Statement May 2026.pdf"}}},"body":{"type":"string","example":"Your OTP is 4821. It expires in 10 minutes."},"subject":{"type":"string","example":"Your statement is ready"},"message_type":{"type":"string","example":"transactional"},"reply_to":{"type":"string","example":"accounts@yourbusiness.co.za"},"html":{"type":"string","example":"<h1>Winter sale</h1><p>20% off all services this month.</p>"},"cc":{"type":"array","items":{"type":"string","example":"partner@example.com"}},"bcc":{"type":"array","items":{"type":"string","example":"archive@yourbusiness.co.za"}},"test_mode":{"type":"boolean","example":true}}},"examples":{"send-message":{"summary":"Send one message","value":{"business_id":"22222222-2222-4222-9222-222222222222","channel_id":"11111111-1111-4111-9111-111111111111","channel":"whatsapp","to":{"phone":"+27821234567"},"template_id":"1f2f3f4f-0000-4000-9000-abcdef123456","template_variables":{"1":"Sam","2":"#1001"}}},"send-document-message":{"summary":"Send a customer statement (template with PDF)","value":{"channel":"whatsapp","to":{"phone":"+27821234567"},"template_id":"1f2f3f4f-0000-4000-9000-abcdef123456","template_variables":{"1":"Sam","2":"May 2026"},"document":{"url":"https://files.example.com/statements/acct-1001.pdf","filename":"Statement May 2026.pdf"}}},"send-sms":{"summary":"Send an SMS","value":{"channel":"sms","to":{"phone":"+27821234567"},"body":"Your OTP is 4821. It expires in 10 minutes."}},"send-email":{"summary":"Send an email","value":{"business_id":"22222222-2222-4222-9222-222222222222","channel":"email","to":{"email":"sam@example.com"},"subject":"Your statement is ready","body":"Hi Sam, your May statement is attached in your account.","message_type":"transactional","reply_to":"accounts@yourbusiness.co.za"}},"send-marketing-email":{"summary":"Send a marketing email (HTML + cc/bcc)","value":{"business_id":"22222222-2222-4222-9222-222222222222","channel":"email","to":{"email":"sam@example.com"},"subject":"20% off this month","message_type":"marketing","html":"<h1>Winter sale</h1><p>20% off all services this month.</p>","cc":["partner@example.com"],"bcc":["archive@yourbusiness.co.za"],"reply_to":"hello@yourbusiness.co.za"}},"test-message":{"summary":"Validate one message","value":{"test_mode":true,"channel":"whatsapp","to":{"phone":"+27821234567"},"template_id":"1f2f3f4f-0000-4000-9000-abcdef123456","template_variables":{"1":"Sam"}}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"message_id":{"type":"string","example":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b"},"conversation_message_id":{"type":"string","example":"80d3f720-2c69-46b8-9678-f30e8b3a0d12"},"conversation_id":{"type":"string","example":"6c43b920-6a9e-4c0a-a7f5-5c7450aa6d24"},"status":{"type":"string","example":"queued"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"send-message":{"summary":"Send one message","value":{"message_id":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b","conversation_message_id":"80d3f720-2c69-46b8-9678-f30e8b3a0d12","conversation_id":"6c43b920-6a9e-4c0a-a7f5-5c7450aa6d24","status":"queued","request_id":"req_abc123"}},"send-document-message":{"summary":"Send a customer statement (template with PDF)","value":{"message_id":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b","conversation_message_id":"80d3f720-2c69-46b8-9678-f30e8b3a0d12","conversation_id":"6c43b920-6a9e-4c0a-a7f5-5c7450aa6d24","status":"queued","request_id":"req_abc123"}},"send-sms":{"summary":"Send an SMS","value":{"message_id":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b","conversation_message_id":"80d3f720-2c69-46b8-9678-f30e8b3a0d12","conversation_id":"6c43b920-6a9e-4c0a-a7f5-5c7450aa6d24","status":"queued","request_id":"req_abc123"}},"send-email":{"summary":"Send an email","value":{"message_id":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b","conversation_message_id":"80d3f720-2c69-46b8-9678-f30e8b3a0d12","conversation_id":"6c43b920-6a9e-4c0a-a7f5-5c7450aa6d24","status":"queued","request_id":"req_abc123"}},"send-marketing-email":{"summary":"Send a marketing email (HTML + cc/bcc)","value":{"message_id":"1a2b3c4d-7a9f-4f30-bd8a-84384cfb3f3b","conversation_message_id":"80d3f720-2c69-46b8-9678-f30e8b3a0d12","conversation_id":"6c43b920-6a9e-4c0a-a7f5-5c7450aa6d24","status":"queued","request_id":"req_def456"}},"test-message":{"summary":"Validate one message","value":{"test_mode":true,"status":"validated","channel":"whatsapp","to":"+27821234567","contact_id":"con_123","rendered_body_preview":"Hi Sam, just letting you know...","would_enqueue":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/events/send":{"post":{"operationId":"send-event","summary":"Send an automation event","description":"Trigger a saved Blueticked automation from a booking system, CRM, website form or other external app.\n\nCreate an API key with the least-privilege `events:send` scope.\n\nThe contact must already exist; identify it with exactly one of contact_id, email, or phone.\n\nSet channel to the automation channel you want to run: email, sms, or whatsapp.\n\nUse test_mode: true or a blu_test_ key to evaluate the automation without sending live messages.\n\nUse an Idempotency-Key header so external retries do not fire duplicate actions.","tags":["events"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"channel":{"type":"string","enum":["whatsapp","sms","email"],"example":"email"},"event":{"type":"string","example":"appointment_requested"},"email":{"type":"string","example":"sam@example.com"},"data":{"type":"object","properties":{"service":{"type":"string","example":"Consultation"},"preferred_date":{"type":"string","example":"2026-07-01"}}},"test_mode":{"type":"boolean","example":true}}},"examples":{"send-event":{"summary":"Send an automation event","value":{"business_id":"22222222-2222-4222-9222-222222222222","channel":"email","event":"appointment_requested","email":"sam@example.com","data":{"service":"Consultation","preferred_date":"2026-07-01"},"test_mode":true}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean","example":true},"test_mode":{"type":"boolean","example":true},"handled":{"type":"boolean","example":true},"event":{"type":"string","example":"appointment_requested"},"channel":{"type":"string","enum":["whatsapp","sms","email"],"example":"email"},"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"contact_id":{"type":"string","example":"con_123"},"matched_filter_id":{"type":"string","example":"api-event-appointment"},"matched_filter_label":{"type":"string","example":"Appointment requested"},"action_ids":{"type":"array","items":{"type":"string","example":"send-confirmation"}},"request_id":{"type":"string","example":"req_evt123"}}},"examples":{"send-event":{"summary":"Send an automation event","value":{"accepted":true,"test_mode":true,"handled":true,"event":"appointment_requested","channel":"email","business_id":"22222222-2222-4222-9222-222222222222","contact_id":"con_123","matched_filter_id":"api-event-appointment","matched_filter_label":"Appointment requested","action_ids":["send-confirmation"],"request_id":"req_evt123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/messages/{id}":{"get":{"operationId":"get-message","summary":"Get message status","description":"Fetch the latest status and provider identifiers for a previously queued message.\n\nUse webhooks for production status changes; polling is useful during testing.","tags":["messages"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"status":{"type":"string","example":"delivered"},"external_id":{"type":"string","example":"wamid.HBgL..."},"delivered_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-message":{"summary":"Get message status","value":{"id":"0f32f898-7a9f-4f30-bd8a-84384cfb3f3b","channel":"whatsapp","status":"delivered","external_id":"wamid.HBgL...","delivered_at":"2026-05-22T10:30:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/contacts":{"post":{"operationId":"create-contact","summary":"Create or update contact","description":"Create a contact or update the existing contact matched by phone or email.\n\nPhone numbers must be E.164 for WhatsApp and SMS sends.\n\nPass business_id to assign the contact to a managed business.\n\nThe created/updated contact is returned flat (fields at the top level), matching GET /api/v1/contacts/{id}.","tags":["contacts"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"phone":{"type":"string","example":"+27821234567"},"first_name":{"type":"string","example":"Sam"},"last_name":{"type":"string","example":"Mokoena"},"tags":{"type":"array","items":{"type":"string","example":"vip"}}}},"examples":{"create-contact":{"summary":"Create or update contact","value":{"business_id":"22222222-2222-4222-9222-222222222222","phone":"+27821234567","first_name":"Sam","last_name":"Mokoena","tags":["vip","launch"]}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"con_123"},"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"first_name":{"type":"string","example":"Sam"},"last_name":{"type":"string","example":"Mokoena"},"phone":{"type":"string","example":"+27821234567"},"email":{"type":"string","example":null},"tags":{"type":"array","items":{"type":"string","example":"vip"}},"channels":{"type":"object","properties":{"has_whatsapp":{"type":"boolean","example":true},"has_sms":{"type":"boolean","example":true},"has_email":{"type":"boolean","example":false}}},"suppressed":{"type":"boolean","example":false},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"create-contact":{"summary":"Create or update contact","value":{"id":"con_123","business_id":"22222222-2222-4222-9222-222222222222","first_name":"Sam","last_name":"Mokoena","phone":"+27821234567","email":null,"tags":["vip","launch"],"channels":{"has_whatsapp":true,"has_sms":true,"has_email":false},"suppressed":false,"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T10:30:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"list-contacts","summary":"List contacts","description":"List contacts in the workspace, oldest first, with cursor pagination.\n\nCursor-paginate with ?limit= and ?cursor= (the previous page's next_cursor).\n\nFilter by ?business_id= when syncing one managed business at a time.","tags":["contacts"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"con_123"},"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"first_name":{"type":"string","example":"Sam"},"last_name":{"type":"string","example":"Mokoena"},"phone":{"type":"string","example":"+27821234567"},"email":{"type":"string","example":null},"tags":{"type":"array","items":{"type":"string","example":"vip"}},"channels":{"type":"object","properties":{"has_whatsapp":{"type":"boolean","example":true},"has_sms":{"type":"boolean","example":true},"has_email":{"type":"boolean","example":false}}},"suppressed":{"type":"boolean","example":false},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-contacts":{"summary":"List contacts","value":{"data":[{"id":"con_123","business_id":"22222222-2222-4222-9222-222222222222","first_name":"Sam","last_name":"Mokoena","phone":"+27821234567","email":null,"tags":["vip"],"channels":{"has_whatsapp":true,"has_sms":true,"has_email":false},"suppressed":false,"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T10:30:00.000Z"}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/conversations":{"get":{"operationId":"list-conversations","summary":"List conversations","description":"Read conversation state for inbox, CRM sync, or support tooling.\n\nUse cursor pagination when syncing large inboxes.","tags":["conversations"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"conv_123"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"status":{"type":"string","example":"open"},"last_message_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-conversations":{"summary":"List conversations","value":{"data":[{"id":"conv_123","channel":"whatsapp","status":"open","last_message_at":"2026-05-22T10:30:00.000Z"}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/campaigns":{"post":{"operationId":"create-campaign","summary":"Create campaign","description":"Create, schedule, validate, or queue a bulk WhatsApp campaign.\n\nSet test_mode: true to validate audience counts without queueing.\n\nScheduled campaigns cannot be more than 90 days ahead.\n\nPass business_id when creating campaigns for one managed business.\n\nWhatsApp templates are attached to a specific WhatsApp number; pass channel_id to choose the sending number explicitly.\n\nEmail campaigns require `subject` (supports {{n}} variables) and may pass `document_source` to attach a per-recipient PDF.","tags":["campaigns"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"Launch announcement"},"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"channel":{"type":"string","enum":["whatsapp","sms","email"],"example":"whatsapp"},"channel_id":{"type":"string","example":"11111111-1111-4111-9111-111111111111"},"audience":{"type":"object","properties":{"type":{"type":"string","example":"list"},"list_id":{"type":"string","example":"8f0d0b9a-0000-4000-9000-abcdef123456"}}},"template_id":{"type":"string","example":"1f2f3f4f-0000-4000-9000-abcdef123456"},"template_variables":{"type":"object","properties":{"1":{"type":"object","properties":{"source":{"type":"string","example":"first_name"}}},"2":{"type":"object","properties":{"source":{"type":"string","example":"custom"},"value":{"type":"string","example":"Blueticked"}}}}},"mode":{"type":"string","example":"now"}}},"examples":{"create-campaign":{"summary":"Create campaign","value":{"name":"Launch announcement","business_id":"22222222-2222-4222-9222-222222222222","channel":"whatsapp","channel_id":"11111111-1111-4111-9111-111111111111","audience":{"type":"list","list_id":"8f0d0b9a-0000-4000-9000-abcdef123456"},"template_id":"1f2f3f4f-0000-4000-9000-abcdef123456","template_variables":{"1":{"source":"first_name"},"2":{"source":"custom","value":"Blueticked"}},"mode":"now"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"campaign_id":{"type":"string","example":"camp_123"},"status":{"type":"string","example":"active_in_progress"},"message_count":{"type":"number","example":240},"queued":{"type":"boolean","example":true},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"create-campaign":{"summary":"Create campaign","value":{"campaign_id":"camp_123","status":"active_in_progress","message_count":240,"queued":true,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"list-campaigns","summary":"List campaigns","description":"Fetch campaign status, counters, filters and cursor pagination.\n\nFilter by status or channel for operational dashboards.","tags":["campaigns"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"camp_123"},"name":{"type":"string","example":"Launch announcement"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"status":{"type":"string","example":"active_in_progress"},"counts":{"type":"object","properties":{"sent":{"type":"number","example":240},"delivered":{"type":"number","example":198},"failed":{"type":"number","example":3}}}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-campaigns":{"summary":"List campaigns","value":{"data":[{"id":"camp_123","name":"Launch announcement","channel":"whatsapp","status":"active_in_progress","counts":{"sent":240,"delivered":198,"failed":3}}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/templates":{"post":{"operationId":"create-template","summary":"Submit template","description":"Submit a WhatsApp template for Meta approval through a connected WABA.\n\nOnly approved templates can be used for outbound WhatsApp sends.\n\nThe template is returned flat (fields at the top level), matching GET /api/v1/templates/{id}.","tags":["templates"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"order_update_v1"},"category":{"type":"string","example":"utility"},"language":{"type":"string","example":"en_US"},"body":{"type":"string","example":"Hi {{1}}, your order {{2}} is ready."}}},"examples":{"create-template":{"summary":"Submit template","value":{"name":"order_update_v1","category":"utility","language":"en_US","body":"Hi {{1}}, your order {{2}} is ready."}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tpl_123"},"name":{"type":"string","example":"order_update_v1"},"category":{"type":"string","example":"utility"},"language":{"type":"string","example":"en_US"},"status":{"type":"string","example":"pending"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"create-template":{"summary":"Submit template","value":{"id":"tpl_123","name":"order_update_v1","category":"utility","language":"en_US","status":"pending","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"list-templates","summary":"List templates","description":"List WhatsApp templates and their approval status, with cursor pagination.\n\nFilter by ?status= to find approved templates ready to send.","tags":["templates"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"tpl_123"},"name":{"type":"string","example":"order_update_v1"},"category":{"type":"string","example":"utility"},"language":{"type":"string","example":"en_US"},"status":{"type":"string","example":"approved"}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-templates":{"summary":"List templates","value":{"data":[{"id":"tpl_123","name":"order_update_v1","category":"utility","language":"en_US","status":"approved"}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/channels/whatsapp/readiness":{"get":{"operationId":"whatsapp-readiness","summary":"WhatsApp readiness","description":"Check WABA connection, template, test send, reply and webhook readiness.\n\nRun this before live pilots and after Meta account changes.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ready":{"type":"boolean","example":false},"checks":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","example":"whatsapp_channel"},"status":{"type":"string","example":"ready"}}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"whatsapp-readiness":{"summary":"WhatsApp readiness","value":{"ready":false,"checks":[{"key":"whatsapp_channel","status":"ready"},{"key":"approved_template","status":"blocked"}],"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/flows":{"post":{"operationId":"create-flow","summary":"Create Flow draft","description":"Create a WhatsApp Flow draft from a valid Flow JSON definition.\n\nUse the Flow builder UI for visual editing and validation.\n\nThe flow is returned flat (fields at the top level), matching GET /api/v1/flows/{id}.","tags":["flows"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"customer_feedback_v1"},"description":{"type":"string","example":"Simple feedback Flow"},"definition":{"type":"object","properties":{"version":{"type":"string","example":"7.0"},"screens":{"type":"array","items":{}}}}}},"examples":{"create-flow":{"summary":"Create Flow draft","value":{"name":"customer_feedback_v1","description":"Simple feedback Flow","definition":{"version":"7.0","screens":[]}}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"flow_123"},"name":{"type":"string","example":"customer_feedback_v1"},"status":{"type":"string","example":"draft"},"definition":{"type":"object","properties":{"version":{"type":"string","example":"7.0"},"screens":{"type":"array","items":{}}}},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"create-flow":{"summary":"Create Flow draft","value":{"id":"flow_123","name":"customer_feedback_v1","status":"draft","definition":{"version":"7.0","screens":[]},"created_at":"2026-05-22T10:30:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"list-flows","summary":"List Flows","description":"List WhatsApp Flows and their publish status, with cursor pagination.\n\nUse the Flow builder UI for visual editing.","tags":["flows"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"flow_123"},"name":{"type":"string","example":"customer_feedback_v1"},"status":{"type":"string","example":"published"}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-flows":{"summary":"List Flows","value":{"data":[{"id":"flow_123","name":"customer_feedback_v1","status":"published"}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/flows/{id}/publish":{"post":{"operationId":"publish-flow","summary":"Publish Flow","description":"Publish a valid WhatsApp Flow draft to Meta.\n\nPublishing requires a connected WABA and valid Flow definition.\n\nThe flow is returned flat (fields at the top level).","tags":["flows"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"flow_123"},"name":{"type":"string","example":"customer_feedback_v1"},"status":{"type":"string","example":"published"},"meta_flow_id":{"type":"string","example":"meta_flow_123"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"publish-flow":{"summary":"Publish Flow","value":{"id":"flow_123","name":"customer_feedback_v1","status":"published","meta_flow_id":"meta_flow_123","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/suppression":{"get":{"operationId":"list-suppression","summary":"List suppression entries","description":"List do-not-contact entries (opt-outs), newest first, with cursor pagination.\n\nSuppressed identifiers are excluded from every send automatically.","tags":["suppression"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"sup_123"},"identifier":{"type":"string","example":"+27821234567"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"reason":{"type":"string","example":"stop_keyword"},"created_at":{"type":"string","example":"2026-06-12T08:00:00.000Z"}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-suppression":{"summary":"List suppression entries","value":{"data":[{"id":"sup_123","identifier":"+27821234567","channel":"whatsapp","reason":"stop_keyword","created_at":"2026-06-12T08:00:00.000Z"}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"add-suppression","summary":"Add suppression entry","description":"Add a do-not-contact entry. Idempotent: re-adding returns the existing entry.\n\nUse channel \"all\" to block every channel for the identifier.","tags":["suppression"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"identifier":{"type":"string","example":"+27821234567"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"all"},"reason":{"type":"string","example":"manual"},"reason_detail":{"type":"string","example":"Opted out via CRM"}}},"examples":{"add-suppression":{"summary":"Add suppression entry","value":{"identifier":"+27821234567","channel":"all","reason":"manual","reason_detail":"Opted out via CRM"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"entry":{"type":"object","properties":{"id":{"type":"string","example":"sup_123"},"identifier":{"type":"string","example":"+27821234567"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"all"},"reason":{"type":"string","example":"manual"}}},"already_present":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"add-suppression":{"summary":"Add suppression entry","value":{"entry":{"id":"sup_123","identifier":"+27821234567","channel":"all","reason":"manual"},"already_present":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks":{"post":{"operationId":"create-webhook","summary":"Create webhook subscription","description":"Subscribe an https endpoint to events. The signing secret is returned exactly once.\n\nStore the secret - it is not retrievable later.\n\nPATCH /api/v1/webhooks/{id} updates url/events/is_active, or pass rotate_secret: true to issue a new signing secret.\n\nDELETE /api/v1/webhooks/{id} removes the subscription.","tags":["webhooks"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","example":"https://api.example.com/blueticked/events"},"events":{"type":"array","items":{"type":"string","example":"message.delivered"}},"description":{"type":"string","example":"Production event handler"}}},"examples":{"create-webhook":{"summary":"Create webhook subscription","value":{"url":"https://api.example.com/blueticked/events","events":["message.delivered","message.failed","message.received"],"description":"Production event handler"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"id":{"type":"string","example":"wh_123"},"url":{"type":"string","example":"https://api.example.com/blueticked/events"},"events":{"type":"array","items":{"type":"string","example":"message.delivered"}},"is_active":{"type":"boolean","example":true},"secret":{"type":"string","example":"whsec_..."}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"create-webhook":{"summary":"Create webhook subscription","value":{"webhook":{"id":"wh_123","url":"https://api.example.com/blueticked/events","events":["message.delivered","message.failed","message.received"],"is_active":true,"secret":"whsec_..."},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"list-webhooks","summary":"List webhook subscriptions","description":"List the workspace's webhook subscriptions. Secrets are never returned.\n\nThe signing secret is only shown once, at creation time.","tags":["webhooks"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"wh_123"},"url":{"type":"string","example":"https://api.example.com/blueticked/events"},"events":{"type":"array","items":{"type":"string","example":"message.delivered"}},"is_active":{"type":"boolean","example":true},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"}}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-webhooks":{"summary":"List webhook subscriptions","value":{"data":[{"id":"wh_123","url":"https://api.example.com/blueticked/events","events":["message.delivered","message.failed"],"is_active":true,"created_at":"2026-05-22T10:30:00.000Z"}],"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{id}/test":{"post":{"operationId":"test-webhook","summary":"Send test webhook","description":"Fire a signed sample event (payload carries test: true) at the subscription.\n\nOmit event to use the subscription's first subscribed event.","tags":["webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","example":"message.delivered"}}},"examples":{"test-webhook":{"summary":"Send test webhook","value":{"event":"message.delivered"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"delivery":{"type":"object","properties":{"id":{"type":"string","example":"del_123"},"event":{"type":"string","example":"message.delivered"}}},"queued":{"type":"boolean","example":true},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"test-webhook":{"summary":"Send test webhook","value":{"delivery":{"id":"del_123","event":"message.delivered"},"queued":true,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/conversations/{id}":{"patch":{"operationId":"update-conversation","summary":"Update conversation","description":"Assign, resolve, or reopen a conversation from support tooling.\n\nstatus: open | pending | resolved. assigned_to: a workspace user id, or null to unassign.\n\nTo reply into a conversation, use POST /api/v1/messages — the send pipeline routes by contact.","tags":["conversations"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"resolved"},"assigned_to":{"type":"string","example":null}}},"examples":{"update-conversation":{"summary":"Update conversation","value":{"status":"resolved","assigned_to":null}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"conversation":{"type":"object","properties":{"id":{"type":"string","example":"conv_123"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"status":{"type":"string","example":"resolved"},"assigned_to":{"type":"string","example":null}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"update-conversation":{"summary":"Update conversation","value":{"conversation":{"id":"conv_123","channel":"whatsapp","status":"resolved","assigned_to":null},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"get-conversation","summary":"Get a conversation","description":"Fetch a single conversation's state.\n\nThe conversation is wrapped under `conversation`.","tags":["conversations"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"conversation":{"type":"object","properties":{"id":{"type":"string","example":"conv_123"},"contact_id":{"type":"string","example":"con_123"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"status":{"type":"string","example":"open"},"assigned_to":{"type":"string","example":null},"last_message_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-conversation":{"summary":"Get a conversation","value":{"conversation":{"id":"conv_123","contact_id":"con_123","channel":"whatsapp","status":"open","assigned_to":null,"last_message_at":"2026-05-22T10:30:00.000Z"},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/channels":{"get":{"operationId":"list-channels","summary":"List channels","description":"Inventory of connected channels and their connection status.\n\nCredentials are never exposed; use the dashboard to connect or disconnect channels.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"ch_123"},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"display_name":{"type":"string","example":"Main practice line"},"identifier":{"type":"string","example":"+27210000000"},"status":{"type":"string","example":"connected"}}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-channels":{"summary":"List channels","value":{"data":[{"id":"ch_123","channel":"whatsapp","display_name":"Main practice line","identifier":"+27210000000","status":"connected"}],"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/contacts/{id}":{"get":{"operationId":"get-contact","summary":"Get a contact","description":"Fetch a single contact by id.\n\nReturns 404 not_found if the contact does not exist in your workspace.","tags":["contacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"con_123"},"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"first_name":{"type":"string","example":"Sam"},"last_name":{"type":"string","example":"Mokoena"},"phone":{"type":"string","example":"+27821234567"},"email":{"type":"string","example":null},"tags":{"type":"array","items":{"type":"string","example":"vip"}},"channels":{"type":"object","properties":{"has_whatsapp":{"type":"boolean","example":true},"has_sms":{"type":"boolean","example":true},"has_email":{"type":"boolean","example":false}}},"suppressed":{"type":"boolean","example":false},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-contact":{"summary":"Get a contact","value":{"id":"con_123","business_id":"22222222-2222-4222-9222-222222222222","first_name":"Sam","last_name":"Mokoena","phone":"+27821234567","email":null,"tags":["vip"],"channels":{"has_whatsapp":true,"has_sms":true,"has_email":false},"suppressed":false,"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T10:30:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update-contact","summary":"Update a contact","description":"Partially update a contact's profile, tags, or suppressed flag.\n\nSend only the fields you want to change. Setting phone/email to null clears the channel flags.","tags":["contacts"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"first_name":{"type":"string","example":"Samuel"},"tags":{"type":"array","items":{"type":"string","example":"vip"}},"suppressed":{"type":"boolean","example":false}}},"examples":{"update-contact":{"summary":"Update a contact","value":{"business_id":"22222222-2222-4222-9222-222222222222","first_name":"Samuel","tags":["vip","renewed"],"suppressed":false}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"con_123"},"business_id":{"type":"string","example":"22222222-2222-4222-9222-222222222222"},"first_name":{"type":"string","example":"Samuel"},"last_name":{"type":"string","example":"Mokoena"},"phone":{"type":"string","example":"+27821234567"},"email":{"type":"string","example":null},"tags":{"type":"array","items":{"type":"string","example":"vip"}},"channels":{"type":"object","properties":{"has_whatsapp":{"type":"boolean","example":true},"has_sms":{"type":"boolean","example":true},"has_email":{"type":"boolean","example":false}}},"suppressed":{"type":"boolean","example":false},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T11:00:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"update-contact":{"summary":"Update a contact","value":{"id":"con_123","business_id":"22222222-2222-4222-9222-222222222222","first_name":"Samuel","last_name":"Mokoena","phone":"+27821234567","email":null,"tags":["vip","renewed"],"channels":{"has_whatsapp":true,"has_sms":true,"has_email":false},"suppressed":false,"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T11:00:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/conversations/{id}/messages":{"get":{"operationId":"list-conversation-messages","summary":"List conversation messages","description":"Read the message history (inbound and outbound) for one conversation, newest first.\n\nThis is how you read inbound replies; for a real-time feed subscribe to the message.received webhook instead of polling.","tags":["conversations"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"msg_123"},"direction":{"type":"string","example":"inbound"},"body":{"type":"string","example":"Yes, 2pm works"},"status":{"type":"string","example":"delivered"},"is_draft":{"type":"boolean","example":false},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"}}}},"next_cursor":{"type":"string","example":null},"has_more":{"type":"boolean","example":false},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"list-conversation-messages":{"summary":"List conversation messages","value":{"data":[{"id":"msg_123","direction":"inbound","body":"Yes, 2pm works","status":"delivered","is_draft":false,"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T10:30:00.000Z"}],"next_cursor":null,"has_more":false,"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/campaigns/{id}":{"get":{"operationId":"get-campaign","summary":"Get a campaign","description":"Fetch one campaign's status and delivery counters.\n\nPoll this for progress, or subscribe to message.* webhooks per recipient.","tags":["campaigns"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"camp_123"},"name":{"type":"string","example":"Launch announcement"},"description":{"type":"string","example":null},"channel":{"type":"string","enum":["whatsapp","sms","email","telegram"],"example":"whatsapp"},"status":{"type":"string","example":"active_in_progress"},"scheduled_at":{"type":"string","example":null},"template_id":{"type":"string","example":"tpl_123"},"counts":{"type":"object","properties":{"sent":{"type":"number","example":240},"delivered":{"type":"number","example":198},"failed":{"type":"number","example":3}}},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T10:35:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-campaign":{"summary":"Get a campaign","value":{"id":"camp_123","name":"Launch announcement","description":null,"channel":"whatsapp","status":"active_in_progress","scheduled_at":null,"template_id":"tpl_123","counts":{"sent":240,"delivered":198,"failed":3},"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T10:35:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/templates/{id}":{"get":{"operationId":"get-template","summary":"Get a template","description":"Fetch one template, including its body, buttons, and rejection reason if any.\n\nTemplate status updates also arrive via webhook once you subscribe.","tags":["templates"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"tpl_123"},"channel_id":{"type":"string","example":"ch_123"},"name":{"type":"string","example":"order_update_v1"},"category":{"type":"string","example":"utility"},"language":{"type":"string","example":"en_US"},"body":{"type":"string","example":"Hi {{1}}, your order {{2}} is ready."},"footer":{"type":"string","example":null},"buttons":{"type":"array","items":{}},"status":{"type":"string","example":"approved"},"external_id":{"type":"string","example":"1234567890"},"rejection_reason":{"type":"string","example":null},"submitted_at":{"type":"string","example":"2026-05-20T08:00:00.000Z"},"approved_at":{"type":"string","example":"2026-05-20T09:00:00.000Z"},"created_at":{"type":"string","example":"2026-05-20T08:00:00.000Z"},"updated_at":{"type":"string","example":"2026-05-20T09:00:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-template":{"summary":"Get a template","value":{"id":"tpl_123","channel_id":"ch_123","name":"order_update_v1","category":"utility","language":"en_US","body":"Hi {{1}}, your order {{2}} is ready.","footer":null,"buttons":[],"status":"approved","external_id":"1234567890","rejection_reason":null,"submitted_at":"2026-05-20T08:00:00.000Z","approved_at":"2026-05-20T09:00:00.000Z","created_at":"2026-05-20T08:00:00.000Z","updated_at":"2026-05-20T09:00:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/flows/{id}":{"get":{"operationId":"get-flow","summary":"Get a Flow","description":"Fetch one Flow, including its full JSON definition.","tags":["flows"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"flow_123"},"name":{"type":"string","example":"customer_feedback_v1"},"description":{"type":"string","example":"Simple feedback Flow"},"status":{"type":"string","example":"published"},"meta_flow_id":{"type":"string","example":"meta_flow_123"},"definition":{"type":"object","properties":{"version":{"type":"string","example":"7.0"},"screens":{"type":"array","items":{}}}},"created_at":{"type":"string","example":"2026-05-22T10:30:00.000Z"},"updated_at":{"type":"string","example":"2026-05-22T10:35:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-flow":{"summary":"Get a Flow","value":{"id":"flow_123","name":"customer_feedback_v1","description":"Simple feedback Flow","status":"published","meta_flow_id":"meta_flow_123","definition":{"version":"7.0","screens":[]},"created_at":"2026-05-22T10:30:00.000Z","updated_at":"2026-05-22T10:35:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update-flow","summary":"Update a Flow draft","description":"Update a draft Flow's name, description, or definition.\n\nPublished Flows must be edited and re-published through Meta's versioning rules.","tags":["flows"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","example":"customer_feedback_v2"},"definition":{"type":"object","properties":{"version":{"type":"string","example":"7.0"},"screens":{"type":"array","items":{}}}}}},"examples":{"update-flow":{"summary":"Update a Flow draft","value":{"name":"customer_feedback_v2","definition":{"version":"7.0","screens":[]}}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","example":"flow_123"},"name":{"type":"string","example":"customer_feedback_v2"},"status":{"type":"string","example":"draft"},"definition":{"type":"object","properties":{"version":{"type":"string","example":"7.0"},"screens":{"type":"array","items":{}}}},"updated_at":{"type":"string","example":"2026-05-22T11:00:00.000Z"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"update-flow":{"summary":"Update a Flow draft","value":{"id":"flow_123","name":"customer_feedback_v2","status":"draft","definition":{"version":"7.0","screens":[]},"updated_at":"2026-05-22T11:00:00.000Z","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete-flow","summary":"Delete a Flow","description":"Soft-delete a Flow so it no longer appears in the workspace.\n\nIdempotent: deleting an already-deleted Flow still returns deleted: true.","tags":["flows"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","example":true},"id":{"type":"string","example":"flow_123"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"delete-flow":{"summary":"Delete a Flow","value":{"deleted":true,"id":"flow_123","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/suppression/{id}":{"delete":{"operationId":"delete-suppression","summary":"Remove a suppression entry","description":"Remove a do-not-contact entry so the identifier becomes contactable again.\n\nUse this to reverse a manual opt-out; provider-driven opt-outs (STOP, bounces) usually should not be removed.","tags":["suppression"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","example":true},"id":{"type":"string","example":"sup_123"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"delete-suppression":{"summary":"Remove a suppression entry","value":{"deleted":true,"id":"sup_123","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/webhooks/{id}":{"patch":{"operationId":"update-webhook","summary":"Update a webhook subscription","description":"Update a subscription's url, subscribed events, or active flag.\n\nSubscribable events: message.received, message.sent, message.delivered, message.read, message.failed, contact.created, contact.updated, flow.submitted, agent.run.completed.\n\nRotate a webhook secret: Issue a new signing secret for a webhook subscription. The new secret is returned once.","tags":["webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"events":{"type":"array","items":{"type":"string","example":"message.delivered"}},"is_active":{"type":"boolean","example":true},"rotate_secret":{"type":"boolean","example":true}}},"examples":{"update-webhook":{"summary":"Update a webhook subscription","value":{"events":["message.delivered","message.read","message.failed"],"is_active":true}},"rotate-webhook-secret":{"summary":"Rotate a webhook secret","value":{"rotate_secret":true}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"type":"object","properties":{"id":{"type":"string","example":"wh_123"},"url":{"type":"string","example":"https://api.example.com/blueticked/events"},"events":{"type":"array","items":{"type":"string","example":"message.delivered"}},"is_active":{"type":"boolean","example":true}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"update-webhook":{"summary":"Update a webhook subscription","value":{"webhook":{"id":"wh_123","url":"https://api.example.com/blueticked/events","events":["message.delivered","message.read","message.failed"],"is_active":true},"request_id":"req_abc123"}},"rotate-webhook-secret":{"summary":"Rotate a webhook secret","value":{"webhook":{"id":"wh_123","url":"https://api.example.com/blueticked/events","events":["message.delivered","message.read","message.failed"],"is_active":true,"secret":"whsec_..."},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete-webhook","summary":"Delete a webhook subscription","description":"Remove a webhook subscription. No further deliveries are attempted.\n\nPast deliveries remain in the delivery log for audit and replay.","tags":["webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean","example":true},"id":{"type":"string","example":"wh_123"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"delete-webhook":{"summary":"Delete a webhook subscription","value":{"deleted":true,"id":"wh_123","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/email/sending-domain":{"get":{"operationId":"get-sending-domain","summary":"Get email sending identity","description":"Read a business email sending identity and its DNS verification status.\n\nReturns sending_domain: null when no identity is configured.\n\nIf the workspace has more than one email channel, pass business_id to choose the business.\n\nPossible statuses: not_started, pending, verified, partially_verified, partially_failed, failed, temporary_failure.\n\nWhile status is not 'verified', this refreshes the live status so polling reflects DNS propagation.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"sending_domain":{"type":"object","properties":{"id":{"type":"string","example":"d-abc123"},"domain":{"type":"string","example":"mail.yourbusiness.co.za"},"from_local_part":{"type":"string","example":"accounts"},"status":{"type":"string","example":"pending"},"records":{"type":"array","items":{"type":"object","properties":{"record":{"type":"string","example":"DKIM"},"name":{"type":"string","example":"resend._domainkey"},"type":{"type":"string","example":"TXT"},"value":{"type":"string","example":"p=MIGf..."},"status":{"type":"string","example":"pending"}}}}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"get-sending-domain":{"summary":"Get email sending identity","value":{"sending_domain":{"id":"d-abc123","domain":"mail.yourbusiness.co.za","from_local_part":"accounts","status":"pending","records":[{"record":"DKIM","name":"resend._domainkey","type":"TXT","value":"p=MIGf...","status":"pending"}]},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create-sending-domain","summary":"Add an email sending identity","description":"Register a Blueticked-managed sending identity and get back the DNS records to add. Emails use that sender once it verifies.\n\nAdd the returned DNS records at your domain registrar, then call the verify endpoint.\n\nIf the workspace has more than one email channel, pass business_id to choose the business.\n\nOne sending identity per business - remove the current one (DELETE) before adding another.\n\nUntil verified, emails keep sending from the shared Blueticked address; once verified they send from from_local_part@domain.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"domain":{"type":"string","example":"mail.yourbusiness.co.za"},"from_local_part":{"type":"string","example":"accounts"}}},"examples":{"create-sending-domain":{"summary":"Add an email sending identity","value":{"domain":"mail.yourbusiness.co.za","from_local_part":"accounts"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"sending_domain":{"type":"object","properties":{"id":{"type":"string","example":"d-abc123"},"domain":{"type":"string","example":"mail.yourbusiness.co.za"},"from_local_part":{"type":"string","example":"accounts"},"status":{"type":"string","example":"pending"},"records":{"type":"array","items":{"type":"object","properties":{"record":{"type":"string","example":"DKIM"},"name":{"type":"string","example":"resend._domainkey"},"type":{"type":"string","example":"TXT"},"value":{"type":"string","example":"p=MIGf..."},"status":{"type":"string","example":"pending"}}}}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"create-sending-domain":{"summary":"Add an email sending identity","value":{"sending_domain":{"id":"d-abc123","domain":"mail.yourbusiness.co.za","from_local_part":"accounts","status":"pending","records":[{"record":"DKIM","name":"resend._domainkey","type":"TXT","value":"p=MIGf...","status":"pending"},{"record":"SPF","name":"send","type":"MX","value":"feedback-smtp.eu-west-1.amazonses.com","priority":10,"status":"pending"}]},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete-sending-domain","summary":"Remove the email sending identity","description":"Remove the custom sending identity and revert the workspace to the shared Blueticked sender.\n\nIf the workspace has more than one email channel, pass business_id to choose the business.\n\nIdempotent on the provider side: a failed remote delete still reverts the channel locally.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"removed":{"type":"string","example":"mail.yourbusiness.co.za"},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"delete-sending-domain":{"summary":"Remove the email sending identity","value":{"removed":"mail.yourbusiness.co.za","request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/email/sending-domain/verify":{"post":{"operationId":"verify-sending-domain","summary":"Verify the email sending identity","description":"Trigger a DNS re-check now. When it returns verified, every send uses the verified sender address.\n\nCall this after adding the DNS records; DNS can take minutes to hours to propagate.\n\nIf the workspace has more than one email channel, pass business_id to choose the business.","tags":["channels"],"security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"sending_domain":{"type":"object","properties":{"id":{"type":"string","example":"d-abc123"},"domain":{"type":"string","example":"mail.yourbusiness.co.za"},"from_local_part":{"type":"string","example":"accounts"},"status":{"type":"string","example":"verified"},"records":{"type":"array","items":{"type":"object","properties":{"record":{"type":"string","example":"DKIM"},"name":{"type":"string","example":"resend._domainkey"},"type":{"type":"string","example":"TXT"},"value":{"type":"string","example":"p=MIGf..."},"status":{"type":"string","example":"verified"}}}}}},"request_id":{"type":"string","example":"req_abc123"}}},"examples":{"verify-sending-domain":{"summary":"Verify the email sending identity","value":{"sending_domain":{"id":"d-abc123","domain":"mail.yourbusiness.co.za","from_local_part":"accounts","status":"verified","records":[{"record":"DKIM","name":"resend._domainkey","type":"TXT","value":"p=MIGf...","status":"verified"}]},"request_id":"req_abc123"}}}}}},"400":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"x-ratelimit-limit":{"schema":{"type":"integer"}},"x-ratelimit-remaining":{"schema":{"type":"integer"}},"x-ratelimit-reset":{"schema":{"type":"string","format":"date-time"}}}},"500":{"description":"Internal error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}