{"openapi":"3.0.3","info":{"title":"Bird WhatsApp Central","version":"1.0.0","description":"Independent multi-integration WhatsApp transport. Each key owns its instances, events and callbacks. No CRM or AI runs here. A configured instance ceiling is not a certified real-device capacity. Human applications control sending."},"servers":[{"url":"/v1"}],"security":[{"IntegrationKey":[]}],"components":{"securitySchemes":{"IntegrationKey":{"type":"http","scheme":"bearer","description":"Exclusive per-client integration key. Provision and revoke through the private operator CLI."}},"schemas":{"Message":{"type":"object","additionalProperties":false,"required":["to","consent"],"properties":{"to":{"type":"string","pattern":"^\\d{10,15}$"},"text":{"type":"string","maxLength":4096},"consent":{"type":"boolean","enum":[true]},"media":{"type":"object","additionalProperties":false,"required":["type","mimetype","base64"],"properties":{"type":{"type":"string","enum":["image","audio","document"]},"mimetype":{"type":"string"},"base64":{"type":"string","maxLength":5592408,"description":"Canonical base64; maximum decoded size 4 MiB"},"filename":{"type":"string","maxLength":100}}}}}}},"paths":{"/health":{"get":{"summary":"Liveness","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}},"security":[]}},"/privacy":{"get":{"summary":"Mandatory registered-leads-only admission policy; instances:read","responses":{"200":{"description":"Privacy policy status","content":{"application/json":{"schema":{"type":"object","required":["mode","enforced","policyVersion"],"properties":{"mode":{"type":"string","enum":["registered_leads_only"]},"enforced":{"type":"boolean"},"policyVersion":{"type":"integer","enum":[1,2]},"campaignPhraseAdmission":{"type":"boolean","description":"Version 2: explicitly configured inbound plaintext phrase may register a lead through the authenticated local app before normal processing. Unmatched messages are not persisted or sent to AI."}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/ready":{"get":{"summary":"Capacity, queues and disk status; instances:read required","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/openapi.json":{"get":{"summary":"This contract; integration authentication required","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances":{"get":{"summary":"List only instances accessible to this integration; instances:read","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}},"post":{"summary":"Create an independent instance; instances:write","responses":{"200":{"description":"Success"},"201":{"description":"Created; connect explicitly to begin pairing"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100}}}}}}}},"/instances/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}}],"get":{"summary":"Instance status; instances:read","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances/{id}/connect":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}}],"post":{"summary":"Queue connection or resume existing paired session; instances:write","responses":{"200":{"description":"Success"},"202":{"description":"Queued; authentication may require QR"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances/{id}/qr":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}}],"get":{"summary":"Current raw QR string; instances:write; never cached","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances/{id}/disconnect":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}}],"post":{"summary":"Pause without deleting pairing; optional confirmed WhatsApp logout","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"logout":{"type":"boolean"},"confirmation":{"type":"string","enum":["LOGOUT_WHATSAPP"]}}}}}}}},"/instances/{id}/messages":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}}],"post":{"summary":"Queue one consented direct message; messages:write","responses":{"200":{"description":"Success"},"202":{"description":"Durable job; poll job status. Unknown sends are needs_review and never automatically resent."},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[a-zA-Z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}}}},"/instances/{id}/jobs/{jobId}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}},{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Job status; messages:read","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances/{id}/messages/{messageId}/media":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}},{"name":"messageId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"summary":"Download retained incoming media while connected; maximum 4 MiB; messages:read","responses":{"200":{"description":"Binary attachment"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"413":{"description":"Media exceeds limit"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances/{id}/events":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}}],"get":{"summary":"Cursor-based retained events; messages:read","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}},"parameters":[{"name":"after","in":"query","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}]}},"/webhook":{"put":{"summary":"Set or disable this integration HTTPS webhook; webhooks:write","responses":{"200":{"description":"Success"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","description":"Public HTTPS destination, or empty to disable"}}}}}}}},"/events/{eventId}/retry":{"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"summary":"Replay retained event to its owner integration; webhooks:write","responses":{"200":{"description":"Success"},"202":{"description":"Webhook pending; same event ID"},"400":{"description":"Invalid input"},"401":{"description":"Missing or revoked integration key"},"403":{"description":"Scope or sending permission required"},"404":{"description":"Resource not found in integration scope"},"409":{"description":"Conflict"},"429":{"description":"Rate limit"},"503":{"description":"Capacity unavailable"}}}},"/instances/{id}/contacts/{phone}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^wa_[a-f0-9]{32}$"}},{"name":"phone","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{10,15}$"}}],"put":{"summary":"Authorize one consented recipient for this instance; contacts:write","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["consent"],"properties":{"consent":{"type":"boolean","enum":[true]},"reference":{"type":"string","maxLength":100}}}}}},"responses":{"200":{"description":"Authorized; idempotent"},"401":{"description":"Invalid integration key"},"403":{"description":"Scope required"},"404":{"description":"Instance not owned by this integration"}}},"delete":{"summary":"Revoke admission before any future extraction, send or media download; contacts:write","responses":{"200":{"description":"Revoked; idempotent"},"401":{"description":"Invalid integration key"},"403":{"description":"Scope required"},"404":{"description":"Instance not owned by this integration"}}}},"/capacity":{"get":{"summary":"Configured server ceiling and this integration quota; instances:read","responses":{"200":{"description":"Capacity configuration, never a real-device benchmark"}}}},"/admission":{"get":{"summary":"This integration admission callback configuration; webhooks:write","responses":{"200":{"description":"Mode and own callback URL"},"401":{"description":"Invalid key"},"403":{"description":"Scope required"}}},"put":{"summary":"Choose signed live admission callback instead of the contact registry; webhooks:write","description":"Public HTTPS callback receives {id,instanceId,phone}, signed with this integration webhook secret. Must return {allowed:true} after checking its current lead registry. Every capture/send/download checks again, without caching. Error or timeout denies. Empty url restores explicit contact registry.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","maxLength":2048}}}}}},"responses":{"200":{"description":"Saved"},"400":{"description":"Invalid destination"},"401":{"description":"Invalid key"},"403":{"description":"Scope required"}}}}}}