{"openapi":"3.0.3","info":{"title":"ConvoConnect Public API","version":"1.0.0","description":"Plan-gated public API for WhatsApp, SMS, inbox, contacts, bookings, invoices, and signed webhooks.\n\nAuthenticate with `Authorization: Bearer {token}`. Optional `X-Company-Id` selects a company the token can access. Write requests may send `Idempotency-Key` (replayed for 24 hours).\n\nLegacy `\/api\/wpbox\/*` routes remain as aliases. `POST \/api\/wpbox\/sendmessage` is an alias of `POST \/api\/v1\/messages` with `channel=whatsapp`.\n\nWhatsApp campaign\/broadcast sending is capped at **10 messages per second** (Meta Cloud API default throughput).\n\nRate limits (per company, per minute): Agency 600 read \/ 120 write; Pro 120 \/ 30; otherwise 60 \/ 20. Errors use `{error:{code,message,details,request_id}}` with HTTP 401\/403\/429."},"servers":[{"url":"\/api\/v1","description":"Public API v1"}],"tags":[{"name":"Account"},{"name":"Contacts"},{"name":"Messages"},{"name":"Conversations"},{"name":"Events"},{"name":"Webhooks"},{"name":"Bookings"},{"name":"Invoices"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Sanctum personal access token. Body\/query `token` is also accepted on legacy aliases."}},"parameters":{"CompanyId":{"name":"X-Company-Id","in":"header","required":false,"schema":{"type":"integer"}},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"}},"Cursor":{"name":"cursor","in":"query","schema":{"type":"string"}},"Limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}},"schemas":{"Error":{"type":"object","properties":{"status":{"type":"string","example":"error"},"message":{"type":"string"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"object"},"request_id":{"type":"string"}}}}},"Success":{"type":"object","properties":{"status":{"type":"string","example":"success"},"data":[],"meta":{"type":"object"}}}}},"paths":{"\/me":{"get":{"tags":["Account"],"summary":"Current token user and company","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"}],"responses":{"200":{"description":"Authenticated account"},"401":{"description":"Invalid token"}}}},"\/contacts":{"get":{"tags":["Contacts"],"summary":"List contacts (cursor pagination, hard cap 100)","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/Cursor"},{"$ref":"#\/components\/parameters\/Limit"},{"name":"phone","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated contacts"}}},"post":{"tags":["Contacts"],"summary":"Create or update a contact by phone","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","required":["phone"],"properties":{"phone":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"groups":{"type":"array","items":{"type":"string"}},"custom":{"type":"object"}}}}}},"responses":{"201":{"description":"Contact created"}}}},"\/contacts\/{contact}":{"get":{"tags":["Contacts"],"summary":"Get a contact","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"contact","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Contact"},"404":{"description":"Not found"}}},"patch":{"tags":["Contacts"],"summary":"Update a contact","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"},{"name":"contact","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Updated"}}}},"\/messages":{"post":{"tags":["Messages"],"summary":"Send a WhatsApp or SMS message","description":"Wraps existing send paths: session text\/media, template, list\/interactive. Set `channel=sms` for HostPinnacle SMS. Alias: POST \/api\/wpbox\/sendmessage.","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application\/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","enum":["whatsapp","sms","instagram","messenger"],"default":"whatsapp"},"to":{"type":"string"},"phone":{"type":"string"},"contact_id":{"type":"integer"},"body":{"type":"string"},"message":{"type":"string"},"template_name":{"type":"string"},"template_language":{"type":"string"},"media_url":{"type":"string"},"action":{"type":"object"}}}}}},"responses":{"201":{"description":"Queued or sent"}}}},"\/messages\/{message}":{"get":{"tags":["Messages"],"summary":"Get a message","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"message","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Message"}}}},"\/conversations":{"get":{"tags":["Conversations"],"summary":"List inbox conversations","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/Cursor"},{"$ref":"#\/components\/parameters\/Limit"},{"name":"status","in":"query","schema":{"type":"string","enum":["open","resolved"]}}],"responses":{"200":{"description":"Conversations"}}}},"\/conversations\/{conversation}":{"get":{"tags":["Conversations"],"summary":"Get a conversation and recent messages","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Conversation"}}}},"\/conversations\/{conversation}\/messages":{"post":{"tags":["Conversations"],"summary":"Reply in a conversation","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"201":{"description":"Sent"}}}},"\/conversations\/{conversation}\/assign":{"post":{"tags":["Conversations"],"summary":"Assign an agent","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["user_id"],"properties":{"user_id":{"type":"integer"}}}}}},"responses":{"200":{"description":"Assigned"}}}},"\/conversations\/{conversation}\/resolve":{"post":{"tags":["Conversations"],"summary":"Resolve a conversation","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Resolved"}}}},"\/conversations\/{conversation}\/reopen":{"post":{"tags":["Conversations"],"summary":"Reopen a conversation","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Reopened"}}}},"\/conversations\/{conversation}\/notes":{"get":{"tags":["Conversations"],"summary":"List internal notes","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Notes"}}},"post":{"tags":["Conversations"],"summary":"Add an internal note","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"conversation","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["note"],"properties":{"note":{"type":"string"}}}}}},"responses":{"201":{"description":"Created"}}}},"\/events":{"post":{"tags":["Events"],"summary":"Ingest a tenant-scoped store event","description":"Replaces POST \/webhook\/wpbox\/store-event. Fires campaign triggers for order.created, cart.abandoned, fulfillment.shipped and signed partner webhooks.","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","properties":{"event":{"type":"string","example":"order.created"},"event_type":{"type":"string"},"data":{"type":"object"}}}}}},"responses":{"202":{"description":"Accepted"}}}},"\/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook endpoints","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"}],"responses":{"200":{"description":"Endpoints"}}},"post":{"tags":["Webhooks"],"summary":"Create a signed webhook endpoint","description":"Deliveries use HMAC SHA-256 header X-ConvoConnect-Signature: t={unix},v1={hex} and retry with backoff.","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"},"example":["message.*","contact.created"]},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Created with secret shown once"}}}},"\/webhooks\/{webhook}":{"delete":{"tags":["Webhooks"],"summary":"Delete a webhook endpoint","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"webhook","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Deleted"}}}},"\/bookings":{"get":{"tags":["Bookings"],"summary":"List bookings","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/Cursor"},{"$ref":"#\/components\/parameters\/Limit"}],"responses":{"200":{"description":"Bookings"}}},"post":{"tags":["Bookings"],"summary":"Create a booking","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["phone","name","source"],"properties":{"phone":{"type":"string"},"name":{"type":"string"},"source":{"type":"string"},"slot_id":{"type":"string"},"start_date":{"type":"string"},"end_date":{"type":"string"}}}}}},"responses":{"201":{"description":"Created"}}}},"\/bookings\/services":{"get":{"tags":["Bookings"],"summary":"List bookable services","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"}],"responses":{"200":{"description":"Services"}}}},"\/bookings\/availability":{"get":{"tags":["Bookings"],"summary":"List availability","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"source","in":"query","required":true,"schema":{"type":"string"}},{"name":"date","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Slots or dates"}}}},"\/bookings\/pay":{"post":{"tags":["Bookings"],"summary":"Start booking payment","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"responses":{"201":{"description":"Booked"},"202":{"description":"Payment required"}}}},"\/bookings\/{booking}":{"get":{"tags":["Bookings"],"summary":"Get a booking","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"booking","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Booking"}}}},"\/bookings\/{booking}\/cancel":{"post":{"tags":["Bookings"],"summary":"Cancel a booking","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"booking","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Cancelled"}}}},"\/bookings\/{booking}\/reschedule":{"post":{"tags":["Bookings"],"summary":"Reschedule a booking","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"},{"name":"booking","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Rescheduled"}}}},"\/invoices":{"post":{"tags":["Invoices"],"summary":"Create an invoice and optionally send it on WhatsApp","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"$ref":"#\/components\/parameters\/IdempotencyKey"}],"requestBody":{"content":{"application\/json":{"schema":{"type":"object","required":["customer_phone","amount"],"properties":{"customer_phone":{"type":"string"},"customer_name":{"type":"string"},"customer_email":{"type":"string"},"amount":{"type":"number"},"currency":{"type":"string","example":"KES"},"description":{"type":"string"},"items":{"type":"array"},"send_whatsapp":{"type":"boolean","default":true}}}}}},"responses":{"201":{"description":"Created"}}}},"\/invoices\/{invoice}":{"get":{"tags":["Invoices"],"summary":"Get an invoice by id or public UUID","parameters":[{"$ref":"#\/components\/parameters\/CompanyId"},{"name":"invoice","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Invoice"}}}}}}