# API overview > Send WhatsApp messages from your own software with the ONPAD REST API. > Source: https://onpad.in/docs/api The ONPAD API lets your own software send WhatsApp messages — from your website, your CRM, your order system or a script. It is a small API on purpose. Two resources, JSON in and JSON out, bearer authentication. ## Base URL ```text https://app.onpad.in/api/v1 ``` ## Endpoints | Method | Path | What it does | |---|---|---| | `POST` | `/messages` | [Queue a message](https://onpad.in/docs/api/send-message) for delivery | | `GET` | `/messages?id=` | [Look up a message](https://onpad.in/docs/api/get-message) you sent | | `GET` | `/status` | [Check the connection](https://onpad.in/docs/api/status) and your workspace | A machine-readable [OpenAPI specification](https://onpad.in/docs/openapi.json) is available. Hand it to Codex, Claude or any API client and it will generate correct calls. ## Authentication Every request carries an API key as a bearer token: ```text Authorization: Bearer wh_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` Keys always start with `wh_live_`. There is no sandbox key — see [Testing](#testing) below. ### Getting a key 1. Open **Settings** in your workspace. 2. Find the **API keys** section. 3. Create a key and give it a name you will recognise later. 4. **Copy it immediately.** Only a short prefix is stored afterwards, so the full key is shown once and cannot be retrieved again. Lose it and you create a new one. Keys belong to a workspace, not to a person. A key keeps working after the person who created it leaves. ### Keeping a key safe - Keep it on your server. Never put it in browser JavaScript, a mobile app, or a public repository — anyone holding it can message your customers from your number. - Use a separate key per integration, so revoking one does not break the others. - Revoke a key the moment you suspect it leaked. Revoking is immediate. Every request is logged with its key, method, path, status code and IP address. You can see this under API keys in Settings — useful when you need to know what a key has been doing. ## The API is a plan feature API access is switched on by your plan. If your plan does not include it, every request returns `401 invalid_api_key` — the same response as a bad key, because the API does not reveal which workspaces exist. If your key is definitely correct and you still get 401, check **Plans & billing** first. ## How sending works `POST /messages` does not send the message during the request. It validates everything, stores the message, and returns **`202 Accepted`** with an id. A background worker then delivers it, usually within seconds, and retries on failure: - Up to **3 attempts**. - Backoff of **15s, 30s, 60s**, capped at 5 minutes. - A permanent error — an invalid number, an unapproved template — fails immediately without retrying, because retrying cannot help. Poll `GET /messages?id=` for the outcome, or watch the inbox. This is why validation errors come back instantly as `422` while delivery failures appear later as a `failed` status: everything knowable up front is checked up front. ## Rules that still apply The API does not bypass WhatsApp's rules. Everything in [WhatsApp Business API](https://onpad.in/docs/whatsapp-business-api) still holds: - **Free text only inside the 24-hour window.** `type: "text"` is rejected with `422` if the customer has not messaged you in the last 24 hours. - **Templates must be approved.** Sending an unapproved or non-existent template is a `422`. - **Messaging limits are Meta's.** A send that exceeds them fails at delivery, not at the API. ## Testing There is no sandbox. Keys are live, and a message sent is a message delivered and charged by Meta. To test safely: 1. Send to **your own number** first. 2. Use a template you created for testing. 3. Check the response id, then poll `GET /messages?id=` and watch the status move. ## Conventions **Everything is JSON.** Send `Content-Type: application/json`. A malformed body returns `400 invalid_json`. **Phone numbers go in full international form**, digits only, 8 to 15 of them. `919876543210` is right. `+91 98765 43210` also works — separators are stripped — but `9876543210` without a country code is not, because the API will not guess a country for you. **Timestamps are ISO 8601 with a timezone**, for example `2026-10-04T09:21:33+05:30`. **Every response has an `ok` field.** `true` on success, `false` on error with an `error` code and a human `message`. ## Next - [Send a message](https://onpad.in/docs/api/send-message) — the main endpoint, field by field - [Idempotency](https://onpad.in/docs/api/idempotency) — why every send needs a key, and what it protects you from - [Errors](https://onpad.in/docs/api/errors) — every code the API returns - [Code examples](https://onpad.in/docs/api/examples) — curl, PHP, Node.js and Python