> ## Documentation Index
> Fetch the complete documentation index at: https://docs.robase.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> For chatbots and coding agents, start at /guides/ai-agents.
> Hosted MCP: POST https://api.robase.dev/mcp (Streamable HTTP). Auth: Authorization: Bearer robe_… or robe_agent_….
> Phase 1 tools: get_pricing, send_otp, verify_otp, get_otp, send_sms, get_sms. No payment or top-up tools.
> Call get_pricing; treat listed:true as marketed markets (NG, GH, KE, ZA, GB, BJ, CI, US). Do not invent countries or delivery percentages.
> Prefer OTP-shaped tests such as "Your Robase test OTP is 123456". Do not send Hello or Good morning as tests. Match errors on error.type.

# Errors

> A stable error.type plus prose in error.message. Match on type, never on message.

Failures use one envelope:

```json theme={null}
{
  "error": {
    "type": "insufficient_credits",
    "message": "insufficient credit balance"
  }
}
```

`error.type` is stable and never translated. `error.message` is prose: it follows the workspace language, or `Accept-Language: en` / `fr` on that request. `Accept-Language` does not change the SMS body.

## Types

| Type | HTTP | Meaning |
| - | - | - |
| `validation_error` | 400 | Malformed body or missing field |
| `invalid_phone` | 400 | Not valid E.164 |
| `country_not_supported` | 400 | No SMS route for that destination |
| `unauthorized` | 401 | Missing, malformed, or unknown API key |
| `insufficient_credits` | 402 | Balance below the cost of this send. Rejections are counted, and the workspace is emailed a digest of them. Top up or enable auto top-up under [Billing](https://robase.dev/app/billing). Agents have no payment tool. |
| `kyc_required` | 403 | Workspace is on a KYB hold; sends are refused until the pack is approved |
| `account_temporarily_restricted` | 403 | 48h antispam pause (warning-ban). Do not retry sends until it lifts. |
| `insufficient_scope` | 403 | The API key lacks the scope this endpoint or tool needs; `error.required_scope` names it. See [scopes](/concepts/authentication#scopes). |
| `prefix_blocked` | 403 | Sending to this number range is blocked for your workspace after unusual traffic (see [SMS pumping](/concepts/rate-limits#sms-pumping-protection)). Contact support. |
| `content_blocked` | 403 | `/v1/sms/send` from a new workspace: the message reads as non-transactional. Not sent, not charged. Send only transactional content. A workspace stays new until it is old enough, has enough message history and has enough SMS already sent. A recent spam block makes it new again. |
| `country_not_enabled` | 403 | The destination country is not turned on for your workspace. Returned only where country permissions are enforced. |
| `otp_not_found` | 404 | No OTP with that id in this workspace |
| `sms_not_found` | 404 | No SMS with that id in this workspace |
| `otp_expired` | 409 | Code past TTL |
| `otp_already_verified` | 409 | Already accepted |
| `max_attempts_exceeded` | 409 | Verify budget burned |
| `request_in_progress` | 409 | A request with this `Idempotency-Key` is still running; retry shortly with the same key |
| `idempotency_key_reused` | 422 | This `Idempotency-Key` was used for a different request; use a new key |
| `rate_limited` | 429 | See [rate limits](/concepts/rate-limits) |
| `internal_error` | 500 | Unexpected failure; retry with the same `Idempotency-Key` |
| `screening_unavailable` | 503 | `/v1/sms/send` from a new workspace: the content check failed. Not sent, not charged. Retry after `Retry-After`. |

A **wrong OTP code** with attempts remaining is not an error: `200` with `valid: false`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.