Credentials
Per-agent provider, MCP and channel credentials. Writes take a value; reads return metadata only.
On this page
Provider credential metadata and config overrides
/agents/{id}/providers/{providerId}/credentialsMetadata only; stored values never leave the daemon.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
providerIdrequired | string | Provider id in the agent config |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Metadata | ProviderCredentialsResponse | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
providerConfigobject | 3 fields of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defaultModel | string | |||||||
params | array<object> | |||||||
2 fields of | ||||||||
keyrequired | string | |
valuerequired | string |
requestDelayMsErrors 401 · 403 · 404 · 500
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl "http://127.0.0.1:7385/agents/agent-1/providers/anthropic/credentials" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Store a provider API key in the agent
/agents/{id}/providers/{providerId}/credentialStored as provider:{providerId}:apiKey. Values go in, never out. While the agent's credentials envelope is locked (or foreign) on this daemon the write is refused with 409 credentials_locked: a plain write would destroy a sealed value it cannot read, or store a new one unsealed. Unlock the owner identity first, or send replace: true (the owner's override: a locked sealed value is discarded unread, the new value stored plain and sealed once the envelope unlocks, logged as credential_replaced; the response then has replaced: true). replace is refused for key material (crypto:*, 400). A write to an agent locked by a legacy whole-file identity password answers 500 (unlock it with POST …/identity/password/unlock).
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
providerIdrequired | string | Provider id in the agent config |
Request bodyapplication/json · IdentityValueBody · required
| Field | Type | Description |
|---|---|---|
valuerequired | string | |
replace | boolean | Owner override while the agent's credentials envelope is locked on this daemon: a locked sealed value is discarded unread and the new value is stored plain, sealed again on unlock; logged to adf_logs ( |
Responses
| Status | Description | Body | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Stored | ProviderCredentialWriteResponse | ||||||||||||
| ||||||||||||||
Errors 400 · 401 · 403 · 404 · 409 · 500
| 400 | Missing value, or replace on key material | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 409 | Bad value (key material cannot be replaced over the API), or the agent's credentials envelope is locked on this daemon (credentials_locked): unlock the owner identity, or retry with replace: true. A legacy agent locked with a whole-file password answers 409 credentials_locked until POST /agents/{id}/identity/password/unlock | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X PUT "http://127.0.0.1:7385/agents/agent-1/providers/anthropic/credential" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{"value":"sk-…"}'MCP credential metadata by package
/agents/{id}/mcp/credentialsMetadata only.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Query parameters
| Name | Type | Description |
|---|---|---|
npmPackagerequired | string | Package or server name |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Metadata by env key | McpCredentialsResponse | |||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||
Errors 400 · 401 · 403 · 404 · 500
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl "http://127.0.0.1:7385/agents/agent-1/mcp/credentials?npmPackage=@acme/mcp-server" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Store an MCP credential
/agents/{id}/mcp/credentialsStored as mcp:{npmPackage}:{envKey}. Values go in, never out. While the agent's credentials envelope is locked (or foreign) on this daemon the write is refused with 409 credentials_locked: a plain write would destroy a sealed value it cannot read, or store a new one unsealed. Unlock the owner identity first, or send replace: true (the owner's override: a locked sealed value is discarded unread, the new value stored plain and sealed once the envelope unlocks, logged as credential_replaced; the response then has replaced: true). replace is refused for key material (crypto:*, 400). A write to an agent locked by a legacy whole-file identity password answers 500 (unlock it with POST …/identity/password/unlock).
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Request bodyapplication/json · McpCredentialBody · required
| Field | Type | Description |
|---|---|---|
npmPackagerequired | string | Package or server name the credential belongs to |
envKeyrequired | string | |
valuerequired | string | |
replace | boolean | Owner override while the agent's credentials envelope is locked on this daemon: a locked sealed value is discarded unread and the new value is stored plain, sealed again on unlock; logged to adf_logs ( |
Responses
| Status | Description | Body | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Stored | McpCredentialWriteResponse | |||||||||||||||
| |||||||||||||||||
Errors 400 · 401 · 403 · 404 · 409 · 500
| 400 | Missing field, or replace on key material | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 409 | Bad value (key material cannot be replaced over the API), or the agent's credentials envelope is locked on this daemon (credentials_locked): unlock the owner identity, or retry with replace: true. A legacy agent locked with a whole-file password answers 409 credentials_locked until POST /agents/{id}/identity/password/unlock | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X PUT "http://127.0.0.1:7385/agents/agent-1/mcp/credentials" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"npmPackage": "@acme/mcp-server",
"envKey": "ACME_TOKEN",
"value": "…"
}'Channel adapter credential metadata by type
/agents/{id}/adapters/credentialsMetadata only.
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Query parameters
| Name | Type | Description |
|---|---|---|
adapterTyperequired | string | Adapter type |
Responses
| Status | Description | Body | |||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Metadata by env key | AdapterCredentialsResponse | |||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||
Errors 400 · 401 · 403 · 404 · 500
| 400 | Invalid request: missing or malformed field, query parameter or body. A body Fastify cannot parse gets Fastify's own shape (statusCode, code, error, message).bad_requestFST_ERR_CTP_EMPTY_JSON_BODY | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl "http://127.0.0.1:7385/agents/agent-1/adapters/credentials?adapterType=telegram" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN"Store a channel adapter credential
/agents/{id}/adapters/credentialsStored as adapter:{adapterType}:{envKey}. Values go in, never out. While the agent's credentials envelope is locked (or foreign) on this daemon the write is refused with 409 credentials_locked: a plain write would destroy a sealed value it cannot read, or store a new one unsealed. Unlock the owner identity first, or send replace: true (the owner's override: a locked sealed value is discarded unread, the new value stored plain and sealed once the envelope unlocks, logged as credential_replaced; the response then has replaced: true). replace is refused for key material (crypto:*, 400). A write to an agent locked by a legacy whole-file identity password answers 500 (unlock it with POST …/identity/password/unlock).
Path parameters
| Name | Type | Description |
|---|---|---|
idrequired | string | Loaded agent: its id, handle or name. |
Request bodyapplication/json · AdapterCredentialBody · required
| Field | Type | Description |
|---|---|---|
adapterTyperequired | string | |
envKeyrequired | string | |
valuerequired | string | |
replace | boolean | Owner override while the agent's credentials envelope is locked on this daemon: a locked sealed value is discarded unread and the new value is stored plain, sealed again on unlock; logged to adf_logs ( |
Responses
| Status | Description | Body | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 200 | Stored | AdapterCredentialWriteResponse | |||||||||||||||
| |||||||||||||||||
Errors 400 · 401 · 403 · 404 · 409 · 500
| 400 | Missing field, or replace on key material | |
| 401 | Missing or wrong bearer token (unauthorized) | |
| 403 | The request guard refused it: Host header not allowed (host_not_allowed, DNS-rebinding protection) or a browser cross-site request (cross_origin)host_not_allowedcross_origin | |
| 404 | Unknown agent (or the named resource: loop, task, file, …) | |
| 409 | Bad value (key material cannot be replaced over the API), or the agent's credentials envelope is locked on this daemon (credentials_locked): unlock the owner identity, or retry with replace: true. A legacy agent locked with a whole-file password answers 409 credentials_locked until POST /agents/{id}/identity/password/unlock | |
| 500 | Unexpected runtime failure |
Error bodies use the error format.
Example
curl -X PUT "http://127.0.0.1:7385/agents/agent-1/adapters/credentials" \
-H "Authorization: Bearer $ADF_DAEMON_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"adapterType": "telegram",
"envKey": "TELEGRAM_BOT_TOKEN",
"value": "…"
}'