> ## 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.

# Idempotency

> Retry a POST safely. The same Idempotency-Key returns the original response for 24 hours.

`POST /v1/otp/send`, `POST /v1/otp/verify`, and `POST /v1/sms/send` accept an `Idempotency-Key` header (max 255 characters). Replaying the same key within **24 hours** returns the cached status and body instead of sending a second message or charging twice.

Keys are scoped to the workspace that owns the API key. Two customers can send `"1"` without seeing each other's responses.

Official SDKs generate a key for every POST automatically.

```bash theme={null}
curl -X POST https://api.robase.dev/v1/sms/send \
  -H "Authorization: Bearer robe_your_api_key" \
  -H "Idempotency-Key: order-12345-shipped" \
  -H "Content-Type: application/json" \
  -d '{"phone_number":"+2348012345678","message":"Your order #12345 has shipped."}'
```

If the header is omitted, the request is not cached and a network retry can double-charge. Prefer always sending a key (or using an SDK).

A replayed response carries `Idempotent-Replayed: true`.

A key belongs to one request:

* The same key on a different endpoint, or with a different body, returns `422` with `error.type: idempotency_key_reused`. Use a new key for a new request.
* A repeat that arrives while the first request is still running returns `409` with `error.type: request_in_progress`. Retry shortly with the same key.
* Keys longer than 255 characters return `400 validation_error`.

A `500` with `error.type: internal_error` is safe to retry with the **same** key. So is a `429`: rate-limited responses are not kept, so the retry runs again once `Retry-After` has passed.


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