Skip to content

Platform API reference

Download .md

The Platform API (/v1) field by field: every endpoint, every field, its type, its allowed values and its limits. Generated from /openapi/v1.json; interactive version: API reference.

The rules every endpoint shares (base URL, keys, strict bodies, paging, ids) are in the Overview; what every error code means is in Errors. To get a task done, start from a guide: Send a text, Send a WhatsApp template, Place a call, Run a campaign, Receive webhooks or Test without spending.

One SMS, MMS or WhatsApp template per request, read back by id, and pictures people text you: GET /v1/messages, POST /v1/messages, GET /v1/messages/{id}, POST /v1/media, GET /v1/media/{id}. Fields: Messages.

An AI agent calls one number; read the call and its recording: GET /v1/calls, POST /v1/calls, GET /v1/calls/{id}, GET /v1/calls/{id}/transcript, POST /v1/calls/{id}/end, GET /v1/calls/{id}/voicemail, GET /v1/recordings/{conversation_id}, GET /v1/voicemail-recordings, POST /v1/voicemail-recordings, GET /v1/voicemail-recordings/{id}, DELETE /v1/voicemail-recordings/{id}. Fields: Calls.

One message or call to many people, drafted, previewed and started: GET /v1/campaigns, POST /v1/campaigns, GET /v1/campaigns/{id}, PATCH /v1/campaigns/{id}, DELETE /v1/campaigns/{id}, POST /v1/campaigns/{id}/start, POST /v1/campaigns/{id}/pause, POST /v1/campaigns/{id}/resume, POST /v1/campaigns/{id}/cancel. Fields: Campaigns.

Who a draft reaches and what it costs, then what happened to each person and what it cost: POST /v1/campaigns/{id}/previews, GET /v1/campaigns/{id}/previews/{preview_id}, GET /v1/campaigns/{id}/recipients, GET /v1/campaigns/{id}/usage, GET /v1/campaigns/{id}/recipients/{recipient_id}. Fields: Campaigns → CampaignPreview, CampaignRecipient and CampaignUsage.

How an AI-call campaign went, in counts, and its next round: GET /v1/campaigns/{id}/results, POST /v1/campaigns/{id}/clone. Fields: Campaigns → CampaignResults and CampaignClone.

The people you text and call, and the lists a campaign sends to: GET /v1/contacts, POST /v1/contacts, GET /v1/contacts/{id}, PATCH /v1/contacts/{id}, DELETE /v1/contacts/{id}, POST /v1/contacts/{id}/tags, DELETE /v1/contacts/{id}/tags/{tag}, POST /v1/contacts/{id}/dnc, GET /v1/contacts/{id}/consent-events, POST /v1/contacts/{id}/consent-events, GET /v1/contacts/{id}/channels, POST /v1/contacts/{id}/channels, DELETE /v1/contacts/{id}/channels/{address}, GET /v1/contact-fields, GET /v1/lists, POST /v1/lists, GET /v1/lists/{id}, PATCH /v1/lists/{id}, DELETE /v1/lists/{id}, GET /v1/lists/{id}/contacts, POST /v1/lists/{id}/contacts, DELETE /v1/lists/{id}/contacts/{contact}. Fields: Contacts, Contact lists.

What each call finds out, as typed fields; its answers are a call’s extracted: GET /v1/insights, POST /v1/insights, GET /v1/insights/{id}, PATCH /v1/insights/{id}, DELETE /v1/insights/{id}. Fields: Insights.

The read-only lists you pick from, and the key a request runs as: GET /v1/senders, GET /v1/templates, GET /v1/templates/{id}, GET /v1/sms-templates, GET /v1/sms-templates/{id}, GET /v1/agents, GET /v1/agents/{id}, PATCH /v1/agents/{id}, GET /v1/agents/{id}/prompt-versions, GET /v1/agents/{id}/prompt-versions/{version}, POST /v1/agents/{id}/test-turns, GET /v1/agents/{id}/phrase-rules, POST /v1/agents/{id}/phrase-rules, PATCH /v1/agents/{id}/phrase-rules/{rule_id}, DELETE /v1/agents/{id}/phrase-rules/{rule_id}, GET /v1/segments, POST /v1/segments, GET /v1/segments/{id}, PATCH /v1/segments/{id}, DELETE /v1/segments/{id}, GET /v1/segments/{id}/contacts, GET /v1/me. Fields: Senders and lookups.

The credit balance a send or a campaign start can be refused over, what the credits went on (usage), and the outbound compliance acknowledgment a campaign start can be refused over: GET /v1/balance, GET /v1/usage, GET /v1/usage/events, GET /v1/usage/export, GET /v1/compliance, POST /v1/compliance/accept. Fields: Balance and compliance.

Where events are delivered, and how they are signed: GET /v1/webhooks, POST /v1/webhooks, GET /v1/webhooks/{id}, PATCH /v1/webhooks/{id}, DELETE /v1/webhooks/{id}, POST /v1/webhooks/{id}/rotate-secret, POST /v1/webhooks/{id}/test, GET /v1/webhooks/{id}/deliveries, GET /v1/webhooks/{id}/deliveries/{delivery_id}. Fields: Webhooks.

What arrives at an endpoint or on the stream: GET /v1/events. Fields: Events.

Every /v1 refusal is this envelope, with an HTTP status. What each code means and how to fix it: Errors.

fieldtypedescription
errorobject, required
error.typestring, requiredFollows the HTTP status: invalid_request_error (400, 405, 413, 415, 422), billing_error (402), permission_error (403), not_found_error (404), conflict_error (409), rate_limit_exceeded (429) or server_error (5xx). A missing or bad key is 401 with invalid_request_error and code invalid_api_key, as OpenAI answers it. Branch on code.
error.codestring, requiredStable machine code. Branch on this.
error.messagestring, requiredWhat went wrong, in a sentence. Show this.
error.paramstring or null, requiredWhat the error is about, in /v1 names: a body field (to, audience.contacts.0.phone), a query parameter (status), a path segment (id) or a header (idempotency-key); null when it is about none of them.
error.hintstringWhat to do next.
error.docs_urlstring
error.request_idstringQuote this when you contact support.
error.fieldsarray of stringEvery field the refusal is about, when there is more than one (unknown_variable, unmapped_variable): the first is param.
error.fieldstringunmapped_variable: the placeholder nothing fills.
error.missingarray of stringlaunch_fields_missing: the /v1 fields to set before a start.
error.statusstring or nullA state refusal (campaign_not_pausable, campaign_not_cancellable, campaign_not_resumable, campaign_not_previewable, campaign_not_editable, campaign_not_deletable): the campaign’s status now.
error.allowedarray of stringA state refusal (campaign_not_pausable, campaign_not_cancellable, campaign_not_resumable, campaign_not_previewable): the statuses the action takes. A cancel never lists draft: a draft is deleted instead.
error.problemsarray of objectsinvalid_variable, unknown_variable, unmapped_variable: every variable the refusal is about, one entry each with its own message and hint, ordered by param; the first is the refusal’s own param, message and hint. field is the variable’s name (or the placeholder nothing fills).
error.problems[].fieldstring, required
error.problems[].paramstring, required
error.problems[].messagestring, required
error.problems[].hintstring
error.problems[].suggestionstringunknown_variable: the closest name the content has.
error.partstring
text, field, fallback
invalid_variable for a value over 200 characters: which part of the first one is too long (the plain text, the field name, or the fallback).
error.template_statusstringtemplate_not_approved: the template’s status.
error.retry_afternumberSeconds to wait before retrying, as in Retry-After.
error.short_creditsnumberinsufficient_credits: how many more credits the send needs.
error.campaign_idstringA refusal after the campaign was created: the campaign, kept as a draft.
error.issuesarray of objectsinvalid_request: every problem the body has, one per entry.
error.issues[].patharray of string, required
error.issues[].codestring, required
error.issues[].messagestring, required
error.channelstringfield_not_for_channel: the campaign’s channel (fields names the fields of another channel).
error.errorsarray of anyAn audience refusal (empty_audience_input, an import with no usable row): the rows that could not be read, one entry each ([] when there were none).
error.receivednumberAn audience refusal: how many rows were sent.
error.invalid_rowsnumberAn audience refusal: how many rows could not be used.
error.sender_statusstringsender_not_cleared: the number’s sms.status in GET /v1/senders (receiving_only, in_review, rejected, …).
error.skipped_by_reasonmap of string to numberno_recipients: how many of the audience are left out, by reason (no_phone_number, opted_out, duplicate, …), accounting for every member.
error.reasonstring or nullWhy, in a word, where a code has several causes: billing_not_eligible (no card on file, or a past-due or canceled subscription).
error.message_idstring or nullA WhatsApp send refused after the message was stored (opted_out, send_failed): the stored message’s id, for GET /v1/messages/{id}.
error.versionstring or nulloutbound_compliance_required: the acknowledgment version to accept (POST /v1/compliance/accept).
error.current_versionstringversion_mismatch (POST /v1/compliance/accept): the acknowledgment’s version now; read it with GET /v1/compliance and accept that one.
error.candidatesarray of stringambiguous_contact: the ct-… ids of the contacts that hold the number; remove one by its id.
error.campaignsarray of stringlist_in_use: the ca-… ids of the campaigns not yet finished that use the list.
error.contactstringcontact_exists: the ct-… id of the contact that already has the phone or email.
error.channelsarray of stringstopped_by_person, no_address (POST /v1/contacts/{id}/dnc): the channels the refusal is about.
error.capnumberdaily_voice_minutes_exceeded: the workspace’s daily talk-minute cap. spend_cap_reached, spend_cap_raise_needs_person: the campaign’s spending limit, in credits.
error.usednumberdaily_voice_minutes_exceeded: what the day already owes: metered + held minutes. spend_cap_reached: the credits the campaign has been billed.
error.remainingnumberdaily_voice_minutes_exceeded: the minutes left on day. spend_cap_reached: the credits left under the limit after the calls under way (cap − used − in_flight).
error.in_flightnumberspend_cap_reached: the projected credits of the campaign’s calls under way.
error.next_callnumberspend_cap_reached: the projected credits of one more call (a median call on the campaign’s agent).
error.dashboard_urlstringspend_cap_reached, spend_cap_raise_needs_person: the campaign’s page in the dashboard, where a person raises its spending limit.
error.meterednumberdaily_voice_minutes_exceeded: voice minutes already billed on day.
error.heldnumberdaily_voice_minutes_exceeded: minutes held on day by queued or scheduled campaigns that start that day or earlier.
error.held_byarray of objectsdaily_voice_minutes_exceeded: the campaigns holding held, largest first.
error.held_by[].campaignstring, requiredThe campaign’s ca-… id.
error.held_by[].namestring, required
error.held_by[].minutesnumber, required
error.held_by[].starts_atstring or null, required
error.daystring or nulldaily_voice_minutes_exceeded: the budget day checked (YYYY-MM-DD in time_zone): the campaign’s start day.
error.time_zonestring or nulldaily_voice_minutes_exceeded: the zone the workspace’s budget day follows (UTC when none is set).
error.per_call_minutesnumber or nulldaily_voice_minutes_exceeded: the minutes each call is projected at (this workspace’s average, at least 1.5).
error.resets_atstring or nullWhen the daily allowance clears (ISO 8601): trial_daily_cap for the trial number’s calls, daily_voice_minutes_exceeded for the voice budget (midnight in time_zone).
error.allowed_countrystring or nullroute_blocked: the country your calling rules let you call.
error.closes_atstring or nullreply_window_closed: when Meta’s 24-hour window closed (ISO 8601), or null when the person never wrote.