Errors

Every error, across the whole API, uses one envelope, so you can handle failures with a single code path.

Error shape

error envelope
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "The request was invalid.",
    "details": [
      { "path": "declaredNumber", "message": "must be E.164" }
    ]
  }
}

The HTTP status matches the code. details is present only for validation errors.

Error codes

CodeHTTPWhen
UNAUTHORIZED401Missing or invalid key.
FORBIDDEN403The key lacks the required scope.
NOT_FOUND404No such resource on your account.
VALIDATION_FAILED400The request body or query was invalid.
CONFLICT409The action conflicts with current state (e.g. sending from a number that is not connected).
RATE_LIMITED429Too many requests. Slow down and retry.
OUTBOUND_LIMIT429The cold-outbound floor: this number started too many NEW conversations this hour. Replies are never counted. Wait for Retry-After, and keep first-contact volume moderate.
SLOT_REQUIRED402Connecting a number needs a free slot.
ACCOUNT_SUSPENDED402The whole account is on hold. Every route answers this except sign-in and billing. The key is valid and retrying will not help: contact us to restore access.
TRANSPORT_UNAVAILABLE503The connection service is briefly unavailable. Retry shortly.
TRANSPORT_BUSY503The messaging service is busy. Wait for the Retry-After header, then try again; anything already issued stays valid.
BILLING_UNAVAILABLE503This deployment has no payment processor configured.
INTERNAL500An unexpected error on our side.

Backing off

Three codes tell you to wait, and they mean different things. RATE_LIMITED means slow down. OUTBOUND_LIMIT means stop messaging new people for a while - replies still go through, and the budget belongs to the number rather than to your key. TRANSPORT_BUSY means the messaging service is throttling us: it is load, never a defect in your request, and anything already issued stays valid. All three carry Retry-After in seconds where a wait is known; wait at least that long.

429 Too Many Requests
{
  "error": {
    "code": "OUTBOUND_LIMIT",
    "message": "This number has started too many new conversations in the last hour."
  }
}

Validation errors

For a VALIDATION_FAILED error, details lists each offending field by path so you can surface the problem next to the right input.

handling errors
const res = await fetch("https://api.sendveo.com/v1/numbers", options)
if (!res.ok) {
  const { error } = await res.json()
  if (error.code === "VALIDATION_FAILED") {
    for (const d of error.details ?? []) showFieldError(d.path, d.message)
  } else {
    showBanner(error.message)
  }
}
API error codes and envelope · Sendveo docs