Workspaces
Sub-accounts / locations. Either a connected platform location or a stand-alone Custom Location.
Sub-accounts / locations. Either a connected platform location or a stand-alone Custom Location.
Every route takes Authorization: Bearer <ACCESS_TOKEN> unless the auth line says otherwise. Ids are numbers. Errors use the shape on the errors page.
| Route | Scope | What it does |
|---|---|---|
GET /v1/workspaces | workspaces.read | List workspaces (sub-accounts / locations) owned by the installer. |
GET /v1/workspaces/{id} | workspaces.read | Fetch a single workspace by id. |
POST /v1/workspaces | workspaces.write | Create a new Custom Location workspace. |
PATCH /v1/workspaces/{id} | workspaces.write | Partially update a workspace. |
DELETE /v1/workspaces/{id} | workspaces.write | Permanently delete a workspace. |
List workspaces
GET https://api.bluereacher.com/v1/workspacesAuth: Bearer access token. Scope: workspaces.read.
List workspaces (sub-accounts / locations) owned by the installer.
Returns the sub-account workspaces owned by the authenticated installer. The top-level "Company" account is excluded — only actual workspaces (Location / Custom Location, etc.) are returned. Each carries its user_type; server-side filtering by user_type is not supported, so clients filter client-side when needed.
Pagination: limit is clamped to [1, 200] (default 50) and page to >= 1 (default 1). To read past the first limit rows, request page=2, page=3, … until page reaches total_pages. Invalid bounds are normalised rather than rejected, and the response pagination object reports the applied page and limit, total_pages, the max_limit (200), the raw requested_page / requested_limit, and a normalized flag that is true when clamping changed a requested value.
Ids: id is the numeric workspace id used by every /workspaces/{id} path and workspace_id field. remote_id is the external platform location id (the location_id in the support articles) for Location workspaces, or a server-generated hex string for Custom Location workspaces.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | number | no | Page size — integer clamped to [1, 200]; default 50. Out-of-range or non-numeric values (0, negative, > 200, non-numeric) are normalised, NOT rejected; the applied bounds are echoed in the response pagination object (limit, max_limit, requested_limit, normalized). |
page | query | number | no | 1-based page number; default 1. Clamped to >= 1 (page=0 becomes 1 and sets normalized). Rows are ordered by id descending, so with limit 200 and total 450 pages 1–3 return the full set. The applied page is echoed in pagination.page, with total_pages and the raw requested_page. |
Request
curl -X GET "https://api.bluereacher.com/v1/workspaces?page=1" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Responses
A 200 reply (OK):
{
"success": true,
"data": [
{
"id": 7,
"remote_id": "4f8a7e1d2c9b3a5f6e0d1",
"source": "Blue Reacher",
"user_id": 42,
"user_type": "Custom Location",
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com",
"meta": {
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com"
},
"allow_contact": "0",
"company_id": null,
"whitelabel_setting_id": 1,
"custom_menu_link_id": null,
"subaccount_action": 0,
"is_token_expired": 0,
"created_at": "2026-05-21T09:14:22.000Z",
"updated_at": "2026-05-21T09:14:22.000Z",
"deleted_at": null
}
],
"pagination": {
"total": 1,
"page": 1,
"limit": 50,
"max_limit": 200,
"total_pages": 1,
"requested_page": null,
"requested_limit": null,
"normalized": false
}
}| Status | When | Message |
|---|---|---|
| 200 | OK | |
| 401 | Missing or invalid token | Invalid or expired access token. |
| 403 | Missing scope | Missing scope(s): workspaces.read. |
Response fields
workspaces: Array of workspaces. Fields:
| Field | Type | Description |
|---|---|---|
id | number | Unique workspace id. Example: 7 |
remote_id | string | Server-generated unique identifier (20-character hex string). Not accepted in the request body — always assigned when the workspace is created. Example: 4f8a7e1d2c9b3a5f6e0d1 |
source | string | Where the workspace came from. Workspaces created via this API have source "Blue Reacher". Example: Blue Reacher |
user_id | number | The installer this workspace belongs to. Example: 42 |
user_type | enum | The workspace type. Workspaces created via this API are always "Custom Location" — "Location" appears for workspaces that originated from a connected platform. Example: Custom Location |
name | string, nullable | Display name. Stored inside meta and surfaced here for convenience. Example: Acme HQ |
address | string, nullable | Street address. From meta. |
phone_number | string, nullable | Primary phone number. From meta. |
email | string, nullable | Primary email. Lowercased. From meta. |
url | string, nullable | Public website. From meta. |
meta | object | Raw meta JSON. The fields above are mirrored here. |
allow_contact | string | "0" or "1" — whether inbound contacts can auto-create here. Defaults to "0". Example: 0 |
company_id | number, nullable | External platform company ID (for Location workspaces). |
whitelabel_setting_id | number, nullable | Identifier of the white-label brand this workspace belongs to. |
custom_menu_link_id | string, nullable | Embedded app menu link ID. |
subaccount_action | number | Bitfield describing the sub-account action state. 0 = default. Example: 0 |
is_token_expired | number, nullable | 1 if the upstream OAuth token for this workspace has expired and needs re-authorization. |
created_at | string (ISO 8601) | When the workspace was created. |
updated_at | string (ISO 8601) | When the workspace was last modified. |
deleted_at | string (ISO 8601), nullable | Set when the workspace has been soft-deleted. null for active records. |
Get workspace
GET https://api.bluereacher.com/v1/workspaces/{id}Auth: Bearer access token. Scope: workspaces.read.
Fetch a single workspace by id.
Returns the workspace. When an inbound webhook is configured for the workspace, the response also includes an inbound_webhook object with the registered url and headers. When no webhook is configured, the field is omitted.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | number | yes | Workspace id. |
Request
curl -X GET "https://api.bluereacher.com/v1/workspaces/7" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Responses
A 200 reply (OK (with inbound webhook configured)):
{
"success": true,
"data": {
"id": 7,
"remote_id": "4f8a7e1d2c9b3a5f6e0d1",
"source": "Blue Reacher",
"user_id": 42,
"user_type": "Custom Location",
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com",
"meta": {
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com"
},
"allow_contact": "0",
"company_id": null,
"whitelabel_setting_id": 1,
"custom_menu_link_id": null,
"subaccount_action": 0,
"is_token_expired": 0,
"created_at": "2026-05-21T09:14:22.000Z",
"updated_at": "2026-05-21T09:14:22.000Z",
"deleted_at": null,
"inbound_webhook": {
"url": "https://your-app.example.com/inbound/messages",
"headers": [
{
"key": "x-webhook-secret",
"value": "your-shared-secret"
},
{
"key": "Authorization",
"value": "Bearer your-token-here"
}
]
}
}
}| Status | When | Message |
|---|---|---|
| 200 | OK (with inbound webhook configured) | |
| 200 | OK (no inbound webhook configured) | |
| 404 | Workspace does not exist or belongs to a different installer | Workspace not found |
Response fields
workspace: The workspace requested. Fields:
| Field | Type | Description |
|---|---|---|
id | number | Unique workspace id. Example: 7 |
remote_id | string | Server-generated unique identifier (20-character hex string). Not accepted in the request body — always assigned when the workspace is created. Example: 4f8a7e1d2c9b3a5f6e0d1 |
source | string | Where the workspace came from. Workspaces created via this API have source "Blue Reacher". Example: Blue Reacher |
user_id | number | The installer this workspace belongs to. Example: 42 |
user_type | enum | The workspace type. Workspaces created via this API are always "Custom Location" — "Location" appears for workspaces that originated from a connected platform. Example: Custom Location |
name | string, nullable | Display name. Stored inside meta and surfaced here for convenience. Example: Acme HQ |
address | string, nullable | Street address. From meta. |
phone_number | string, nullable | Primary phone number. From meta. |
email | string, nullable | Primary email. Lowercased. From meta. |
url | string, nullable | Public website. From meta. |
meta | object | Raw meta JSON. The fields above are mirrored here. |
allow_contact | string | "0" or "1" — whether inbound contacts can auto-create here. Defaults to "0". Example: 0 |
company_id | number, nullable | External platform company ID (for Location workspaces). |
whitelabel_setting_id | number, nullable | Identifier of the white-label brand this workspace belongs to. |
custom_menu_link_id | string, nullable | Embedded app menu link ID. |
subaccount_action | number | Bitfield describing the sub-account action state. 0 = default. Example: 0 |
is_token_expired | number, nullable | 1 if the upstream OAuth token for this workspace has expired and needs re-authorization. |
created_at | string (ISO 8601) | When the workspace was created. |
updated_at | string (ISO 8601) | When the workspace was last modified. |
deleted_at | string (ISO 8601), nullable | Set when the workspace has been soft-deleted. null for active records. |
Create workspace
POST https://api.bluereacher.com/v1/workspacesAuth: Bearer access token. Scope: workspaces.write.
Create a new Custom Location workspace.
Creates a stand-alone Custom Location workspace. The remote_id is generated server-side (a 20-character hex string) and is never accepted in the request body. A new workspace may take a few seconds to become fully active — if a follow-up call returns 404 immediately after creation, retry shortly.
Optionally pass inbound_webhook_url (and inbound_webhook_headers) to register an inbound webhook in the same call. When supplied, the webhook is registered on the workspace so inbound messages can be POSTed straight in. The webhook URL must be an http(s) URL.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
name | body | string | yes | Display name. Max 255 characters. |
address | body | string | no | Stored in meta.address. |
phone_number | body | string | no | Stored in meta.phone_number. |
email | body | string | no | Normalized to lowercase. Stored in meta.email. |
url | body | string | no | Public website URL. Stored in meta.url. |
inbound_webhook_url | body | string | no | Optional. When supplied, an inbound webhook row is created for this workspace so inbound messages can be POSTed to this URL. Must be http(s). |
inbound_webhook_headers | body | array<{key,value}> | no | Optional. Extra headers to forward with each inbound webhook delivery — typically an auth header. Sent as an array of { key, value } objects, e.g. [{ "key": "x-webhook-secret", "value": "abc123" }]. Each entry must include a non-empty key. |
Request
curl -X POST "https://api.bluereacher.com/v1/workspaces" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com",
"inbound_webhook_url": "https://your-app.example.com/inbound/messages",
"inbound_webhook_headers": [
{
"key": "x-webhook-secret",
"value": "your-shared-secret"
},
{
"key": "Authorization",
"value": "Bearer your-token-here"
}
]
}'Responses
A 201 reply (Created.):
{
"success": true,
"data": {
"id": 7,
"remote_id": "4f8a7e1d2c9b3a5f6e0d1",
"source": "Blue Reacher",
"user_id": 42,
"user_type": "Custom Location",
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com",
"meta": {
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com"
},
"allow_contact": "0",
"company_id": null,
"whitelabel_setting_id": 1,
"custom_menu_link_id": null,
"subaccount_action": 0,
"is_token_expired": 0,
"created_at": "2026-05-21T09:14:22.000Z",
"updated_at": "2026-05-21T09:14:22.000Z",
"deleted_at": null,
"inbound_webhook": {
"url": "https://your-app.example.com/inbound/messages",
"headers": [
{
"key": "x-webhook-secret",
"value": "your-shared-secret"
},
{
"key": "Authorization",
"value": "Bearer your-token-here"
}
]
}
}
}| Status | When | Message |
|---|---|---|
| 201 | Created. | |
| 400 | Missing name. | name is required |
| 400 | inbound_webhook_url is not an http(s) URL. | inbound_webhook_url must be an http(s) URL. |
| 400 | inbound_webhook_headers is not an array of { key, value } objects. | inbound_webhook_headers must be an array of { key, value } objects. |
| 400 | inbound_webhook_headers entries are missing a key. | inbound_webhook_headers entries must each include a non-empty key. |
| 200 | Partial success — workspace was created, but the inbound webhook row could not be stored. The presence of the warning field signals partial success; full success returns 201 Created. | |
| 409 | Auto-generated remote_id collided — retry should succeed. | Failed to generate a unique remote_id. Please retry. |
Response fields
workspace: The newly created workspace. Fields:
| Field | Type | Description |
|---|---|---|
id | number | Unique workspace id. Example: 7 |
remote_id | string | Server-generated unique identifier (20-character hex string). Not accepted in the request body — always assigned when the workspace is created. Example: 4f8a7e1d2c9b3a5f6e0d1 |
source | string | Where the workspace came from. Workspaces created via this API have source "Blue Reacher". Example: Blue Reacher |
user_id | number | The installer this workspace belongs to. Example: 42 |
user_type | enum | The workspace type. Workspaces created via this API are always "Custom Location" — "Location" appears for workspaces that originated from a connected platform. Example: Custom Location |
name | string, nullable | Display name. Stored inside meta and surfaced here for convenience. Example: Acme HQ |
address | string, nullable | Street address. From meta. |
phone_number | string, nullable | Primary phone number. From meta. |
email | string, nullable | Primary email. Lowercased. From meta. |
url | string, nullable | Public website. From meta. |
meta | object | Raw meta JSON. The fields above are mirrored here. |
allow_contact | string | "0" or "1" — whether inbound contacts can auto-create here. Defaults to "0". Example: 0 |
company_id | number, nullable | External platform company ID (for Location workspaces). |
whitelabel_setting_id | number, nullable | Identifier of the white-label brand this workspace belongs to. |
custom_menu_link_id | string, nullable | Embedded app menu link ID. |
subaccount_action | number | Bitfield describing the sub-account action state. 0 = default. Example: 0 |
is_token_expired | number, nullable | 1 if the upstream OAuth token for this workspace has expired and needs re-authorization. |
created_at | string (ISO 8601) | When the workspace was created. |
updated_at | string (ISO 8601) | When the workspace was last modified. |
deleted_at | string (ISO 8601), nullable | Set when the workspace has been soft-deleted. null for active records. |
Update workspace
PATCH https://api.bluereacher.com/v1/workspaces/{id}Auth: Bearer access token. Scope: workspaces.write.
Partially update a workspace.
Send any subset of the writable fields. remote_id is not updatable — it ties the workspace to its source system, and changing it would break synchronization.
The inbound webhook can also be managed through this endpoint:
• Send inbound_webhook_url with a new URL to register or change the webhook (creates it if it does not yet exist).
• Send inbound_webhook_headers to update the headers — when omitted the previously stored headers are preserved.
• Send inbound_webhook_url: "" (or null) to remove the webhook entirely.
The response always includes the current inbound_webhook object when one is configured, mirroring Get workspace.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | number | yes | Workspace id. |
user_type | body | enum | no | Must be "Custom Location" (the only workspace type the external API can manage). |
name | body | string | no | Display name. Max 255. |
address | body | string | no | Updates meta.address. |
phone_number | body | string | no | Updates meta.phone_number. |
email | body | string | no | Lowercased. Updates meta.email. |
url | body | string | no | Updates meta.url. |
allow_contact | body | string | no | "0" or "1". |
inbound_webhook_url | body | string | no | Register, change, or clear the inbound webhook URL. Pass "" or null to remove the webhook entirely. Must be http(s) when supplied. |
inbound_webhook_headers | body | array<{key,value}> | no | Replace the stored headers with this list. Sent as [{ "key": "...", "value": "..." }]. Omit to keep the existing headers untouched. |
Request
curl -X PATCH "https://api.bluereacher.com/v1/workspaces/7" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme HQ (renamed)",
"allow_contact": "1",
"inbound_webhook_url": "https://your-app.example.com/inbound/messages",
"inbound_webhook_headers": [
{
"key": "x-webhook-secret",
"value": "your-shared-secret"
}
]
}'Responses
A 200 reply (Updated (with inbound webhook)):
{
"success": true,
"data": {
"id": 7,
"remote_id": "4f8a7e1d2c9b3a5f6e0d1",
"source": "Blue Reacher",
"user_id": 42,
"user_type": "Custom Location",
"name": "Acme HQ (renamed)",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com",
"meta": {
"name": "Acme HQ",
"address": "12 Mayfair St, London",
"phone_number": "+442071234567",
"email": "hq@acme.example.com",
"url": "https://acme.example.com"
},
"allow_contact": "1",
"company_id": null,
"whitelabel_setting_id": 1,
"custom_menu_link_id": null,
"subaccount_action": 0,
"is_token_expired": 0,
"created_at": "2026-05-21T09:14:22.000Z",
"updated_at": "2026-05-21T09:14:22.000Z",
"deleted_at": null,
"inbound_webhook": {
"url": "https://your-app.example.com/inbound/messages",
"headers": [
{
"key": "x-webhook-secret",
"value": "your-shared-secret"
}
]
}
}
}| Status | When | Message |
|---|---|---|
| 200 | Updated (with inbound webhook) | |
| 200 | Updated (webhook unchanged or absent) | |
| 400 | No editable fields provided | No editable fields provided. |
| 400 | inbound_webhook_url is not an http(s) URL. | inbound_webhook_url must be an http(s) URL. |
| 400 | inbound_webhook_headers is not an array of { key, value } objects. | inbound_webhook_headers must be an array of { key, value } objects. |
| 400 | inbound_webhook_headers entries are missing a key. | inbound_webhook_headers entries must each include a non-empty key. |
| 404 | Workspace does not exist or is not owned by the installer | Workspace not found |
Response fields
workspace: The updated workspace. Fields:
| Field | Type | Description |
|---|---|---|
id | number | Unique workspace id. Example: 7 |
remote_id | string | Server-generated unique identifier (20-character hex string). Not accepted in the request body — always assigned when the workspace is created. Example: 4f8a7e1d2c9b3a5f6e0d1 |
source | string | Where the workspace came from. Workspaces created via this API have source "Blue Reacher". Example: Blue Reacher |
user_id | number | The installer this workspace belongs to. Example: 42 |
user_type | enum | The workspace type. Workspaces created via this API are always "Custom Location" — "Location" appears for workspaces that originated from a connected platform. Example: Custom Location |
name | string, nullable | Display name. Stored inside meta and surfaced here for convenience. Example: Acme HQ |
address | string, nullable | Street address. From meta. |
phone_number | string, nullable | Primary phone number. From meta. |
email | string, nullable | Primary email. Lowercased. From meta. |
url | string, nullable | Public website. From meta. |
meta | object | Raw meta JSON. The fields above are mirrored here. |
allow_contact | string | "0" or "1" — whether inbound contacts can auto-create here. Defaults to "0". Example: 0 |
company_id | number, nullable | External platform company ID (for Location workspaces). |
whitelabel_setting_id | number, nullable | Identifier of the white-label brand this workspace belongs to. |
custom_menu_link_id | string, nullable | Embedded app menu link ID. |
subaccount_action | number | Bitfield describing the sub-account action state. 0 = default. Example: 0 |
is_token_expired | number, nullable | 1 if the upstream OAuth token for this workspace has expired and needs re-authorization. |
created_at | string (ISO 8601) | When the workspace was created. |
updated_at | string (ISO 8601) | When the workspace was last modified. |
deleted_at | string (ISO 8601), nullable | Set when the workspace has been soft-deleted. null for active records. |
Delete workspace
DELETE https://api.bluereacher.com/v1/workspaces/{id}Auth: Bearer access token. Scope: workspaces.write.
Permanently delete a workspace.
Permanently deletes the workspace — this is a hard delete and cannot be undone. A subsequent GET / PATCH / DELETE on its id returns 404 Not Found.
Unassign or delete those first, then retry the delete.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | number | yes | Workspace id. |
Request
curl -X DELETE "https://api.bluereacher.com/v1/workspaces/7" \
-H "Authorization: Bearer <ACCESS_TOKEN>"Responses
A 200 reply (Deleted permanently):
{
"success": true,
"message": "Workspace deleted.",
"data": {
"id": 7,
"deleted": true
}
}| Status | When | Message |
|---|---|---|
| 200 | Deleted permanently | |
| 404 | Workspace does not exist or is not owned by the installer | Workspace not found |

