API Keys
Overview
You can authorize your access using the API keys. All API keys have the same permissions and full account access if not linked to an agent. You can optionally link an API key to an agent in the same workspace. When a key is linked:
- Authorization identifies the agent for actions related to conversations and messages.
- The API key access is limited to the Agent+ role permissions.
See Agent API keys for how to create one and what changes when a key is linked.
The API key can be added to the ‘authorization’ request header to authorize the request. Each API key has the following fields:
API key object
Each API key has the following fields
| Attributes | Type | Description |
|---|---|---|
id | string | The unique ID of the API key. |
label | string | The label for this API key. May be duplicate with other labels. |
key | string | The API key. The key is prefixed with |
createdAt | string | The timestamp when this instance was created. |
agentId | string | The ID of the agent if the key is linked to an agent. |
In JSON Format
{
"workspaceId": 12,
"id": "67642054b6cc2888638e4600",
"key": "bcak_******************************",
"label": "Dev API Key",
"createdAt": "2024-12-19T13:32:04.009Z",
"agentId": "507f1f77bcf86cd799439011"
}GraphQL requests with an API key
Server-to-server calls to POST https://gateway.bcrumbs.net/core/gq must include:
- The raw API key in the
Authorizationheader (notBearer …). Keys are prefixed withbcak_. workspaceIdinsidevariables.input(for examplevariables.input.workspaceId).workspaceIdas a JSON number (for example1255, not"1255").
Workspace API keys (not linked to an agent) can call conversation read queries such as convs, conv, convLastMessage, and openConversationsNeedResponseCount without a browser session. Agent-linked keys are scoped to Agent+ permissions.
Example — unread conversations count:
curl -s -X POST 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: bcak_YOUR_API_KEY' \
-H 'content-type: application/json' \
--data-raw '{"query":"query($input: OpenConversationsNeedResponseInput!) { openConversationsNeedResponseCount(input: $input) }","variables":{"input":{"workspaceId":12}}}'Common authentication errors:
| Message | Likely cause |
|---|---|
Your request does not have workspaceId in GraphQL variables | Missing variables.input.workspaceId |
Invalid API key | Wrong or revoked secret (do not use the key record id) |
You do not have permission to access this resource using that API key | workspaceId does not match the workspace that owns the key |
Your token is invalid or expired | Bearer token path was used instead of a raw API key |
Generate API Key API
This endpoint lets you generate an API key.
To get your first API key, visit API Keys in the dashboard, choose a label, then save.
| Attributes | Type | Description |
|---|---|---|
workspaceId | number | The workspace ID. |
label | string | Required. The label to assign to this API key. It may be duplicated with other labels. |
agentId | ID | Optional. If set, the key is linked to this agent in the workspace. The agent must exist and belong to |
Request & Response
POST https://gateway.bcrumbs.net/core/gqmutation genApiKey($input: ApiKeyGenInput!) {
genApiKey(input: $input) {
workspaceId
id
key
label
createdAt
agentId
}
}
input ApiKeyGenInput {
workspaceId: Int!
label: String!
agentId: ID
}The mutation above returns JSON structured like this:
{
"data": {
"genApiKey": {
"workspaceId": 12,
"id": "67642054b6cc2888638e4600",
"key": "bcak_******************************",
"label": "Dev API Key",
"createdAt": "2024-12-19T13:32:04.009Z",
"agentId": "507f1f77bcf86cd799439011"
}
}
}Programming language examples
curl 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: API-KEY' \
-H 'content-type: application/json' \
--data-raw $'{"operationName":"genApiKey","variables":{"input":{"label":"Dev API Key","workspaceId":12}},"query":"mutation genApiKey($input: ApiKeyGenInput!) {\\n genApiKey(input: $input) {\\n workspaceId\\n id\\n key\\n label\\n createdAt\\n }\\n}"}'Agent API keys
An agent API key is an API key linked to an agent of the same workspace. Requests authorized with it act as that agent instead of acting as the whole workspace, which is what you want for a backend service, an automated responder, or an external system that should appear as a single agent identity in Inbox.
There are two ways to get one:
- Link a key to an agent that already exists — call
genApiKeywithagentId(see below). - Create the agent and its key in one call — call
createAgentWithApiKeywhen the agent does not exist yet. This is the right choice for API-only agents that never sign in to the portal.
Both paths produce the same kind of key. The raw secret (prefixed with bcak_) is returned only in the response that creates it, so store it immediately.
Link a key to an existing agent
Step 1 — Get the agent ID. List the workspace agents and pick the one the key should act as. You can filter by email, name, or surname. See List Agents API.
curl -s -X POST 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: API-KEY' \
-H 'content-type: application/json' \
--data-raw '{"operationName":"agents","variables":{"input":{"workspaceId":12,"email":"[email protected]"}},"query":"query agents($input: AgentsInput!) {\n agents(input: $input) {\n nodes {\n id\n name\n surname\n email\n }\n }\n}"}'Step 2 — Generate the key with agentId. Pass the agent ID from the previous step in input.agentId.
curl -s -X POST 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: API-KEY' \
-H 'content-type: application/json' \
--data-raw '{"operationName":"genApiKey","variables":{"input":{"workspaceId":12,"label":"Support bot key","agentId":"507f1f77bcf86cd799439011"}},"query":"mutation genApiKey($input: ApiKeyGenInput!) {\n genApiKey(input: $input) {\n workspaceId\n id\n key\n label\n agentId\n createdAt\n }\n}"}'{
"data": {
"genApiKey": {
"workspaceId": 12,
"id": "67642054b6cc2888638e4600",
"key": "bcak_******************************",
"label": "Support bot key",
"agentId": "507f1f77bcf86cd799439011",
"createdAt": "2024-12-19T13:32:04.009Z"
}
}
}The agent must belong to the same workspaceId and must not be deleted, otherwise the mutation fails with Target agent does not exist. Generating API keys requires the MANAGE_WORKSPACE permission, so the calling key or session must be an Owner/Admin one — an agent API key cannot create other API keys.
Step 3 — Use the key. Send the raw secret in the Authorization header and keep workspaceId in the GraphQL variables, exactly like a workspace key:
curl -s -X POST 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: bcak_YOUR_AGENT_API_KEY' \
-H 'content-type: application/json' \
--data-raw '{"query":"query($input: ConvsInput!) { convs(input: $input) { nodes { id assigneeId } } }","variables":{"input":{"workspaceId":12}}}'The response contains only the conversations that agent is allowed to see.
Create the agent and the key together
When there is no agent yet, one mutation creates both. userId and email are optional: omit them for an API-only agent, or pass an email that is invited to the workspace so the agent gets linked to that user once the user accesses the workspace.
mutation createAgentWithApiKey($input: AgentCreateWithApiKeyInput!) {
createAgentWithApiKey(input: $input) {
agent {
id
name
surname
}
apiKey {
id
key
label
agentId
}
}
}{
"input": {
"workspaceId": 12,
"name": "Support",
"surname": "Bot",
"apiKeyLabel": "Support bot key"
}
}See Create agent with API key for the full field list and defaults.
What changes when a key is linked to an agent
| Behavior | Workspace key (no agentId) | Agent API key |
|---|---|---|
| Identity of the caller | The API key label | The linked agent (name, email) |
| Permission ceiling | Full workspace access | The Agent+ role |
convs, conv, messages, convLastMessage, openConversationsNeedResponseCount | All conversations in the workspace | Only conversations assigned to that agent, plus unassigned ones |
Conversation mutations such as addMessage, assignConv, endConv, patchConv, tagConv | Any conversation | Only conversations assigned to that agent, plus unassigned ones |
Reports (agentsReport) | Allowed | Rejected, it needs MANAGE_CONVS |
Workspace administration (genApiKey, createAgent, patchWorkspaceSettings) | Allowed | Rejected, it needs MANAGE_WORKSPACE |
Role mutations (assignOwner, assignUserRole) and deleteWorkspace | Rejected | Rejected |
Endpoints that require more than Agent+ fail with You do not have permission to access this resource with your current role assignment.
Client reads (clients, client) work with both kinds of key and contact details are not masked, because Agent+ includes the MANAGE_CLIENTS permission. Messages sent with an agent API key are attributed to the linked agent, so the agent shows up in reports and in the conversation timeline like any other agent.
Create an agent API key from the portal
- Open API Keys and click Add New API Key.
- Type a Label.
- Choose the agent in Linked agent. Keep None (workspace-wide key) for a key with full workspace access.
- Save. The key and the workspace ID are shown once — click Copy details and store them securely.
The Linked agent column of the API Keys list shows which agent each key acts as, and a dash for workspace-wide keys. To create the agent and its key at the same time, use the API key agent option on the Agents page — see Agents in the portal.
List API Keys API
This endpoint returns API keys for a specific workspace.
| Parameter | Type | Description |
|---|---|---|
workspaceId | number | The workspace ID. |
label | string | Optional. Filter by label. |
Request & Response
POST https://gateway.bcrumbs.net/core/gqquery apiKeys($input: ApiKeysInput!) {
apiKeys(input: $input) {
nodes {
workspaceId
id
label
createdAt
agentId
}
}
}
input ApiKeysInput {
workspaceId: Int!
label: String
}The query above returns JSON structured like this:
{
"data": {
"apiKeys": {
"nodes": [
{
"workspaceId": 12,
"id": "67642054b6cc2888638e4600",
"label": "Dev API Key",
"createdAt": "2024-12-19T13:32:04.009Z",
"agentId": "507f1f77bcf86cd799439011"
}
]
}
}
}Programming language examples
curl 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: API-KEY' \
-H 'content-type: application/json' \
--data-raw $'{"operationName":"apiKeys","variables":{"input":{"workspaceId":12}},"query":"query apiKeys($input: ApiKeysInput!) {\\n apiKeys(input: $input) {\\n nodes {\\n workspaceId\\n id\\n key\\n label\\n createdAt\\n }\\n }\\n}"}'Delete API Key API
This endpoint lets you delete an API key.
| Parameter | Type | Description |
|---|---|---|
workspaceId | number | The workspace ID. |
id | string | The ID of the API key to delete. |
Request & Response
POST https://gateway.bcrumbs.net/core/gqmutation deleteApiKey($input: ApiKeyDeleteInput!) {
deleteApiKey(input: $input) {
workspaceId
id
label
createdAt
agentId
}
}
input ApiKeyDeleteInput {
workspaceId: Int!
id: ID!
}The mutation above returns JSON structured like this:
{
"data": {
"deleteApiKey": {
"workspaceId": 12,
"id": "67642054b6cc2888638e4600",
"key": "e108d6e3-****-****-****-************",
"label": "Dev API Key",
"createdAt": "2024-12-19T13:32:04.009Z",
"agentId": "507f1f77bcf86cd799439011"
}
}
}Programming language examples
curl 'https://gateway.bcrumbs.net/core/gq' \
-H 'authorization: API-KEY' \
-H 'content-type: application/json' \
--data-raw $'{"operationName":"deleteApiKey","variables":{"input":{"id":"6764755e282eb541bb8c9ec9","workspaceId":12}},"query":"mutation deleteApiKey($input: ApiKeyDeleteInput!) {\\n deleteApiKey(input: $input) {\\n workspaceId\\n id\\n key\\n label\\n createdAt\\n }\\n}"}'MCP Server
To connect external AI clients (Codex, Claude Desktop, Claude Code, Cursor) to Bread Crumbs conversation tools over the Model Context Protocol, put your raw API key in the Authorization header (no Bearer prefix) together with your workspace ID. See the MCP Server integration guide for endpoint URLs, required headers, and client configuration examples.