Authentication
The Sendveo API authenticates every request with an API key. Keys are created and revoked in the dashboard under API keys.
API keys
A key is shown in full exactly once, when you create it. Store it securely. Sendveo keeps only a prefix so you can recognise it later. Treat keys like passwords: never commit them to source control or expose them in a browser.
Sending the key
Pass the key in the X-API-KEY header:
curl https://api.sendveo.com/v1/numbers \
-H "X-API-KEY: sv_live_your_key_here"A bearer token is also accepted, if that fits your HTTP client better:
curl https://api.sendveo.com/v1/numbers \
-H "Authorization: Bearer sv_live_your_key_here"Scopes
Each key carries a set of scopes that limit what it can do. Grant only what a given integration needs.
| Scope | Grants |
|---|---|
| numbers:read | List and read numbers. |
| numbers:write | Create, verify, reconnect and disconnect numbers. |
| messages:read | Read stored messages. |
| messages:send | Send messages. |
| messages:manage | React, forward, delete for everyone, and mark a conversation read. |
| chats:read | List and read conversations. |
| chats:manage | Archive, mute, and pull older history. |
| contacts:read | Contact profiles, contact pictures, and the on-WhatsApp lookup. |
| groups:read | List and read groups, and group pictures. |
| groups:manage | Create a group, add and remove members, leave. |
| webhooks:manage | Read and set your relay webhook. |
| *:read | Every read scope at once (a read-only key). |
Read and write are split per area, and contacts:read has no write twin on purpose: Sendveo never writes a contact anywhere. A key issued before a scope existed does not carry it and answers 403 on the routes that need it; the scope cannot be added to it, so issue a new key.
Unauthorized
A missing, revoked, or out-of-scope key returns 401 or 403 with the standard error envelope:
{
"error": {
"code": "UNAUTHORIZED",
"message": "The request was not authenticated."
}
}Account on hold
One refusal is not a key problem at all: a 402 with the code ACCOUNT_SUSPENDED is an account state. The key is valid, its scopes are right, and rotating it or re-running a consent flow changes nothing. While the account is on hold every route answers the same way except sign-in and billing. Contact us to restore access.
{
"error": {
"code": "ACCOUNT_SUSPENDED",
"message": "Your account is on hold. Contact us to restore access."
}
}