# API Reference
The RelayBook REST API lets you read and write contact data programmatically. Use it to build integrations, sync with external tools, or automate workflows around your team's contacts.
> [!quote] Connect Everything
> Relay stays simple: contacts, collaboration, and an API. ==Everything else connects through the API and webhooks.==
## Base URL
All API requests are made to:
```
https://app.relaybook.io/api/v1
```
## Authentication
The API uses **Bearer token** authentication with API keys. API keys are created from the **Team Dashboard** under **API & Webhooks** and are scoped to your team.
Include your API key in the `Authorization` header of every request:
```
Authorization: Bearer rlb_your_api_key_here
```
> [!note] Key format
> API keys start with `rlb_` followed by a unique string. The full key is only shown once at creation — store it securely.
### Key Security
- API keys grant **full read/write access** to all books in your team
- Keys are stored as irreversible hashes — RelayBook cannot recover a lost key
- Revoked keys stop working immediately and cannot be reactivated
- Rotate keys regularly and never commit them to source control
### Invalid or Missing Key
If the key is missing, invalid, or revoked, the API returns:
```
HTTP/1.1 401 Unauthorized
```
```json
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}
```
A revoked key returns:
```json
{
"error": {
"code": "KEY_REVOKED",
"message": "This API key has been revoked"
}
}
```
## Required Headers
| Header | Required | Description |
|--------|----------|-------------|
| `Authorization` | Always | `Bearer rlb_your_key` |
| `Content-Type` | POST, PATCH | `application/json` |
| `X-Book-ID` | Most endpoints | UUID of the book to operate on |
The `X-Book-ID` header tells the API which book to scope the request to. Most contact and label endpoints require it. Book listing endpoints do not.
## Rate Limiting
The API enforces a **fixed-window rate limit** of **100 requests per minute** per API key.
Every response includes rate limit headers:
| Header | Description |
|--------|-------------|
| `X-RateLimit-Limit` | Maximum requests allowed per window (100) |
| `X-RateLimit-Remaining` | Requests remaining in the current window |
| `X-RateLimit-Reset` | Unix timestamp when the window resets |
When you exceed the limit, the API returns:
```
HTTP/1.1 429 Too Many Requests
Retry-After: 60
```
```json
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 60 seconds."
}
}
```
> [!tip] Handling rate limits
> Check the `X-RateLimit-Remaining` header to monitor your usage. If you hit the limit, wait until the `X-RateLimit-Reset` timestamp before retrying.
## Response Format
All successful responses wrap data in a `data` key:
**Single resource:**
```json
{
"data": {
"id": "uuid",
"first_name": "Jane",
"last_name": "Doe"
}
}
```
**Collection with pagination:**
```json
{
"data": [ ... ],
"meta": {
"page": 1,
"limit": 50,
"total": 142
}
}
```
**Action confirmation:**
```json
{
"data": {
"message": "Label added"
}
}
```
## Error Format
All errors follow a consistent structure:
```json
{
"error": {
"code": "ERROR_CODE",
"message": "A human-readable description of what went wrong"
}
}
```
Validation errors include field-level details:
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"errors": {
"first_name": "At least a name or company is required"
}
}
}
```
### HTTP Status Codes
| Status | Meaning |
|--------|---------|
| `200 OK` | Request succeeded |
| `201 Created` | Resource created successfully |
| `204 No Content` | Resource deleted successfully (no response body) |
| `400 Bad Request` | Missing required header or invalid request body |
| `401 Unauthorized` | Invalid or missing API key |
| `403 Forbidden` | The resource doesn't belong to your team |
| `404 Not Found` | The resource doesn't exist |
| `422 Unprocessable Entity` | Validation failed — check the `errors` object |
| `429 Too Many Requests` | Rate limit exceeded |
| `500 Internal Server Error` | Something went wrong on our end |
### Common Error Codes
| Code | Status | Description |
|------|--------|-------------|
| `UNAUTHORIZED` | 401 | API key is missing or invalid |
| `KEY_REVOKED` | 401 | API key has been revoked |
| `RATE_LIMITED` | 429 | Rate limit exceeded |
| `MISSING_BOOK` | 400 | `X-Book-ID` header is required but missing |
| `FORBIDDEN` | 403 | Book or resource doesn't belong to your team |
| `NOT_FOUND` | 404 | Resource not found |
| `INVALID_INPUT` | 400 | Request body is not valid JSON |
| `VALIDATION_ERROR` | 422 | One or more fields failed validation |
| `SERVER_ERROR` | 500 | Internal server error |
## Pagination
Endpoints that return collections support pagination with query parameters:
| Parameter | Type | Default | Max | Description |
|-----------|------|---------|-----|-------------|
| `limit` | integer | 50 | 200 | Number of items to return |
| `offset` | integer | 0 | — | Number of items to skip |
The response `meta` object contains the total count for building pagination controls:
```json
{
"meta": {
"page": 1,
"limit": 50,
"total": 142
}
}
```
## Data Types
| Type | Format | Example |
|------|--------|---------|
| ID | UUID v4 | `"a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"` |
| Timestamp | ISO 8601 | `"2026-02-18T16:52:56Z"` |
| Date | YYYY-MM-DD | `"1990-03-15"` |
| Boolean | JSON boolean | `true` or `false` |
| Array | JSON array | `[{"label": "work", "value": "
[email protected]"}]` |
## Available Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/v1/contacts` | [[Contacts\|List contacts]] |
| `GET` | `/api/v1/contacts/{id}` | [[Contacts\|Get a contact]] |
| `POST` | `/api/v1/contacts` | [[Contacts\|Create a contact]] |
| `PATCH` | `/api/v1/contacts/{id}` | [[Contacts\|Update a contact]] |
| `DELETE` | `/api/v1/contacts/{id}` | [[Contacts\|Delete a contact]] |
| `GET` | `/api/v1/books` | [[Books & Labels\|List books]] |
| `GET` | `/api/v1/books/{id}` | [[Books & Labels\|Get a book]] |
| `GET` | `/api/v1/books/{id}/labels` | [[Books & Labels\|List labels]] |
| `POST` | `/api/v1/contacts/{id}/labels` | [[Books & Labels\|Add label to contact]] |
| `DELETE` | `/api/v1/contacts/{id}/labels/{lid}` | [[Books & Labels\|Remove label from contact]] |
| `GET` | `/api/v1/campaign-templates` | [[Campaigns\|List campaign templates]] |
| `GET` | `/api/v1/campaign-templates/{id}` | [[Campaigns\|Get a template]] |
| `POST` | `/api/v1/campaign-templates` | [[Campaigns\|Create a template]] |
| `PATCH` | `/api/v1/campaign-templates/{id}` | [[Campaigns\|Update a template]] |
| `DELETE` | `/api/v1/campaign-templates/{id}` | [[Campaigns\|Delete a template]] |
| `GET` | `/api/v1/campaigns` | [[Campaigns\|List campaigns]] |
| `GET` | `/api/v1/campaigns/{id}` | [[Campaigns\|Get a campaign]] |
| `POST` | `/api/v1/campaigns` | [[Campaigns\|Create a campaign]] |
| `PATCH` | `/api/v1/campaigns/{id}` | [[Campaigns\|Update a campaign]] |
| `DELETE` | `/api/v1/campaigns/{id}` | [[Campaigns\|Delete a campaign]] |
| `POST` | `/api/v1/campaigns/{id}/steps` | [[Campaigns\|Create a step]] |
| `POST` | `/api/v1/campaigns/{id}/participants` | [[Campaigns\|Enroll contacts]] |
| `POST` | `/api/v1/contacts/bulk-delete` | [[Bulk Operations\|Bulk delete contacts]] |
| `POST` | `/api/v1/contacts/bulk-add-label` | [[Bulk Operations\|Bulk add label]] |
| `POST` | `/api/v1/contacts/bulk-remove-label` | [[Bulk Operations\|Bulk remove label]] |
| `POST` | `/api/v1/contacts/bulk-update-field` | [[Bulk Operations\|Bulk update custom field]] |
> [!note] Campaign endpoints
> Campaign API endpoints require the **Campaigns add-on** to be enabled for your team. If the add-on is not active, these endpoints return `403 ADDON_REQUIRED`.
## Next Steps
- **[[Contacts]]** - Full endpoint reference for creating, reading, updating, and deleting contacts
- **[[Books & Labels]]** - List books and manage label assignments
- **[[Campaigns]]** - Create and manage email campaigns, templates, and drip sequences
- **[[Bulk Operations]]** - Delete, tag, and update multiple contacts in a single request
- **[[Internal Endpoints]]** - App-level endpoints for campaign management, stats, email settings, and image uploads
- **[[Webhooks]]** - Real-time event notifications with signature verification and retry logic
- **[[Examples & Use Cases]]** - Real-world integration scenarios with sample code
---
**Next:** Start building with the [[Contacts]] endpoint reference, or jump to [[Campaigns]] to set up automated email sequences via the API.