L'API d'Aelby Week
L'application est API-first : l'interface consomme exactement l'API décrite ici. Tout ce que tu peux faire à l'écran, un programme peut le faire : lire ton planning, y poser, déplacer ou supprimer des blocs, sur les semaines réelles comme sur la semaine type.
Authentification
Génère une clé dans Paramètres → Clés d'API, puis envoie-la à chaque requête :
Authorization: Bearer awk_xxxxxxxxxxxx
Chaque clé donne accès au planning de son propriétaire, et à rien d'autre. La gestion des clés elle-même n'est accessible qu'en session (l'application), jamais avec une clé.
Conventions
- Les semaines sont repérées par leur numéro ISO 8601 (année + semaine, lundi premier jour) : la « semaine 35 de 2026 ».
- Les jours vont de
0(lundi) à6(dimanche) ; les heures sont des minutes depuis minuit (9h30 = 570). Aucune date absolue, aucun fuseau sur les blocs. - Deux types de blocs, pas plus :
slot(créneau avec début et fin) ettask(tâche du jour, cochable, sans heure).
{
"id": "3f2c…", // UUID (fourni ou généré)
"day": 1, // 0 = lundi … 6 = dimanche
"kind": "slot", // "slot" (créneau) ou "task" (tâche du jour)
"title": "Dev Aelby Bar",
"start_min": 540, // minutes depuis minuit (9h00), créneaux uniquement
"end_min": 660, // 11h00, créneaux uniquement
"done": false, // tâches uniquement
"color": null, // null = auto, ou "peche" | "soleil" | "sauge" | "ciel" | "lilas" | "rose"
"important": false, // rouge plein dans l'app, et ses rappels armés (la couleur reste dessous)
"reminders": null, // null = tous ; créneau : "veille" | "4h" | "1h" ; tâche : "veille" | "matin"
"origin": "manual", // "template" si hérité de la semaine type
"position": 0 // ordre des tâches dans la bande du jour
}Règle du chevauchement, comme dans l'app : un créneau créé ou déplacé sur d'autres les tranche. Chacun se referme autour de lui : il se rogne, se coupe en deux s'il tombe en plein milieu, et ne s'efface que s'il ne restait rien de lui. La réponse dit tout : replaced(effacés), cropped (rognés, dans leur nouvel état), added (morceaux nés de la coupe), de quoi proposer une annulation exacte. Ajoute ?replace=0 pour ne rien trancher : les créneaux cohabitent alors, côte à côte.
Semaines réelles
Une semaine = lignes stockées (passé figé, blocs détachés, ajouts) + occurrences projetées en direct depuis la semaine type (linked: true, id du bloc du calque). Lire est sans effet.
- GET
/api/v1/weeks/currentLa semaine en cours (?tz=Europe/Paris par défaut). Réponse : { week, blocks }.
- GET
/api/v1/weeks/{année}/{semaine}Une semaine par son numéro ISO, ex. /weeks/2026/35.
- POST
/api/v1/weeks/{année}/{semaine}/blocksCréer un bloc dans cette semaine. Réponse : { week, block, replaced, cropped, added }.
- PATCH
/api/v1/blocks/{id}Modifier un bloc stocké (day, title, start_min, end_min, done, color, important, reminders, position, details, full_title). Réponse : { block, replaced, cropped, added }.
- DELETE
/api/v1/blocks/{id}Supprimer un bloc stocké. Réponse : { deleted, block }.
- PATCH
/api/v1/weeks/{année}/{semaine}/blocks/{id}Modifier une occurrence projetée : la détache du calque pour cette semaine (nouvel id).
- DELETE
/api/v1/weeks/{année}/{semaine}/blocks/{id}Masquer une occurrence projetée pour cette semaine : le calque est intact ailleurs.
- POST
/api/v1/weeks/{année}/{semaine}/blocks/{id}/restoreRéattacher une occurrence masquée (l'inverse du DELETE d'occurrence).
Semaine type
Le calque vivant : projeté en direct sur tout le futur, à la minute près. Le modifier change toutes les occurrences à venir ; le passé, lui, est figé pour toujours.
- GET
/api/v1/templateTous les blocs de la semaine type.
- POST
/api/v1/template/blocksCréer un bloc dans la semaine type.
- PATCH
/api/v1/template/blocks/{id}Modifier un bloc de la semaine type.
- DELETE
/api/v1/template/blocks/{id}Supprimer un bloc de la semaine type.
Les rappels
Un bloc important prévient sur les appareils abonnés (Web Push) : la veille au soir (un récap pour tout le lendemain), 4 h avant un créneau (au réveil si ça tombait la nuit), 1 h avant, et le matin même pour une tâche. Un bloc retouché après le moment de son rappel ne le reçoit pas ; chaque rappel ne part qu'une fois.
- GET
/api/v1/pushLa clé publique VAPID du serveur, les appareils abonnés, les réglages et ai (Coco improvise-t-il). Réponse : { public_key, devices, settings, ai }.
- PATCH
/api/v1/pushLes réglages : { evening_min (16h–23h30, en minutes), evening_tasks, morning, coco_ai }.
- POST
/api/v1/push/devicesAbonner un appareil : le corps de PushSubscription.toJSON(), plus label et replaces (facultatifs). Réponse : { device } ; 409 si cette adresse est abonnée à un autre compte avec d'autres clés.
- DELETE
/api/v1/push/devices/{id}Désabonner un appareil.
- POST
/api/v1/push/testUne notification d'essai, tout de suite : à un appareil ({ endpoint }) ou à tous. Réponse : { sent, failed }.
Divers
- GET
/api/v1/syncL'empreinte des données du compte : un jeton opaque qui change dès que quelque chose change, où que le geste ait eu lieu. Réponse : { rev, at }. Tant qu'elle ne bouge pas, il n'y a rien à relire : c'est ainsi que l'app reste à jour toute seule.
- GET
/api/v1/meL'utilisateur authentifié (pratique pour tester une clé).
- GET
/api/v1/keysLister ses clés d'API (session uniquement).
- POST
/api/v1/keysCréer une clé : la valeur complète n'est renvoyée qu'une fois (session uniquement).
- DELETE
/api/v1/keys/{id}Révoquer une clé (session uniquement).
Applications reliées
Un bloc peut venir d'une autre application (source + source_id, ex. une tâche envoyée depuis Quilly). Cette application est prévenue (POST sur son adresse, « Authorization: Bearer <secret> ») chaque fois que le bloc est coché, déplacé, effacé ou restauré : { event: "block.updated" | "block.deleted", source_id, block: { id, done, day, year, week } }.
- PUT
/api/v1/hooks/{app}Dire où prévenir l'application {app} : { url (https), secret }.
- DELETE
/api/v1/hooks/{app}Ne plus la prévenir.
- GET
/api/v1/links?ids=…&source={app}L'état des blocs nommés (200 au plus) venus d'une application, pour se rattraper si une notification s'est perdue. Un bloc absent de la réponse n'existe plus. Réponse : { blocks: [{ id, source_id, done, day, year, week }] }.
Exemples
Lire la semaine en cours :
curl https://ton-app.vercel.app/api/v1/weeks/current \ -H "Authorization: Bearer awk_xxxxxxxxxxxx"
Poser un rendez-vous jeudi de 10h à 11h30 (semaine 35 de 2026) :
curl -X POST https://ton-app.vercel.app/api/v1/weeks/2026/35/blocks \
-H "Authorization: Bearer awk_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "day": 3, "kind": "slot", "title": "Rendez-vous client", "start_min": 600, "end_min": 690 }'Cocher une tâche :
# l'id vient de la lecture de la semaine (GET /weeks/current)
curl -X PATCH https://ton-app.vercel.app/api/v1/blocks/3f2c… \
-H "Authorization: Bearer awk_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "done": true }'Marquer un créneau important, avec seulement le rappel d'1 h :
curl -X PATCH https://ton-app.vercel.app/api/v1/blocks/3f2c… \
-H "Authorization: Bearer awk_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "important": true, "reminders": ["1h"] }'Erreurs
Toujours le même format, avec un code HTTP parlant (401 non authentifié, 404 introuvable, 409 conflit d'id, 422 requête invalide) :
{ "error": { "code": "invalid_request", "message": "start_min doit être avant end_min." } }Coco lui-même lit ton planning par cette API.
Aelby Week · API v1