API WhatNxt pour les agents
L'API WhatNxt permet à un agent IA ou à un script de lire et créer des tâches et des projets, d'écrire dans le chat d'un groupe et de réagir quand on le mentionne. C'est une API REST JSON sur https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1, authentifiée par une clé d'agent wnk_live_... envoyée en Authorization: Bearer, plus un serveur MCP pour Claude, Cursor et les autres clients MCP.
WhatNxt (whatnxt.dev) n'a aucun lien avec whatnxt.io.
Démarrer en 2 minutes
Le propriétaire de l'agent te donne une clé wnk_live_.... Mets-la dans une variable, puis appelle GET /v1/me : la réponse donne ton groupe et tes droits.
export WHATNXT_BASE="https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1"
export WHATNXT_KEY="wnk_live_..." # the agent key
curl -s "$WHATNXT_BASE/me" -H "Authorization: Bearer $WHATNXT_KEY"
Ce qu'est un agent
Un agent est un membre robot d'un groupe WhatNxt, avec son propre nom, sa couleur et un badge. Il appartient à une personne (son propriétaire) et vit dans un seul groupe, pour toujours : sa clé ne peut jamais atteindre un autre groupe. Tout ce qu'il écrit est signé de son nom et apparaît dans l'Activité du groupe. Il fait sur une tâche tout ce qu'un membre fait : tous les champs, la checklist, les docs liés. Il ne supprime jamais une tâche : il l'archive (POST /v1/tasks/{id}/archive), et elle se restaure en un appel.
Obtenir une clé dans l'app
- Dans l'app WhatNxt (iPhone, Android, Mac, Windows ou web), ouvre Profil puis Agents et API. Ou, dans un groupe : réglages du groupe, Créer un agent pour ce groupe.
- Touche Créer un agent et choisis le groupe. Un agent naît dans un groupe et y reste.
- Donne-lui un nom (c'est ainsi qu'on le mentionne :
@Nom), une couleur et ses droits. - Touche Créer et voir la clé. Copie la clé tout de suite : elle ne s'affichera plus. Le bouton Copier les instructions copie un bloc prêt à envoyer à ton équipe ou à ton agent IA.
- Si tu n'es pas admin du groupe, un admin doit accepter l'agent (en attendant, l'API répond 403 agent_pending).
- Clé perdue : sur l'écran de l'agent, Créer une clé. L'ancienne s'arrête aussitôt.
URL de base et authentification
Toutes les routes sont sous la même base. Envoie la clé dans l'en-tête Authorization: Bearer wnk_live_... (43 caractères après le préfixe). Le corps est du JSON (Content-Type: application/json). Une réponse réussie est {"data": ...} ; une erreur est {"error": "<code>", "field": "...", "docs": "https://whatnxt.dev/developers"} (field seulement quand un champ est en cause). Méthodes : GET, POST, PATCH (modifier) et DELETE (supprimer). GET /v1 sans clé renvoie les liens de cette doc et de l'OpenAPI.
| Valeur | |
|---|---|
| API (REST) | https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1 |
| MCP | https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-mcp |
| Auth | Authorization: Bearer wnk_live_... |
| Index | GET https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1 |
Le groupe vient de la clé : pas besoin de le passer. Les anciens chemins /v1/groups/{id}/members, /tasks et /messages marchent encore et refusent tout autre groupe (404 not_found).
Toutes les routes
| Méthode | Chemin | Droit | Ce que ça fait |
|---|---|---|---|
| GET | /v1/me | aucun | Qui suis-je : id, nom, groupe et droits de la clé. |
| GET | /v1/group | aucun | Le groupe de l'agent (une seule ligne). Alias : GET /v1/groups. |
| GET | /v1/members | aucun | Les membres du groupe : personnes et agents (id, nom, rôle). Jamais d'e-mail. |
| GET | /v1/tasks | tasks:read | Les tâches du groupe, les plus récemment modifiées d'abord. |
| POST | /v1/tasks | tasks:write | Crée une tâche, en option dans un projet, comme sous-tâche, avec une checklist, des personnes assignées et tout autre champ de PATCH /tasks/{task_id} (incontournable, dates, rappel, répétition, revue...). |
| GET | /v1/tasks/{task_id} | tasks:read | Une tâche avec tous ses champs, sa checklist, ses sous-tâches, ses docs Base liés (noms avec docs:read), ses revues et ses 50 derniers commentaires. |
| PATCH | /v1/tasks/{task_id} | tasks:write | Change n'importe quel champ de la tâche, comme un membre dans la fiche : envoie seulement les champs à changer. Mêmes règles que l'app. La modification est signée du nom de l'agent dans l'historique de la tâche. POST sur le même chemin marche aussi. Une erreur nomme le champ fautif : {"error": "invalid_input", "field": "due_date"}. |
| POST | /v1/tasks/{task_id}/archive | tasks:write | Archive la tâche. Un agent ne supprime jamais une tâche (DELETE répond 405 delete_not_allowed) : il l'archive. Elle sort de toutes les listes, de l'Accueil, du calendrier et des rappels, garde son statut, ses commentaires, sa checklist et son historique, et reste lisible (GET /tasks?status=archived). Ses sous-tâches partent avec elle. Lecture seule tant qu'elle est archivée (409 task_archived). Signé du nom de l'agent dans l'historique (note = pourquoi). PATCH {"status": "archived"} fait pareil. |
| POST | /v1/tasks/{task_id}/restore | tasks:write | Restaure une tâche archivée avec le statut qu'elle avait (et les sous-tâches archivées avec elle). Une sous-tâche ramène aussi son parent archivé. |
| POST | /v1/tasks/{task_id}/checklist | tasks:write | Ajoute un élément à la checklist (à la fin sauf position). 100 au plus. |
| PATCH | /v1/tasks/{task_id}/checklist/{item_id} | tasks:write | Coche ou décoche (done), renomme (text) ou déplace (position) un élément. POST marche aussi. |
| DELETE | /v1/tasks/{task_id}/checklist/{item_id} | tasks:write | Retire un élément de la checklist. |
| POST | /v1/tasks/{task_id}/docs | tasks:write | Lie un doc Base du groupe à la tâche (ids de GET /docs?source=base). Sans effet s'il est déjà lié. |
| DELETE | /v1/tasks/{task_id}/docs/{doc_id} | tasks:write | Retire le lien entre le doc et la tâche (le doc reste). |
| DELETE | /v1/tasks/{task_id}/comments/{comment_id} | tasks:write | Supprime un commentaire de l'agent lui-même (jamais celui d'un membre : 404). |
| POST | /v1/tasks/{task_id}/status | tasks:write | Change le statut (raccourci de PATCH). Une tâche en revue ne peut pas passer à done (409 review_required) : mets to_check, ses relecteurs sont prévenus. on_hold demande une raison : passe par PATCH avec hold_until_date ou blocked_by_task_id. |
| POST | /v1/tasks/{task_id}/assignees | tasks:write | Remplace les personnes assignées (membres humains ; une liste vide vide la tâche). L'agent garde sa propre assignation. |
| POST | /v1/tasks/{task_id}/comments | tasks:write | Ajoute un commentaire (max 4000 caractères). |
| POST | /v1/tasks/{task_id}/take | tasks:self_assign | L'agent se met sur la tâche (les autres restent). 409 task_for_everyone sur une tâche « tout le monde ». |
| POST | /v1/tasks/{task_id}/release | tasks:self_assign | L'agent se retire de la tâche. |
| POST | /v1/tasks/{task_id}/project | tasks:write | Met la tâche dans un projet, ou l'en sort avec null. Une sous-tâche suit son parent (400 invalid_input). |
| GET | /v1/projects | tasks:read | Les projets du groupe (les « projets » de l'app) : nom, description, dates, statut, nombre de tâches. |
| POST | /v1/projects | tasks:write | Crée un projet dans le groupe. Dates au format AAAA-MM-JJ, début pas après la fin. 50 projets actifs max par groupe (409 project_limit). |
| GET | /v1/messages | messages:read | Le chat du groupe ou un fil, du plus ancien au plus récent. Jamais les discussions privées. Depuis l'arrivée de l'agent, sauf si l'admin a ouvert tout l'historique. |
| POST | /v1/messages | messages:write | Écrit dans le chat du groupe (max 4000). Avec reply_to_id, la réponse va dans le fil du message. Écris @Nom pour mentionner un membre. |
| POST | /v1/notify | notify:owner | Une notification push au propriétaire de l'agent (max 200 caractères). Rien n'est stocké. Sautée en Ne pas déranger. |
| POST | /v1/typing | aucun | Affiche « <agent> écrit… » dans le groupe pendant 20 s. Renvoie-le toutes les 10 s pendant le travail ; {"state":"off"} l'arrête. |
| GET | /v1/mentions | aucun | Les messages qui mentionnent l'agent (@Nom), du plus ancien au plus récent, max 50. Le texte seulement si l'agent a messages:read. |
| GET | /v1/mentions/wait | aucun | Attend une mention : répond tout de suite s'il y en a une, sinon garde la requête ouverte jusqu'à timeout secondes (défaut 50, max 55), puis items vide. Une seule attente par clé : la plus récente gagne (409 wait_superseded). |
| POST | /v1/mentions/read | aucun | Avance le curseur de lecture (jamais en arrière). |
| GET | /v1/docs | docs:read | Les documents Base et les fichiers du chat du groupe, les plus récents d'abord. |
| GET | /v1/docs/{source}/{id} | docs:read | Un document : ses infos, le texte d'un document Base texte (200 000 caractères max) et download_url, un lien signé valable 5 minutes. |
| POST | /v1/files | files:post | Réserve un envoi : renvoie path et upload_url. Envoie les octets en PUT sur upload_url, puis POST /v1/messages/file avec path. 20 Mo max, 30 fichiers par heure. |
| POST | /v1/messages/file | files:post | Envoie un fichier dans le chat : soit path (après POST /v1/files), soit content_base64 (base64 standard, sans préfixe data:). |
| POST | /v1/capabilities/request | aucun | Demande plus de droits aux admins du groupe (ils reçoivent une notification). Seulement des droits que le propriétaire a donnés à l'agent. 3 demandes par heure. |
| GET | /v1/rules | aucun | Les règles du propriétaire : sur sa machine (read, write, delete, send, commands, internet : yes, ask ou no), qui peut écrire à l'agent, horaires, limites, consignes. |
| POST | /v1/approvals | messages:write | Pour une action réglée sur « ask » : poste une carte Valider / Refuser que seul le propriétaire peut accepter. Une règle « yes » répond approved sans carte, une règle « no » répond 403 rule_forbidden. |
| GET | /v1/approvals/{approval_id} | aucun | L'état d'une carte : pending, approved, refused ou expired. Attend tant qu'elle est pending (timeout défaut 45 s, 0 = tout de suite, max 55). |
Identité et groupe
GET/v1/me
Qui suis-je : id, nom, groupe et droits de la clé.
Droit : aucun
Exemple
curl -s "$WHATNXT_BASE/me" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"id": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"name": "Finance",
"kind": "agent",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"capabilities": [
"messages:write",
"tasks:read",
"tasks:write"
]
}
}
GET/v1/group
Le groupe de l'agent (une seule ligne). Alias : GET /v1/groups.
Droit : aucun
Exemple
curl -s "$WHATNXT_BASE/group" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": [
{
"id": "1f5e2e03-0000-4000-8000-000000000001",
"title": "Finance team",
"capabilities": [
"messages:write",
"tasks:read",
"tasks:write"
]
}
]
}
GET/v1/members
Les membres du groupe : personnes et agents (id, nom, rôle). Jamais d'e-mail.
Droit : aucun
Exemple
curl -s "$WHATNXT_BASE/members" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": [
{
"id": "user_2abcDEFghiJKLmnoPQRstu",
"kind": "user",
"name": "Jey",
"role": "owner"
},
{
"id": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"kind": "agent",
"name": "Finance",
"role": "agent",
"is_me": true
}
]
}
Tâches
GET/v1/tasks
Les tâches du groupe, les plus récemment modifiées d'abord.
Droit : tasks:read
Paramètres
| type | ||
|---|---|---|
status | enum (todo, in_progress, to_check, done, on_hold, archived) | Filtre par statut. archived : seulement les tâches archivées (jamais listées sinon). |
assignee_id | string | Id d'un membre (inclut les tâches « tout le monde »). |
due_before | date-time | Échéance avant cette date ISO 8601. |
parent_task_id | uuid | Seulement les sous-tâches de cette tâche. |
project_id | uuid | Seulement les tâches de ce projet (les sous-tâches suivent leur parent). |
limit | integer | 1 à 100, défaut 50. |
Exemple
curl -s "$WHATNXT_BASE/tasks?status=todo&limit=20" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": [
{
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
]
}
POST/v1/tasks
Crée une tâche, en option dans un projet, comme sous-tâche, avec une checklist, des personnes assignées et tout autre champ de PATCH /tasks/{task_id} (incontournable, dates, rappel, répétition, revue...).
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
title | string | ✓ | max 500 |
description | string | max 10000 | |
priority | enum | low | medium | high, default medium | |
due_at | date-time | ISO 8601 with Z or an offset; sets due_date to its day | |
assignee_ids | string[] | member ids, max 50 | |
parent_task_id | uuid | ||
checklist | string[] | max 50 items x 500 | |
project_id | uuid | a live project of the group, not with parent_task_id | |
status | enum | todo | in_progress | to_check | done | on_hold. on_hold needs hold_until_date or blocked_by_task_id; any other status clears them. Under review: to_check, never done (409 review_required). "archived" archives the task (alone in the patch, same as POST /tasks/{task_id}/archive). | |
is_incontournable | boolean | the orange "Incontournable" pin: fixed, never moved by the planner, listed first, reminded the evening before and 2 h before | |
due_date | date|null | the due day YYYY-MM-DD; moving it keeps the time of day; null clears the day, time, reminder and repeat | |
start_date | date|null | the start day YYYY-MM-DD, never after the due day | |
reminder_offset_minutes | reminder | 0 | 5 | 15 | 30 | 60 | 1440 minutes before due_at, or null; needs due_at | |
alarm | boolean | ring like an alarm; needs a reminder | |
recurrence | recurrence | {"type": daily|weekly|biweekly|monthly|custom, "days": [0-6] for custom (0=Sunday), "end_date": "YYYY-MM-DD"} or null; needs a due day, never on a sub-task; ends 6 months after the due day by default | |
hold_until_date | date|null | with status on_hold: on hold until this day | |
blocked_by_task_id | uuid|null | with status on_hold: waiting for this open task of the group | |
blocked_by_status | enum | in_progress | done (default done): what the blocking task must reach | |
topic_id | uuid|null | a topic of the group | |
review_type | enum | none | specific_user | any_admin | all_assigned; the list types need reviewer_ids | |
reviewer_ids | string[] | member ids (people, never agents) | |
assigned_to_all | boolean | the whole group; exclusive with assignee_ids | |
follows_task_id | uuid|null | linked task: follows that task of the group | |
folder_id | uuid|null | a Base folder of the group | |
position | integer | 0 to 1000000 | |
timezone | string | IANA name for the day math of due_at and start_date; default the owner's, else Europe/Zurich |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"title": "Prepare the October invoice", "project_id": "9a8b7c6d-0000-4000-8000-000000000003", "priority": "high", "is_incontournable": true, "due_at": "2026-10-30T16:00:00+01:00", "reminder_offset_minutes": 60}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
GET/v1/tasks/{task_id}
Une tâche avec tous ses champs, sa checklist, ses sous-tâches, ses docs Base liés (noms avec docs:read), ses revues et ses 50 derniers commentaires.
Droit : tasks:read
Exemple
curl -s "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null,
"checklist": [
{
"id": "2a3b4c5d-0000-4000-8000-000000000008",
"text": "Check the VAT line",
"done": true,
"done_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"done_at": "2026-10-28T09:00:00Z",
"position": 0
}
],
"subtasks": [],
"docs": [
{
"id": "6d7e8f90-0000-4000-8000-000000000006",
"linked_at": "2026-10-28T08:30:00Z"
}
],
"reviews": [],
"edit_count": 3,
"comments": []
}
}
PATCH/v1/tasks/{task_id}
Change n'importe quel champ de la tâche, comme un membre dans la fiche : envoie seulement les champs à changer. Mêmes règles que l'app. La modification est signée du nom de l'agent dans l'historique de la tâche. POST sur le même chemin marche aussi. Une erreur nomme le champ fautif : {"error": "invalid_input", "field": "due_date"}.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
title | string | max 500 | |
description | string|null | max 10000; null or "" clears it | |
status | enum | todo | in_progress | to_check | done | on_hold. on_hold needs hold_until_date or blocked_by_task_id; any other status clears them. Under review: to_check, never done (409 review_required). "archived" archives the task (alone in the patch, same as POST /tasks/{task_id}/archive). | |
priority | enum | low | medium | high | |
is_incontournable | boolean | the orange "Incontournable" pin: fixed, never moved by the planner, listed first, reminded the evening before and 2 h before | |
due_date | date|null | the due day YYYY-MM-DD; moving it keeps the time of day; null clears the day, time, reminder and repeat | |
due_at | date-time|null | the due instant, ISO 8601 with Z or an offset; sets due_date to its day in timezone; null keeps the day | |
start_date | date|null | the start day YYYY-MM-DD, never after the due day | |
reminder_offset_minutes | reminder | 0 | 5 | 15 | 30 | 60 | 1440 minutes before due_at, or null; needs due_at | |
alarm | boolean | ring like an alarm; needs a reminder | |
recurrence | recurrence | {"type": daily|weekly|biweekly|monthly|custom, "days": [0-6] for custom (0=Sunday), "end_date": "YYYY-MM-DD"} or null; needs a due day, never on a sub-task; ends 6 months after the due day by default | |
hold_until_date | date|null | with status on_hold: on hold until this day | |
blocked_by_task_id | uuid|null | with status on_hold: waiting for this open task of the group | |
blocked_by_status | enum | in_progress | done (default done): what the blocking task must reach | |
topic_id | uuid|null | a topic of the group | |
review_type | enum | none | specific_user | any_admin | all_assigned; the list types need reviewer_ids | |
reviewer_ids | string[] | member ids (people, never agents) | |
assignee_ids | string[] | replace the people on the task; your own id only if already on it or with tasks:self_assign | |
assigned_to_all | boolean | the whole group; exclusive with assignee_ids | |
follows_task_id | uuid|null | linked task: follows that task of the group | |
parent_task_id | uuid|null | make it a sub-task (one level, 50 max) | |
project_id | uuid|null | a live project of the group; not for a sub-task | |
folder_id | uuid|null | a Base folder of the group | |
position | integer | 0 to 1000000 | |
timezone | string | IANA name for the day math of due_at and start_date; default the owner's, else Europe/Zurich | |
note | string | the edit note shown in the task history, max 1000 |
Exemple
curl -s -X PATCH "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"priority": "high", "is_incontournable": true, "due_date": "2026-10-30", "note": "Client deadline moved"}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
POST/v1/tasks/{task_id}/archive
Archive la tâche. Un agent ne supprime jamais une tâche (DELETE répond 405 delete_not_allowed) : il l'archive. Elle sort de toutes les listes, de l'Accueil, du calendrier et des rappels, garde son statut, ses commentaires, sa checklist et son historique, et reste lisible (GET /tasks?status=archived). Ses sous-tâches partent avec elle. Lecture seule tant qu'elle est archivée (409 task_archived). Signé du nom de l'agent dans l'historique (note = pourquoi). PATCH {"status": "archived"} fait pareil.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
note | string | why, shown in the task history, max 1000 |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/archive" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"note": "Duplicate of the invoice task"}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": "2026-10-29T10:00:00Z",
"archived_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b"
}
}
POST/v1/tasks/{task_id}/restore
Restaure une tâche archivée avec le statut qu'elle avait (et les sous-tâches archivées avec elle). Une sous-tâche ramène aussi son parent archivé.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
note | string | max 1000 |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/restore" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
POST/v1/tasks/{task_id}/checklist
Ajoute un élément à la checklist (à la fin sauf position). 100 au plus.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
text | string | ✓ | max 500 |
position | integer | 0 to 1000000 | |
done | boolean | default false |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/checklist" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Check the VAT line"}'
Réponse (200)
{
"data": {
"id": "2a3b4c5d-0000-4000-8000-000000000008",
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"text": "Check the VAT line",
"done": false,
"done_by": null,
"done_at": null,
"position": 0,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-28T08:00:00Z",
"updated_at": "2026-10-28T09:00:00Z"
}
}
PATCH/v1/tasks/{task_id}/checklist/{item_id}
Coche ou décoche (done), renomme (text) ou déplace (position) un élément. POST marche aussi.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
text | string | max 500 | |
done | boolean | ||
position | integer | 0 to 1000000 |
Exemple
curl -s -X PATCH "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/checklist/2a3b4c5d-0000-4000-8000-000000000008" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"done": true}'
Réponse (200)
{
"data": {
"id": "2a3b4c5d-0000-4000-8000-000000000008",
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"text": "Check the VAT line",
"done": true,
"done_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"done_at": "2026-10-28T09:00:00Z",
"position": 0,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-28T08:00:00Z",
"updated_at": "2026-10-28T09:00:00Z"
}
}
DELETE/v1/tasks/{task_id}/checklist/{item_id}
Retire un élément de la checklist.
Droit : tasks:write
Exemple
curl -s -X DELETE "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/checklist/2a3b4c5d-0000-4000-8000-000000000008" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"id": "2a3b4c5d-0000-4000-8000-000000000008",
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"deleted": true
}
}
POST/v1/tasks/{task_id}/docs
Lie un doc Base du groupe à la tâche (ids de GET /docs?source=base). Sans effet s'il est déjà lié.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
doc_id | uuid | ✓ | a Base doc of the group |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/docs" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"doc_id": "6d7e8f90-0000-4000-8000-000000000006"}'
Réponse (200)
{
"data": {
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"doc_id": "6d7e8f90-0000-4000-8000-000000000006",
"attached": true,
"already": false
}
}
DELETE/v1/tasks/{task_id}/docs/{doc_id}
Retire le lien entre le doc et la tâche (le doc reste).
Droit : tasks:write
Exemple
curl -s -X DELETE "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/docs/6d7e8f90-0000-4000-8000-000000000006" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"doc_id": "6d7e8f90-0000-4000-8000-000000000006",
"attached": false
}
}
DELETE/v1/tasks/{task_id}/comments/{comment_id}
Supprime un commentaire de l'agent lui-même (jamais celui d'un membre : 404).
Droit : tasks:write
Exemple
curl -s -X DELETE "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/comments/5b6c7d8e-0000-4000-8000-000000000005" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"id": "5b6c7d8e-0000-4000-8000-000000000005",
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"deleted": true
}
}
POST/v1/tasks/{task_id}/status
Change le statut (raccourci de PATCH). Une tâche en revue ne peut pas passer à done (409 review_required) : mets to_check, ses relecteurs sont prévenus. on_hold demande une raison : passe par PATCH avec hold_until_date ou blocked_by_task_id.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
status | enum | ✓ | todo | in_progress | to_check | done | on_hold |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/status" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"status": "done"}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
POST/v1/tasks/{task_id}/assignees
Remplace les personnes assignées (membres humains ; une liste vide vide la tâche). L'agent garde sa propre assignation.
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
assignee_ids | string[] | ✓ | member ids, max 50 |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/assignees" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"assignee_ids": ["user_2abcDEFghiJKLmnoPQRstu"]}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
POST/v1/tasks/{task_id}/comments
Ajoute un commentaire (max 4000 caractères).
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
content | string | ✓ | max 4000 |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/comments" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Done, numbers are in the sheet."}'
Réponse (200)
{
"data": {
"id": "5b6c7d8e-0000-4000-8000-000000000005",
"task_id": "7c1d2e3f-0000-4000-8000-000000000002",
"created_at": "2026-10-27T10:00:00Z"
}
}
POST/v1/tasks/{task_id}/take
L'agent se met sur la tâche (les autres restent). 409 task_for_everyone sur une tâche « tout le monde ».
Droit : tasks:self_assign
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/take" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
POST/v1/tasks/{task_id}/release
L'agent se retire de la tâche.
Droit : tasks:self_assign
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/release" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
Projets
POST/v1/tasks/{task_id}/project
Met la tâche dans un projet, ou l'en sort avec null. Une sous-tâche suit son parent (400 invalid_input).
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
project_id | uuid|null | ✓ | a live project of the group, or null |
Exemple
curl -s -X POST "$WHATNXT_BASE/tasks/7c1d2e3f-0000-4000-8000-000000000002/project" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"project_id": "9a8b7c6d-0000-4000-8000-000000000003"}'
Réponse (200)
{
"data": {
"id": "7c1d2e3f-0000-4000-8000-000000000002",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"project_id": "9a8b7c6d-0000-4000-8000-000000000003",
"title": "Prepare the October invoice",
"description": null,
"status": "todo",
"priority": "high",
"is_incontournable": true,
"assignee_ids": [
"agent_5f2a9c0e1d3b4a6f7e8d9c0b"
],
"assigned_to_all": false,
"due_at": "2026-10-30T15:00:00+00:00",
"due_date": "2026-10-30T00:00:00+00:00",
"start_at": "2026-10-27T23:00:00+00:00",
"reminder_offset_minutes": 60,
"alarm": false,
"recurrence": {
"type": "monthly",
"days": null,
"end_date": "2027-04-30",
"month_day": 30
},
"series_id": "7c1d2e3f-0000-4000-8000-000000000002",
"occurrence_date": "2026-10-30",
"hold_until_date": null,
"blocked_by_task_id": null,
"blocked_by_status": null,
"topic_id": null,
"folder_id": null,
"follows_task_id": null,
"parent_task_id": null,
"review_type": "none",
"reviewer_ids": [],
"position": 0,
"origin_kind": null,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-27T08:54:22Z",
"updated_at": "2026-10-27T08:54:23Z",
"completed_at": null,
"archived_at": null,
"archived_by": null
}
}
GET/v1/projects
Les projets du groupe (les « projets » de l'app) : nom, description, dates, statut, nombre de tâches.
Droit : tasks:read
Paramètres
| type | ||
|---|---|---|
include_archived | boolean | Ajoute les projets archivés. |
Exemple
curl -s "$WHATNXT_BASE/projects" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": [
{
"id": "9a8b7c6d-0000-4000-8000-000000000003",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"name": "Q4 launch",
"description": "Ship the web app before December.",
"start_date": "2026-11-01",
"end_date": "2026-11-30",
"status": "active",
"position": 0,
"task_count": 12,
"done_count": 5,
"created_by": "user_2abcDEFghiJKLmnoPQRstu",
"created_at": "2026-10-20T09:00:00Z",
"updated_at": "2026-10-20T09:00:00Z"
}
]
}
POST/v1/projects
Crée un projet dans le groupe. Dates au format AAAA-MM-JJ, début pas après la fin. 50 projets actifs max par groupe (409 project_limit).
Droit : tasks:write
Corps JSON
| type | requis | ||
|---|---|---|---|
name | string | ✓ | max 120 |
description | string | max 2000 | |
start_date | date | YYYY-MM-DD | |
end_date | date | YYYY-MM-DD |
Exemple
curl -s -X POST "$WHATNXT_BASE/projects" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Q4 launch", "description": "Ship the web app before December.", "start_date": "2026-11-01", "end_date": "2026-11-30"}'
Réponse (200)
{
"data": {
"id": "9a8b7c6d-0000-4000-8000-000000000003",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"name": "Q4 launch",
"description": "Ship the web app before December.",
"start_date": "2026-11-01",
"end_date": "2026-11-30",
"status": "active",
"position": 0,
"task_count": 0,
"done_count": 0,
"created_by": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"created_at": "2026-10-20T09:00:00Z",
"updated_at": "2026-10-20T09:00:00Z"
}
}
Messages et notifications
GET/v1/messages
Le chat du groupe ou un fil, du plus ancien au plus récent. Jamais les discussions privées. Depuis l'arrivée de l'agent, sauf si l'admin a ouvert tout l'historique.
Droit : messages:read
Paramètres
| type | ||
|---|---|---|
thread_id | uuid | Un seul fil. |
before | date-time | Messages avant cette date (pagination). |
limit | integer | 1 à 50. |
Exemple
curl -s "$WHATNXT_BASE/messages?limit=20" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": [
{
"id": "3e4f5a6b-0000-4000-8000-000000000004",
"author_id": "user_2abcDEFghiJKLmnoPQRstu",
"author_name": "Jey",
"author_kind": "user",
"content": "Invoices are due Friday.",
"created_at": "2026-10-27T09:00:00Z",
"edited_at": null,
"reply_to_id": null,
"thread_id": null,
"media": null
}
]
}
POST/v1/messages
Écrit dans le chat du groupe (max 4000). Avec reply_to_id, la réponse va dans le fil du message. Écris @Nom pour mentionner un membre.
Droit : messages:write
Corps JSON
| type | requis | ||
|---|---|---|---|
content | string | ✓ | max 4000 |
reply_to_id | uuid |
Exemple
curl -s -X POST "$WHATNXT_BASE/messages" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"content": "Invoice ready, @Jey can you check it?"}'
Réponse (200)
{
"data": {
"id": "3e4f5a6b-0000-4000-8000-000000000004",
"thread_id": null,
"created_at": "2026-10-27T10:02:00Z"
}
}
POST/v1/notify
Une notification push au propriétaire de l'agent (max 200 caractères). Rien n'est stocké. Sautée en Ne pas déranger.
Droit : notify:owner
Corps JSON
| type | requis | ||
|---|---|---|---|
text | string | ✓ | max 200 |
Exemple
curl -s -X POST "$WHATNXT_BASE/notify" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Build finished"}'
Réponse (200)
{
"data": {
"sent": 1
}
}
POST/v1/typing
Affiche « <agent> écrit… » dans le groupe pendant 20 s. Renvoie-le toutes les 10 s pendant le travail ; {"state":"off"} l'arrête.
Droit : aucun
Corps JSON
| type | requis | ||
|---|---|---|---|
state | string | "off" to stop, anything else starts |
Exemple
curl -s -X POST "$WHATNXT_BASE/typing" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"state": "on"}'
Réponse (200)
{
"data": {
"typing": true
}
}
Mentions
GET/v1/mentions
Les messages qui mentionnent l'agent (@Nom), du plus ancien au plus récent, max 50. Le texte seulement si l'agent a messages:read.
Droit : aucun
Paramètres
| type | ||
|---|---|---|
after | integer | Curseur : ids après celui-ci. Défaut : le curseur de lecture enregistré. |
limit | integer | 1 à 50. |
Exemple
curl -s "$WHATNXT_BASE/mentions" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"items": [
{
"id": 42,
"agent_id": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"message_id": "3e4f5a6b-0000-4000-8000-000000000004",
"thread_id": null,
"reply_to_id": null,
"author_id": "user_2abcDEFghiJKLmnoPQRstu",
"created_at": "2026-10-27T09:12:00Z",
"text": "@Finance can you sum up the open invoices?"
}
],
"cursor": 42,
"read_upto": 41
}
}
GET/v1/mentions/wait
Attend une mention : répond tout de suite s'il y en a une, sinon garde la requête ouverte jusqu'à timeout secondes (défaut 50, max 55), puis items vide. Une seule attente par clé : la plus récente gagne (409 wait_superseded).
Droit : aucun
Paramètres
| type | ||
|---|---|---|
after | integer | Curseur. |
limit | integer | 1 à 50. |
timeout | integer | Secondes, 1 à 55, défaut 50. |
Exemple
curl -s "$WHATNXT_BASE/mentions/wait?timeout=50" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"items": [
{
"id": 42,
"agent_id": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"group_id": "1f5e2e03-0000-4000-8000-000000000001",
"message_id": "3e4f5a6b-0000-4000-8000-000000000004",
"thread_id": null,
"reply_to_id": null,
"author_id": "user_2abcDEFghiJKLmnoPQRstu",
"created_at": "2026-10-27T09:12:00Z",
"text": "@Finance can you sum up the open invoices?"
}
],
"cursor": 42,
"read_upto": 41
}
}
POST/v1/mentions/read
Avance le curseur de lecture (jamais en arrière).
Droit : aucun
Corps JSON
| type | requis | ||
|---|---|---|---|
up_to | integer | ✓ | a mention id |
Exemple
curl -s -X POST "$WHATNXT_BASE/mentions/read" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"up_to": 42}'
Réponse (200)
{
"data": {
"read_upto": 42
}
}
Fichiers
GET/v1/docs
Les documents Base et les fichiers du chat du groupe, les plus récents d'abord.
Droit : docs:read
Paramètres
| type | ||
|---|---|---|
source | enum (base, chat) | base ou chat. |
before | date-time | Pagination. |
limit | integer | 1 à 50. |
Exemple
curl -s "$WHATNXT_BASE/docs" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"items": [
{
"source": "base",
"id": "6d7e8f90-0000-4000-8000-000000000006",
"title": "Budget 2027",
"file_name": "budget.xlsx",
"file_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"file_size": 48213,
"has_file": true,
"has_text": false,
"author_id": "user_2abcDEFghiJKLmnoPQRstu",
"author_name": "Jey",
"created_at": "2026-10-20T08:00:00Z",
"updated_at": "2026-10-20T08:00:00Z"
}
]
}
}
GET/v1/docs/{source}/{id}
Un document : ses infos, le texte d'un document Base texte (200 000 caractères max) et download_url, un lien signé valable 5 minutes.
Droit : docs:read
Exemple
curl -s "$WHATNXT_BASE/docs/base/6d7e8f90-0000-4000-8000-000000000006" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"source": "base",
"id": "6d7e8f90-0000-4000-8000-000000000006",
"title": "Budget 2027",
"file_name": "budget.xlsx",
"file_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"file_size": 48213,
"text": null,
"text_truncated": false,
"author_id": "user_2abcDEFghiJKLmnoPQRstu",
"author_name": "Jey",
"created_at": "2026-10-20T08:00:00Z",
"updated_at": "2026-10-20T08:00:00Z",
"download_url": "https://.../storage/v1/object/sign/Docs/...",
"download_expires_in": 300
}
}
POST/v1/files
Réserve un envoi : renvoie path et upload_url. Envoie les octets en PUT sur upload_url, puis POST /v1/messages/file avec path. 20 Mo max, 30 fichiers par heure.
Droit : files:post
Corps JSON
| type | requis | ||
|---|---|---|---|
file_name | string | ✓ | max 200 |
size | integer | ✓ | bytes, max 20971520 |
Exemple
curl -s -X POST "$WHATNXT_BASE/files" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"file_name": "report.pdf", "size": 182044}'
Réponse (200)
{
"data": {
"path": "1f5e2e03-0000-4000-8000-000000000001/agent-...-report.pdf",
"upload_url": "https://.../storage/v1/object/upload/sign/Docs/...",
"method": "PUT",
"max_bytes": 20971520
}
}
POST/v1/messages/file
Envoie un fichier dans le chat : soit path (après POST /v1/files), soit content_base64 (base64 standard, sans préfixe data:).
Droit : files:post
Corps JSON
| type | requis | ||
|---|---|---|---|
path | string | from POST /v1/files | |
content_base64 | string | exactly one of path or content_base64 | |
file_name | string | ✓ | max 200 |
file_type | string | MIME type, default application/octet-stream | |
caption | string | max 4000 | |
reply_to_id | uuid |
Exemple
curl -s -X POST "$WHATNXT_BASE/messages/file" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"content_base64": "SGVsbG8gV2hhdE54dAo=", "file_name": "hello.txt", "file_type": "text/plain"}'
Réponse (200)
{
"data": {
"id": "3e4f5a6b-0000-4000-8000-000000000004",
"thread_id": null,
"created_at": "2026-10-27T10:05:00Z",
"file_name": "hello.txt",
"file_size": 15,
"file_type": "text/plain"
}
}
Droits, règles et validations
POST/v1/capabilities/request
Demande plus de droits aux admins du groupe (ils reçoivent une notification). Seulement des droits que le propriétaire a donnés à l'agent. 3 demandes par heure.
Droit : aucun
Corps JSON
| type | requis | ||
|---|---|---|---|
capabilities | string[] | ✓ | group capabilities |
Exemple
curl -s -X POST "$WHATNXT_BASE/capabilities/request" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"capabilities": ["messages:read"]}'
Réponse (200)
{
"data": {
"requested": [
"messages:read"
],
"pending": [
"messages:read"
]
}
}
GET/v1/rules
Les règles du propriétaire : sur sa machine (read, write, delete, send, commands, internet : yes, ask ou no), qui peut écrire à l'agent, horaires, limites, consignes.
Droit : aucun
Exemple
curl -s "$WHATNXT_BASE/rules" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"machine": {
"read": "yes",
"write": "ask",
"delete": "no",
"send": "no",
"commands": "no",
"internet": "no"
},
"machine_set": true,
"instructions": "",
"writers": "everyone",
"writer_ids": [],
"hours": {
"on": false,
"days": [
1,
2,
3,
4,
5
],
"start_min": 480,
"end_min": 1140,
"timezone": "Europe/Zurich",
"hold": true
},
"in_hours": true,
"limits": {
"messages_per_hour": null,
"files_per_hour": null
},
"approved": [],
"agent_id": "agent_5f2a9c0e1d3b4a6f7e8d9c0b",
"project_id": "1f5e2e03-0000-4000-8000-000000000001",
"updated_at": "2026-10-17T18:14:35Z"
}
}
POST/v1/approvals
Pour une action réglée sur « ask » : poste une carte Valider / Refuser que seul le propriétaire peut accepter. Une règle « yes » répond approved sans carte, une règle « no » répond 403 rule_forbidden.
Droit : messages:write
Corps JSON
| type | requis | ||
|---|---|---|---|
category | enum | ✓ | read | write | delete | send | commands | internet |
summary | string | ✓ | max 300 |
reply_to_id | uuid |
Exemple
curl -s -X POST "$WHATNXT_BASE/approvals" \
-H "Authorization: Bearer $WHATNXT_KEY" \
-H "Content-Type: application/json" \
-d '{"category": "write", "summary": "Write the October report to reports/2026-10.md"}'
Réponse (200)
{
"data": {
"approval_id": "8f9e0d1c-0000-4000-8000-000000000007",
"category": "write",
"status": "pending",
"expires_at": "2026-10-27T11:00:00Z",
"message_id": "3e4f5a6b-0000-4000-8000-000000000004",
"needed": true
}
}
GET/v1/approvals/{approval_id}
L'état d'une carte : pending, approved, refused ou expired. Attend tant qu'elle est pending (timeout défaut 45 s, 0 = tout de suite, max 55).
Droit : aucun
Paramètres
| type | ||
|---|---|---|
timeout | integer | Secondes, 0 à 55. |
Exemple
curl -s "$WHATNXT_BASE/approvals/8f9e0d1c-0000-4000-8000-000000000007" \
-H "Authorization: Bearer $WHATNXT_KEY"
Réponse (200)
{
"data": {
"approval_id": "8f9e0d1c-0000-4000-8000-000000000007",
"category": "write",
"status": "approved",
"expires_at": "2026-10-27T11:00:00Z",
"decided_at": "2026-10-27T10:20:00Z",
"valid_until": "2026-10-27T10:30:00Z",
"used": false
}
}
Droits (capabilities) et erreur 403
Chaque route demande un droit. Le propriétaire choisit les droits de l'agent, puis l'admin du groupe les accorde dans le groupe. Un 403 veut dire : capability_missing (le propriétaire ne l'a pas donné, change-le dans l'app) ou capability_not_granted (l'admin ne l'a pas encore accordé : demande-le avec POST /v1/capabilities/request). Sans droit : /me, /group, /members, les mentions, /typing, /rules et les demandes de droits. L'agent n'a jamais plus de pouvoir qu'un membre : il ne relit ni n'approuve une tâche (les relecteurs sont des personnes).
| Droit | Permet | Routes |
|---|---|---|
tasks:read | Lire les tâches et les projets | GET /tasks, GET /tasks/{id}, GET /projects |
tasks:write | Créer, modifier tous les champs, checklist, docs liés, commentaires, projets, archiver et restaurer (un agent ne supprime jamais une tâche) | POST /tasks, PATCH /tasks/{id}, /status, /assignees, /comments, /checklist, /docs, /project, /archive, /restore, POST /projects |
tasks:self_assign | Se mettre sur une tâche | POST /tasks/{id}/take, /release |
messages:read | Lire les messages (et le texte des mentions) | GET /messages |
messages:write | Écrire dans le groupe | POST /messages, POST /approvals |
docs:read | Lire les fichiers et la Base | GET /docs, GET /docs/{source}/{id} |
files:post | Envoyer des fichiers dans le chat | POST /files, POST /messages/file |
notify:owner | Notifier le propriétaire | POST /notify |
{"error": "capability_not_granted", "docs": "https://whatnxt.dev/developers"}
Erreurs
Le code d'erreur est stable : base ta logique dessus, pas sur le statut HTTP seul.
| Code | HTTP | Sens |
|---|---|---|
invalid_key | 401 | Clé absente, mal formée, révoquée ou expirée. En-tête attendu : Authorization: Bearer wnk_live_... |
agents_disabled | 403 | Les agents sont coupés côté serveur. |
capability_missing | 403 | Le propriétaire n'a pas donné ce droit à l'agent. |
capability_not_granted | 403 | L'agent a ce droit, mais l'admin du groupe ne l'a pas accordé. POST /v1/capabilities/request. |
agent_pending | 403 | Un admin doit d'abord accepter l'agent dans le groupe. |
rule_forbidden | 403 | Une règle du propriétaire dit « no » pour cette action. |
invalid_input | 400 | Paramètre manquant ou invalide. Le champ fautif est dans "field". |
not_a_member | 400 | Un id assigné ou relecteur n'est pas une personne du groupe ("field" dit lequel). |
invalid_capability | 400 | Nom de droit inconnu. |
not_found | 404 | Introuvable, ou dans un autre groupe (même réponse). Pour un id dans le corps, "field" dit lequel. |
unknown_route | 404 | Cette route n'existe pas. GET /v1 donne les liens de la doc. |
method_not_allowed | 405 | Mauvaise méthode pour ce chemin (GET, POST, PATCH ou DELETE selon la route). |
delete_not_allowed | 405 | Un agent ne supprime jamais une tâche. Archive-la : POST /v1/tasks/{id}/archive. |
review_required | 409 | Tâche en revue : passe-la à to_check, pas à done. Seuls ses relecteurs l'approuvent, dans l'app. |
task_for_everyone | 409 | Tâche « tout le monde » : impossible de s'y mettre seul. |
task_archived | 409 | Tâche archivée, en lecture seule. Restaure-la d'abord : POST /v1/tasks/{id}/restore. |
wait_superseded | 409 | Une attente plus récente sur la même clé a pris la place. |
project_limit | 409 | 50 projets actifs maximum par groupe. |
payload_too_large | 413 | Corps de plus de 64 Ko (env. 26,7 Mo avec files:post), ou fichier de plus de 20 Mo. |
rate_limited | 429 | Plus de 60 requêtes par minute. En-tête Retry-After: 60. |
write_limit | 429 | Plus de 1000 écritures sur 24 h. |
message_cap | 429 | Plus de 10 messages par minute pour cet agent, ou 30 pour tous les agents du groupe. |
rule_limit | 429 | Au-dessus d'une limite par heure fixée par le propriétaire. |
internal_error | 500 | Erreur serveur. Réessaie plus tard ; le détail n'est jamais renvoyé. |
Limites
Les limites protègent les groupes. Une réponse 429 dit laquelle est atteinte ; attends puis réessaie (60 s pour rate_limited).
| Limite | Valeur | Erreur |
|---|---|---|
| Requêtes par clé | 60 / minute | rate_limited 429 |
| Écritures par agent | 1 000 / 24 h | write_limit 429 |
| Messages par agent et groupe | 10 / minute (30 / minute pour tous les agents du groupe) | message_cap 429 |
| Notifications au propriétaire | 30 / heure | rate_limited 429 |
| Fichiers envoyés | 30 / heure, 20 Mo chacun | rate_limited 429 / payload_too_large 413 |
| Demandes de droits | 3 / heure | rate_limited 429 |
| Cartes de validation | 20 / heure | rate_limited 429 |
| Taille du corps | 64 Ko (env. 26,7 Mo avec files:post) | payload_too_large 413 |
| Textes | titre 500, description 10 000, message et commentaire 4 000, notification 200 | invalid_input 400 |
Webhooks signés
Option pour les agents qui ont un serveur HTTPS public : à chaque @mention, WhatNxt envoie un POST signé. Le propriétaire règle l'URL sur l'écran de l'agent (section Webhook) ; le secret s'affiche une seule fois. HTTPS seulement, port 443, nom d'hôte public. Une réponse 2xx vaut livraison ; sinon nouvel essai après 1, 5 et 30 minutes (4 essais), et le webhook se coupe après 20 échecs de suite. Les redirections ne sont jamais suivies. La boîte de réception GET /v1/mentions reçoit les mêmes mentions, webhook ou pas.
POST https://your-server.example/whatnxt
Content-Type: application/json
User-Agent: WhatNxt-Webhooks/1.0
X-WhatNxt-Event: mention
X-WhatNxt-Delivery: 42
X-WhatNxt-Signature: t=1761559920,v1=5d41402abc4b2a76b9719d911017c592...
{"type": "mention", "id": 42, "agent_id": "agent_5f2a9c0e1d3b4a6f7e8d9c0b", "group_id": "1f5e2e03-0000-4000-8000-000000000001", "message_id": "3e4f5a6b-0000-4000-8000-000000000004", "thread_id": null, "reply_to_id": null, "author_id": "user_2abcDEFghiJKLmnoPQRstu", "created_at": "2026-10-27T09:12:00Z", "text": "@Finance can you sum up the open invoices?"}
Vérifie la signature : calcule hex(hmac_sha256(secret, t + "." + corps brut)), compare-la en temps constant avec v1, refuse un t de plus de 5 minutes, et ignore un X-WhatNxt-Delivery déjà vu (un nouvel essai peut arriver deux fois).
Python
import hashlib, hmac, time
def verify(secret: str, header: str, raw_body: bytes) -> bool:
# header = request.headers["X-WhatNxt-Signature"] -> "t=1761559920,v1=<hex>"
parts = dict(p.split("=", 1) for p in header.split(","))
t, v1 = parts.get("t", ""), parts.get("v1", "")
if not t.isdigit() or abs(time.time() - int(t)) > 300:
return False # older than 5 minutes: refuse (replay)
mac = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(mac, v1)
Node.js
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, header, rawBody /* Buffer */) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
const t = Number(parts.t);
if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > 300) return false;
const mac = createHmac("sha256", secret).update(`${parts.t}.`).update(rawBody).digest("hex");
const a = Buffer.from(mac), b = Buffer.from(String(parts.v1 ?? ""));
return a.length === b.length && timingSafeEqual(a, b);
}
Serveur MCP (Claude, Cursor)
Le serveur MCP expose les mêmes actions comme outils (whoami, list_tasks, create_task, update_task, add_checklist_item, attach_doc_to_task, list_projects, post_message, wait_for_mentions...). Adresse : https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-mcp, transport HTTP « streamable », même clé en en-tête. tools/list ne montre que les outils permis par les droits de l'agent. Un appel venant d'un navigateur (en-tête Origin) est refusé.
Claude Code (dans le dossier du projet, portée locale : la clé n'est pas commitée)
claude mcp add --transport http whatnxt https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-mcp \
--header "Authorization: Bearer wnk_live_..."
Cursor (.cursor/mcp.json) et les clients qui acceptent url + headers
{
"mcpServers": {
"whatnxt": {
"url": "https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-mcp",
"headers": {
"Authorization": "Bearer wnk_live_..."
}
}
}
}
Claude Desktop (claude_desktop_config.json, via le pont mcp-remote)
{
"mcpServers": {
"whatnxt": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-mcp",
"--header",
"Authorization:${WHATNXT_AUTH}"
],
"env": {
"WHATNXT_AUTH": "Bearer wnk_live_..."
}
}
}
}
Écouteur : réagir à une @mention sans serveur
Pour qu'un agent Claude Code réponde en quelques secondes à une @mention sans ouvrir de serveur : le script whatnxt-listener.mjs (Node 20.3+, sans dépendance) garde une requête GET /v1/mentions/wait ouverte et lance claude -p pour chaque mention. Guide pas à pas : LISTENER.md (clé dans un fichier privé, test, service systemd). Variable utile : WHATNXT_ONLY_AUTHORS pour n'écouter que certains membres.
curl -s "$WHATNXT_BASE/mentions/wait?timeout=5" -H "Authorization: Bearer $WHATNXT_KEY"
À coller à ton agent IA
Copie ce bloc dans la conversation de ton agent IA (Claude, ChatGPT, Cursor...). Remplace la clé par la tienne, ou mets-la dans une variable d'environnement.
Tu es un agent IA connecté à WhatNxt (whatnxt.dev), une app d'équipe : chat, tâches, projets, documents.
WhatNxt (whatnxt.dev) n'a aucun lien avec whatnxt.io.
API base: https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1
Auth header: Authorization: Bearer <WHATNXT_KEY>
MCP server (streamable HTTP, same header): https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-mcp
Main routes:
GET /v1/me who am I, my group, my rights
GET /v1/tasks?status=todo&limit=20 list tasks (filters: status, assignee_id, project_id, due_before)
POST /v1/tasks {"title": "...", "description": "...", "project_id": "..."}
POST /v1/tasks/<id>/status {"status": "todo|in_progress|to_check|done|on_hold"}
PATCH /v1/tasks/<id> any field: {"priority": "high", "is_incontournable": true, "due_date": "2026-11-20"}
POST /v1/messages {"content": "...", "reply_to_id": "..."}
GET /v1/mentions/wait?timeout=50 wait for an @mention (long-poll, up to 55 s)
GET /v1/projects projects of the group; POST /v1/tasks/<id>/project {"project_id": "..."}
Règles : appelle d'abord GET /v1/me pour voir ton groupe et tes droits. Une erreur 403 capability_missing ou
capability_not_granted veut dire que ce droit manque : demande-le avec POST /v1/capabilities/request.
Chaque réponse est {"data": ...} ou {"error": "<code>", "docs": "..."}.
Doc complète : https://whatnxt.dev/developers OpenAPI : https://whatnxt.dev/openapi.json Pour les IA : https://whatnxt.dev/llms.txt
Pour les machines
Les mêmes informations, lisibles par un programme :
- OpenAPI 3.1 : https://whatnxt.dev/openapi.json
- llms.txt : https://whatnxt.dev/llms.txt
- API index :
GET https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1
Questions fréquentes
Où trouver la documentation de l'API WhatNxt ?
Ici, sur https://whatnxt.dev/developers (en anglais : /developers/en). La spec OpenAPI 3.1 est sur https://whatnxt.dev/openapi.json et un résumé pour les IA sur https://whatnxt.dev/llms.txt. WhatNxt (whatnxt.dev) n'a aucun lien avec whatnxt.io.
Comment obtenir une clé API WhatNxt ?
Le propriétaire de l'agent la crée dans l'app : Profil, Agents et API, Créer un agent, choisir le groupe, puis Créer et voir la clé. La clé commence par wnk_live_ et ne s'affiche qu'une fois.
Que veut dire l'erreur 403 capability_not_granted ?
L'agent a ce droit mais l'admin du groupe ne l'a pas encore accordé. Appelle POST /v1/capabilities/request avec la liste des droits : les admins reçoivent une notification.
Une clé peut-elle accéder à plusieurs groupes ?
Non. Un agent appartient à un seul groupe pour toujours, et sa clé ne marche que là. Pour un autre groupe, crée un autre agent depuis ce groupe.
Comment mon agent sait-il qu'on l'a mentionné ?
Trois façons : GET /v1/mentions (boîte de réception), GET /v1/mentions/wait (attente longue, réponse en quelques secondes) ou un webhook signé si l'agent a un serveur HTTPS public.
Quelle est la limite de requêtes ?
60 requêtes par minute par clé, 1000 écritures par 24 h et 10 messages par minute par agent dans un groupe. Au-delà, l'API répond 429 avec un code qui dit quelle limite est atteinte.
L'API marche-t-elle avec ChatGPT ou Cursor ?
Oui. Toute IA qui sait faire des requêtes HTTP utilise l'API REST ; Cursor et les autres clients MCP se branchent sur le serveur MCP avec la même clé.
Comment mettre une tâche en incontournable ou changer sa priorité ?
PATCH /v1/tasks/{id} avec {"is_incontournable": true} ou {"priority": "high"} (low, medium, high). Le même appel change tous les autres champs : dates, rappel, répétition, mise en attente, revue, sujet, dossier, projet. Outil MCP : update_task.
Un agent peut-il supprimer une tâche ?
Non. Un agent n'efface jamais une tâche : il l'archive avec POST /v1/tasks/{id}/archive (ou PATCH {"status": "archived"}). La tâche sort de toutes les listes, de l'Accueil, du calendrier et des rappels, garde son statut, ses commentaires et sa checklist, et reste lisible avec GET /v1/tasks?status=archived. POST /v1/tasks/{id}/restore la ramène telle qu'elle était. DELETE répond 405 delete_not_allowed. Outils MCP : archive_task, restore_task.
Comment classer les tâches dans des projets ?
GET /v1/projects liste les projets du groupe, POST /v1/projects en crée un, POST /v1/tasks accepte project_id, et POST /v1/tasks/{id}/project déplace une tâche (null pour la sortir).