type— machine-readable error code, stable across versions. Switch on this.message— human-readable explanation. Never switch on this; we refine copy over time.field— when the error relates to a specific input field, this tells you which one.
Error type reference
validation_error · 400
validation_error · 400
The request body is malformed or missing a required field.
field tells you which one. Fix: correct the payload and retry.phone_invalid · 400
phone_invalid · 400
SMS only. The Fix: normalize to E.164 before sending. libphonenumber is the standard tool.
to field is not a valid E.164 phone number. Must start with + and contain 8–15 digits.sender_id_invalid · 400
sender_id_invalid · 400
SMS only. Either the sender ID is longer than 11 characters, or it was rejected by carrier compliance (e.g. NCC rejected an NG sender).Fix: register a new compliant sender ID. See Sender IDs.
dnd_blocked · 400
dnd_blocked · 400
SMS only. The destination number is on the Do Not Disturb registry and this sender ID is not on the whitelist for that recipient.Fix: either register the sender for premium routes (contact support), or remove that recipient from your send list. See the DND compliance guide.
authentication_error · 401
authentication_error · 401
The API key is missing, malformed, revoked, or unknown.Fix: double-check the
Authorization: Bearer ... header. Rotate the key if needed.permission_error · 403
permission_error · 403
The key exists but lacks the permission for this endpoint (e.g. a
sending-scoped key can’t hit GET /v1/sms).Fix: use a full-permission key, or scope this operation to a different key.not_found · 404
not_found · 404
The resource you’re fetching doesn’t exist, or doesn’t belong to your project.Fix: verify the ID. Remember that message IDs are UUIDs — not the provider-specific
provider_message_id.conflict · 409
conflict · 409
The action conflicts with current state. E.g. you tried to cancel an SMS that’s already
sent.Fix: re-fetch the resource, check its state, only act if the state permits.idempotency_conflict · 409
idempotency_conflict · 409
Same
Idempotency-Key used with a different request body within 24 hours.Fix: use a new idempotency key, or match the original body exactly.rate_limit_exceeded · 429
rate_limit_exceeded · 429
You’re sending faster than the rate limit allows. The
Retry-After header tells you when to try again.Fix: back off, add jitter. See Rate limits.quota_exceeded · 402
quota_exceeded · 402
Your monthly plan quota is used up AND your wallet has insufficient balance for overage.Fix: top up via Dashboard → Billing, or upgrade your plan.
sms_quota_exceeded · 402
sms_quota_exceeded · 402
Specific to SMS: monthly SMS segment quota used up, wallet empty. Same fix as
quota_exceeded.domain_unverified · 400
domain_unverified · 400
Email only. You tried to send from a domain that isn’t DNS-verified yet.Fix: complete DKIM + SPF + DMARC setup. See Domains.
address_suppressed · 400
address_suppressed · 400
Email only. The recipient is on your project’s suppression list (bounce, complaint, manual add).Fix: remove from suppressions if you have consent to retry — but think twice about it.
upstream_error · 502
upstream_error · 502
One of our upstream carriers is misbehaving. We’ve already retried internally; the message is in the DLQ.Fix: nothing on your end. Monitor the message’s webhooks — we’ll retry the upstream automatically.
internal_error · 500
internal_error · 500
Something went wrong on our side. Our on-call will page.Fix: retry with exponential backoff. If it persists, check status.robase.dev.