{"openapi":"3.1.0","info":{"title":"DripTell Public API","version":"v1","description":"Public workspace-scoped API for DripTell."},"servers":[{"url":"https://app.driptell.com"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key"}}},"paths":{"/api/v1/whatsapp/connections":{"get":{"tags":["Channels"],"operationId":"whatsapp_connections","summary":"List authorised WhatsApp numbers","description":"Discover the WhatsApp sender connections this API key is allowed to use.\n\nThe immutable `uuid` is the sender selector used by multi-number endpoints. Existing keys initially return only the workspace default number; an owner must explicitly grant any additional numbers under Settings → API keys.\n\nOmitting connection_uuid on other endpoints preserves legacy behaviour by using the workspace default number.\n\nProvider access tokens and Meta phone-number IDs are never returned.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"connections":[{"uuid":"11112222-3333-4444-8555-666677778888","display_name":"Dubai Sales","display_number":"+971500000000","business_account_id":"1234567890","is_default":true,"coexistence":true,"status":"connected"}]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}}},"/api/v1/whatsapp/capabilities":{"get":{"tags":["Channels"],"operationId":"whatsapp_capabilities","summary":"WhatsApp capability readiness","description":"Read configuration readiness without changing a connection or enabling features.\n\nRequires a full workspace API key. Mobile sessions and lead-capture-only keys are not accepted. This is a configuration report, not a live Meta eligibility check.\n\nAll capability entries are returned; the example shows one.\n\nNo tokens, credentials, phone numbers or cross-workspace information are returned.\n\nConfiguration does not guarantee eligibility or successful delivery.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"schema_version":1,"checked_at":"2026-09-15T00:00:00.000Z","verification":"driptell_configuration_only","capabilities":[{"key":"whatsapp_calling","label":"WhatsApp voice calls","status":"not_implemented","detail":"Call settings and logs do not yet provide a calling service. Existing AI Calls is separate."}]}}}}},"401":{"description":"Missing, revoked or insufficiently scoped API key; mobile credentials are not accepted.","content":{"application/json":{"example":{"success":false,"error":"Missing, revoked or insufficiently scoped API key; mobile credentials are not accepted."}}}}}}},"/api/v1/verify":{"get":{"tags":["Account"],"operationId":"verify","summary":"Verify API key","description":"Validate the API key and return the workspace it belongs to.\n\nUse this as a health check to confirm a key is valid and to discover which workspace (organization) it is scoped to. Every other endpoint is automatically scoped to this same workspace.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"valid":true,"organization":{"id":1,"name":"Example Workspace","identifier":"example-workspace"},"user":{"id":1,"email":"owner@example.com","name":"Account Owner","role":"owner"}}}}}},"401":{"description":"The Authorization header is missing or the key is invalid/revoked.","content":{"application/json":{"example":{"success":false,"error":"The Authorization header is missing or the key is invalid/revoked."}}}}}}},"/api/v1/health":{"get":{"tags":["Account"],"operationId":"health","summary":"API health","description":"Check that the public API is reachable.\n\nUse this unauthenticated endpoint for uptime checks or connector smoke tests. It does not reveal workspace data.","security":[],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"ok":true,"status":"ok","service":"driptell-v4","timestamp":"2026-07-08T00:00:00.000Z"}}}}}}},"/api/v1/contacts":{"get":{"tags":["Contacts"],"operationId":"contacts_list","summary":"List contacts","description":"Paginated list of contacts in the workspace, with optional search.","security":[{"bearerAuth":[]}],"parameters":[{"name":"search","in":"query","required":false,"description":"Filter by name, phone, or email (case-insensitive).","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, starting at 1. Default 1.","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"Items per page, 1–100. Default 25.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"contacts":[{"uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","first_name":"Jane","last_name":"Doe","phone":"+971500000000","email":"jane@example.com","is_subscribed":true,"is_favorite":false,"address":{},"metadata":{},"created_at":"2026-06-01T09:30:00.000Z","updated_at":"2026-06-10T11:05:00.000Z"}],"page":1,"per_page":25}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}},"post":{"tags":["Contacts"],"operationId":"contacts_create","summary":"Create a contact","description":"Create a new contact. The phone number is normalized to E.164.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"first_name":{"type":"string","description":"Contact's first name."},"phone":{"type":"string","description":"Phone number; accepts local/00/+ formats and is normalized to E.164."},"last_name":{"type":"string","description":"Contact's last name."},"email":{"type":"string","description":"Email address."},"address":{"type":"object","additionalProperties":true,"description":"Free-form address object stored as JSON."},"metadata":{"type":"object","additionalProperties":true,"description":"Free-form custom fields stored as JSON."}},"required":["first_name","phone"],"additionalProperties":true},"example":{"first_name":"Jane","last_name":"Doe","phone":"+971500000000","email":"jane@example.com"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"contact":{"uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","first_name":"Jane","last_name":"Doe","phone":"+971500000000","email":"jane@example.com","created_at":"2026-06-16T09:30:00.000Z"}}}}}},"400":{"description":"first_name is missing, or phone is missing/invalid.","content":{"application/json":{"example":{"success":false,"error":"first_name is missing, or phone is missing/invalid."}}}},"409":{"description":"A contact with the same phone number already exists.","content":{"application/json":{"example":{"success":false,"error":"A contact with the same phone number already exists."}}}}}}},"/api/v1/contacts/{uuid}":{"get":{"tags":["Contacts"],"operationId":"contacts_get","summary":"Get a contact","description":"Fetch a single contact by its UUID.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The contact's UUID (the `uuid` field returned by other calls).","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"contact":{"uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","first_name":"Jane","last_name":"Doe","phone":"+971500000000","email":"jane@example.com","is_subscribed":true,"is_favorite":false,"blocked_at":null,"address":{},"metadata":{},"created_at":"2026-06-01T09:30:00.000Z","updated_at":"2026-06-10T11:05:00.000Z"}}}}}},"404":{"description":"No contact with that UUID exists in the workspace.","content":{"application/json":{"example":{"success":false,"error":"No contact with that UUID exists in the workspace."}}}}}},"put":{"tags":["Contacts"],"operationId":"contacts_update","summary":"Update a contact","description":"Update fields on a contact. Only the fields you send are changed.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The contact's UUID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"first_name":{"type":"string","description":"New first name."},"last_name":{"type":"string","description":"New last name (send null to clear)."},"phone":{"type":"string","description":"New phone; normalized to E.164. Rejected if it collides with another contact."},"email":{"type":"string","description":"New email (send null to clear)."},"address":{"type":"object","additionalProperties":true,"description":"Replace the address JSON."},"metadata":{"type":"object","additionalProperties":true,"description":"Replace the metadata/custom-fields JSON."}},"required":[],"additionalProperties":true},"example":{"email":"jane.doe@example.com"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"contact":{"uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","first_name":"Jane","last_name":"Doe","phone":"+971500000000","email":"jane.doe@example.com","updated_at":"2026-06-16T10:00:00.000Z"}}}}}},"400":{"description":"The provided phone number is invalid.","content":{"application/json":{"example":{"success":false,"error":"The provided phone number is invalid."}}}},"404":{"description":"No contact with that UUID exists.","content":{"application/json":{"example":{"success":false,"error":"No contact with that UUID exists."}}}},"409":{"description":"The new phone number belongs to another contact.","content":{"application/json":{"example":{"success":false,"error":"The new phone number belongs to another contact."}}}}}},"delete":{"tags":["Contacts"],"operationId":"contacts_delete","summary":"Delete a contact","description":"Soft-delete a contact. The record is hidden from all subsequent API calls.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The contact's UUID.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"deleted":true}}}}},"404":{"description":"No contact with that UUID exists.","content":{"application/json":{"example":{"success":false,"error":"No contact with that UUID exists."}}}}}}},"/api/v1/leads":{"post":{"tags":["Leads"],"operationId":"leads_create","summary":"Create or update a lead","description":"Create a lead from an external webhook/API payload and optionally upsert its contact.\n\nUse this endpoint for website forms, landing pages, lead ads, or partner systems. The API reuses the DripTell lead pipeline, contact record, WhatsApp conversation, custom lead fields, health scoring, and lead.created/lead.updated webhooks.\n\nSend the same Idempotency-Key or external_source_id again to receive the original lead instead of creating a duplicate.\n\nWhen an open lead already exists for the contact, DripTell updates it unless update_existing is false.\n\nConfigured outbound webhooks receive lead.created or lead.updated automatically.\n\nWhen create_conversation is true, an explicit connection_uuid opens the conversation on that sender. An invalid or unauthorized sender is rejected without fallback.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"phone":{"type":"string","description":"Contact phone. Normalized to E.164 and used to find or create the contact."},"email":{"type":"string","description":"Contact email. Used when phone/contact_uuid is not provided."},"contact_uuid":{"type":"string","description":"Existing contact UUID. Takes precedence over phone/email lookup."},"first_name":{"type":"string","description":"Contact first name."},"last_name":{"type":"string","description":"Contact last name."},"title":{"type":"string","description":"Lead title. Defaults to the contact phone/email."},"source":{"type":"string","description":"Lead source, for example website, api, webhook, shopify, or lead_ad. Default api."},"external_source_id":{"type":"string","description":"External/idempotency id. Also accepted through the Idempotency-Key header."},"stage_name":{"type":"string","description":"Pipeline stage name. Defaults to the workspace default stage."},"value_amount":{"type":"number","description":"Potential deal value."},"value_currency":{"type":"string","description":"Currency code. Defaults to the workspace currency."},"priority":{"type":"string","description":"Lead priority. Default normal."},"lead_score":{"type":"number","description":"Optional explicit health score, 0-100. Otherwise DripTell computes health."},"custom_fields":{"type":"array","items":{"type":"string"},"description":"Map lead custom fields by name or [{ field_id, value }]."},"create_conversation":{"type":"boolean","description":"Create/open the WhatsApp conversation when the contact has a phone. Default true."},"connection_uuid":{"type":"string","description":"WhatsApp sender to use when create_conversation is true. Omit to use the workspace default number."}},"required":[],"additionalProperties":true},"example":{"phone":"+971500000000","first_name":"Jane","title":"Website enquiry","source":"website","external_source_id":"landing-page-12345","stage_name":"New lead","value_amount":2500,"value_currency":"AED","priority":"high","custom_fields":{"budget":"2500 AED","interest":"WhatsApp automation"}}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"created":true,"connection_uuid":"11112222-3333-4444-8555-666677778888","lead":{"id":128,"public_id":"7c34773d-88a0-43c4-8c7a-5c32e0f80213","title":"Website enquiry","source":"website","status":"open","stage":"New lead","lead_health_score":57,"lead_health_status":"active","contact_name":"Jane","phone":"+971500000000","conversation_public_id":"d8e5fc33-37e3-4923-90b0-2d46d7fbf412"}}}}}},"400":{"description":"No phone/email/contact_uuid is supplied, the phone is invalid, the value is not numeric, or the contact is blocked.","content":{"application/json":{"example":{"success":false,"error":"No phone/email/contact_uuid is supplied, the phone is invalid, the value is not numeric, or the contact is blocked."}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}}},"/api/v1/contact-groups":{"get":{"tags":["Contact groups"],"operationId":"groups_list","summary":"List contact groups","description":"All contact groups in the workspace with their member counts.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"groups":[{"uuid":"8a2b1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d","name":"VIP customers","description":"High-value accounts","created_at":"2026-05-20T08:00:00.000Z","contacts":42}]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}},"post":{"tags":["Contact groups"],"operationId":"groups_create","summary":"Create a contact group","description":"Create a new group that contacts can be organized into.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Group name."},"description":{"type":"string","description":"Optional description."}},"required":["name"],"additionalProperties":true},"example":{"name":"VIP customers","description":"High-value accounts"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"group":{"uuid":"8a2b1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d","name":"VIP customers","description":"High-value accounts","created_at":"2026-06-16T09:30:00.000Z"}}}}}},"400":{"description":"name is missing.","content":{"application/json":{"example":{"success":false,"error":"name is missing."}}}}}}},"/api/v1/contact-groups/{uuid}":{"put":{"tags":["Contact groups"],"operationId":"groups_update","summary":"Update a contact group","description":"Rename a group or change its description.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The group's UUID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New group name."},"description":{"type":"string","description":"New description (omit/empty to clear)."}},"required":["name"],"additionalProperties":true},"example":{"name":"VIP"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"updated":true}}}}},"400":{"description":"name is missing.","content":{"application/json":{"example":{"success":false,"error":"name is missing."}}}},"404":{"description":"No group with that UUID exists.","content":{"application/json":{"example":{"success":false,"error":"No group with that UUID exists."}}}}}},"delete":{"tags":["Contact groups"],"operationId":"groups_delete","summary":"Delete a contact group","description":"Soft-delete a group. Members are not deleted, only the grouping.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The group's UUID.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"deleted":true}}}}},"404":{"description":"No group with that UUID exists.","content":{"application/json":{"example":{"success":false,"error":"No group with that UUID exists."}}}}}}},"/api/v1/contact-groups/{uuid}/contacts":{"post":{"tags":["Contact groups"],"operationId":"groups_add_contact","summary":"Add a contact to a group","description":"Add an existing workspace contact to a contact group.\n\nAdding a contact that is already a member is safe and does not create a duplicate membership.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The group's UUID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_uuid":{"type":"string","description":"The contact's UUID."}},"required":["contact_uuid"],"additionalProperties":true},"example":{"contact_uuid":"11112222-3333-4444-8555-666677778888"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"membership":{"id":"8a2b1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d:11112222-3333-4444-8555-666677778888","group_uuid":"8a2b1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d","group_name":"VIP customers","contact_uuid":"11112222-3333-4444-8555-666677778888","added":true}}}}}},"404":{"description":"The contact or group does not exist in this workspace.","content":{"application/json":{"example":{"success":false,"error":"The contact or group does not exist in this workspace."}}}}}},"delete":{"tags":["Contact groups"],"operationId":"groups_remove_contact","summary":"Remove a contact from a group","description":"Remove an existing contact from a contact group without deleting the contact.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The group's UUID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_uuid":{"type":"string","description":"The contact's UUID."}},"required":["contact_uuid"],"additionalProperties":true},"example":{"contact_uuid":"11112222-3333-4444-8555-666677778888"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"membership":{"id":"8a2b1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d:11112222-3333-4444-8555-666677778888","group_uuid":"8a2b1c3d-4e5f-6a7b-8c9d-0e1f2a3b4c5d","group_name":"VIP customers","contact_uuid":"11112222-3333-4444-8555-666677778888","removed":true}}}}}},"404":{"description":"The contact or group does not exist in this workspace.","content":{"application/json":{"example":{"success":false,"error":"The contact or group does not exist in this workspace."}}}}}}},"/api/v1/webhook-events":{"get":{"tags":["Webhooks"],"operationId":"webhook_events_list","summary":"Find recent Zapier event records","description":"Fetch real workspace records when testing an instant Zapier trigger.\n\nReturns recent Zapier event payloads from this workspace. Contact triggers can also use recent contacts before a subscription exists. Other triggers return an empty array until a matching event is recorded. No callback URLs, headers, or credentials are returned.","security":[{"bearerAuth":[]}],"parameters":[{"name":"events","in":"query","required":true,"description":"Comma-separated list of 1–10 supported event names.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Maximum records, from 1 to 25. Defaults to 10.","schema":{"type":"number"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"events":[{"event":"contact.created","timestamp":"2026-09-09T10:00:00.000Z","data":{"uuid":"11112222-3333-4444-8555-666677778888","first_name":"Jane","phone":"+971500000000"}}]}}}}},"400":{"description":"Missing or unsupported events.","content":{"application/json":{"example":{"success":false,"error":"Missing or unsupported events."}}}},"401":{"description":"A valid Full API workspace key is required.","content":{"application/json":{"example":{"success":false,"error":"A valid Full API workspace key is required."}}}}}}},"/api/v1/webhook-subscriptions":{"get":{"tags":["Webhooks"],"operationId":"webhook_subscriptions_list","summary":"List Zapier subscriptions","description":"List the Zapier event subscriptions created with the current API key.\n\nSubscriptions are isolated by workspace and API key. A key can only view or remove subscriptions that it created.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"subscriptions":[{"uuid":"44445555-6666-4777-8888-9999aaaabbbb","target_url":"https://hooks.zapier.com/hooks/standard/123/example/","label":"New incoming message","is_active":true,"events":["message.received"]}]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}},"post":{"tags":["Webhooks"],"operationId":"webhook_subscriptions_create","summary":"Create a Zapier subscription","description":"Subscribe a Zapier hook to one or more workspace events.\n\nOnly secure hooks.zapier.com destinations are accepted.\n\nCreating the same callback again updates its events instead of making a duplicate.\n\nExisting subscriptions remain bound to the workspace default WhatsApp number. Additional numbers require explicit API-key and subscription grants.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target_url":{"type":"string","description":"Secure hooks.zapier.com callback URL."},"events":{"type":"string","description":"One or more supported event names."},"label":{"type":"string","description":"A short label identifying the Zapier trigger."},"whatsapp_connection_scope":{"type":"string","description":"default_only (default), selected, or all_connections. Cannot exceed this API key's number access."},"whatsapp_connection_uuids":{"type":"string","description":"Required when scope is selected. Only the listed numbers are included; add the default number explicitly if you want it included."}},"required":["target_url","events"],"additionalProperties":true},"example":{"target_url":"https://hooks.zapier.com/hooks/standard/123/example/","events":["message.received"],"label":"New incoming message","whatsapp_connection_scope":"default_only"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"subscription":{"uuid":"44445555-6666-4777-8888-9999aaaabbbb","target_url":"https://hooks.zapier.com/hooks/standard/123/example/","label":"New incoming message","events":["message.received"],"active":true,"whatsapp_connection_scope":"default_only","whatsapp_connection_uuids":[]}}}}}},"400":{"description":"The callback URL is invalid or an event is unsupported.","content":{"application/json":{"example":{"success":false,"error":"The callback URL is invalid or an event is unsupported."}}}}}}},"/api/v1/webhook-subscriptions/{uuid}":{"delete":{"tags":["Webhooks"],"operationId":"webhook_subscriptions_delete","summary":"Delete a Zapier subscription","description":"Stop event delivery for a subscription created with the current API key.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The subscription UUID.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"deleted":true}}}}},"404":{"description":"The subscription does not exist or was created by another API key.","content":{"application/json":{"example":{"success":false,"error":"The subscription does not exist or was created by another API key."}}}}}}},"/api/v1/send":{"post":{"tags":["Messaging"],"operationId":"send_text","summary":"Send a text message","description":"Send a free-form WhatsApp text message inside the 24-hour service window.\n\nIdentify the recipient by either `phone` (a contact is created automatically if new) or `contact_uuid`. Free-form messages are only allowed when the customer has messaged you within the last 24 hours; otherwise send an approved template instead.\n\nSubject to a per-workspace send rate limit (default 300/minute).\n\nReturns 422 when the 24-hour service window is closed — use POST /api/v1/send/template instead.\n\nconnection_uuid selects the sender; phone/contact_uuid selects the recipient. Omit connection_uuid for the workspace default sender.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Message text, up to 4096 characters."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number."},"phone":{"type":"string","description":"Recipient phone (E.164). Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID. Required unless phone is given."},"first_name":{"type":"string","description":"Name to use if a new contact is created from `phone`."}},"required":["message"],"additionalProperties":true},"example":{"phone":"+971500000000","message":"Hi Jane, your order has shipped!"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918273,"status":"sent","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"400":{"description":"message is missing, exceeds 4096 chars, or neither phone nor contact_uuid is provided.","content":{"application/json":{"example":{"success":false,"error":"message is missing, exceeds 4096 chars, or neither phone nor contact_uuid is provided."}}}},"422":{"description":"Outside the 24-hour customer service window.","content":{"application/json":{"example":{"success":false,"error":"Outside the 24-hour customer service window."}}}},"429":{"description":"Send rate limit exceeded (see Retry-After header / retry_after_seconds).","content":{"application/json":{"example":{"success":false,"error":"Send rate limit exceeded (see Retry-After header / retry_after_seconds)."}}}}}}},"/api/v1/send/template":{"post":{"tags":["Messaging"],"operationId":"send_template","summary":"Send a template message","description":"Send an approved WhatsApp template — works outside the 24-hour window.\n\nTemplates can be sent at any time. Supply `variables` in order for the body placeholders, and `header_media_url` when the template's header is an image/video/document.\n\nList available templates and their variables with GET /api/v1/templates.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","description":"Approved template name."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Templates are resolved within that sender's WhatsApp Business Account."},"phone":{"type":"string","description":"Recipient phone (E.164). Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID. Required unless phone is given."},"language":{"type":"string","description":"Template language code (e.g. en_US). Defaults to the template's language."},"variables":{"type":"string","description":"Body placeholder values, in order. Must cover every body variable."},"header_media_url":{"type":"string","description":"Public http(s) URL for a media header (image/video/document)."},"header_variable":{"type":"string","description":"Value for a text-header placeholder, when applicable."}},"required":["template"],"additionalProperties":true},"example":{"phone":"+971500000000","template":"order_update","language":"en_US","variables":["Jane","#10234"]}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918274,"status":"sent","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"400":{"description":"template is missing, or fewer variables supplied than the template requires.","content":{"application/json":{"example":{"success":false,"error":"template is missing, or fewer variables supplied than the template requires."}}}},"404":{"description":"Template not found or not approved.","content":{"application/json":{"example":{"success":false,"error":"Template not found or not approved."}}}},"422":{"description":"A required media header URL is missing or fails validation.","content":{"application/json":{"example":{"success":false,"error":"A required media header URL is missing or fails validation."}}}},"429":{"description":"Send rate limit exceeded.","content":{"application/json":{"example":{"success":false,"error":"Send rate limit exceeded."}}}}}}},"/api/v1/send/marketing-template":{"post":{"tags":["Messaging"],"operationId":"send_marketing_template","summary":"Send a marketing template","description":"Send an approved MARKETING template through Meta's marketing message path.\n\nUse this for opted-in promotional sends. The endpoint requires explicit `consent_confirmed=true` so marketing sends are auditable and not mixed with service templates.\n\nOnly approved MARKETING templates are accepted.\n\nMarketing sends are recorded in the WhatsApp commerce/platform audit tables.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","description":"Approved MARKETING template name."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number."},"consent_confirmed":{"type":"boolean","description":"Must be true; confirms the recipient has opted in."},"consent_source":{"type":"string","description":"Where consent came from, e.g. website form, checkout, CRM import."},"phone":{"type":"string","description":"Recipient phone (E.164). Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID. Required unless phone is given."},"language":{"type":"string","description":"Template language code."},"variables":{"type":"string","description":"Body placeholder values, in order."},"header_media_url":{"type":"string","description":"Public media URL when the template has a media header."}},"required":["template","consent_confirmed"],"additionalProperties":true},"example":{"phone":"+971500000000","template":"summer_offer","language":"en_US","variables":["Jane"],"consent_confirmed":true,"consent_source":"checkout opt-in"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918276,"status":"sent","endpoint":"marketing_messages","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"404":{"description":"Marketing template not found or not approved.","content":{"application/json":{"example":{"success":false,"error":"Marketing template not found or not approved."}}}},"422":{"description":"consent_confirmed is not true, or required header media is invalid.","content":{"application/json":{"example":{"success":false,"error":"consent_confirmed is not true, or required header media is invalid."}}}},"429":{"description":"Send rate limit exceeded.","content":{"application/json":{"example":{"success":false,"error":"Send rate limit exceeded."}}}}}}},"/api/v1/send/media":{"post":{"tags":["Messaging"],"operationId":"send_media","summary":"Send a media message","description":"Send an image, video, audio, document, or sticker from a public URL.\n\nLike free-form text, media messages require an open 24-hour service window.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string","description":"One of image, video, audio, document, sticker."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number."},"url":{"type":"string","description":"Public http(s) URL of the media file."},"phone":{"type":"string","description":"Recipient phone (E.164). Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID. Required unless phone is given."},"caption":{"type":"string","description":"Optional caption (image/video/document)."},"filename":{"type":"string","description":"Optional file name shown for documents."}},"required":["type","url"],"additionalProperties":true},"example":{"phone":"+971500000000","type":"image","url":"https://cdn.example.com/promo.jpg","caption":"New arrivals"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918275,"status":"sent","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"400":{"description":"type is invalid or url is not a public http(s) link.","content":{"application/json":{"example":{"success":false,"error":"type is invalid or url is not a public http(s) link."}}}},"422":{"description":"Outside the 24-hour customer service window.","content":{"application/json":{"example":{"success":false,"error":"Outside the 24-hour customer service window."}}}},"429":{"description":"Send rate limit exceeded.","content":{"application/json":{"example":{"success":false,"error":"Send rate limit exceeded."}}}}}}},"/api/send/media/fetch":{"post":{"tags":["Messaging"],"operationId":"fetch_received_media","summary":"Download received media","description":"Fetch a secure download URL or file stream for media received from a WhatsApp contact.\n\nUse this after receiving a webhook with an inbound image, video, audio, document, or sticker. You can pass either the WhatsApp message ID from `messages[].id` or the media object ID from `messages[].document.id`, `messages[].audio.id`, `messages[].image.id`, etc. Set `response_type` to `url` when your integration needs JSON with a temporary download URL.\n\n`messages[].id` is the WhatsApp message ID. Media object IDs live inside the media payload, for example `messages[].document.id` for PDFs and `messages[].audio.id` for audio or voice notes.\n\nWithout `response_type=url`, the endpoint streams the file directly instead of returning JSON.\n\nThe request is scoped to the workspace API key, so the media must belong to the same workspace as the API key.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Generic identifier. Accepts a full WhatsApp message ID starting with `wamid.` or a numeric WhatsApp media object ID."},"wam_id":{"type":"string","description":"WhatsApp message ID from `messages[].id`."},"media_id":{"type":"string","description":"WhatsApp media object ID from the inbound media object, such as `document.id`, `audio.id`, `image.id`, `video.id`, or `sticker.id`."},"response_type":{"type":"string","description":"Set to `url` to receive a JSON response containing a temporary media URL. Omit to stream the file."}},"required":[],"additionalProperties":true},"example":{"wam_id":"wamid.EXAMPLE_MESSAGE_ID","response_type":"url"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"statusCode":200,"success":true,"message":"Media URL generated successfully.","data":{"media_url":"https://app.driptell.com/api/media/51f43544-cfca-46ee-9c42-505f2598b2f5?media_token=SIGNED_ACCESS_TOKEN","media_id":123,"wam_id":"wamid.EXAMPLE_MESSAGE_ID","file_name":"example-document.pdf","mime_type":"application/pdf"}}}}},"400":{"description":"No message ID, media ID, or chat UUID was supplied.","content":{"application/json":{"example":{"success":false,"error":"No message ID, media ID, or chat UUID was supplied."}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}},"404":{"description":"The media was not found in this workspace, or the media file is no longer available.","content":{"application/json":{"example":{"success":false,"error":"The media was not found in this workspace, or the media file is no longer available."}}}}}}},"/api/v1/send/location":{"post":{"tags":["Messaging"],"operationId":"send_location","summary":"Send a location","description":"Send a WhatsApp map pin inside the 24-hour service window.\n\nRequires an open 24-hour service window.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"latitude":{"type":"number","description":"Latitude."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number."},"longitude":{"type":"number","description":"Longitude."},"name":{"type":"string","description":"Optional place name."},"address":{"type":"string","description":"Optional address."},"phone":{"type":"string","description":"Recipient phone. Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID."}},"required":["latitude","longitude"],"additionalProperties":true},"example":{"phone":"+971500000000","latitude":25.1972,"longitude":55.2744,"name":"Dubai Mall"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918277,"status":"sent","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"422":{"description":"Outside the 24-hour customer service window.","content":{"application/json":{"example":{"success":false,"error":"Outside the 24-hour customer service window."}}}}}}},"/api/v1/send/contacts":{"post":{"tags":["Messaging"],"operationId":"send_contacts","summary":"Send contact cards","description":"Send one or more WhatsApp contact-card payloads.\n\nRequires an open 24-hour service window.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contacts":{"type":"object","additionalProperties":true,"description":"Meta contact card objects. Max 10."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number."},"phone":{"type":"string","description":"Recipient phone. Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID."}},"required":["contacts"],"additionalProperties":true},"example":{"phone":"+971500000000","contacts":[{"name":{"formatted_name":"Support Team"},"phones":[{"phone":"+971500000001","type":"WORK"}]}]}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918278,"status":"sent","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"400":{"description":"contacts is empty or has more than 10 cards.","content":{"application/json":{"example":{"success":false,"error":"contacts is empty or has more than 10 cards."}}}}}}},"/api/v1/send/product":{"post":{"tags":["Messaging"],"operationId":"send_product","summary":"Send catalog products","description":"Send a single product or multi-product catalog message.\n\nRequires an open 24-hour service window.\n\nOrders submitted from catalog carts are stored in WhatsApp commerce history.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"catalog_id":{"type":"string","description":"Meta catalog id."},"connection_uuid":{"type":"string","description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number."},"product_retailer_id":{"type":"string","description":"Single product retailer id."},"products":{"type":"object","additionalProperties":true,"description":"Multiple products or section rows."},"phone":{"type":"string","description":"Recipient phone. Required unless contact_uuid is given."},"contact_uuid":{"type":"string","description":"Existing contact UUID."}},"required":["catalog_id"],"additionalProperties":true},"example":{"phone":"+971500000000","catalog_id":"123456789","product_retailer_id":"sku-100"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message_id":918279,"status":"sent","connection_uuid":"11112222-3333-4444-8555-666677778888"}}}}},"400":{"description":"catalog_id or product ids are missing.","content":{"application/json":{"example":{"success":false,"error":"catalog_id or product ids are missing."}}}}}}},"/api/v1/chats":{"get":{"tags":["Conversations"],"operationId":"chats_list","summary":"List chats or messages","description":"List recent conversations, or the messages of a single contact.\n\nWithout `contact_uuid` you get the workspace conversation list (most recent first). With `contact_uuid` you get that contact's message history.\n\nWhen `contact_uuid` is supplied the response contains `messages` (newest first) instead of `chats`.","security":[{"bearerAuth":[]}],"parameters":[{"name":"contact_uuid","in":"query","required":false,"description":"If set, returns this contact's messages instead of the conversation list.","schema":{"type":"string"}},{"name":"connection_uuid","in":"query","required":false,"description":"Authorised WhatsApp sender UUID. Omit to use the workspace default number while preserving non-WhatsApp results.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, starting at 1. Default 1.","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"Items per page, 1–100. Default 25.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"chats":[{"uuid":"c0ffee00-1111-2222-3333-444455556666","status":"open","last_message_at":"2026-06-16T08:45:00.000Z","last_message_preview":"Thanks, see you then!","unread_count":0,"contact_uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","contact_name":"Jane Doe","phone":"+971500000000","connection_uuid":"11112222-3333-4444-8555-666677778888"}],"page":1,"per_page":25}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}}},"/api/v1/channels":{"get":{"tags":["Channels"],"operationId":"channels_list","summary":"List channels","description":"Discover every DripTell channel and its workspace-specific availability.\n\nReturns safe connection details, plan access, supported operations, message types, text limits, and reply-window rules. The WhatsApp summary represents the workspace default number; use GET /api/v1/whatsapp/connections to discover every sender authorised for the API key. Credentials and provider tokens are never returned.\n\nSnapchat is profile-only because its Public Profile API does not provide private Inbox conversations.\n\nTikTok appears as planned and cannot be used through the stable public API.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"channels":[{"key":"whatsapp","label":"WhatsApp","kind":"messaging","release":"available","status":"connected","available":true,"connected":true,"plan":{"allowed":true,"current":"Business","required":null},"capabilities":{"operations":["conversations.list","messages.list","messages.send"],"message_types":["text","template","image","video","audio","document","location","contacts","product"],"max_text_length":4096,"reply_window_hours":24},"connection":{"display_name":"Example Business","display_address":"+971500000000","last_synced_at":"2026-07-30T08:40:00.000Z"}}]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}}},"/api/v1/channels/{channel}":{"get":{"tags":["Channels"],"operationId":"channels_get","summary":"Get channel","description":"Inspect one channel's connection state and supported operations.","security":[{"bearerAuth":[]}],"parameters":[{"name":"channel","in":"path","required":true,"description":"whatsapp, messenger, instagram, telegram, webchat, ai-calls, snapchat, or tiktok.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"channel":{"key":"telegram","label":"Telegram","status":"connected","available":true,"connected":true,"capabilities":{"operations":["conversations.list","messages.list","messages.send"],"message_types":["text"],"max_text_length":4096,"reply_window_hours":null}}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}},"404":{"description":"The channel key is unknown.","content":{"application/json":{"example":{"success":false,"error":"The channel key is unknown."}}}}}}},"/api/v1/channels/{channel}/conversations":{"get":{"tags":["Channels"],"operationId":"channel_conversations_list","summary":"List channel conversations","description":"List only the Inbox conversations for one messaging channel.\n\nThis route never creates a channel identity or conversation.\n\nUse the returned conversation UUID when listing or sending messages.\n\nWhatsApp results include the sending-number identity. Omit connection_uuid to list only the workspace default number's conversations.","security":[{"bearerAuth":[]}],"parameters":[{"name":"channel","in":"path","required":true,"description":"whatsapp, messenger, instagram, telegram, or webchat.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Optional: open, pending, or closed.","schema":{"type":"string"}},{"name":"connection_uuid","in":"query","required":false,"description":"For channel=whatsapp, restrict results to this authorised sender. Omit to use the workspace default number.","schema":{"type":"string"}},{"name":"search","in":"query","required":false,"description":"Search contact name, phone, email, or channel address.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, starting at 1. Default 1.","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"Items per page, 1-100. Default 25.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"conversations":[{"uuid":"c0ffee00-1111-2222-3333-444455556666","channel":"whatsapp","status":"open","unread_count":1,"last_message_at":"2026-07-30T08:40:00.000Z","reply_window_open":true,"contact":{"uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","name":"Jane Doe","phone":"+971500000000","email":"jane@example.com","channel_address":"+971500000000","channel_display_name":"Jane Doe","blocked":false},"connection_uuid":"11112222-3333-4444-8555-666677778888","whatsapp_sender":{"uuid":"11112222-3333-4444-8555-666677778888","display_name":"Dubai Sales","display_number":"+971500000000","is_default":false}}],"page":1,"per_page":25,"total":1}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}},"403":{"description":"The active plan does not include the channel.","content":{"application/json":{"example":{"success":false,"error":"The active plan does not include the channel."}}}},"422":{"description":"The channel does not provide Inbox conversations.","content":{"application/json":{"example":{"success":false,"error":"The channel does not provide Inbox conversations."}}}}}}},"/api/v1/channels/{channel}/conversations/{conversationUuid}/messages":{"get":{"tags":["Channels"],"operationId":"channel_messages_list","summary":"List channel messages","description":"Read a paginated, sanitized message history for one conversation.\n\nRaw provider responses, access tokens, and internal message error payloads are not returned.","security":[{"bearerAuth":[]}],"parameters":[{"name":"channel","in":"path","required":true,"description":"whatsapp, messenger, instagram, telegram, or webchat.","schema":{"type":"string"}},{"name":"conversationUuid","in":"path","required":true,"description":"Conversation UUID returned by the channel conversation list.","schema":{"type":"string"}},{"name":"connection_uuid","in":"query","required":false,"description":"For channel=whatsapp, the authorised sender that owns the conversation. Omit for the workspace default number.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, starting at 1. Default 1.","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"Items per page, 1-100. Default 50.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"conversation":{"uuid":"c0ffee00-1111-2222-3333-444455556666","channel":"telegram","status":"open"},"messages":[{"uuid":"d0ffee00-1111-2222-3333-444455556666","channel":"telegram","direction":"inbound","type":"text","status":"delivered","body":"Can you help me?","content":{"text":{"body":"Can you help me?"}},"provider_message_id":"telegram:123:456","is_read":false,"media":null,"created_at":"2026-07-30T08:40:00.000Z"}],"page":1,"per_page":50,"total":1}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}},"404":{"description":"The conversation does not exist in this workspace and channel.","content":{"application/json":{"example":{"success":false,"error":"The conversation does not exist in this workspace and channel."}}}}}}},"/api/v1/channels/{channel}/messages":{"post":{"tags":["Channels"],"operationId":"channel_message_send","summary":"Send channel text","description":"Send a text reply through an existing channel conversation.\n\nThe recipient identity is always taken from the existing conversation; arbitrary social IDs are not accepted.\n\nWhatsApp rich messages and templates continue to use the existing /api/v1/send/* endpoints.\n\nAll public send endpoints share the same workspace rate limit.","security":[{"bearerAuth":[]}],"parameters":[{"name":"channel","in":"path","required":true,"description":"whatsapp, messenger, instagram, telegram, or webchat.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"conversation_uuid":{"type":"string","description":"Existing conversation UUID from the same workspace and channel."},"connection_uuid":{"type":"string","description":"For channel=whatsapp, the authorised sender that owns the conversation. Omit for the workspace default number."},"message":{"type":"string","description":"Text to send. Channel-specific limits apply."}},"required":["conversation_uuid","message"],"additionalProperties":true},"example":{"conversation_uuid":"c0ffee00-1111-2222-3333-444455556666","message":"Thanks for contacting us."}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"message":{"uuid":"d0ffee00-1111-2222-3333-444455556666","channel":"messenger","conversation_uuid":"c0ffee00-1111-2222-3333-444455556666","provider_message_id":"m_mid.abc123","status":"sent","created_at":"2026-07-30T08:41:00.000Z"}}}}}},"400":{"description":"conversation_uuid or message is missing or invalid.","content":{"application/json":{"example":{"success":false,"error":"conversation_uuid or message is missing or invalid."}}}},"403":{"description":"The active plan does not include the channel.","content":{"application/json":{"example":{"success":false,"error":"The active plan does not include the channel."}}}},"404":{"description":"The conversation does not exist in this workspace and channel.","content":{"application/json":{"example":{"success":false,"error":"The conversation does not exist in this workspace and channel."}}}},"409":{"description":"The channel is not connected or enabled.","content":{"application/json":{"example":{"success":false,"error":"The channel is not connected or enabled."}}}},"422":{"description":"The contact is blocked, the reply window is closed, or the text exceeds the channel limit.","content":{"application/json":{"example":{"success":false,"error":"The contact is blocked, the reply window is closed, or the text exceeds the channel limit."}}}},"429":{"description":"The workspace API send rate limit has been exceeded.","content":{"application/json":{"example":{"success":false,"error":"The workspace API send rate limit has been exceeded."}}}},"502":{"description":"The provider rejected or could not deliver the request.","content":{"application/json":{"example":{"success":false,"error":"The provider rejected or could not deliver the request."}}}}}}},"/api/v1/channels/ai-calls/agents":{"get":{"tags":["AI calls"],"operationId":"ai_call_agents_list","summary":"List AI call agents","description":"List the workspace's AI call agents without exposing provider credentials or system instructions.","security":[{"bearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Optional agent status filter.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, starting at 1. Default 1.","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"Items per page, 1-100. Default 25.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"agents":[{"uuid":"9b7bd67f-4414-4ea6-bab3-821331f3981f","name":"Sales qualification","direction":"both","status":"active","language":"en","voice_name":"Professional","document_count":3,"phone_number_count":1,"call_count":42}],"page":1,"per_page":25,"total":1}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}},"403":{"description":"AI Calls is not available for the workspace.","content":{"application/json":{"example":{"success":false,"error":"AI Calls is not available for the workspace."}}}}}}},"/api/v1/channels/ai-calls/calls":{"get":{"tags":["AI calls"],"operationId":"ai_calls_list","summary":"List AI calls","description":"List AI call records with outcomes, contact association, duration, and workspace charge.","security":[{"bearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"description":"Optional call status filter.","schema":{"type":"string"}},{"name":"direction","in":"query","required":false,"description":"Optional: inbound, outbound, or browser_test.","schema":{"type":"string"}},{"name":"page","in":"query","required":false,"description":"Page number, starting at 1. Default 1.","schema":{"type":"integer"}},{"name":"per_page","in":"query","required":false,"description":"Items per page, 1-100. Default 25.","schema":{"type":"integer"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"calls":[{"uuid":"6f418324-eac9-4cbc-8049-291aec105832","direction":"inbound","status":"completed","from_number":"+971500000000","to_number":"+97140000000","contact_uuid":"1f0a9c2e-1b3d-4e5f-9a8b-7c6d5e4f3a2b","agent_uuid":"9b7bd67f-4414-4ea6-bab3-821331f3981f","duration_seconds":184,"outcome":"qualified","sentiment":"positive","customer_charge_minor":87,"currency":"USD"}],"page":1,"per_page":25,"total":1}}}}},"403":{"description":"AI Calls is not available for the workspace.","content":{"application/json":{"example":{"success":false,"error":"AI Calls is not available for the workspace."}}}}}}},"/api/v1/channels/ai-calls/calls/{callUuid}":{"get":{"tags":["AI calls"],"operationId":"ai_call_get","summary":"Get AI call","description":"Read one AI call's result, transcript, and safe recording availability flag.\n\nProvider conversation IDs, telephony IDs, raw recording objects, credentials, and agent system instructions are excluded.","security":[{"bearerAuth":[]}],"parameters":[{"name":"callUuid","in":"path","required":true,"description":"Call UUID.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"call":{"uuid":"6f418324-eac9-4cbc-8049-291aec105832","direction":"inbound","status":"completed","duration_seconds":184,"outcome":"qualified","sentiment":"positive","summary":"Customer requested a product demo.","transcript":[{"role":"agent","text":"How can I help?"},{"role":"customer","text":"I would like a demo."}],"recording_available":true}}}}}},"403":{"description":"AI Calls is not available for the workspace.","content":{"application/json":{"example":{"success":false,"error":"AI Calls is not available for the workspace."}}}},"404":{"description":"The call does not exist in this workspace.","content":{"application/json":{"example":{"success":false,"error":"The call does not exist in this workspace."}}}}}}},"/api/v1/templates":{"get":{"tags":["Templates"],"operationId":"templates_list","summary":"List templates","description":"All approved message templates with their structure.\n\nUse the `name` and the body `{{n}}` placeholders to build the `variables` array for POST /api/v1/send/template.","security":[{"bearerAuth":[]}],"parameters":[{"name":"connection_uuid","in":"query","required":false,"description":"Authorised WhatsApp sender UUID. Returns templates valid for its WhatsApp Business Account; omit for the workspace default number.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"templates":[{"uuid":"55556666-7777-8888-9999-aaaabbbbcccc","name":"order_update","category":"UTILITY","language":"en_US","status":"APPROVED","components":[{"type":"BODY","text":"Hi {{1}}, your order {{2}} has shipped."}],"created_at":"2026-04-12T10:00:00.000Z"}]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}}},"/api/v1/canned-replies":{"get":{"tags":["Canned replies"],"operationId":"canned_list","summary":"List canned replies","description":"All keyword-triggered automatic replies in the workspace.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"canned_replies":[{"uuid":"dddd1111-eeee-2222-ffff-333344445555","name":"Business hours","triggers":["hours","open"],"response":{"type":"text","data":{"text":"We're open 9am–6pm, Sun–Thu."},"match":"contains"},"status":"active","updated_at":"2026-06-01T12:00:00.000Z"}]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"example":{"success":false,"error":"Missing or invalid API key."}}}}}},"post":{"tags":["Canned replies"],"operationId":"canned_create","summary":"Create a canned reply","description":"Create a keyword-triggered automatic text reply.","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Internal name for the reply."},"keywords":{"type":"string","description":"Trigger keywords (at least one)."},"text":{"type":"string","description":"The reply text to send."},"match":{"type":"string","description":"\"contains\" (default) or \"exact\" keyword matching."}},"required":["name","keywords","text"],"additionalProperties":true},"example":{"name":"Business hours","keywords":["hours","open"],"text":"We are open 9am-6pm.","match":"contains"}}}},"responses":{"201":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"canned_reply":{"uuid":"dddd1111-eeee-2222-ffff-333344445555","name":"Business hours","status":"active"}}}}}},"400":{"description":"name, keywords[], or text is missing.","content":{"application/json":{"example":{"success":false,"error":"name, keywords[], or text is missing."}}}}}}},"/api/v1/canned-replies/{uuid}":{"put":{"tags":["Canned replies"],"operationId":"canned_update","summary":"Update a canned reply","description":"Update the name, keywords, text, match mode, or active status.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The canned reply's UUID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New name."},"keywords":{"type":"string","description":"Replace the trigger keywords."},"text":{"type":"string","description":"Replace the reply text."},"match":{"type":"string","description":"\"contains\" or \"exact\"."},"status":{"type":"string","description":"\"active\" or \"inactive\"."}},"required":[],"additionalProperties":true},"example":{"status":"inactive"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"updated":true}}}}},"404":{"description":"No canned reply with that UUID exists.","content":{"application/json":{"example":{"success":false,"error":"No canned reply with that UUID exists."}}}}}},"delete":{"tags":["Canned replies"],"operationId":"canned_delete","summary":"Delete a canned reply","description":"Soft-delete a canned reply.","security":[{"bearerAuth":[]}],"parameters":[{"name":"uuid","in":"path","required":true,"description":"The canned reply's UUID.","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"example":{"success":true,"data":{"deleted":true}}}}},"404":{"description":"No canned reply with that UUID exists.","content":{"application/json":{"example":{"success":false,"error":"No canned reply with that UUID exists."}}}}}}}}}