> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.voicebip.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.voicebip.com/_mcp/server.

# Authentication

> How to authenticate with the Voicebip API using API keys.

Every request to the Voicebip API must include a valid API key in the `Authorization` header using the Bearer scheme.

## API Key Format

Voicebip issues two types of API keys:

| Prefix     | Environment | Description                                          |
| ---------- | ----------- | ---------------------------------------------------- |
| `pk_live_` | Production  | Real calls, real SMS, real billing                   |
| `pk_test_` | Sandbox     | Simulated lifecycle, no charges, no real MNO traffic |

API keys are generated via the [Create API Key](/api-reference/api-keys/create-api-key) endpoint or the [Voicebip Dashboard](https://app.voicebip.com/settings).

> **Warning**
>
> API keys are shown **only once** at creation time. Voicebip stores a bcrypt hash — the plaintext key cannot be retrieved later. If you lose a key, rotate it.

## Making Authenticated Requests

Include your API key in the `Authorization` header:

```bash
curl -X GET "https://api.voicebip.com/v1/agents" \
  -H "Authorization: Bearer pk_live_your_api_key_here"
```

## Base URL

| Environment | Base URL                      |
| ----------- | ----------------------------- |
| Production  | `https://api.voicebip.com/v1` |
| Sandbox     | `https://api.voicebip.com/v1` |

Sandbox mode is activated by your key prefix, not a different base URL. Use a `pk_test_` key against the same `https://api.voicebip.com/v1` endpoint — the API detects the prefix and routes requests through the sandbox pipeline automatically.

All endpoints are versioned under `/v1/`. All timestamps are ISO 8601 UTC. All phone numbers use E.164 format.

## Sandbox Mode

Use a `pk_test_` key to enter sandbox mode automatically. In sandbox mode:

* Agent and number CRUD works identically to production
* Calls and messages simulate the full lifecycle (webhook events fire normally)
* Webhook signatures use real HMAC-SHA256 — your verification code works unchanged
* No real SIP/RTP calls, no real SMPP messages, no billing charges
* Sandbox numbers are provisioned from reserved test pools: `+234800000xxxx` (mobile virtual), `+234100000xxxx` (Lagos DID)

Switch to production by replacing `pk_test_` with `pk_live_` in your `Authorization` header. No other code changes needed.

## Error on Invalid Key

If the API key is missing, malformed, revoked, or expired, the API returns `401 Unauthorized`:

```json
{
  "error_code": "UNAUTHENTICATED",
  "message": "Invalid or missing API key",
  "request_id": "req_abc123def456",
  "documentation_url": "https://docs.voicebip.com/errors/UNAUTHENTICATED"
}
```

## Request IDs

Every API response includes a `request_id` (format: `req_{nanoid}`). Include this when contacting support — it links to the full trace in our observability stack.

## API Key Lifecycle

| Operation | Endpoint                            | Description                                     |
| --------- | ----------------------------------- | ----------------------------------------------- |
| Create    | `POST /v1/api-keys`                 | Returns the raw key (shown once)                |
| List      | `GET /v1/api-keys`                  | Returns key metadata (prefix, label, last used) |
| Rotate    | `POST /v1/api-keys/{key_id}/rotate` | Invalidates old key, returns new key            |
| Revoke    | `DELETE /v1/api-keys/{key_id}`      | Permanently invalidates the key                 |

Key revocation takes effect within 60 seconds (Redis cache TTL).

## Rate Limits

Requests are rate-limited per workspace using a sliding window:

| Tier    | Limit               |
| ------- | ------------------- |
| Starter | 1,000 requests/min  |
| Builder | 5,000 requests/min  |
| Scale   | 20,000 requests/min |

When rate-limited, the API returns `429 Too Many Requests` with a `Retry-After` header indicating seconds until the next allowed request.

```json
{
  "error_code": "RATE_LIMITED",
  "message": "Rate limit exceeded. Retry after 12 seconds.",
  "request_id": "req_xyz789",
  "documentation_url": "https://docs.voicebip.com/errors/RATE_LIMITED"
}
```

## Session Management

These endpoints let you inspect the authenticated identity and revoke all active sessions. All three require a valid API key in the `Authorization` header.

### GET /v1/auth/me

Returns the user and workspace associated with the API key used to make the request. Use this to verify that a key is valid and to retrieve workspace metadata without making a business-logic call.

```bash
curl -X GET "https://api.voicebip.com/v1/auth/me" \
  -H "Authorization: Bearer pk_live_your_api_key_here"
```

**Response — 200 OK**

```json
{
  "user_id": "usr_abc123",
  "email": "owner@example.com",
  "workspace_id": "ws_xyz789",
  "role": "owner",
  "verified": true,
  "created_at": "2024-11-01T09:00:00Z"
}
```

| Field          | Type    | Description                                          |
| -------------- | ------- | ---------------------------------------------------- |
| `user_id`      | string  | Unique ID of the user who owns the workspace         |
| `email`        | string  | Email address of the workspace owner                 |
| `workspace_id` | string  | Workspace ID associated with the API key             |
| `role`         | string  | Role of the user within the workspace (e.g. `owner`) |
| `verified`     | boolean | Whether the owner's email address has been verified  |
| `created_at`   | string  | ISO 8601 UTC timestamp of account creation           |

**Error codes**

| Status | Error code        | Cause                                   |
| ------ | ----------------- | --------------------------------------- |
| 401    | `UNAUTHENTICATED` | Missing or invalid API key              |
| 404    | `NOT_FOUND`       | No user record found for this workspace |

---

### POST /v1/auth/logout-all

Revokes all active sessions for the workspace owner. Internally this increments the token revision counter, which causes every existing JWT issued for this account to be rejected by the API gateway on its next request. The current API key's JWT is also immediately added to the Redis blocklist so invalidation is effective within milliseconds rather than waiting for the cache TTL.

Use this endpoint when responding to a suspected credential compromise or during a planned credential rotation.

No request body is required.

```bash
curl -X POST "https://api.voicebip.com/v1/auth/logout-all" \
  -H "Authorization: Bearer pk_live_your_api_key_here"
```

**Response — 200 OK**

```json
{
  "message": "All sessions have been revoked."
}
```

> **Note**
>
> This endpoint revokes dashboard sessions and JWT-based access. It does not revoke API keys themselves. To invalidate an API key, use `DELETE /v1/api-keys/{key_id}`.

**Error codes**

| Status | Error code        | Cause                                              |
| ------ | ----------------- | -------------------------------------------------- |
| 401    | `UNAUTHENTICATED` | Missing or invalid API key                         |
| 404    | `NOT_FOUND`       | No user record found for this workspace            |
| 500    | `INTERNAL`        | Failed to increment token revision in the database |

---

### POST /v1/auth/delete-account

Permanently deletes the user account and soft-deletes the associated workspace. This operation cannot be undone.

The request body must include the account password as a confirmation step. An incorrect password returns `401 INVALID_PASSWORD` before any deletion takes place.

> **Warning**
>
> This endpoint deletes the user account and triggers workspace deactivation. All agents, numbers, and configuration associated with the workspace will become inaccessible. This cannot be reversed. If you only want to remove a workspace, use `DELETE /v1/workspace` instead.

```bash
curl -X POST "https://api.voicebip.com/v1/auth/delete-account" \
  -H "Authorization: Bearer pk_live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"password": "your-account-password"}'
```

**Request body**

| Field      | Type   | Required | Description                                            |
| ---------- | ------ | -------- | ------------------------------------------------------ |
| `password` | string | Yes      | Current account password, used to confirm the deletion |

**Response — 200 OK**

```json
{
  "message": "Account deleted successfully."
}
```

**Error codes**

| Status | Error code         | Cause                                   |
| ------ | ------------------ | --------------------------------------- |
| 400    | `INVALID_REQUEST`  | Malformed or missing request body       |
| 401    | `UNAUTHENTICATED`  | Missing or invalid API key              |
| 401    | `INVALID_PASSWORD` | The supplied password did not match     |
| 404    | `NOT_FOUND`        | No user record found for this workspace |
| 500    | `INTERNAL`         | Database write failed                   |