# Bulk Operations API
Perform operations on multiple contacts at once. Bulk endpoints accept an array of contact IDs and apply the action to all of them in a single request.
> [!quote] Scale Your Workflows
> Tag 500 contacts, update a field across your entire book, or clean up duplicates - ==all in one API call.==
## Requirements
All bulk endpoints require:
| Header | Required | Description |
|--------|----------|-------------|
| `Authorization` | Yes | `Bearer rlb_your_key` |
| `Content-Type` | Yes | `application/json` |
| `X-Book-ID` | Yes | UUID of the book |
---
## Bulk Delete Contacts
Delete multiple contacts in a single request.
```
POST /api/v1/contacts/bulk-delete
```
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `contact_ids` | array of UUIDs | Yes | Contact IDs to delete (max 10,000) |
### Example Request
```bash
curl -X POST "https://app.relaybook.io/api/v1/contacts/bulk-delete" \
-H "Authorization: Bearer rlb_your_key" \
-H "Content-Type: application/json" \
-H "X-Book-ID: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
-d '{
"contact_ids": [
"f47ac10b-58cc-4372-a567-0e02b2c3d479",
"b23dc4e5-6789-4abc-def0-123456789abc",
"d34ef5a6-7890-4bcd-ef01-234567890def"
]
}'
```
### Response
```
HTTP/1.1 200 OK
```
```json
{
"data": {
"deleted": 3
}
}
```
> [!note] Permanent deletion
> Deleted contacts cannot be recovered. Related data (labels, interactions, campaign enrollments) is also removed.
### Errors
| Status | Code | Cause |
|--------|------|-------|
| 400 | `MISSING_BOOK` | `X-Book-ID` header is missing |
| 400 | `INVALID_INPUT` | Empty contact_ids or exceeds 10,000 limit |
| 403 | `FORBIDDEN` | Book doesn't belong to your team |
| 500 | `SERVER_ERROR` | Database error |
---
## Bulk Add Label
Add a label to multiple contacts at once. Contacts that already have the label are silently skipped.
```
POST /api/v1/contacts/bulk-add-label
```
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `contact_ids` | array of UUIDs | Yes | Contact IDs to tag |
| `label_id` | UUID | Yes | Label to add |
### Example Request
```bash
curl -X POST "https://app.relaybook.io/api/v1/contacts/bulk-add-label" \
-H "Authorization: Bearer rlb_your_key" \
-H "Content-Type: application/json" \
-H "X-Book-ID: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
-d '{
"contact_ids": ["f47ac10b-58cc-4372-a567-0e02b2c3d479", "b23dc4e5-6789-4abc-def0-123456789abc"],
"label_id": "c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f"
}'
```
### Response
```
HTTP/1.1 200 OK
```
```json
{
"data": {
"added": 2
}
}
```
### Errors
| Status | Code | Cause |
|--------|------|-------|
| 400 | `INVALID_INPUT` | Missing contact_ids or label_id |
| 403 | `FORBIDDEN` | Book doesn't belong to your team |
| 500 | `SERVER_ERROR` | Database error |
---
## Bulk Remove Label
Remove a label from multiple contacts.
```
POST /api/v1/contacts/bulk-remove-label
```
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `contact_ids` | array of UUIDs | Yes | Contact IDs to untag |
| `label_id` | UUID | Yes | Label to remove |
### Example Request
```bash
curl -X POST "https://app.relaybook.io/api/v1/contacts/bulk-remove-label" \
-H "Authorization: Bearer rlb_your_key" \
-H "Content-Type: application/json" \
-H "X-Book-ID: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
-d '{
"contact_ids": ["f47ac10b-58cc-4372-a567-0e02b2c3d479", "b23dc4e5-6789-4abc-def0-123456789abc"],
"label_id": "c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f"
}'
```
### Response
```
HTTP/1.1 200 OK
```
```json
{
"data": {
"removed": 2
}
}
```
### Errors
| Status | Code | Cause |
|--------|------|-------|
| 400 | `INVALID_INPUT` | Missing contact_ids or label_id |
| 403 | `FORBIDDEN` | Book doesn't belong to your team |
| 500 | `SERVER_ERROR` | Database error |
---
## Bulk Update Custom Field
Set a custom field value on multiple contacts. Creates the value if it doesn't exist, updates it if it does.
```
POST /api/v1/contacts/bulk-update-field
```
### Request Body
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `contact_ids` | array of UUIDs | Yes | Contact IDs to update |
| `field_definition_id` | UUID | Yes | Custom field definition to set |
| `value` | string | Yes | Value to apply to all contacts |
### Example Request
```bash
curl -X POST "https://app.relaybook.io/api/v1/contacts/bulk-update-field" \
-H "Authorization: Bearer rlb_your_key" \
-H "Content-Type: application/json" \
-H "X-Book-ID: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
-d '{
"contact_ids": ["f47ac10b-58cc-4372-a567-0e02b2c3d479", "b23dc4e5-6789-4abc-def0-123456789abc"],
"field_definition_id": "fd1a2b3c-d4e5-4f6a-7b8c-9d0e1f2a3b4c",
"value": "https://www.example.com/listing"
}'
```
### Response
```
HTTP/1.1 200 OK
```
```json
{
"data": {
"updated": 2
}
}
```
### Errors
| Status | Code | Cause |
|--------|------|-------|
| 400 | `INVALID_INPUT` | Missing contact_ids or field_definition_id |
| 403 | `FORBIDDEN` | Book doesn't belong to your team |
| 404 | `NOT_FOUND` | Custom field definition doesn't exist in this book |
| 500 | `SERVER_ERROR` | Database error |
---
## Example: Tag and Enroll Contacts in a Campaign
A common workflow - tag a batch of contacts, then enroll them in a drip campaign:
```bash
# 1. Add "New Customer" label to contacts
curl -X POST https://app.relaybook.io/api/v1/contacts/bulk-add-label \
-H "Authorization: Bearer rlb_your_key" \
-H "X-Book-ID: your-book-id" \
-H "Content-Type: application/json" \
-d '{
"contact_ids": ["id-1", "id-2", "id-3"],
"label_id": "new-customer-label-id"
}'
# 2. Set their onboarding URL
curl -X POST https://app.relaybook.io/api/v1/contacts/bulk-update-field \
-H "Authorization: Bearer rlb_your_key" \
-H "X-Book-ID: your-book-id" \
-H "Content-Type: application/json" \
-d '{
"contact_ids": ["id-1", "id-2", "id-3"],
"field_definition_id": "onboarding-url-field-id",
"value": "https://app.example.com/welcome"
}'
# 3. Enroll them in the onboarding campaign
curl -X POST https://app.relaybook.io/api/v1/campaigns/CAMPAIGN_ID/participants \
-H "Authorization: Bearer rlb_your_key" \
-H "X-Book-ID: your-book-id" \
-H "Content-Type: application/json" \
-d '{"contact_ids": ["id-1", "id-2", "id-3"]}'
```
---
## Limits
- Maximum **10,000 contact IDs** per bulk request
- All contacts must belong to the book specified in `X-Book-ID`
- Labels and custom fields must belong to the same book
- Contacts not found in the book are silently skipped
---
**Next:** Set up [[Campaigns|automated email campaigns]] for your contacts, or explore [[Webhooks]] for real-time event notifications.