Français
Clés d’API
Les routes sont relatives à <PUBLIC_BASE_URL> ; les corps de requête et de réponse sont en JSON sauf mention contraire. L’authentification, les portées, la pagination et le format des erreurs sont décrits dans les guides de l’API REST.
GET /api/v1/api-keys
Lister mes clés d’API
Les clés du membre connecté, les vivantes d’abord. Jamais un secret : seulement le repère de huit caractères.
Accès — Session de membre seulement : les clés d’API sont refusées (api_key.session_required).
Réponses
200 — Les clés.
| Champ | Type | Requis |
|---|---|---|
keys | object[] | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"keys": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"prefix": { "type": "string" },
"scopes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"workflows:read",
"workflows:write",
"workflows:*",
"executions:read",
"executions:write",
"executions:*",
"mailboxes:read",
"mailboxes:write",
"mailboxes:*",
"messages:read",
"messages:write",
"messages:*",
"tables:read",
"tables:write",
"tables:*",
"contacts:read",
"contacts:write",
"contacts:*",
"templates:read",
"templates:write",
"templates:*",
"connections:read",
"connections:write",
"connections:*",
"approvals:read",
"approvals:write",
"approvals:*",
"notifications:read",
"notifications:write",
"notifications:*",
"review:read",
"review:write",
"review:*",
"analyzer:read",
"analyzer:write",
"analyzer:*",
"assistant:read",
"assistant:write",
"assistant:*",
"dashboard:read",
"dashboard:write",
"dashboard:*",
"profile:read",
"profile:write",
"profile:*",
"admin:read",
"admin:write",
"admin:*",
"signals:write"
]
}
},
"memberId": { "type": "string" },
"memberEmail": { "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))$"
},
"expiresAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
},
"lastUsedAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
},
"revokedAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
}
},
"required": [
"id",
"name",
"prefix",
"scopes",
"memberId",
"memberEmail",
"createdAt",
"expiresAt",
"lastUsedAt",
"revokedAt"
],
"additionalProperties": false
}
}
},
"required": [ "keys" ],
"additionalProperties": false
}401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
POST /api/v1/api-keys
Créer une clé d’API
Crée une clé qui agit au nom du membre connecté, limitée aux portées données. Le secret est rendu une fois, ici, et plus jamais. Les portées réservées aux administrateurs sont refusées aux autres membres.
Accès — Session de membre seulement : les clés d’API sont refusées (api_key.session_required).
Corps de la requête (application/json)
| Champ | Type | Requis |
|---|---|---|
name | string | oui |
scopes | string (enum)[] | oui |
expiresInDays | integer | non |
Schéma JSON
json
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1, "maxLength": 120 },
"scopes": {
"minItems": 1,
"maxItems": 20,
"type": "array",
"items": {
"type": "string",
"enum": [
"workflows:read",
"workflows:write",
"workflows:*",
"executions:read",
"executions:write",
"executions:*",
"mailboxes:read",
"mailboxes:write",
"mailboxes:*",
"messages:read",
"messages:write",
"messages:*",
"tables:read",
"tables:write",
"tables:*",
"contacts:read",
"contacts:write",
"contacts:*",
"templates:read",
"templates:write",
"templates:*",
"connections:read",
"connections:write",
"connections:*",
"approvals:read",
"approvals:write",
"approvals:*",
"notifications:read",
"notifications:write",
"notifications:*",
"review:read",
"review:write",
"review:*",
"analyzer:read",
"analyzer:write",
"analyzer:*",
"assistant:read",
"assistant:write",
"assistant:*",
"dashboard:read",
"dashboard:write",
"dashboard:*",
"profile:read",
"profile:write",
"profile:*",
"admin:read",
"admin:write",
"admin:*",
"signals:write"
]
}
},
"expiresInDays": { "type": "integer", "minimum": 1, "maximum": 730 }
},
"required": [ "name", "scopes" ]
}Réponses
201 — La clé, avec son secret.
| Champ | Type | Requis |
|---|---|---|
key | object | oui |
token | string | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"key": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"prefix": { "type": "string" },
"scopes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"workflows:read",
"workflows:write",
"workflows:*",
"executions:read",
"executions:write",
"executions:*",
"mailboxes:read",
"mailboxes:write",
"mailboxes:*",
"messages:read",
"messages:write",
"messages:*",
"tables:read",
"tables:write",
"tables:*",
"contacts:read",
"contacts:write",
"contacts:*",
"templates:read",
"templates:write",
"templates:*",
"connections:read",
"connections:write",
"connections:*",
"approvals:read",
"approvals:write",
"approvals:*",
"notifications:read",
"notifications:write",
"notifications:*",
"review:read",
"review:write",
"review:*",
"analyzer:read",
"analyzer:write",
"analyzer:*",
"assistant:read",
"assistant:write",
"assistant:*",
"dashboard:read",
"dashboard:write",
"dashboard:*",
"profile:read",
"profile:write",
"profile:*",
"admin:read",
"admin:write",
"admin:*",
"signals:write"
]
}
},
"memberId": { "type": "string" },
"memberEmail": { "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))$"
},
"expiresAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
},
"lastUsedAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
},
"revokedAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
}
},
"required": [
"id",
"name",
"prefix",
"scopes",
"memberId",
"memberEmail",
"createdAt",
"expiresAt",
"lastUsedAt",
"revokedAt"
],
"additionalProperties": false
},
"token": { "type": "string" }
},
"required": [ "key", "token" ],
"additionalProperties": false
}400 — La requête ne respecte pas son schéma.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — api_key.bad_request, api_key.scope_forbidden. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
Exemple de requête
json
{
"name": "CRM sync",
"scopes": [ "workflows:read", "executions:write" ],
"expiresInDays": 365
}Exemple de réponse (201)
json
{
"key": {
"id": "0192f1c2-3b4d-7e8f-9a0b-1c2d3e4f5a6b",
"name": "CRM sync",
"prefix": "Qm9uam91",
"scopes": [ "executions:write", "workflows:read" ],
"memberId": "0192f1c2-0000-7000-8000-000000000001",
"memberEmail": "alice@example.test",
"createdAt": "2026-10-04T09:00:00.000Z",
"expiresAt": "2027-10-04T09:00:00.000Z",
"lastUsedAt": null,
"revokedAt": null
},
"token": "mk_Qm9uam91cl9jZXN0X3VuX2V4ZW1wbGVfZGVfY2xl"
}POST /api/v1/api-keys/{id}/revoke
Révoquer une de mes clés d’API
Immédiat et définitif. La ligne reste, pour le journal d’audit. Idempotent : révoquer deux fois garde la première date.
Accès — Session de membre seulement : les clés d’API sont refusées (api_key.session_required).
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
200 — La clé, révoquée.
| Champ | Type | Requis |
|---|---|---|
key | object | oui |
Schéma JSON
json
{
"type": "object",
"properties": {
"key": {
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"prefix": { "type": "string" },
"scopes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"workflows:read",
"workflows:write",
"workflows:*",
"executions:read",
"executions:write",
"executions:*",
"mailboxes:read",
"mailboxes:write",
"mailboxes:*",
"messages:read",
"messages:write",
"messages:*",
"tables:read",
"tables:write",
"tables:*",
"contacts:read",
"contacts:write",
"contacts:*",
"templates:read",
"templates:write",
"templates:*",
"connections:read",
"connections:write",
"connections:*",
"approvals:read",
"approvals:write",
"approvals:*",
"notifications:read",
"notifications:write",
"notifications:*",
"review:read",
"review:write",
"review:*",
"analyzer:read",
"analyzer:write",
"analyzer:*",
"assistant:read",
"assistant:write",
"assistant:*",
"dashboard:read",
"dashboard:write",
"dashboard:*",
"profile:read",
"profile:write",
"profile:*",
"admin:read",
"admin:write",
"admin:*",
"signals:write"
]
}
},
"memberId": { "type": "string" },
"memberEmail": { "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))$"
},
"expiresAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
},
"lastUsedAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
},
"revokedAt": {
"anyOf": [
{
"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))$"
},
{ "type": "null" }
]
}
},
"required": [
"id",
"name",
"prefix",
"scopes",
"memberId",
"memberEmail",
"createdAt",
"expiresAt",
"lastUsedAt",
"revokedAt"
],
"additionalProperties": false
}
},
"required": [ "key" ],
"additionalProperties": false
}401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — api_key.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.
GET /api/v1/admin/api-keys
Lister toutes les clés d’API de l’instance
Accès — Session de membre ou clé d’API portant admin:read (rôle administrateur requis).
Réponses
200 — Les clés.
| Champ | Type | Requis |
|---|---|---|
keys | object[] | oui |
Même schéma que GET /api/v1/api-keys.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
POST /api/v1/admin/api-keys/{id}/revoke
Révoquer n’importe quelle clé d’API
Accès — Session de membre ou clé d’API portant admin:write (rôle administrateur requis).
Paramètres
| Nom | Où | Type | Requis |
|---|---|---|---|
id | chemin | string | oui |
Réponses
200 — La clé, révoquée.
| Champ | Type | Requis |
|---|---|---|
key | object | oui |
Même schéma que POST /api/v1/api-keys/{id}/revoke.
401 — Aucune session ni clé d’API valide (auth.unauthenticated).
403 — Refusé : rôle insuffisant (auth.forbidden), portée manquante (api_key.scope_missing, details.required la nomme) ou route fermée aux clés (api_key.session_required).
429 — La clé d’API dépasse son débit (api_key.rate_limited) ; Retry-After dit quand réessayer.
Codes d’erreur — api_key.not_found. Les codes communs (request.bad_request, auth.unauthenticated, api_key.scope_missing, api_key.rate_limited…) s’appliquent à toutes les routes ; voir Erreurs.