# 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.