Skip to content

All errors share one shape — status is always false, error_code is stable and machine-readable:

{
"status": false,
"error_code": "UNAUTHORIZED",
"description": "Human-readable message"
}

Match on error_code, never on description (wording may change).

HTTPCodeWhen
401UNAUTHORIZEDMissing or unrecognized credentials
401INVALID_TOKENJWT invalid, malformed or revoked
401TOKEN_EXPIREDJWT past expiry
401INVALID_API_KEYAPI key not found or hash mismatch
401API_KEY_INACTIVEAPI key disabled
401API_KEY_EXPIREDAPI key expired
401INVALID_CREDENTIALSWrong username/password
401USER_NOT_ACTIVEAccount suspended or inactive
401IP_NOT_ALLOWEDJWT was issued with an IP restriction and the client IP is not allowed (API keys have no IP allowlist)
401SIGNATURE_REQUIREDKey requires HMAC but signature headers missing
401INVALID_SIGNATUREHMAC signature failed verification
401API_KEY_REQUIREDStrict integration endpoint requires X-API-Key; JWT is not accepted
403FORBIDDENAuthenticated, but route or permission denied
403NO_SMS_ACCESSSMS not configured on the account
403CONFIG_ERRORCredentials incomplete — contact support
403CROSS_TENANT_WORKSPACEX-Workspace-ID names a workspace you don’t own (or deleted)
403NO_MAIN_WORKSPACENo live main workspace — contact support
403WORKSPACE_NOT_AVAILABLETarget workspace deleted — use a live workspace
403INTEGRATION_NOT_ENABLEDLive strict integration sending is not enabled for this workspace
HTTPCodeWhen
400INVALID_BODYMalformed JSON body
400INVALID_PARAMSInvalid query or path parameters
400INVALID_TOMissing, malformed or overlong recipient phone number
400INVALID_MESSAGEMissing/empty message, oversized body or over-10-segment SMS text
400INVALID_SENDERMissing or invalid sender_id (3–11 ASCII alphanumeric characters, not starting with a number)
400INVALID_SENDER_IDStrict integration endpoint received an invalid sender_id
400TOO_MANY_RECIPIENTSOver 100 recipients
400INVALID_MESSAGES/sms/send-individual body has no messages[] entries
400TOO_MANY_MESSAGES/sms/send-individual has over 1000 entries
400IDEMPOTENCY_KEY_REQUIRED/sms/send-individual missing required Idempotency-Key header
400IDEMPOTENCY_KEY_REQUIREDStrict integration request is missing both Idempotency-Key and X-CIO-Idempotency-Key; exactly one is required
400MULTIPLE_IDEMPOTENCY_KEYSStrict integration request sent both sources or repeated either header
400INVALID_IDEMPOTENCY_HEADERStrict endpoint received a legacy or unsupported idempotency header
400INVALID_IDEMPOTENCY_KEYStandard Idempotency-Key is over 128 characters/uses unsupported characters, or Customer.io’s key is not 1–1024 visible ASCII bytes
400INVALID_WORKSPACE_HEADERX-Workspace-ID is not a positive integer
409IDEMPOTENCY_KEY_REUSEDSame Idempotency-Key was used with a different request body
409IDEMPOTENCY_REQUEST_IN_PROGRESSSame Idempotency-Key is still processing; retry later
413REQUEST_TOO_LARGEStrict integration wire body exceeds 32 KiB
415UNSUPPORTED_MEDIA_TYPEStrict integration request is not application/json
422DESTINATION_BLOCKEDDestination is blocked; no SMS or completed claim was created
HTTPCodeWhen
429RATE_LIMIT_EXCEEDEDPer-account rate limit hit
429TOO_MANY_ATTEMPTSLogin/2FA brute-force limit (includes Retry-After)
503RATE_LIMIT_UNAVAILABLEPer-account limiter is temporarily unavailable; retry with the same idempotency key for /sms/send-individual

Details and recommended client behavior: rate limits.

HTTPCodeWhen
404NOT_FOUNDMessage or resource not found
500INTERNAL_ERRORServer-side error
500DB_ERRORSend request could not be queued — atomic rollback, safe to retry
500IDEMPOTENCY_ERRORThe server could not reserve an idempotency key; retry with the same key
503SANDBOX_UNAVAILABLESandbox simulator is not enabled for sk_test_ sends
503QUEUE_UNAVAILABLESMS queue temporarily unavailable; retry shortly
503INTEGRATION_GATE_UNAVAILABLEStrict live access could not be verified; retry with the same key
  • Retry 429 (after a delay) and 500 DB_ERROR (idempotent by design). Do not blind-retry 4xx — fix the request instead.
  • Alert on credit_blocked from balance, and use DLRs for the final outcome of messages already accepted by the API.
  • Re-authenticate on 401 TOKEN_EXPIRED / INVALID_TOKEN if using JWT.
  • Log error_code + description + the request ID from your HTTP client for support escalations.