Plateforme6 min

Journal d'audit

Lire qui a fait quoi dans une organisation : une entrée par commande réussie, filtrable par compte, par acteur et par texte libre.

Chaque commande réussie exécutée par Billabex laisse une entrée dans le journal d’audit de l’organisation, quel qu’en soit l’auteur : une personne dans la webapp, un client tiers via cette API ou le serveur MCP, l’agent Billabex, ou un chemin système interne comme la synchronisation d’un connecteur.

L’historique d’un compte n’est pas une ressource à part. C’est ce même journal restreint à un compte, et c’est aussi la seule façon de lire l’historique d’un compte supprimé.

Endpoint

GET /api/public/v1/organizations/{organizationId}/audit

Exige organizations:read ou organizations:all.

Paramètre Type Description
accountId UUID Ne garder que les entrées ayant agi sur ce compte
actorTypes USER | AGENT | SYSTEM | SERVICE_ACCOUNT, répétable Ne garder que ces types d’acteur
action chaîne Ne garder que ce nom de commande, par exemple DeleteAccount
search chaîne Correspondance insensible à la casse dans les métadonnées, ou sur un identifiant de compte audité
page entier Page à renvoyer, à partir de 1, vaut 1 par défaut
limit entier Entrées par page, 20 par défaut, 100 au maximum

Contrairement aux autres endpoints de liste, celui-ci pagine par numéro de page et non par curseur. Le journal est en ajout seul et se lit du plus récent au plus ancien : un numéro de page y est donc assez stable, et cela vous épargne un curseur pour une liste dont vous ne lisez la plupart du temps que la tête.

Réponse

{
  "nodes": [
    {
      "id": "f5183985-1f0e-4c2b-9a35-1a2b3c4d5e6f",
      "organizationId": "6effaee1-01d0-4205-b2da-911e28483dc6",
      "accountIds": ["78ce0186-2b4f-4b1c-9c3a-0d1e2f3a4b5c"],
      "actorType": "USER",
      "actorId": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
      "actorFullName": "Marie Dupont",
      "actorEmail": "marie@example.com",
      "actorDeleted": false,
      "actorChannel": "WEBAPP",
      "actorSource": null,
      "action": "DeleteAccount",
      "metadata": "{\"accountId\":\"78ce0186-2b4f-4b1c-9c3a-0d1e2f3a4b5c\"}",
      "createdAt": "2026-08-27T19:40:35.542Z"
    }
  ],
  "totalCount": 1,
  "page": 1,
  "limit": 20,
  "totalPages": 1
}

Lire une entrée

  • accountIds liste tous les comptes sur lesquels la commande a agi. Une action en masse sur deux cents comptes produit une entrée portant deux cents identifiants, pas deux cents entrées. Une action à l’échelle de l’organisation, comme un changement de réglage, porte un tableau vide.
  • actorType dit qui : USER pour une personne, AGENT pour l’agent Billabex, SYSTEM pour un chemin interne.
  • actorChannel n’est renseigné que pour une personne et dit par quelle porte elle est passée : WEBAPP, PUBLIC_API ou MCP.
  • actorSource n’est renseigné que pour un acteur système : CONNECTOR, SCHEDULER, WEBHOOK, ADMIN_API, MIGRATION, WORKFLOW ou INTERNAL.
  • actorDeleted ne vaut true que pour un utilisateur dont la suppression est connue. Un nom absent avec actorDeleted: false signifie que la projection n’est pas encore à jour, pas que la personne a disparu.
  • metadata est l’entrée de la commande sérialisée, dont les valeurs password, secret et token sont caviardées. Au-delà de quatre mille caractères, elle est remplacée par {"truncated": true, "action": "..."}.

Retrouver un compte qui n’existe plus

Une fois supprimé, un compte disparaît de toutes les listes, et son identifiant seul ne vous apprend rien. Son nom, lui, survit dans les métadonnées des commandes qui l’ont touché. Cherchez le nom, lisez l’identifiant sur l’entrée CreateAccount, puis restreignez le journal à cet identifiant :

# 1. Retrouver le compte par son nom
curl -H "Authorization: Bearer $TOKEN" \
  "$BASE_URL/api/public/v1/organizations/$ORG/audit?search=CCOG&action=CreateAccount"

# 2. Lire tout son historique, y compris qui l'a supprimé
curl -H "Authorization: Bearer $TOKEN" \
  "$BASE_URL/api/public/v1/organizations/$ORG/audit?accountId=$ACCOUNT_ID"

search porte aussi sur les identifiants de comptes audités : coller un identifiant retrouve donc toutes les commandes qui ont touché le compte, y compris celles dont l’entrée ne le nommait pas.

MCP

Le même journal est accessible à un client MCP par list-audit-entries, avec les mêmes filtres et le scope mcp:read.

Limites

  • Le journal commence le 6 août 2026. Rien de plus ancien n’a été enregistré.
  • L’écriture d’une entrée est au mieux : elle ne fait jamais échouer la commande qu’elle décrit. Une entrée manquante signifie donc « non attribué », jamais « n’a pas eu lieu ».
  • Les commandes qui ne font qu’entretenir un état dérivé sont volontairement exclues, comme celles qui touchent aux mots de passe et aux jetons OAuth.