Errors
Errors have a non-2xx status (three exceptions below) and a JSON body:
successboolean- Always
false. errorstring- A sentence for people. It can change: don’t parse it. Some say "refresh the page" because the dashboard shares these endpoints.
error_code,codestring- The stable code to branch on. Read
error_code ?? code: some errors usecodeinstead oferror_code, some use both, and a few put the code inerror(the table says which). Codes are case-sensitive, and a few conditions have an upper and a lower case form from different endpoints (both are in the table). …- Extra fields where they apply, such as
next_allowed_at,alternatives,field,balance_cents.
- A
400with no code is a malformed request: fix the body, don’t retry. - An unknown path or an unsupported method returns a JSON 404 with
error_codeNOT_FOUND. A missing resource on a real path returns a JSON 404 with its own code, such asCONTACT_NOT_FOUND. - Not successes:
200 empty_merge_field,200 generation_refusedand202 send_outcome_unknown. - Any endpoint can answer these, so endpoint sections don’t list them:
403 permission_denied(the key’s user lacks the permission the endpoint needs),403 test_key_not_allowed(a test key on a write that isn’t simulated),403 OWNER_ONLY(the key isn’t the account owner’s) and503 ACCESS_CHECK_UNAVAILABLE(we couldn’t check who is asking; nothing changed, retry). - Every response has an
X-Request-Id: the one you sent if it is up to 200 letters, digits,_,.,:or-, else a new UUID. Include it when you contact support.
#When to retry
| Response | What to do |
|---|---|
429 rate_limited, throughput_exceeded, RATE_LIMITED, validation_in_progress |
Nothing ran. Wait Retry-After (a minute if absent), retry with the same key. A 429 is never stored under the key. |
429 daily_cap, number_daily_cap | A cap, not a speed limit, with no Retry-After: don’t loop. Resets at midnight Pacific (America/Los_Angeles). |
429 monthly_cap, 402 MONTHLY_CAP_REACHED |
Don’t loop. The cap uses a 30-day window, not a calendar month. Wait for capacity or complete registration with a paid number (see Sending caps). |
429 ramp_cap, 409 RAMP_CAP_REACHED | Wait for your registration to be approved (ramp_ends_at, our estimate, when present). After a content check, wait until tomorrow. |
409 idempotency_in_progress | Wait a few seconds, retry with the same key. |
500 send_failed, 500 hold_not_returned, 500 reservation_unconfirmed, any 503 on a send |
Not sent, not charged. Retry with a new key (the old one replays the error).
ExceptionsForhold_not_returned, support returns the held amount. For reservation_unconfirmed, the amount held for the text comes back to your balance on its own within minutes: check your balance first. Wait Retry-After first when it’s there (60 seconds on provider_busy). ADMISSION_SHED and permission_check_unavailable come before the key is recorded, and a 503 that couldn’t read your balance, account or a price isn’t stored, so the same key works for them too.
|
| Your client timed out | May still be running. Retry with the same key after a minute. A new key can send twice. Once the first request has finished, you get its real result with Idempotent-Replayed: true; before that, 409 idempotency_in_progress. |
504 REQUEST_TIMEOUT_OUTCOME_UNKNOWN |
May still go through. Check whether it did (below) before you send again with a new key. A new key can send twice. The 504 isn’t stored: a retry with the same key answers 409 idempotency_in_progress until the request finishes, then replays its real result. It never runs the request twice. |
202 send_outcome_unknown, 500 INTERNAL_ERROR_OUTCOME_UNKNOWN |
May have been delivered and charged. Decide whether a duplicate or a missed text is worse. Retrying with the same key returns this same answer, and sending again with a new key can deliver it twice. |
Other 4xx | Fix the request, send it with a new key. |
422 | Don’t retry. The number can’t receive texts. |
#Checking whether a text went out
There is no lookup by Idempotency-Key, and GET /v1/messages lists refused and unconfirmed attempts too. A listed attempt is not proof of delivery. queued means handed to the carrier; delivered means delivery confirmed. unknown means carrier acceptance could not be confirmed: it may still have delivered.
What the list shows
- The list filters only on
direction,to,fromandstatus. - A send refused with an error (an opt-out, a cap, a
send_failed) is saved as an outbound row withstatus: "failed",cost_usd: 0and the samebody. Finding the body in the list doesn’t mean it was sent. - A
202 send_outcome_unknownattempt is recorded asunknown, separate from a definitive failure. A zero cost does not prove it was unsent or refunded. Later evidence may update the outcome; do not resend with a new key just because delivery is unconfirmed. - A
failedrow withcost_usdabove 0 went out and the carrier didn’t deliver it. See Failures Ready resends for you before you send it again.
#Status codes
Standard HTTP meanings. The ones to know: 402 payment needed, 409 not sendable right now, 422 the number can’t receive texts, 503 a safety check couldn’t run (not sent, not charged), 504 a write may still go through.
Details: every status
200OK.201created (contacts).202accepted but not finished, or outcome unknown.400bad request.401no or bad credentials.402payment needed.403not allowed (often: can’t text this contact).404not found.406unsupported API version.408timed out, nothing changed.409conflict, or not sendable now.413body too large (limits).422number can’t receive texts.423legal hold.429too fast or over a limit.500,502failed on our side.503a safety check couldn’t run: not sent, not charged.504a write timed out and may still go through.
{
"success": false,
"error": "This contact replied STOP and is opted out. They must reply START from their phone to opt back in.",
"error_code": "opt_out_locked",
"reason": "sms_stop_keyword"
}
{
"success": false,
"error": "to should be a single value, not a list or object.",
"code": "invalid_field",
"field": "to",
"error_code": "invalid_field"
}
{
"success": false,
"error": "Enter a phone number for this contact."
}
const body = await res.json();
const code = body.error_code ?? body.code; // undefined on a 400 malformed request, and on the few errors whose code is in body.error (see the table)
#Error codes
The codes more than one endpoint returns. A code only one endpoint returns is in that endpoint’s errors. The first table is what sending, contacts and the rest of the API return; registration, number-buying, scrub and sub-account codes are in their own tables after it. Retry: Same key: nothing ran, or it’s still running, so wait (Retry-After when there is one) and send the same request with the same Idempotency-Key. New key: nothing was sent, so fix the request or wait as the row says, then send it with a new key. Check first: it may have gone through, so check before you send again. No: retrying won’t help; do what the row says.
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
empty_merge_field | 200 | A merge field is blank. Nothing sent. Resend with "confirm_empty_merge": true to send it with the blank. | New key |
generation_refused | 200 | AI drafts: the ask breaks texting rules. Charged, not refunded. Body has "success": false and "refused": true. | New key |
send_outcome_unknown | 202 | May have been delivered and charged: we couldn’t confirm the carrier took it. A retry with the same key returns this answer again (When to retry). | No |
attestation_required | 400 403 | A confirmation is missing; error says which. 400: a waiver, such as turning off tcpa or dnc_complainers without confirmation_text: "I UNDERSTAND", turning off the opt-out footer, removing a do-not-call entry or turning on number protection. 403: a campaign scheduled, or its audience changed, without consent_attested: true (Campaigns). Every one carries the code in error_code; read that. The same missing consent on a drip enroll answers 403 CONSENT_REQUIRED and on an automation bulk enroll 400 NO_CONSENT, and both also carry error_code: "attestation_required". | New key |
ca_not_provisioned | 400 | Canada sending isn’t set up on this account. Nothing sent, not charged. Contact support to turn it on. | No |
country_not_supported | 400 | The recipient is outside the United States, Canada, Australia and the United Kingdom. Nothing sent, not charged. | No |
CONTACT_UPDATE_FAILED | 400 | A value can’t be saved (e.g. non-integer score). The same code with 500 means the save failed; retry. | New key |
CONTENT_BLOCKED | 400 | Blocked content. Nothing sent; a compliance fee may apply. Link shorteners, prohibited or regulated content. error states the fee and reasons lists what was flagged. Other send paths use lower case content_blocked. Creating or editing a campaign answers 400; sending one answers 422. | No |
idempotency_key_required | 400 | No Idempotency-Key header. Buying an iMessage line (POST /v1/imessage-lines/checkout) and placing a FaceTime call answer it today, and nothing is held or placed. On a text send it is not enforced yet: the send goes through. Add a new unique key per request. | New key |
idempotency_key_too_long | 400 | Idempotency-Key is over 255 characters. | New key |
invalid_assignee | 400 | One of the ids isn’t on your team. | New key |
INVALID_CONTACT_ID | 400 | Use the contact’s id, not its phone number. | New key |
invalid_field | 400 | Wrong type; field names it when the code is in code. | New key |
invalid_from | 400 | from isn’t one of your numbers. | New key |
INVALID_JSON | 400 | The body isn’t valid JSON. | New key |
invalid_number | 400 | The phone number has fewer than 10 digits, or isn’t a valid number. | New key |
INVALID_PHONE | 400 | The contact’s phone number can’t be read. | New key |
invalid_offset | 400 | offset isn’t a whole number, 0 or more. | New key |
invalid_request | 400 | Missing or misshapen body; error says what. | New key |
invalid_event | 400 | An event name in events isn’t one Ready sends.DetailsThe message lists the valid names. Nothing is saved until every name is valid. | New key |
invalid_status | 400 | Must be open, active, closed or archived. | New key |
invalid_url | 400 | Webhook URL not usable. A bad URL, not http or https, or a private or internal host. | New key |
MESSAGE_TOO_LONG | 400 | Over 25 segments, or 1,600 characters with an image. A length check at send time, here and on other send paths, answers lower case message_too_long. | New key |
NO_APPROVED_CAMPAIGN | 400 | Your business isn’t registered or verified with the carriers yet, or the number’s setup isn’t confirmed yet. Nothing sent, not charged. Check GET /v1/registration: register with POST /v1/registration/brand if there is none, or wait for approval. | No |
no_country_sender | 400 | No active number of yours is in the recipient’s country. Nothing sent, not charged. Buy a number in that country, then send again; where that country can’t be bought yet, error says to contact support instead. | No |
no_sender_number | 400 | No active number to send from. | New key |
no_active_number | 400 | No active number to send from. Campaign sends and drip campaigns answer this; /v1/messages answers the same condition as no_sender_number. | New key |
NO_RECIPIENTS / no_recipients | 400 | Nobody in the audience can be texted. Creating or scheduling a campaign answers NO_RECIPIENTS; sending one answers no_recipients. Same condition, same status. | New key |
PHONE_NOT_EDITABLE | 400 | Contact phone can’t change. Create a new contact. | No |
REQUEST_BLOCKED | 400 | Query string looks like code (HTML, script, SQL). Remove it. Repeats can get your IP blocked (IP_TEMPORARILY_BLOCKED). | New key |
too_many_recipients | 400 | Bulk send with more than 100 recipients. | New key |
unknown_field | 400 | Field not accepted here. Remove it. | New key |
UNRENDERED_MERGE_TOKEN | 400 | A merge tag didn’t fill. Not sent, not charged. | New key |
AUTH_REQUIRED | 401 | No key or an empty variable. | New key |
INVALID_API_KEY | 401 | Key not valid. Revoked, mistyped or cut off. Also any X-API-Key value that is not a valid key. | New key |
INVALID_TOKEN | 401 | A dashboard session that has ended or is not valid. A bearer value that is not a session token, such as a bad or mistyped key, gets INVALID_API_KEY. | New key |
BILLING_PAST_DUE | 402 | Payment failed and no balance left, or the plan was cancelled. Nothing ran. After a failed payment, update your card (billing_url); a cancelled account starts sending again once you activate a number in Numbers. FRAUD_HOLD (402) means the account is on hold: contact support. | New key |
card_declined | 402 | The saved card was declined. Also card_authentication_required. | New key |
CARD_REQUIRED | 402 | Add a card in Settings → Billing. | New key |
client_card_required | 402 | A sub-account that pays with its own card has not added one yet. Add one in Billing. | New key |
insufficient_balance | 402 | Balance too low. Nothing was sent or charged. Top up in Billing, or turn on Auto top-up so your card tops up before you run out (Billing and pricing). Sends and scrub add balance_cents and required_cents. | New key |
insufficient_credits | 402 | Balance can’t cover the whole batch. Bulk send, validation. Nothing was sent or charged. Top up in Billing by at least the difference, then try again. | New key |
MONTHLY_CAP_REACHED | 402 | Monthly sending cap reached. Same limit as monthly_cap (429) from other send paths. | No |
monthly_limit | 402 | Sending this campaign would pass your monthly text limit. Same limit as MONTHLY_CAP_REACHED (402, /v1/messages) and monthly_cap (429, other send paths). | No |
ACCOUNT_SUSPENDED | 403 | Account suspended; every call refused. Contact support. The send path can also answer lower case account_suspended in error_code. | No |
api_consent_attested_required | 403 | Send "consent_attested": true. Not enforced yet. Not returned today: a send without it goes through. It will be once enforcement is on. | New key |
dnc_list | 403 | On a do-not-call list your account screens against. | No |
EXPORT_DISABLED | 403 | Only the account owner can export contacts on this account. | No |
global_blocklist | 403 | The number is on Ready’s blocklist. Branch on error_code: this one body’s older code field reads recipient_blocked, which is also a delivery status, so do not read code here. | No |
IP_TEMPORARILY_BLOCKED | 403 | IP blocked 15+ minutes. Repeated blocked requests from one IP: over-limit requests without a valid key, scanner user agents, blocked paths, query strings that look like code, or oversized bodies. A key that already worked in the last hour skips the block; a key you just fixed waits it out. | Same key |
opt_out_locked | 403 | Recipient opted out. Nothing sent, not charged.Where the opt-out came fromSTOP or marked opted out. On/sms/send and /v1/messages, reason is where the opt-out came from (sms_stop_keyword when unknown). On PUT /contacts/:id: you tried to re-enable texting for a STOP-locked contact. Only the contact texting START lifts a STOP. On a send, a Do Not Disturb or manually opted-out contact also gets opt_out_locked; the error says which. A START does not clear Do Not Disturb. | No |
dnd_sms | 403 | The contact is marked Do Not Disturb for texts. Nothing sent, not charged. | No |
number_not_assigned | 403 | Sending number not assigned to you. Nothing sent. Not assigned to this user or sub-account. | No |
opted_out | 403 409 | 409 on an iMessage send: the contact opted out, nothing was sent. 403 on PUT /contacts/:id: re-enabling texting on an opted-out contact. The contact is opted out but not STOP-locked (for example marked Do Not Disturb). A START from the contact doesn’t undo it. | No |
permission_denied | 403 | The key’s user lacks the permission this endpoint needs. | No |
quiet_hours | 403 | Outside the recipient’s allowed hours. From Zapier, GoHighLevel and automation sends. /sms/send and /v1/messages answer 409 QUIET_HOURS_BLOCK instead. | New key |
READ_ONLY_SESSION | 403 | View-only access can’t make changes or spend money. | No |
REQUEST_BLOCKED | 403 | User-Agent looks like a scanner. Send your own. | No |
OWNER_ONLY | 403 | The key isn’t the account owner’s (a team member’s key, for example). | No |
owner_only | 403 | Same refusal as OWNER_ONLY, spelled in lower case by registration cancel, edit and transfer, and by team invites. Match it case-insensitively. | No |
CONSENT_REQUIRED | 403 | Drip enroll of more than one contact without consent_attested: true; error_code is attestation_required. Not the same as the registration consent_required (400). | New key |
test_key_not_allowed | 403 | A test key called a non-simulated endpoint. Nothing changed. The sentence is in error and message; the code is in error_code and code. | No |
tcpa_block | 403 | On a do-not-call or known litigator list. Nothing sent, not charged. | No |
CONTACT_NOT_FOUND | 404 | No contact with this id on your account. | No |
conversation_not_found | 404 | Same as CONVERSATION_NOT_FOUND, from the iMessage send. | No |
CONVERSATION_NOT_FOUND | 404 | No conversation with this id on your account. | No |
message_not_found | 404 | No such message. Body has status: "unknown". | No |
not_found | 404 | Conversation not found (from PUT /conversations/:id/assign). | No |
number_not_found | 404 | Same as NUMBER_NOT_FOUND, from GET /v1/numbers/:id. | No |
NOT_FOUND | 404 | No endpoint has this path and method. Check the path, the method and the version prefix /v1. | No |
NUMBER_NOT_FOUND | 404 | No number with this id on your account. | No |
unsupported_api_version | 406 | Unserved Accept-Version; supported lists versions. | New key |
REQUEST_TIMEOUT | 408 | Read, or a body still arriving, over its deadline (Timeouts). Nothing changed. | Same key |
already_sending | 409 | The campaign is already sending. Sending it again answers 409; unscheduling or cancelling one that has started answers 400 with the same code. | No |
CONTACT_CHANGED | 409 | Contact opted out mid-save. Read it again. | New key |
CONTACT_EXISTS | 409 | Phone already a contact (GET /contacts?search=). | No |
duplicate_send | 409 | Same text, same number, within 60 s, no key. | No |
idempotency_in_progress | 409 | First request still running. Wait a few seconds. | Same key |
idempotency_outcome_unknown | 409 | First request with this key ran over 20 minutes; outcome unknown. See Checking whether a text went out. | No |
INVALID_SENDER | 409 | Sending number can’t send now. Try another. | No |
number_activating | 409 | The sending number is still being set up. Try again later. | New key |
number_not_active | 409 | The sending number isn’t active yet. Check it with GET /v1/numbers/:id, or send from another number. | No |
NUMBER_NOT_ASSIGNED_CONFIRM | 409 | You are replying from a number that isn’t assigned to you. Nothing was sent. Send again with "confirm_unassigned_number": true to send from from_number anyway. | New key |
QUIET_HOURS_BLOCK | 409 | Recipient’s quiet hours. Body has next_allowed_at, reason, recipient_tz, can_override. When can_override is true, send again with override_quiet_hours. | New key |
RAMP_CAP_REACHED | 409 | Your registration is still in carrier review and the account has sent the texts allowed until it is approved. Body has cap, count and ramp_ends_at, our estimate of the approval date. Full volume opens when the registration is approved. Same limit as ramp_cap (429) from other send paths. | New key |
route_unavailable | 409 | No route to this recipient right now. Try again later. | New key |
PAYLOAD_TOO_LARGE | 413 | The body is over 1 MB (50 MB on bulk, import and upload paths such as /v1/messages/bulk). | New key |
auto_reply_suppressed | 422 | The number keeps answering with an automated reply, so it was skipped. It gets texts again once someone replies from it. | No |
INVALID_DESTINATION | 422 | Not a valid phone number. Nothing sent, not charged. | No |
landline_no_sms | 422 | The number is a landline. | No |
number_disconnected | 422 | A deactivation record or previous delivery failures blocked this attempt. This does not confirm the number is currently disconnected. Read the response’s error for the specific explanation. | No |
PROVIDER_REJECTED | 422 | The carrier refused this text. Not charged. Check the recipient number and your registration; contact support if it keeps happening. | No |
sms_invalid | 422 | The number was marked as unable to receive texts. | No |
undeliverable | 422 | The carrier can’t deliver to this number. | No |
LITIGATION_HOLD | 423 | Legal hold: the contact can’t be deleted. | No |
daily_cap | 429 | Account daily cap reached. No Retry-After. Off unless Ready set one for your account. Resets at midnight Pacific time. | New key |
monthly_cap | 429 | Monthly cap reached. No Retry-After. Same limit as MONTHLY_CAP_REACHED, which /v1/messages answers. | No |
number_daily_cap | 429 | Sending number’s daily cap reached. You set it per number. No Retry-After: it resets at midnight Pacific time. Send from another number or wait. | New key |
ramp_cap | 429 | Warm-up cap. No Retry-After. Same limit as RAMP_CAP_REACHED. Wait for your registration to be approved. Also returned when a blocked message put your account on a daily limit; the message has the limit, and it rises each day with no blocked text. | New key |
rate_limited | 429 | Too many requests. Usually a limit on your account: carrier pacing on a send (with retry_after_ms and cap_per_sec), about 120 requests a minute, the 6,000 sends a minute ceiling, or 140 bulk calls a minute. The pages that need no key (OAuth token and sign in steps, opt in pages, media links) answer it per IP. Always in both code and error_code. With no retry_after_ms, wait Retry-After, or a minute. | Same key |
RATE_LIMITED | 429 | Too many requests from this IP, or from your dashboard session. Most answers carry retry_after_seconds. The sign in code limits do not: wait 15 minutes. | Same key |
throughput_exceeded | 429 | Batch over your carrier pace. Nothing sent. Body has retry_after_ms and cap_per_sec. | Same key |
generation_failed | 500 | Writing drafts failed. Refunded, unless error says the credits couldn’t be returned. | New key |
hold_not_returned | 500 | Not sent, but the hold wasn’t returned yet. Support refunds the held amount; you don’t need to do anything. | New key |
reservation_unconfirmed | 500 | Not sent. We hold the price of a text while it sends; this hold comes back to your balance on its own within a few minutes. Check your balance, then retry with a new key. | New key |
internal_error | 500 | Failed on our side. On billed calls (validate, scrub), check your balance before you retry. | Check first |
INTERNAL_ERROR_OUTCOME_UNKNOWN | 500 | A write failed on our side; outcome unknown. Treat a send like 202 send_outcome_unknown. Reads answer INTERNAL_ERROR instead. | No |
server_error | 500 | Failed on our side. | Check first |
send_failed | 500 | Not sent, not charged. Wait a minute and retry with a new key: the same key replays this error. In bulk results, also used when a recipient’s refusal had no code at all: read error. | New key |
tcpa_check_unavailable | 503 | The do-not-call check couldn’t run, so the contact was not checked against any list. Nothing sent, not charged. Try again later. | New key |
ADMISSION_SHED | 503 | Overloaded; nothing done. Wait Retry-After (1 s) and retry. | Same key |
AUTH_CHECK_UNAVAILABLE | 503 | We couldn’t check your key. Nothing ran. | Same key |
carrier_capacity_busy | 503 | Carrier capacity busy. Not sent, not charged. | New key |
consent_check_failed | 503 | Consent check couldn’t run. Not sent, not charged. | New key |
contact_unavailable | 503 | The contact couldn’t be read. Nothing sent. | New key |
gate_check_failed | 503 | Safety check couldn’t run. Not sent, not charged. Branch on error_code: the older code field on this body reads blocklist_unavailable. | New key |
permission_check_unavailable | 503 | We couldn’t check the key’s permissions. Nothing ran. | New key |
provider_busy | 503 | Carrier is limiting our rate. Not sent, not charged. Has Retry-After: 60: retry after that. | New key |
sending_paused | 503 | Sending is paused. Nothing sent, not charged. Try again later. | New key |
throughput_unavailable | 503 | Throughput couldn’t be read. Try again later. | Same key |
ACCESS_CHECK_UNAVAILABLE | 503 | We couldn’t check who is asking. Nothing changed. | Same key |
REQUEST_TIMEOUT_OUTCOME_UNKNOWN | 504 | A write ran over its time limit (30 s for most) and may still go through. This 504 isn’t stored: a retry with the same Idempotency-Key answers 409 idempotency_in_progress until the write finishes, then replays its real result (it never runs the write twice). Check whether it worked (Checking whether a text went out) before you send again with a new key. | Same key |
Registration and vetting
Returned by the /v1/registration endpoints. A send never returns these.
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
payment_processing | 202 | The registration payment is still processing. Try again later. | Same key |
address_incomplete | 400 | Brand address missing a part. One of street, city, state (US brands only), zip. error names what’s missing. | New key |
brand_required_first | 400 | Register first with POST /v1/registration/brand, which includes your first campaign. | New key |
consent_required | 400 | Registration needs boolean "consent": true, not a string. | New key |
ein_name_mismatch | 400 | EIN doesn’t match the business name. The body has title, message, steps, can_override. The code is in error. | New key |
invalid_ein | 400 | US brand: ein isn’t 9 digits (XX-XXXXXXX or XXXXXXXXX), or isn’t a real EIN (a retired prefix or a placeholder). | New key |
invalid_use_case | 400 | Unknown campaign use_case. On a campaign, valid lists the allowed values. | New key |
payment_intent_mismatch | 400 | The payment isn’t for this vetting. The code is in error. | No |
payment_not_completed | 400 | The registration payment didn’t go through (status). | New key |
preferred_area_code_required | 400 | number_choice: "new" without preferred_area_code. The code is in error. | New key |
registration_approved | 400 | An approved registration can’t be cancelled with DELETE /v1/registration/:id. Turn it off with POST /v1/registration/:id/deregister. | No |
payment_not_owned | 403 | The payment belongs to another account. | No |
not_rejected | 404 | Resubmit works only on a rejected registration. | No |
payment_not_found | 404 | No such registration payment on your account. | No |
registration_not_found | 404 | No registration with this id on your account. | No |
already_vetted | 409 | The brand already has this vetting tier or higher. The code is in error. | No |
duplicate_brand | 409 | You already have this brand (existing_reg_id). | No |
duplicate_use_case | 409 | A campaign with this use case exists. Registering your brand created a campaign for you, with the brand’s use case (MIXED when it had none). | No |
needs_transfer_confirm | 409 | Number is on another brand. Resend with "transfer_confirm": true. Not a code: the 409 body has needs_transfer_confirm: true, number, current_brand and message. | New key |
paid_not_filed | 409 | Paid, not filed. Don’t pay again. Send the payment_intent_id from this answer to Confirm registration payment (POST /v1/registration/confirm) and the registration is filed. The code is in error. | No |
duplicate_submission | 429 | Same registration in the last 2 minutes (existing_reg_id). | No |
resubmit_unconfirmed | 500 | Don’t resubmit again yet; poll GET /v1/registration. | Check first |
payment_unknown | 502 | Registration payment unconfirmed. Don’t resubmit; poll GET /v1/registration. | No |
could_not_retrieve_payment_intent | 503 | Vetting payment unchecked. Don’t pay again; retry. Retry the confirm call. The same code with 400 means the payment wasn’t found: contact support. The code is in error. | Same key |
payment_check_unavailable | 503 | We couldn’t check the registration payment. | Same key |
payments_unavailable | 503 | Registration payments are unavailable. Nothing charged. Try again later. The code is in error. | New key |
Buying and releasing numbers
Returned when you buy or release a number.
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
area_code_invalid | 400 | area_code is missing or not 3 digits. | New key |
payment_intent_required | 400 | Buying a number needs payment_intent_id. Related: payment_not_confirmed, payment_not_for_number, payment_not_taken, payment_not_expected. | New key |
PURCHASE_BLOCKED | 402 | Number purchases blocked. Contact support. Unpaid bill or account review. | No |
area_code_unavailable | 409 | Area code out of stock; see alternatives. | New key |
NUMBER_RESERVED | 409 | This number is protected and can’t be released. Contact support to remove it. | No |
payment_intent_already_used | 409 | Each payment_intent_id buys exactly one number. | No |
purchase_in_progress | 409 | Another number purchase is running. Try again later. | New key |
buy_incomplete | 500 | Added but setup unfinished. Don’t rebuy; check GET /v1/numbers. | No |
RELEASE_INCOMPLETE | 500 | The number release didn’t finish. Check GET /v1/numbers/:id. | Check first |
BILLING_CANCEL_FAILED | 502 | Monthly fee not stopped, so nothing released. Try again later. | New key |
checkout_unconfirmed | 502 | Checkout unconfirmed. Check GET /v1/numbers first. | No |
subscription_cancel_failed | 502 | Monthly fee stop unconfirmed, so it was kept. Try again later. | New key |
checkout_unavailable | 503 | Checkout unavailable. Nothing charged. Also availability_check_unavailable, cap_check_unavailable. Try again later. | New key |
Scrub and validate
Returned by the scrub and number-validation endpoints.
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
categories_required | 400 | Scrub categories: categories missing. The code is in error, code and error_code; the sentence is in message. | New key |
invalid_phone | 400 | GET /v1/validate/:phone: path value over 40 characters. A short value that isn’t a number answers 200 with valid: false. | New key |
phones_required | 400 | Validate needs phones: 1 to 1,000 numbers. | New key |
too_many_numbers | 400 | Scrub with more than 1,000 numbers. | New key |
too_many_phones | 400 | Validate with more than 1,000 numbers. | New key |
unknown_category | 400 | Scrub categories: unknown key. Allowed: tcpa, dnc_complainers, federal_dnc, state_dnc. The code is in error. | New key |
validation_in_progress | 429 | The same numbers are already being validated. | Same key |
tcpa_not_configured | 503 | Scrubbing unavailable. Nothing scrubbed or charged. Try again later. | New key |
validation_unavailable | 503 | Number validation isn’t available right now. Nothing charged. Try again later. | New key |
Sub-accounts and resellers
Returned when you act on a sub-account (X-Sub-Account-Id) or set up reseller pricing.
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
invalid_sub_account_id | 400 | X-Sub-Account-Id isn’t a numeric account id. | New key |
sub_account_header_needs_api_key | 400 | X-Sub-Account-Id needs an API key, not OAuth or session. | New key |
sub_account_header_not_supported | 400 | X-Sub-Account-Id works only on /v1 paths. | New key |
terms_required | 400 | Reseller terms aren’t accepted yet. Contact support to set this up. | New key |
reseller_not_approved | 403 | Markup set while reseller setup is in review. With no markup setup at all, the same call answers 403 forbidden. See Sub-accounts. | New key |
sub_account_forbidden | 403 | That account isn’t a sub-account you manage. | No |
sub_account_suspended | 403 | That sub-account is suspended. | No |
sub_account_not_found | 404 | No account has that id. | No |