Skip to content

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.

ChampTypeRequis
keysobject[]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)

ChampTypeRequis
namestringoui
scopesstring (enum)[]oui
expiresInDaysintegernon
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.

ChampTypeRequis
keyobjectoui
tokenstringoui
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

NomOùTypeRequis
idcheminstringoui

Réponses

200 — La clé, révoquée.

ChampTypeRequis
keyobjectoui
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.

ChampTypeRequis
keysobject[]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

NomOùTypeRequis
idcheminstringoui

Réponses

200 — La clé, révoquée.

ChampTypeRequis
keyobjectoui

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.