---
title: "Authentication · Zaiped API documentation"
description: "Every request carries the API key in the Authorization header as a bearer token. Keys start with zp_ and are 256 bits of entropy; we store only their SHA-256 hash, so a leaked database does not leak keys."
lang: "en-US"
canonical: "https://zaiped.com/en/developers/docs/auth"
alternate: "https://zaiped.com/developers/docs/auth"
---

# Authentication

Every request carries the API key in the Authorization header as a bearer token. Keys start with zp_ and are 256 bits of entropy; we store only their SHA-256 hash, so a leaked database does not leak keys.

```
Authorization: Bearer zp_...
```

- A missing, unknown or revoked key answers 401 with the same body: the API does not confirm which keys exist.
- An account with no active subscription answers 402 with code subscription_required. There is no free trial: an account subscribes at least one number to open the console. Numbers stay connected; subscribing restores access on the next call.
- Revoking a key in the console takes effect on the next request. Keys have no scopes: one key opens the whole account, so keep one per environment and rotate by creating a new one first.

## Errors

Every non-2xx response is an object with an error field carrying a stable code, an English message and, when useful, details. The code is what your code should branch on.

```
{
  "error": {
    "code": "validation_failed",
    "message": "The request body does not match the schema.",
    "details": { "path": "message.text", "expected": "string", "got": "undefined" },
    "docs": "https://zaiped.com/developers/docs"
  }
}
```

- 400: invalid JSON, a body that does not match the route schema (validation_failed, with the path), or a rule the API enforces before Meta (for example recipient_invalid, meta_window_closed).
- 401 and 402: authentication and entitlement, as above.
- 404: the route does not exist, or the id belongs to another account (we never distinguish the two).
- 429: a Zaiped budget or a Meta rate limit. Read Retry-After and wait.
- 502 and 500: Meta refused in a way we could not translate, or we failed. Retry with backoff.

## Rate limits

Per account: 600 requests per minute, plus a sending budget of 1,000 messages per hour and 5,000 per day. Meta applies its own limits per number on top; those come back as 429 with a meta_ code.