English
Connections
Routes are relative to <PUBLIC_BASE_URL>; request and response bodies are JSON unless stated otherwise. Authentication, scopes, pagination and the error format are described in the REST API guides.
GET /api/v1/credentials
List my connections
The member’s connections, then the organisation’s. Without type, every manageable type; with it, one type, OAuth accounts included (read-only). Never a secret.
Access — Member session or API key with scope connections:read.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
type | query | "http_generic" | "imap" | "llm_provider" | "gmail_oauth" | "msgraph_oauth" | string | no |
Responses
200 — The connections.
| Field | Type | Required |
|---|---|---|
items | object[] | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"type": {
"anyOf": [
{
"type": "string",
"enum": [
"http_generic",
"imap",
"llm_provider",
"gmail_oauth",
"msgraph_oauth"
]
},
{ "type": "string" }
]
},
"name": { "type": "string" },
"scope": { "type": "string", "enum": [ "member", "org" ] },
"kind": { "type": "string", "enum": [ "apiKey", "bearer", "basic", "query" ] },
"integration": { "type": "string" },
"hint": { "type": "string", "maxLength": 4 },
"environment": { "type": "string" },
"capabilities": { "type": "array", "items": { "type": "string" } },
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
}
},
"required": [ "id", "type", "name", "scope", "createdAt", "updatedAt" ],
"additionalProperties": false
}
}
},
"required": [ "items" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — credential.bad_request. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
POST /api/v1/credentials
Create a connection
Stores the secret encrypted and returns only its id. scope: "org" is reserved to administrators. Refused when the instance has no encryption key.
Access — Member session or API key with scope connections:write.
Request body (application/json)
Type : object
JSON Schema
json
{
"anyOf": [
{
"type": "object",
"properties": {
"type": { "type": "string", "const": "http_generic" },
"name": { "type": "string", "minLength": 1, "maxLength": 80 },
"scope": { "type": "string", "enum": [ "member", "org" ] },
"data": {
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "apiKey" },
"headerName": { "type": "string", "minLength": 1, "maxLength": 128 },
"value": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "headerName", "value" ],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "bearer" },
"token": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "token" ],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "basic" },
"username": { "type": "string", "minLength": 1, "maxLength": 256 },
"password": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "username", "password" ],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "query" },
"paramName": { "type": "string", "minLength": 1, "maxLength": 128 },
"value": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "paramName", "value" ],
"additionalProperties": false
}
]
}
},
"required": [ "type", "name", "scope", "data" ]
},
{
"type": "object",
"properties": {
"type": { "type": "string" },
"name": { "type": "string", "minLength": 1, "maxLength": 80 },
"scope": { "type": "string", "enum": [ "member", "org" ] },
"data": {
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": { "type": "string" }
}
},
"required": [ "type", "name", "scope", "data" ]
}
]
}Responses
201 — The id of the connection.
| Field | Type | Required |
|---|---|---|
id | string (uuid) | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
}
},
"required": [ "id" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
This operation accepts an Idempotency-Key header: replaying the same request with the same key returns the original response instead of acting twice. See Idempotency.
Error codes — credential.bad_request, credential.admin_required, credential.encryption_disabled. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
Example request
json
{
"type": "http_generic",
"name": "CRM API",
"scope": "member",
"data": { "kind": "bearer", "token": "crm_live_example_token" }
}Example response (201)
json
{ "id": "0192f1c2-3b4d-7e8f-9a0b-1c2d3e4f5a6b" }PUT /api/v1/credentials/{id}
Rename or replace a connection
Without data, the secret is kept (a plain rename). With it, the secret is replaced entirely, never merged. A connection outside the member’s scope is a 404, never a 403.
Access — Member session or API key with scope connections:write.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Request body (application/json)
| Field | Type | Required |
|---|---|---|
name | string | no |
data | object | no |
JSON Schema
json
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 80 },
"data": {
"anyOf": [
{
"oneOf": [
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "apiKey" },
"headerName": { "type": "string", "minLength": 1, "maxLength": 128 },
"value": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "headerName", "value" ],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "bearer" },
"token": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "token" ],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "basic" },
"username": { "type": "string", "minLength": 1, "maxLength": 256 },
"password": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "username", "password" ],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"kind": { "type": "string", "const": "query" },
"paramName": { "type": "string", "minLength": 1, "maxLength": 128 },
"value": { "type": "string", "minLength": 1, "maxLength": 4096 }
},
"required": [ "kind", "paramName", "value" ],
"additionalProperties": false
}
]
},
{
"type": "object",
"propertyNames": { "type": "string" },
"additionalProperties": { "type": "string" }
}
]
}
}
}Responses
200 — The connection, updated.
| Field | Type | Required |
|---|---|---|
credential | object | yes |
JSON Schema
json
{
"type": "object",
"properties": {
"credential": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
},
"type": {
"anyOf": [
{
"type": "string",
"enum": [
"http_generic",
"imap",
"llm_provider",
"gmail_oauth",
"msgraph_oauth"
]
},
{ "type": "string" }
]
},
"name": { "type": "string" },
"scope": { "type": "string", "enum": [ "member", "org" ] },
"kind": { "type": "string", "enum": [ "apiKey", "bearer", "basic", "query" ] },
"integration": { "type": "string" },
"hint": { "type": "string", "maxLength": 4 },
"environment": { "type": "string" },
"capabilities": { "type": "array", "items": { "type": "string" } },
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
}
},
"required": [ "id", "type", "name", "scope", "createdAt", "updatedAt" ],
"additionalProperties": false
}
},
"required": [ "credential" ],
"additionalProperties": false
}400 — The request does not match its schema.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — credential.bad_request, credential.not_found, credential.admin_required, credential.encryption_disabled. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
DELETE /api/v1/credentials/{id}
Delete a connection
Refused (409) while a published workflow references it; details.workflows names them. OAuth accounts are not deleted here but by disconnecting the mailbox.
Access — Member session or API key with scope connections:write.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Responses
204 — Deleted.
401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — credential.not_found, credential.admin_required, credential.in_use, credential.bad_request. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
POST /api/v1/credentials/{id}/test
Test a connection
Calls the third-party service with the stored secret. Always 200: a revoked token is the result, not an error. HTTP errors remain for an unknown connection (404), a type without a checker (400) and a process that cannot reach integrations (503).
Access — Member session or API key with scope connections:write.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Responses
200 — The verdict.
| Field | Type | Required |
|---|---|---|
ok | boolean | yes |
account | string | no |
code | string | no |
status | integer | no |
scopes | string[] | no |
JSON Schema
json
{
"type": "object",
"properties": {
"ok": { "type": "boolean" },
"account": { "type": "string", "maxLength": 200 },
"code": { "type": "string" },
"status": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"scopes": {
"maxItems": 20,
"type": "array",
"items": { "type": "string", "maxLength": 120 }
}
},
"required": [ "ok" ],
"additionalProperties": false
}401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — credential.not_found, integration.not_testable, integration.not_wired. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.
GET /api/v1/credentials/{id}/webhook-handshake
Read a webhook handshake token
The verification token a service (Notion) posted once to the trigger URL, to paste back in its portal. null while nothing was received. Reserved to whoever may modify the connection.
Access — Member session or API key with scope connections:read.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
id | path | string | yes |
Responses
200 — The token, or null.
| Field | Type | Required |
|---|---|---|
token | string | null | yes |
JSON Schema
json
{
"type": "object",
"properties": { "token": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } },
"required": [ "token" ],
"additionalProperties": false
}401 — No valid session or API key (auth.unauthenticated).
403 — Refused: insufficient role (auth.forbidden), missing scope (api_key.scope_missing, details.required names it) or a route closed to API keys (api_key.session_required).
429 — The API key exceeded its rate limit (api_key.rate_limited); Retry-After says when to retry.
Error codes — credential.not_found, credential.bad_request. The common codes (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) apply to every route; see Errors.