Skip to content

Exemples ​

Cette page pilote l’API avec curl, d’une clé neuve jusqu’à la première exécution. Chaque requête et chaque réponse utilisent les vrais noms de champs ; les réponses longues sont abrégées par …. Remplacez <PUBLIC_BASE_URL> par l’adresse de votre instance.

Le parcours demande une clé portant workflows:write (créer, enregistrer, publier), executions:write (essayer et lire les exécutions) et messages:read (choisir un mail pour l’essai).

1. Créer une clé d’API ​

Le plus simple est l’interface : Réglages › Clés d’API › Nouvelle clé, cochez les trois domaines, copiez le secret. Par l’API, les clés se créent par une session seulement : connectez-vous d’abord et gardez le cookie :

sh
curl -s -c cookies.txt -X POST <PUBLIC_BASE_URL>/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{ "email": "alice@example.test", "password": "…" }'

curl -s -b cookies.txt -X POST <PUBLIC_BASE_URL>/api/v1/api-keys \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Parcours",
    "scopes": ["workflows:write", "executions:write", "messages:read"],
    "expiresInDays": 30
  }'
json
{
  "key": {
    "id": "0192f1c2-3b4d-7e8f-9a0b-1c2d3e4f5a6b",
    "name": "Parcours",
    "prefix": "Qm9uam91",
    "scopes": ["executions:write", "messages:read", "workflows:write"],
    "memberId": "0192f1c2-0000-7000-8000-000000000001",
    "memberEmail": "alice@example.test",
    "createdAt": "2026-10-04T09:00:00.000Z",
    "expiresAt": "2026-11-03T09:00:00.000Z",
    "lastUsedAt": null,
    "revokedAt": null
  },
  "token": "mk_Qm9uam91cl9jZXN0X3VuX2V4ZW1wbGVfZGVfY2xl"
}

token est montré ici et plus jamais. Gardez-le dans une variable pour la suite de la page :

sh
export MK_URL='<PUBLIC_BASE_URL>'
export MK_KEY='mk_Qm9uam91cl9jZXN0X3VuX2V4ZW1wbGVfZGVfY2xl'

2. Créer un workflow ​

POST /api/v1/workflows crée un brouillon, propriété du membre. Le corps n’a besoin que d’un name ; sans graph, le serveur crée un brouillon vide avec un seul déclencheur mail. La route crée quelque chose : envoyez une Idempotency-Key. Si la connexion tombe, rejouez la même commande et vous récupérez le même workflow.

sh
curl -s -X POST $MK_URL/api/v1/workflows \
  -H "Authorization: Bearer $MK_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 6f1d4c2e-6b3a-4a0e-9d2b-7c5e1f0a8b43' \
  -d '{ "name": "Marquer les factures comme lues" }'
json
{
  "id": "0192f1c2-aaaa-7000-8000-000000000001",
  "name": "Marquer les factures comme lues",
  "published": false,
  "draftVersion": {
    "id": "0192f1c2-aaaa-7000-8000-00000000000a",
    "number": 1,
    "publishedAt": null,
    "createdAt": "2026-10-04T09:01:00.000Z",
    "updatedAt": "2026-10-04T09:01:00.000Z"
  },
  "publishedVersion": null,
  "archivedAt": null,
  "dispatchPriority": null,
  "pausedAt": null,
  "errorWorkflowId": null,
  "graph": {
    "id": "0192f1c2-aaaa-7000-8000-00000000000a",
    "workflowId": "0192f1c2-aaaa-7000-8000-000000000001",
    "nodes": [
      { "id": "__trigger__", "type": "trigger.email", "version": 1, "name": "Mail reçu", "params": {}, "onError": "fail" }
    ],
    "connections": []
  },
  "validation": { "ok": false, "errors": [ { "code": "empty_workflow", "message": "…" } ], "warnings": [] },
  "createdAt": "2026-10-04T09:01:00.000Z",
  "updatedAt": "2026-10-04T09:01:00.000Z"
}

La réponse est le workflow complet (GET /api/v1/workflows/{id} rend la même forme) : son résumé, le graph du brouillon, et le diagnostic validation de ce graphe. Un brouillon vide n’est pas encore publiable, et le diagnostic le dit.

sh
export WF='0192f1c2-aaaa-7000-8000-000000000001'

3. Enregistrer le brouillon ​

PUT /api/v1/workflows/{id}/draft remplace le graphe du brouillon. Le graphe est le document décrit dans Workflows : nodes et connections, plus l’id et le workflowId de la version (reprenez-les de la réponse précédente ; le serveur les réancre de toute façon sur le vrai brouillon). Ici le déclencheur alimente une étape mail.flag qui marque le mail comme lu.

sh
curl -s -X PUT $MK_URL/api/v1/workflows/$WF/draft \
  -H "Authorization: Bearer $MK_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "graph": {
      "id": "0192f1c2-aaaa-7000-8000-00000000000a",
      "workflowId": "0192f1c2-aaaa-7000-8000-000000000001",
      "nodes": [
        { "id": "__trigger__", "type": "trigger.email", "version": 1, "name": "Mail reçu", "params": {} },
        { "id": "flag", "type": "mail.flag", "version": 1, "name": "Marquer comme lu", "params": { "seen": true } }
      ],
      "connections": [
        { "from": "__trigger__", "output": "main", "to": "flag" }
      ]
    },
    "expectedDraft": { "id": "0192f1c2-aaaa-7000-8000-00000000000a", "updatedAt": "2026-10-04T09:01:00.000Z" }
  }'
json
{
  "version": {
    "id": "0192f1c2-aaaa-7000-8000-00000000000a",
    "number": 1,
    "publishedAt": null,
    "createdAt": "2026-10-04T09:01:00.000Z",
    "updatedAt": "2026-10-04T09:03:12.000Z"
  },
  "validation": { "ok": true, "errors": [], "warnings": [] }
}

L’enregistrement est non bloquant : un graphe incohérent est enregistré et ses problèmes reviennent dans validation ; seul un document mal formé est refusé (400 workflow.invalid_graph). expectedDraft est facultatif : avec lui, l’enregistrement est refusé en 409 workflow.draft_conflict si quelqu’un (un autre onglet, un collègue) a écrit le brouillon depuis votre lecture. Sans lui, vous écrasez.

4. Essayer le brouillon sur un vrai mail ​

Un essai fait tourner le brouillon, pas la version publiée, sur un vrai mail de votre boîte, en simulé : rien n’est envoyé, rien n’est écrit hors de Mankomail (voir Mode test). Choisissez d’abord un mail :

sh
curl -s "$MK_URL/api/v1/messages?limit=1" -H "Authorization: Bearer $MK_KEY"

Puis planifiez l’essai avec son messageId. La réponse est un 202 : l’exécution est planifiée, pas terminée.

sh
curl -s -X POST $MK_URL/api/v1/workflows/$WF/test \
  -H "Authorization: Bearer $MK_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: 0d2a7e4b-3c5f-4e6a-8b9c-1d2e3f4a5b6c' \
  -d '{ "messageId": "0192f1c2-eeee-7000-8000-000000000042" }'
json
{
  "execution": {
    "id": "0192f1c2-bbbb-7000-8000-000000000001",
    "workflowId": "0192f1c2-aaaa-7000-8000-000000000001",
    "workflowVersionId": "0192f1c2-aaaa-7000-8000-00000000000a",
    "mailboxId": "0192f1c2-cccc-7000-8000-000000000001",
    "messageId": "0192f1c2-eeee-7000-8000-000000000042",
    "status": "queued",
    "simulated": true,
    "triggerNodeId": "__trigger__",
    "triggerType": "trigger.email",
    "error": null,
    "startedAt": null,
    "finishedAt": null,
    "createdAt": "2026-10-04T09:05:00.000Z"
  },
  "plannedNodes": ["__trigger__", "flag"]
}

triggerNodeId n’est requis que si le brouillon porte des déclencheurs de natures différentes (un déclencheur mail et un webhook, par exemple) ; targetNodeId arrête l’exécution après un nœud donné. Lisez le résultat comme à l’étape 7 ci-dessous : une exécution simulée a le même détail qu’une vraie, avec simulated: true.

5. Publier ​

POST /api/v1/workflows/{id}/publish fige le brouillon en version publiée et arme ses déclencheurs. C’est bloquant : des erreurs de validation refusent en 409 workflow.not_publishable, avec le diagnostic dans details.validation.

sh
curl -s -X POST $MK_URL/api/v1/workflows/$WF/publish \
  -H "Authorization: Bearer $MK_KEY" \
  -H 'Idempotency-Key: 9b8c7d6e-5f4a-4b3c-9d2e-1f0a9b8c7d6e'
json
{
  "ok": true,
  "validation": { "ok": true, "errors": [], "warnings": [] },
  "publishedVersion": {
    "id": "0192f1c2-aaaa-7000-8000-00000000000a",
    "number": 1,
    "publishedAt": "2026-10-04T09:06:00.000Z",
    "createdAt": "2026-10-04T09:01:00.000Z"
  },
  "armedMailboxes": 1,
  "webhook": null
}

Dès lors, chaque mail qui arrive dans les boîtes du membre lance une vraie exécution. armedMailboxes compte les boîtes que le déclencheur écoute. Pour un workflow dont le déclencheur est un webhook, webhook porte l’URL et son jeton, en clair, cette fois-là seulement. Le prochain PUT …/draft crée la version 2 comme nouveau brouillon ; la version publiée continue de tourner jusqu’à la publication suivante.

6. Lister les exécutions ​

GET /api/v1/executions est paginé par curseur (Pagination) et filtré par workflowId, mailboxId, status (queued, running, waiting, succeeded, failed, cancelled) et simulated.

sh
curl -s "$MK_URL/api/v1/executions?workflowId=$WF&simulated=false&limit=20" \
  -H "Authorization: Bearer $MK_KEY"
json
{
  "executions": [
    {
      "id": "0192f1c2-bbbb-7000-8000-000000000007",
      "workflowId": "0192f1c2-aaaa-7000-8000-000000000001",
      "workflowVersionId": "0192f1c2-aaaa-7000-8000-00000000000a",
      "mailboxId": "0192f1c2-cccc-7000-8000-000000000001",
      "messageId": "0192f1c2-eeee-7000-8000-000000000051",
      "status": "succeeded",
      "simulated": false,
      "triggerNodeId": "__trigger__",
      "triggerType": "trigger.email",
      "messageHeadline": { "subject": "Facture 2026-0142", "fromName": "Acme", "fromEmail": "compta@acme.example" },
      "error": null,
      "startedAt": "2026-10-04T09:12:44.100Z",
      "finishedAt": "2026-10-04T09:12:44.620Z",
      "createdAt": "2026-10-04T09:12:44.000Z"
    }
  ],
  "nextCursor": null
}

Les plus récentes d’abord. Quand nextCursor n’est pas null, renvoyez-le en cursor avec les mêmes filtres pour la page suivante.

7. Lire une exécution ​

GET /api/v1/executions/{id} rend l’exécution pas à pas : chaque étape avec son statut, son numéro de tentative, sa durée, les data qu’elle a publiées et les effets qu’elle a décrits.

sh
curl -s $MK_URL/api/v1/executions/0192f1c2-bbbb-7000-8000-000000000007 \
  -H "Authorization: Bearer $MK_KEY"
json
{
  "id": "0192f1c2-bbbb-7000-8000-000000000007",
  "workflowId": "0192f1c2-aaaa-7000-8000-000000000001",
  "workflowName": "Marquer les factures comme lues",
  "status": "succeeded",
  "simulated": false,
  "…": "…",
  "steps": [
    {
      "id": "0192f1c2-ffff-7000-8000-000000000001",
      "nodeId": "flag",
      "status": "succeeded",
      "attempt": 1,
      "output": "main",
      "data": {},
      "dataTruncated": false,
      "durationMs": 310,
      "…": "…"
    }
  ],
  "attachments": []
}

L’exécution d’un autre membre, ou un identifiant inconnu, est un 404 execution.not_found. Une exécution échouée se rejoue par POST /api/v1/executions/{id}/retry (executions:write), depuis le début ou depuis l’étape échouée ({ "from": "failed_step" }) ; une exécution en cours s’arrête par POST /api/v1/executions/{id}/cancel.

Pour aller plus loin ​

  • Les champs exacts de chaque requête et de chaque réponse : la référence, en particulier Workflows et Exécutions.
  • Réveiller un workflow depuis un autre système, sans boîte mail : un déclencheur webhook (POST /hooks/wf/{token}) ou un signal (POST /api/v1/signals, portée signals:write).
  • Laisser un assistant IA faire de même par ses propres tools : MCP.