> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zexa.ao/llms.txt
> Use this file to discover all available pages before exploring further.

# Zexa REST API — Overview, Base URL, and Quick Reference

> Base URL, request format, authentication, rate limits, error codes, pagination, and every public endpoint available in the Zexa REST API.

The Zexa REST API gives you programmatic access to every feature available in the Zexa dashboard — send messages across SMS, WhatsApp, Telegram, email, and Slack; manage contacts and contact lists; launch broadcast campaigns; and track delivery status in real time. Every request follows a consistent JSON-based format, making it straightforward to integrate Zexa into any backend stack or automation workflow.

## Base URL

All API requests target the following base URL:

```text theme={null}
https://api.zexa.ao/v1
```

Every endpoint path is appended to this base. For example, to check your account's credit balance:

```bash theme={null}
curl https://api.zexa.ao/v1/credits \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Request Format

Send all request bodies as JSON and include the `Content-Type: application/json` header on every `POST` and `PATCH` request. The API always responds with JSON, regardless of whether the request succeeds or fails.

```bash theme={null}
curl -X POST https://api.zexa.ao/v1/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"channel": "sms", "to": "+244912345678", "from": "ZEXA", "body": "Hello!"}'
```

## Authentication

Every request must include your API key as a Bearer token in the `Authorization` header:

```text theme={null}
Authorization: Bearer YOUR_API_KEY
```

Generate API keys in your dashboard under **Settings → API Keys**. See the [Authentication](/api/authentication) page for full details, key rotation guidance, and security best practices.

## Rate Limits

The API enforces per-account rate limits to ensure fair usage across all customers. When you exceed your limit, the API returns a `429 Too Many Requests` response. Implement exponential backoff in your retry logic — wait a short interval after the first failure, then double the wait time on each subsequent retry before trying again.

<Tip>
  The `Retry-After` response header on a 429 response indicates the number of seconds to wait before retrying.
</Tip>

## Error Responses

All errors return a consistent JSON body so you can handle them uniformly in your code:

```json theme={null}
{
  "error": "invalid_request",
  "message": "The 'to' field must be in E.164 format.",
  "details": { "field": "to", "value": "912345678" },
  "request_id": "req_abc123"
}
```

| Field        | Description                                                              |
| ------------ | ------------------------------------------------------------------------ |
| `error`      | A machine-readable error code string                                     |
| `message`    | A human-readable description of what went wrong                          |
| `details`    | Additional context, such as the invalid field and value                  |
| `request_id` | Unique identifier for the request — include this when contacting support |

## HTTP Status Codes

The API uses standard HTTP status codes to indicate the outcome of each request.

| Code  | Meaning                                                              |
| ----- | -------------------------------------------------------------------- |
| `200` | Success                                                              |
| `201` | Resource created                                                     |
| `204` | Success — no content (e.g. DELETE requests)                          |
| `400` | Bad request — malformed syntax or missing required fields            |
| `401` | Unauthorized — API key is missing or invalid                         |
| `404` | Resource not found                                                   |
| `422` | Unprocessable entity — request was well-formed but failed validation |
| `429` | Rate limit exceeded                                                  |
| `500` | Internal server error — try again later                              |

## Pagination

All list endpoints support cursor-based pagination via the `page` and `per_page` query parameters. The default page size is `50`; the maximum is `100`.

```bash theme={null}
curl "https://api.zexa.ao/v1/contacts?page=2&per_page=25" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Every paginated response wraps results in a `data` array alongside a `meta` object:

```json theme={null}
{
  "data": [ ],
  "meta": {
    "total": 340,
    "page": 2,
    "per_page": 25
  }
}
```

Use `meta.total` together with `per_page` to calculate the number of pages and determine when you have retrieved all records.

## Endpoint Reference

The table below lists every public endpoint in the Zexa REST API and where it is documented.

| Method   | Endpoint          | Description                                 | Reference                             |
| -------- | ----------------- | ------------------------------------------- | ------------------------------------- |
| `POST`   | `/messages`       | Send a single message on any channel        | [Messages](/api/messages)             |
| `GET`    | `/messages/{id}`  | Retrieve a message and its delivery status  | [Messages](/api/messages)             |
| `GET`    | `/sender-ids`     | List your registered Sender IDs             | [Messages](/api/messages)             |
| `POST`   | `/campaigns`      | Create and launch a broadcast campaign      | [Campaigns](/api/campaigns)           |
| `GET`    | `/campaigns`      | List all campaigns                          | [Campaigns](/api/campaigns)           |
| `GET`    | `/campaigns/{id}` | Retrieve campaign status and delivery stats | [Campaigns](/api/campaigns)           |
| `POST`   | `/contacts`       | Add or import a contact                     | [Contacts](/api/contacts)             |
| `GET`    | `/contacts`       | List and search contacts                    | [Contacts](/api/contacts)             |
| `DELETE` | `/contacts/{id}`  | Permanently remove a contact                | [Contacts](/api/contacts)             |
| `POST`   | `/webhooks`       | Register a delivery-status webhook          | [Webhooks](/api/webhooks)             |
| `GET`    | `/credits`        | Check your current credit balance           | [Authentication](/api/authentication) |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/api/authentication">
    Generate your API key and learn how to pass it securely in every request.
  </Card>

  <Card title="Send a Message" icon="message" href="/api/messages">
    Send your first message across any supported channel with a single API call.
  </Card>

  <Card title="Campaigns" icon="megaphone" href="/api/campaigns">
    Broadcast messages to entire contact lists using the Campaigns API.
  </Card>

  <Card title="Contacts" icon="address-book" href="/api/contacts">
    Build and manage your recipient database programmatically.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/api/webhooks">
    Receive real-time delivery status events pushed directly to your server.
  </Card>

  <Card title="Sender IDs" icon="id-card" href="/messaging/sender-ids">
    Register and manage the Sender IDs used to identify your messages.
  </Card>
</CardGroup>
