{"openapi":"3.1.0","info":{"title":"Voza API","version":"1.0.0","summary":"WhatsApp messages and calls, by QR code or through Meta's official API.","description":"Message, call and webhook bodies follow the format of the official WhatsApp API (Meta). Full guide: https://www.vozaapi.com/docs.","contact":{"url":"https://www.vozaapi.com/docs"}},"servers":[{"url":"https://www.vozaapi.com/v1"}],"security":[{"apiKey":[]}],"tags":[{"name":"Account"},{"name":"Numbers"},{"name":"Webhooks"},{"name":"Messages"},{"name":"Media"},{"name":"Calls"},{"name":"Web phone"},{"name":"Voice agents"}],"paths":{"/account":{"get":{"tags":["Account"],"summary":"The key's account, with the plan and the limits","operationId":"getAccount","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/account/usage":{"get":{"tags":["Account"],"summary":"A month's usage (UTC), in total and per number","operationId":"getUsage","parameters":[{"name":"month","in":"query","description":"YYYY-MM; the current month when empty.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usage"}}}},"422":{"description":"Month in an invalid format.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/account/ai-keys":{"get":{"tags":["Voice agents"],"summary":"Which AI providers' keys the account stored (never the keys)","operationId":"getAiKeys","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiKeys"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Voice agents"],"summary":"Stores the account's AI providers' keys, encrypted","operationId":"updateAiKeys","description":"Only with an API key created by an owner of the account. Only the providers sent change; null removes the key. Each new key is checked at the provider: if it refuses one (401), no key of the request is saved.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"additionalProperties":false,"properties":{"anthropic":{"type":["string","null"],"minLength":8,"maxLength":500},"deepgram":{"type":["string","null"],"minLength":8,"maxLength":500},"elevenlabs":{"type":["string","null"],"minLength":8,"maxLength":500},"cartesia":{"type":["string","null"],"minLength":8,"maxLength":500}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiKeys"}}}},"403":{"description":"Account blocked, or the API key is not an owner's (owner_only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request), or a provider refused the key (invalid_provider_key; meta.providers says which).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/tts":{"post":{"tags":["Voice agents"],"summary":"A phrase spoken by a voice, as audio","operationId":"textToSpeech","description":"With the provider's key stored in the account. The audio is kept by voice and text: the same phrase comes back without waiting (X-Voza-Cache: hit).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TtsRequest"}}}},"responses":{"200":{"description":"The audio.","content":{"audio/mpeg":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"422":{"description":"Invalid data (invalid_request) or the account has no key for the provider (missing_provider_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The voice provider did not produce the audio (tts_failed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/voices":{"get":{"tags":["Voice agents"],"summary":"The account's voices at a voice provider","operationId":"listVoices","description":"With the provider key stored in the account, so the account's cloned voices come too. The list is kept for an hour, per account and provider.","parameters":[{"name":"provider","in":"query","required":true,"schema":{"type":"string","enum":["elevenlabs","cartesia"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"type":"string","enum":["elevenlabs","cartesia"]},"data":{"type":"array","items":{"$ref":"#/components/schemas/Voice"}}}}}}},"422":{"description":"Invalid provider (invalid_request) or the account has no key for the provider (missing_provider_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The voice provider did not return the list (voices_failed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/test-sessions":{"post":{"tags":["Voice agents"],"summary":"A test call with an agent, from the browser, without WhatsApp","operationId":"createAgentTestSession","description":"Give the token to the browser, which sends the SDP offer to POST /agents/test-sessions/connect. With number_id, the runtime signs with the agent secret of the number, and the events (test: true) go where the number's agent events go; without it, the answer has a secret of this call alone, and the events are not sent. The test call counts in the account's agent sessions (limits.agent_sessions and limits.agent_tests in GET /account) and ends after 10 minutes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agent_ref","callback_url"],"properties":{"agent_ref":{"type":"string","maxLength":255},"callback_url":{"type":"string","format":"uri","description":"Public https."},"number_id":{"type":["string","null"]}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentTestSession"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The number has no agent (agent_not_configured).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/test-sessions/{session}":{"parameters":[{"name":"session","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Voice agents"],"summary":"Ends the test call","operationId":"deleteAgentTestSession","responses":{"204":{"description":"Ended."},"404":{"description":"The test call does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/agents/test-sessions/connect":{"post":{"tags":["Voice agents"],"summary":"The browser sends the test call's SDP offer (once, with the token)","operationId":"connectAgentTestSession","security":[{"agentToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SdpOffer"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"session":{"$ref":"#/components/schemas/SdpAnswer"}}}}}},"409":{"description":"The token was already used (token_used) or the product refused the call (agent_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid offer (invalid_request, invalid_offer) or a provider's key is missing (missing_provider_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account already has as many simultaneous test calls (test_session_limit_reached) or agent sessions (agent_limit_reached) as it may.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The product did not send the agent's configuration (agent_config_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or expired token (invalid_monitor_token, invalid_test_token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/monitor/session":{"delete":{"tags":["Voice agents"],"summary":"The supervisor who joined with this token leaves the call","operationId":"leaveMonitorSession","description":"left is false when the supervisor, or the call, was already gone.","security":[{"agentToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"left":{"type":"boolean"}}}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or expired token (invalid_monitor_token, invalid_test_token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The token has already been used (token_used).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Voice agents"],"summary":"A supervisor's browser joins the call (once, with the token)","operationId":"joinMonitorSession","security":[{"agentToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SdpOffer"},{"type":"object","properties":{"mode":{"type":"string","enum":["listen","takeover"],"default":"listen","description":"listen: listens. takeover: joins speaking to the caller, instead of the AI."}}}]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"monitor_id":{"type":"string","description":"This supervisor's id, for takeover and release."},"call_id":{"type":"string"},"session":{"$ref":"#/components/schemas/SdpAnswer"}}}}}},"409":{"description":"The token has already been used (token_used), the call is not with the agent (call_not_with_agent) or it already has all its supervisors (too_many_monitors).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid offer (invalid_request, invalid_offer).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or expired token (invalid_monitor_token, invalid_test_token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers":{"get":{"tags":["Numbers"],"summary":"The account's numbers","operationId":"listNumbers","parameters":[{"name":"external_ref","in":"query","description":"Only the numbers with this reference of yours.","schema":{"type":"string","maxLength":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Number"}}}}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Numbers"],"summary":"Creates a QR code number or connects an official number","operationId":"createNumber","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NumberCreate"}}}},"responses":{"201":{"description":"Created. A QR code number starts in starting; an official one, in connected. With a webhook in the request, the response also carries webhook, with the secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NumberCreated"}}}},"403":{"description":"Account blocked (trial_expired, subscription_inactive, account_suspended) or at the plan's number limit (number_limit_reached).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request) or Meta refused the credentials (meta_refused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The engine or Meta did not respond (engine_unavailable, meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Numbers"],"summary":"The number, with its status read on the spot","operationId":"getNumber","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Number"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Numbers"],"summary":"Changes the number's name or your reference for it (external_ref)","operationId":"updateNumber","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","minProperties":1,"properties":{"name":{"type":"string","maxLength":80},"external_ref":{"type":["string","null"],"maxLength":100,"description":"null removes the reference."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Number"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Numbers"],"summary":"Deletes the number (and disconnects the phone, for a QR code number)","operationId":"deleteNumber","responses":{"204":{"description":"Deleted."},"503":{"description":"The engine did not respond; nothing was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/qr":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Numbers"],"summary":"The QR code to scan now (QR code numbers only)","operationId":"getNumberQr","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Qr"}}}},"409":{"description":"Official number (not_a_qr_number).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The engine did not respond (engine_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/relink":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Numbers"],"summary":"QR code: change phones. Official: check again at Meta, leaving the calling settings alone","operationId":"relinkNumber","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Number"}}}},"422":{"description":"Meta refused (meta_refused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The engine or Meta did not respond (engine_unavailable, meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/meta":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"put":{"tags":["Numbers"],"summary":"New token (and app secret) for an official number","operationId":"updateNumberMeta","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["access_token"],"properties":{"access_token":{"type":"string"},"app_secret":{"type":["string","null"],"description":"Only when it changed."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Number"}}}},"409":{"description":"QR code number (not_an_official_number).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Meta refused (meta_refused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Meta did not respond (meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calling":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Calls"],"summary":"An official number's calling settings, read at Meta","operationId":"getCallingSettings","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"calling":{"$ref":"#/components/schemas/CallingSettings"}}}}}},"409":{"description":"QR code number (not_an_official_number) or Meta token refused (meta_token_invalid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Meta refused the request (whatsapp_refused), with its error in meta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Meta did not respond (meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Calls"],"summary":"Changes an official number's calling settings at Meta","operationId":"updateCallingSettings","description":"As at Meta: only the fields sent change. sip is not accepted.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["calling"],"properties":{"calling":{"$ref":"#/components/schemas/CallingSettings"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"409":{"description":"QR code number (not_an_official_number) or Meta token refused (meta_token_invalid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid settings (invalid_request) or refused by Meta (whatsapp_refused, with its error in meta).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Meta did not respond (meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/call-permissions/{wa_id}":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"wa_id","in":"path","required":true,"description":"The contact's number, with the country code.","schema":{"type":"string","pattern":"^\\+?\\d{5,20}$"}}],"get":{"tags":["Calls"],"summary":"Whether the number may call the contact now","operationId":"getCallPermission","description":"Official numbers: Meta's answer (call_permissions). QR code numbers: always granted, since there is no permission to ask for.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallPermission"}}}},"409":{"description":"Meta refused the token (meta_token_invalid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid wa_id (invalid_request) or Meta refused the request (whatsapp_refused, with its error in meta).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Meta did not respond (meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/webhook":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Webhooks"],"summary":"The number's webhook","operationId":"getWebhook","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Webhooks"],"summary":"Sets, rotates the secret of or removes the webhook","operationId":"updateWebhook","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":["string","null"],"format":"uri","description":"Public https; null removes the webhook."},"rotate_secret":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Webhook"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/templates":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Messages"],"summary":"An official number's message templates, read at Meta, one page at a time","operationId":"listTemplates","description":"Meta's list (message_templates) of the number's WhatsApp Business account, as Meta gives it. paging.next and paging.previous point at Voza.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"after","in":"query","description":"The cursor of the next page (paging.cursors.after).","schema":{"type":"string"}},{"name":"before","in":"query","description":"The cursor of the previous page (paging.cursors.before).","schema":{"type":"string"}},{"name":"fields","in":"query","description":"Meta's fields of each template, separated by commas.","schema":{"type":"string","default":"id,name,language,category,status,components"}},{"name":"name","in":"query","description":"Meta's filters: name, status, category and language.","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","examples":["APPROVED"]}},{"name":"category","in":"query","schema":{"type":"string","examples":["UTILITY"]}},{"name":"language","in":"query","schema":{"type":"string","examples":["pt_BR"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateList"}}}},"409":{"description":"QR code number (not_an_official_number) or Meta token refused (meta_token_invalid).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid parameters (invalid_request) or refused by Meta (whatsapp_refused, with Meta's error in meta).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Meta did not respond (meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/messages":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Messages"],"summary":"Sends a message, with Meta's body","operationId":"sendMessage","parameters":[{"name":"Idempotency-Key","in":"header","description":"Repeating with the same key returns the first send instead of sending again. Voza keeps the first response for 24 hours, for both kinds of number.","schema":{"type":"string","maxLength":128,"pattern":"^[A-Za-z0-9_.:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageRequest"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"409":{"description":"Number disconnected (number_not_connected), Meta token refused (meta_token_invalid) or another send with the same Idempotency-Key in progress (send_in_progress).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid body (invalid_request), official-only type (unsupported_type) or refused by Meta (whatsapp_refused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit, with Retry-After, or Meta's sending limit on an official number (rate_limited).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"WhatsApp did not accept the message (whatsapp_refused), on a QR code number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Service unavailable (engine_unavailable, number_reconnecting, or meta_unavailable: the send did not reach Meta).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"504":{"description":"The send took too long (send_timeout), or Meta did not answer in time and the message may have reached it (meta_timeout): repeat it with the same Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/media/{media}":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"media","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Media"],"summary":"The bytes of a received media file","operationId":"getMedia","responses":{"200":{"description":"The file, with its Content-Type.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"404":{"description":"The number does not exist in this account, or the media does not exist or expired (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"The file was too large to be stored (media_too_large).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"WhatsApp did not deliver the file (media_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The engine or Meta did not respond (engine_unavailable, meta_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Calls"],"summary":"The call log, newest first","operationId":"listCalls","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":200,"default":50}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Call"}}}}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Calls"],"summary":"A call action, with Meta's body","operationId":"callAction","parameters":[{"name":"Idempotency-Key","in":"header","description":"Repeating with the same key returns the first answer instead of repeating the action (after a meta_timeout, for instance). Voza keeps the first answer for 24 hours.","schema":{"type":"string","maxLength":128,"pattern":"^[A-Za-z0-9_.:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAction"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallActionResponse"}}}},"404":{"description":"The number does not exist in this account (not_found), or the call does not exist or already ended (call_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"number_not_connected, call_not_ready, meta_token_invalid or another action with the same Idempotency-Key in progress (action_in_progress).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"invalid_request, not_on_whatsapp or call_failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"channel_limit_reached, lines_busy or rate_limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"WhatsApp did not accept the action, on a QR code number (call_failed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"lines_starting, engine_unavailable or meta_unavailable (the action did not reach Meta: you may repeat it).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"504":{"description":"The engine took too long to answer (call_timeout), or Meta did not answer in time and the action may have reached it (meta_timeout): repeat it with the same Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/agent":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"get":{"tags":["Voice agents"],"summary":"The number's voice agent, without the secret","operationId":"getNumberAgent","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/Agent"}}}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["Voice agents"],"summary":"Sets the number's voice agent and when it answers","operationId":"updateNumberAgent","description":"Voza keeps no prompt and no configuration: at the start of each call, the runtime asks for the agent's configuration at callback_url. The first time, the answer carries agent.secret, which signs the runtime's requests and the events sent to events_url.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSettings"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/Agent"}}}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Voice agents are not available in this installation (agents_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Voice agents"],"summary":"Switches the number's agent off and forgets the secret","operationId":"deleteNumberAgent","responses":{"204":{"description":"Switched off."},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/agent/secret":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Voice agents"],"summary":"A new secret for the agent; the previous one stops working at once","operationId":"rotateNumberAgentSecret","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"agent":{"$ref":"#/components/schemas/Agent"}}}}}},"409":{"description":"The number has no agent (agent_not_configured).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls/{call}/agent":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"call","in":"path","required":true,"description":"The call's id at WhatsApp (call_id) or its id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Voice agents"],"summary":"Hands an incoming call that is still ringing to the agent","operationId":"answerCallWithAgent","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"agent_ref":{"type":"string","maxLength":255,"description":"Another agent of the product; the number's when empty."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"call":{"$ref":"#/components/schemas/Call"}}}}}},"404":{"description":"The number or the call does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Someone already answered (call_answered_elsewhere), the call is not ringing (call_not_ringing), the number has no agent (agent_not_configured) or the product refused the call (agent_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request) or a provider's key is missing (missing_provider_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account already has as many simultaneous agent sessions as it may (agent_limit_reached).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The product did not send the agent's configuration (agent_config_unavailable).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls/{call}/monitor":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"call","in":"path","required":true,"description":"The call's id at WhatsApp (call_id) or its id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Voice agents"],"summary":"A short token for a supervisor to listen to a call the agent answered","operationId":"monitorCall","responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitorToken"}}}},"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"404":{"description":"The number or the call does not exist in this account (not_found), or the runtime no longer has it (call_not_found, monitor_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The call is not with the agent (call_not_with_agent), is still being answered (call_not_ready) or another supervisor has taken it over (not_in_control).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls/{call}/monitor/{monitor}":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"call","in":"path","required":true,"description":"The call's id at WhatsApp (call_id) or its id at Voza.","schema":{"type":"string"}},{"name":"monitor","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Voice agents"],"summary":"Removes a supervisor from the call (the AI speaks again if they had it)","operationId":"removeMonitor","description":"left is false when the supervisor, or the call, was already gone.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"left":{"type":"boolean"}}}}}},"404":{"description":"The number or the call does not exist in this account (not_found), or the runtime no longer has it (call_not_found, monitor_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The call is not with the agent (call_not_with_agent), is still being answered (call_not_ready) or another supervisor has taken it over (not_in_control).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls/{call}/whisper":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"call","in":"path","required":true,"description":"The call's id at WhatsApp (call_id) or its id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Voice agents"],"summary":"An instruction for the AI, which the caller does not hear","operationId":"whisperToAgent","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["text"],"properties":{"text":{"type":"string","maxLength":2000},"monitor":{"type":"string","description":"The supervisor who sends it, for the call.supervision event."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"404":{"description":"The number or the call does not exist in this account (not_found), or the runtime no longer has it (call_not_found, monitor_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The call is not with the agent (call_not_with_agent), is still being answered (call_not_ready) or another supervisor has taken it over (not_in_control).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls/{call}/takeover":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"call","in":"path","required":true,"description":"The call's id at WhatsApp (call_id) or its id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Voice agents"],"summary":"The AI stops speaking and the supervisor's microphone goes to the call","operationId":"takeOverCall","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["monitor"],"properties":{"monitor":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"404":{"description":"The number or the call does not exist in this account (not_found), or the runtime no longer has it (call_not_found, monitor_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The call is not with the agent (call_not_with_agent), is still being answered (call_not_ready) or another supervisor has taken it over (not_in_control).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/calls/{call}/release":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}},{"name":"call","in":"path","required":true,"description":"The call's id at WhatsApp (call_id) or its id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Voice agents"],"summary":"Gives the call back to the AI","operationId":"releaseCall","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"monitor":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"404":{"description":"The number or the call does not exist in this account (not_found), or the runtime no longer has it (call_not_found, monitor_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The call is not with the agent (call_not_with_agent), is still being answered (call_not_ready) or another supervisor has taken it over (not_in_control).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid data (invalid_request).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The agents' runtime did not answer (agents_unavailable) or is at its limit (agents_busy), with the reason in meta.reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/numbers/{number}/webphone-tokens":{"parameters":[{"name":"number","in":"path","required":true,"description":"The number's id at Voza.","schema":{"type":"string"}}],"post":{"tags":["Web phone"],"summary":"A short-lived token for the web phone SDK","operationId":"createWebphoneToken","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","maxLength":80},"minutes":{"type":"integer","minimum":5,"maximum":720,"default":480}}}}}},"responses":{"201":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebphoneToken"}}}},"401":{"description":"Missing, invalid or revoked key (invalid_api_key).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The account's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The number does not exist in this account (not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webphone/session":{"get":{"tags":["Web phone"],"summary":"The token's number and ICE servers (used by the SDK)","operationId":"webphoneSession","security":[{"webphoneToken":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebphoneSession"}}}},"401":{"description":"Missing, invalid or expired token (invalid_webphone_token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The token's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webphone/events":{"get":{"tags":["Web phone"],"summary":"The call events, through Server-Sent Events (used by the SDK)","operationId":"webphoneEvents","security":[{"webphoneToken":[]}],"parameters":[{"name":"token","in":"query","schema":{"type":"string"},"description":"The token, for EventSource, which does not send headers."},{"name":"Last-Event-ID","in":"header","schema":{"type":"string"},"description":"The last event received: the stream continues from the next one. EventSource sends it by itself when reconnecting."},{"name":"after","in":"query","schema":{"type":"integer"},"description":"The same as Last-Event-ID, for those who cannot send the header."}],"responses":{"200":{"description":"calls and claimed events; resume with Last-Event-ID.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Missing, invalid or expired token (invalid_webphone_token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"The token's request limit (rate_limited), with Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webphone/calls":{"post":{"tags":["Web phone"],"summary":"A call action with the web phone token (used by the SDK)","operationId":"webphoneCallAction","security":[{"webphoneToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAction"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallActionResponse"}}}},"404":{"description":"The call does not exist or already ended (call_not_found).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"number_not_connected, call_not_ready, call_answered_elsewhere or meta_token_invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"invalid_request, not_on_whatsapp or call_failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"channel_limit_reached, lines_busy or rate_limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"WhatsApp did not accept the action, on a QR code number (call_failed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"lines_starting, engine_unavailable or meta_unavailable (the action did not reach Meta: you may repeat it).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"504":{"description":"The engine took too long to answer (call_timeout), or Meta did not answer in time and the action may have reached it (meta_timeout): repeat it with the same Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or expired token (invalid_webphone_token).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account blocked: trial_expired, subscription_inactive or account_suspended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"messages":{"post":{"summary":"Messages received and delivery statuses (Meta's envelope, field: messages)","description":"Without a 2xx, new attempts with growing waits for 24 hours, or for the period agreed with Voza for the account (webhook_retry_hours in GET /account, up to 7 days).","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"}}}},"responses":{"200":{"description":"Any 2xx within 10 seconds."}}}},"calls":{"post":{"summary":"Call events (Meta's envelope, field: calls)","description":"On a queue of their own: without a 2xx, retries after 5, 15 and 30 seconds; those of a ringing call (connect, RINGING) give up after 2 minutes, and the end of a call goes on after that for as long as message events. A call declined over the simultaneous call limit comes as a terminate, with status REJECTED and voza_reason: channel_limit; one the agent declined, with voza_reason: agent_unavailable and the reason in voza_detail.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEnvelope"}}}},"responses":{"200":{"description":"Any 2xx within 10 seconds."}}}},"call.agent":{"post":{"summary":"Voice agent events (object: voza): call.agent.started, call.agent.state, call.transcript, call.agent.tool_call, call.metrics, call.supervision, call.agent.error, call.agent.declined and call.agent.ended","description":"On a queue of their own, to the agent's events_url (signed with the agent's secret) or to the number's webhook: a call's events go out in order, one after the other. Retries within seconds for up to 2 minutes; call.agent.ended, call.agent.error and call.agent.declined, after that, for as long as message events. timestamp in seconds and timestamp_ms in milliseconds.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentEvent"}}}},"responses":{"200":{"description":"Any 2xx within 10 seconds."}}}},"number.status":{"post":{"summary":"Number status change (object: voza)","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NumberStatusEvent"}}}},"responses":{"200":{"description":"Any 2xx within 10 seconds."}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"API key vz_…, created in the dashboard. Only on your server."},"webphoneToken":{"type":"http","scheme":"bearer","description":"Token wp_… from POST /numbers/{id}/webphone-tokens. Also accepted in ?token=."},"agentToken":{"type":"http","scheme":"bearer","description":"A mon_… token from POST /numbers/{id}/calls/{call}/monitor, or agt_… from POST /agents/test-sessions. It works once."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable: use it to decide what to do."},"message":{"type":"string","description":"For people; may change."},"details":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Each field's errors, in invalid_request."},"meta":{"$ref":"#/components/schemas/ErrorMeta"}}}}},"ErrorMeta":{"type":"object","description":"Only when the error came from Meta (the Graph API's error) or from the engine of QR code numbers (reason).","properties":{"code":{"type":"integer","description":"Meta's code: 131047 (outside the 24-hour window), 190 (invalid token), 138006 (no permission to call)…"},"subcode":{"type":["integer","null"]},"type":{"type":["string","null"],"examples":["OAuthException"]},"details":{"type":["string","null"],"description":"Meta's explanation (error_data.details)."},"fbtrace_id":{"type":["string","null"],"description":"For Meta's support."},"reason":{"type":"string","description":"Why the engine refused, on a number linked by QR code, or the agents' runtime.","enum":["unreachable","unknown_session","not_found","not_linked","not_ready","too_large","not_on_whatsapp","invalid_request","lines_busy","whatsapp_refused","restarting","lines_starting","not_connected","timeout","engine_error","agent_config_unavailable","missing_provider_key","invalid_offer","call_not_found","call_ended","call_conflict","call_not_ready","too_many_monitors","monitor_not_found","not_in_control","tts_failed","at_capacity","draining","not_configured","runtime_error"]}}},"Account":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"status":{"type":"string","enum":["trial","active","suspended","canceled"]},"trial_ends_at":{"type":["string","null"],"format":"date-time"},"partner":{"type":"boolean","description":"Partner account (another product, limits set by Voza): calls are not declined over the account's simultaneous calls limit."},"plan":{"type":["string","null"],"enum":["start","pro","scale",null]},"subscription":{"type":["object","null"],"properties":{"status":{"type":"string","description":"The subscription's status at Stripe: active, past_due, canceled…"},"currency":{"type":"string","enum":["brl","usd"]},"renews_at":{"type":["string","null"],"format":"date-time"},"ends_at":{"type":["string","null"],"format":"date-time"}}},"limits":{"type":"object","properties":{"numbers":{"type":"integer"},"channels":{"type":"integer","description":"Simultaneous calls."},"requests_per_minute":{"type":"integer","description":"API requests per minute, across all of the account's keys."},"agent_sessions":{"type":"integer","description":"Voice-agent sessions at the same time: calls answered by the agents and test calls."},"agent_tests":{"type":"integer","description":"How many of those may be test calls."}}},"webhook_retry_hours":{"type":"integer","description":"For how many hours a failed message event is tried again (24, or what was agreed with Voza, up to 168)."}}},"UsageTotals":{"type":"object","properties":{"messages_sent":{"type":"integer"},"messages_received":{"type":"integer"},"calls":{"type":"integer"},"call_seconds":{"type":"integer"},"agent_calls":{"type":"integer","description":"Calls a voice agent answered."},"agent_seconds":{"type":"integer","description":"The AI's seconds in those calls (without the time a supervisor had the call)."}}},"Usage":{"type":"object","properties":{"month":{"type":"string","examples":["2026-10"]},"totals":{"$ref":"#/components/schemas/UsageTotals"},"numbers":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/UsageTotals"},{"type":"object","properties":{"number_id":{"type":["string","null"],"description":"null for a deleted number."},"name":{"type":["string","null"]}}}]}}}},"Number":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"external_ref":{"type":["string","null"],"description":"Your reference for the number (up to 100 characters), which comes back in the webhooks' metadata.external_ref."},"type":{"type":"string","enum":["qr","meta"]},"status":{"type":"string","enum":["starting","qr","connected","failed"]},"status_reason":{"$ref":"#/components/schemas/StatusReason"},"phone":{"type":["string","null"],"description":"The digits, with the country code."},"qr_url":{"type":["string","null"],"description":"The public QR code page (QR code numbers only)."},"webhook_url":{"type":["string","null"]},"agent_mode":{"type":"string","enum":["off","always","fallback"],"description":"When the number's voice agent answers (see GET /numbers/{id}/agent)."},"connected_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"meta":{"type":"object","description":"Official numbers only.","properties":{"phone_number_id":{"type":"string"},"waba_id":{"type":"string"},"display_phone_number":{"type":["string","null"]},"verified_name":{"type":["string","null"]},"quality_rating":{"type":["string","null"],"enum":["GREEN","YELLOW","RED","UNKNOWN",null]},"calling":{"type":["string","null"],"enum":["enabled","disabled","unavailable",null]},"error":{"type":["string","null"],"description":"What Meta refused at the last check."}}}}},"NumberCreated":{"allOf":[{"$ref":"#/components/schemas/Number"},{"type":"object","properties":{"webhook":{"allOf":[{"$ref":"#/components/schemas/Webhook"}],"description":"Only when the request carried a webhook: the address and the secret that signs the events."}}}]},"NumberCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":80},"external_ref":{"type":["string","null"],"maxLength":100,"description":"Your reference for the number, such as the channel's id in your system."},"type":{"type":"string","enum":["qr","meta"],"default":"qr"},"webhook":{"type":"object","properties":{"url":{"type":["string","null"],"format":"uri"}},"description":"The number's webhook (public https), set before the number connects; the answer has its secret. {id} and {external_ref} in the address are replaced by the number's id and its external_ref (URL-encoded; the request must have external_ref)."},"webhook_url":{"type":["string","null"],"format":"uri","description":"The same as webhook.url, with the same placeholders."},"meta":{"type":"object","description":"Required with type: meta.","required":["phone_number_id","waba_id","access_token","app_secret"],"properties":{"phone_number_id":{"type":"string","pattern":"^\\d{5,30}$"},"waba_id":{"type":"string","pattern":"^\\d{5,30}$"},"access_token":{"type":"string","description":"Permanent token of a system user, with whatsapp_business_messaging and whatsapp_business_management."},"app_secret":{"type":"string","pattern":"^[A-Fa-f0-9]{32}$"}}},"calling":{"oneOf":[{"$ref":"#/components/schemas/CallingSettings"},{"type":"string","const":"keep"}],"description":"Only with type: meta. Calling is turned on with these settings; whatever is missing takes Voza's default (ENABLED, DEFAULT, ENABLED). keep registers the number without touching its calling settings at Meta."}}},"StatusReason":{"type":["string","null"],"enum":["logged_out","restarting","failed","meta_refused",null],"description":"Why the number is in this status: logged_out (the phone removed the device), restarting (the engine is reconnecting the number), failed (WhatsApp refused the device) or meta_refused (Meta refused the token or the number). Empty when there is nothing to explain."},"CallingSettings":{"type":"object","description":"The calling object of the number's settings at Meta, without sip.","properties":{"status":{"type":"string","enum":["ENABLED","DISABLED"]},"call_icon_visibility":{"type":"string","enum":["DEFAULT","DISABLE_ALL"],"description":"The call button in the chat."},"callback_permission_status":{"type":"string","enum":["ENABLED","DISABLED"],"description":"Ask the contact for permission to call back."},"call_hours":{"type":"object","description":"The business hours, as at Meta (status, timezone_id, weekly_operating_hours, holiday_schedule)."},"call_icons":{"type":"object","description":"As at Meta (restrict_to_user_countries)."}}},"CallPermission":{"type":"object","properties":{"messaging_product":{"type":"string"},"permission":{"type":"object","properties":{"status":{"type":"string","enum":["granted","temporary","no_permission"],"description":"Always granted on a QR code number."},"expiration_time":{"type":"integer","description":"When a temporary permission expires (Unix)."}}},"actions":{"type":"array","description":"As at Meta: what the number can do now (start_call, send_call_permission_request) and the limits.","items":{"type":"object"}}}},"TemplateList":{"type":"object","description":"Meta's response, as Meta gives it.","properties":{"data":{"type":"array","items":{"type":"object","description":"A template, with the fields asked for: id, name, language, category, status, components…"},"examples":[[{"id":"1234567890","name":"pedido_enviado","language":"pt_BR","category":"UTILITY","status":"APPROVED","components":[{"type":"BODY","text":"Seu pedido {{1}} saiu para entrega."}]}]]},"paging":{"type":"object","properties":{"cursors":{"type":"object","properties":{"before":{"type":"string"},"after":{"type":"string"}}},"next":{"type":"string","description":"The next page, at Voza; missing on the last one."},"previous":{"type":"string","description":"The previous page, at Voza; missing on the first one."}}}}},"Qr":{"type":"object","properties":{"status":{"type":"string"},"qr":{"type":["string","null"],"description":"PNG as a data URI; null once connected."},"qr_url":{"type":"string"}}},"Webhook":{"type":"object","properties":{"url":{"type":["string","null"]},"secret":{"type":["string","null"]}}},"MessageRequest":{"type":"object","required":["to"],"description":"Meta's body. All numbers: text, image, video, audio, document. Official numbers only: template, interactive, sticker, location, contacts, reaction and context.","properties":{"messaging_product":{"type":"string","const":"whatsapp"},"recipient_type":{"type":"string","const":"individual"},"to":{"type":"string","examples":["5511987654321"]},"type":{"type":"string","enum":["text","image","video","audio","document","template","interactive","sticker","location","contacts","reaction"],"default":"text"},"text":{"type":"object","properties":{"body":{"type":"string","maxLength":4096},"preview_url":{"type":"boolean"}}},"image":{"$ref":"#/components/schemas/MediaLink"},"video":{"$ref":"#/components/schemas/MediaLink"},"audio":{"$ref":"#/components/schemas/MediaLink"},"document":{"$ref":"#/components/schemas/MediaLink"},"template":{"type":"object","description":"As in the Meta API (name, language, components)."},"interactive":{"type":"object","description":"As in the Meta API (button, list, cta_url, call_permission_request…)."},"sticker":{"type":"object","description":"As in the Meta API (id or link)."},"location":{"type":"object","description":"As in the Meta API (latitude, longitude, name, address)."},"contacts":{"type":"array","items":{"type":"object"},"description":"As in the Meta API (name, phones…)."},"reaction":{"type":"object","description":"As in the Meta API (message_id, emoji)."},"context":{"type":"object","properties":{"message_id":{"type":"string"}},"description":"Reply to a message."}}},"MediaLink":{"type":"object","required":["link"],"properties":{"link":{"type":"string","format":"uri","description":"Public https."},"caption":{"type":"string","maxLength":1024},"filename":{"type":"string"},"mime_type":{"type":"string"},"voice":{"type":"boolean","description":"Audio as a voice note (OGG/Opus)."}}},"MessageResponse":{"type":"object","properties":{"messaging_product":{"type":"string"},"contacts":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string"},"wa_id":{"type":"string"}}}},"messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}}}}}},"CallAction":{"type":"object","required":["action"],"properties":{"messaging_product":{"type":"string","const":"whatsapp"},"action":{"type":"string","enum":["connect","pre_accept","accept","reject","terminate"]},"to":{"type":"string","description":"In connect."},"call_id":{"type":"string","description":"In the other actions."},"session":{"type":"object","properties":{"sdp_type":{"type":"string","enum":["offer","answer"]},"sdp":{"type":"string"}}},"biz_opaque_callback_data":{"type":"string","maxLength":512}}},"CallActionResponse":{"type":"object","properties":{"messaging_product":{"type":"string"},"calls":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}}},"description":"In connect."},"success":{"type":"boolean"}}},"Call":{"type":"object","properties":{"id":{"type":"integer"},"call_id":{"type":"string"},"direction":{"type":"string","enum":["incoming","outgoing"]},"contact":{"type":"string"},"contact_name":{"type":["string","null"]},"status":{"type":"string","enum":["dialing","ringing","active","completed","missed","rejected","no_answer","failed"]},"end_reason":{"type":["string","null"],"description":"channel_limit (rejected above the simultaneous calls limit), agent_unavailable (the agent could not answer, or the product refused the call, in always) or lost (no end after 6 hours); null for the others."},"end_detail":{"type":["string","null"],"description":"With agent_unavailable, why the agent declined: product_refused, config_unavailable, missing_provider_key, invalid_offer, at_capacity, draining, account_limit, runtime_unavailable, runtime_error, whatsapp_refused or error."},"started_at":{"type":"string","format":"date-time"},"answered_at":{"type":["string","null"],"format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"},"duration":{"type":["integer","null"],"description":"Seconds."},"answered_by":{"type":["string","null"],"enum":["webphone","agent","api",null],"description":"Who answered (on an outgoing call, who placed it): a webphone, the voice agent or your system with the API key. The first one keeps the call."},"agent":{"type":["object","null"],"description":"Only on a call the agent answered.","properties":{"agent_ref":{"type":"string"},"session_id":{"type":["string","null"]},"seconds":{"type":["integer","null"],"description":"The AI's seconds (without a supervisor's time), once the agent ended."}}}}},"AgentSettings":{"type":"object","required":["mode","agent_ref","callback_url"],"properties":{"require_fresh_config":{"type":"boolean","default":false,"description":"Require a fresh product configuration for every call; never use cached configuration on a callback failure."},"mode":{"type":"string","enum":["off","always","fallback"],"description":"off: only when the product hands over the call; always: every incoming call; fallback: the webphones ring first and the agent answers if nobody does."},"fallback_after_seconds":{"type":["integer","null"],"minimum":5,"maximum":120,"default":15},"agent_ref":{"type":"string","maxLength":255,"description":"The agent in your product."},"callback_url":{"type":"string","format":"uri","description":"Where the runtime asks for the configuration (agent.config) and calls the tools (tool.call). Public https."},"events_url":{"type":["string","null"],"format":"uri","description":"For the agent's events; without it, the number's webhook."}}},"Agent":{"allOf":[{"$ref":"#/components/schemas/AgentSettings"},{"type":"object","properties":{"secret":{"type":"string","description":"Only on creation and in POST /numbers/{id}/agent/secret: it signs the runtime's requests (X-Voza-Signature, the HMAC-SHA256 of \"{X-Voza-Timestamp}.{body}\"; refuse a timestamp more than 5 minutes away from your clock) and the events sent to events_url."}}}]},"AiKeys":{"type":"object","description":"Which providers have a stored key.","properties":{"anthropic":{"type":"boolean"},"deepgram":{"type":"boolean"},"elevenlabs":{"type":"boolean"},"cartesia":{"type":"boolean"}}},"Voice":{"type":"object","properties":{"id":{"type":"string","description":"The voice_id of the agent's voice and of POST /tts."},"name":{"type":"string"},"languages":{"type":"array","items":{"type":"string"},"description":"The languages the provider names (pt-BR, en…); empty when it does not say."},"gender":{"type":["string","null"],"description":"male, female or neutral, when the provider says."},"accent":{"type":["string","null"],"description":"When the provider says."},"preview_url":{"type":["string","null"],"format":"uri","description":"A sample of the voice, when there is one."}}},"TtsRequest":{"type":"object","required":["provider","voice_id","text"],"properties":{"provider":{"type":"string","enum":["elevenlabs","cartesia"]},"voice_id":{"type":"string","maxLength":255},"text":{"type":"string","maxLength":1000},"speed":{"type":"number","minimum":0.25,"maximum":4,"default":1},"model":{"type":["string","null"]},"language":{"type":"string","default":"pt-BR"},"format":{"type":"string","enum":["mp3","wav"],"default":"mp3"}}},"SdpOffer":{"type":"object","required":["session"],"properties":{"session":{"type":"object","required":["sdp_type","sdp"],"properties":{"sdp_type":{"type":"string","const":"offer"},"sdp":{"type":"string","description":"The whole SDP, without trickle ICE."}}}}},"SdpAnswer":{"type":"object","properties":{"sdp_type":{"type":"string","const":"answer"},"sdp":{"type":"string"}}},"MonitorToken":{"type":"object","properties":{"token":{"type":"string","description":"mon_…, for the supervisor's browser; it works once."},"ice_servers":{"type":"array","items":{"type":"object"},"description":"For new RTCPeerConnection({ iceServers })."},"expires_at":{"type":"string","format":"date-time"}}},"AgentTestSession":{"type":"object","properties":{"id":{"type":"string"},"token":{"type":"string","description":"agt_…, for the browser; it works once."},"ice_servers":{"type":"array","items":{"type":"object"}},"expires_at":{"type":"string","format":"date-time"},"secret":{"type":"string","description":"Only without number_id: the secret that signs the runtime's requests on this test call."}}},"AgentEvent":{"type":"object","properties":{"object":{"type":"string","const":"voza"},"event":{"type":"string","enum":["call.agent.started","call.agent.state","call.transcript","call.agent.tool_call","call.metrics","call.supervision","call.agent.error","call.agent.declined","call.agent.ended"]},"event_id":{"type":"string","description":"The same on every attempt: use it so you never process an event twice."},"number":{"type":"object","description":"As in number.status."},"call":{"type":"object","description":"Missing on a test call.","properties":{"id":{"type":"string"},"call_id":{"type":"string"},"direction":{"type":"string"},"contact":{"type":"string"},"contact_name":{"type":["string","null"]},"agent_ref":{"type":"string"},"agent_session_id":{"type":["string","null"]}}},"test_session":{"type":"object","description":"Only on a test call.","properties":{"id":{"type":"string"},"agent_ref":{"type":"string"}}},"test":{"type":"boolean"},"data":{"type":"object","description":"What the runtime sent: state (listening, thinking, speaking, handoff, handoff_timeout, supervised); speaker, text, start and end; name, duration_ms and result; the latencies; monitor_id and mode; service, provider, status, category and action of a provider that failed (call.agent.error); reason, detail, mode and outcome of a call the agent declined (call.agent.declined); and, at the end, reason, duration_seconds, ai_seconds, supervised_seconds, transcript, tools and usage."},"timestamp":{"type":"integer","description":"Seconds (Unix)."},"timestamp_ms":{"type":"integer","description":"The same moment in milliseconds, to order events of the same second."}}},"WebphoneToken":{"type":"object","properties":{"token":{"type":"string"},"expires_at":{"type":"string","format":"date-time"},"sdk_url":{"type":"string"}}},"WebphoneSession":{"type":"object","properties":{"session_id":{"type":"string","description":"The id of this session, the same as in the claimed event."},"label":{"type":["string","null"]},"number":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"phone":{"type":["string","null"]},"status":{"type":"string","enum":["starting","qr","connected","failed"]}}},"ice_servers":{"type":"array","description":"For new RTCPeerConnection({ iceServers }). The TURN credentials expire: ask for the session again before each call.","items":{"type":"object","properties":{"urls":{"type":"array","items":{"type":"string"}},"username":{"type":"string"},"credential":{"type":"string"}}}},"expires_at":{"type":"string","format":"date-time"}}},"WebhookEnvelope":{"type":"object","description":"Meta's envelope. metadata.phone_number_id is the number's id at Voza, and metadata.external_ref is your reference, when the number has one. value carries contacts, messages, statuses or calls, and Meta's errors, even on their own.","properties":{"object":{"type":"string","const":"whatsapp_business_account"},"entry":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"changes":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","enum":["messages","calls"]},"value":{"type":"object"}}}}}}}}},"NumberStatusEvent":{"type":"object","properties":{"object":{"type":"string","const":"voza"},"event":{"type":"string","enum":["number.status","test"]},"number":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"external_ref":{"type":["string","null"]},"status":{"type":"string"},"status_reason":{"$ref":"#/components/schemas/StatusReason"},"phone":{"type":["string","null"]}}},"timestamp":{"type":"integer"}}}}}}