# OTPRun > OTPRun sends WhatsApp and Telegram messages and one-time codes through one HTTP API. Messages go out from the customer's own WhatsApp numbers linked to the cloud, so there is no per-message fee. Base URL: https://otprun.com. Everything below is enough to send a message right now. ## Send a message in one request You need an API key that starts with `or_live_`. Send it in the `Authorization: Bearer` header. ``` curl -X POST https://otprun.com/v1/messages \ -H "Authorization: Bearer or_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"to":"+77010000000","text":"Hello from OTPRun"}' ``` - `to`: recipient phone with country code, for example `+77010000000` (spaces, dashes and brackets are ignored; a leading `+` is optional). - `text`: up to 4096 characters, plain text, emoji allowed. - Response `202 Accepted` with the message object; `status` starts as `queued`. - Then poll `GET https://otprun.com/v1/messages/{id}` until `status` is `delivered` or `read` (or `failed`). If your tool can only open links (no POST, no headers), open this URL instead; it does the same thing: ``` https://otprun.com/v1/send?to=%2B77010000000&text=Hello%20from%20OTPRun&api_key=or_live_YOUR_KEY ``` URL-encode `+` as `%2B` and spaces as `%20`. Opening the same link twice within ten minutes sends only once. ## Before the first message 1. `GET https://otprun.com/v1/ping` with the key: returns the project, workspace and scopes. A `401` means the key is wrong. 2. `GET https://otprun.com/v1/slots` with the key: lists the linked WhatsApp numbers. At least one must have `"state": "connected"`, otherwise messages cannot be sent and the API answers `409`. The account owner links a number at https://otprun.com/app/numbers by scanning a QR code or entering a pairing code in WhatsApp → Linked devices. ## Message statuses `queued` → `sending` → `sent` (accepted by WhatsApp servers) → `delivered` (on the recipient's phone) → `read`. `failed` has an `error_code`. `scheduled_at` shows when a queued message goes out; messages to the same recipient are spaced by at least 15 seconds automatically, so several messages in a row are queued, not rejected. ## Common errors All errors are JSON: `{"status": 422, "title": "...", "detail": "human readable reason"}`. Read `detail`, it says what to fix. - `401`: key missing or invalid. Use `Authorization: Bearer or_live_...` (also accepted: `X-API-Key: or_live_...`). - `403`: the key lacks the `messages` scope or the caller IP is not in the key allowlist. - `409`: no connected WhatsApp number in the workspace. - `422`: invalid phone, empty text, or the recipient is not on WhatsApp. - `429`: the recipient already got 20 messages this hour or 100 today, or the key exceeded 600 requests per minute. Respect the `Retry-After` header. ## Documentation - [Full guide for agents and developers](https://otprun.com/llms-full.txt): every endpoint, field and example in one plain-text file. - [API reference](https://otprun.com/docs): interactive OpenAPI reference. - [OpenAPI 3.1 schema](https://otprun.com/openapi.json): machine-readable contract. - [API index](https://otprun.com/v1): JSON list of endpoints. ## Optional - [Verify API](https://otprun.com/llms-full.txt): one-time codes with automatic fallback from WhatsApp to Telegram, code checking, tap-to-verify links. - [Pricing](https://otprun.com/en/pricing): flat price per linked number, unlimited messages. - [Dashboard](https://otprun.com/app): numbers, API keys, message log, webhooks.