Errors

RFC 9457 problem responses and every error code the API returns.

Every failed API call returns application/problem+json as defined by RFC 9457. The type links to the section of this page for the status, title and code name the error, and detail says what to do about it. Quote request_id when you contact jonathan@getwabi.dev; you can also send your own in X-Request-Id.

403 Forbidden
{  "type": "https://getwabi.dev/docs/errors#403",  "title": "scope_missing",  "status": 403,  "detail": "simulate_inbound_message needs the sandbox:write scope; this API key has messages:read.",  "request_id": "5b0e3c7a-…",  "code": "scope_missing",  "required_scope": "sandbox:write",  "scopes": [    "messages:read"  ]}

A 401 also carries WWW-Authenticate: Bearer resource_metadata=…, which MCP clients follow to sign in with OAuth. Over MCP, the same errors come back as tool errors with the code and message.

400 Bad request

CodeMeaning
invalid_jsonThe body (or ?input for GET) is not valid JSON.
invalid_inputThe input failed the op's schema. `issues` lists each problem with its path.
invalid_slugThe name produced no usable slug. Use letters, digits and dashes.
confirm_mismatchA destructive op needs its target's name typed back in `confirm`, and it did not match.
principal_requiredName exactly one team or person to share with or remove.
same_personThe op cannot target yourself (for example transferring ownership to yourself).
no_personNo member of this organization has that email address or id.
invalid_grantCLI sign-in: the device code is unknown or was already used. Run login again.
expired_tokenCLI sign-in: the device code expired before it was approved. Run login again.
access_deniedCLI sign-in: the person declined the request in the browser.

401 Unauthorized

CodeMeaning
unauthorizedNo credential. Send `Authorization: Bearer wabi_…`.
invalid_keyThe API key does not exist or was revoked.
expired_keyThe API key passed its expiry date. Create a new one.
invalid_tokenThe OAuth access token is invalid or expired. Refresh it and retry.

402 Payment required

CodeMeaning
payment_failedStripe declined the charge for a plan change. Ask a human to update the card (get_billing_link) or pay through create_checkout_link.

403 Forbidden

CodeMeaning
forbiddenThe op needs a higher role than this credential has. `required_role` names it.
scope_missingThe API key's scopes do not cover this op. `required_scope` names the scope it needs.
scope_escalationA scoped key tried to create a key with wider scopes than its own.
dashboard_onlyA person does this in the dashboard (inviting members, changing roles); it is not available to keys.
person_requiredOnly a signed-in person can do this, not an API key.
no_organizationThe signed-in user is not a member of the requested organization (or of any).

404 Not found

CodeMeaning
unknown_opNo op has that name. `GET /api/v1` lists them.
not_foundThe account, contact, template, agent or other record is not in this organization, or you cannot see it.

405 Method not allowed

CodeMeaning
method_not_allowedA write op was sent with GET. Use POST.

409 Conflict

CodeMeaning
organization_existsAn organization with that slug already exists.
team_existsA team with that name already exists in this organization.
already_memberThat person is already a member of the organization.
last_ownerAn organization keeps at least one owner: the last owner cannot leave or be demoted.
sandbox_not_provisionedThe organization's sandbox does not exist yet. Call get_sandbox first; it creates it.
already_subscribedThe organization is already on that plan and interval. get_billing shows the subscription.
subscription_activeThe organization already pays for a plan; change it with subscribe or the billing portal.
no_subscriptionThere is no paid subscription to cancel or resume.
checkout_incompleteThe Stripe Checkout session was not paid yet.
already_claimedThat Checkout session is already attached to an organization.

413 Content too large

CodeMeaning
context_too_largeThe context attached to an issue report is over 128 KB.

428 Precondition required

CodeMeaning
authorization_pendingCLI sign-in: the person has not approved the code yet. Poll again after `interval` seconds.

429 Too many requests

CodeMeaning
rate_limitedToo many requests. Wait for `Retry-After` seconds and retry.

500 Internal error

CodeMeaning
internal_errorSomething failed on our side. Retry, and quote `request_id` if it persists.

503 Service unavailable

CodeMeaning
billing_unavailableBilling is not configured on this server yet. Email support to subscribe.

Retrying

  • 4xx errors will fail the same way again until you change the request.
  • 429 and 5xx errors are safe to retry with backoff. A write may have taken effect before a 5xx: read the record back before sending it again.
  • A 402 carries the paid plans and a checkout_url, so an agent can hand a person the fix in one step.

Meta error codes

When Meta refuses or fails a message, the message's timeline and its message.failed event carry Meta's own code. The sandbox returns the same codes. The common ones:

  • 131047: Free-form message outside the 24-hour customer service window. Send an approved template instead.
  • 131026: Undeliverable: the number is not on WhatsApp, blocked the business, or Meta held the message back.
  • 130429, 131056: Rate limited by Meta (throughput or per-recipient pair rate). Retried with backoff.
  • 132000–132999: Template problem: not approved in that language, paused, disabled, or the parameters do not match.
  • 190: The WhatsApp Business Account's access token expired or was revoked. Reconnect the account.