Base : https://letock.fr. Tout est en JSON, tout est en UTF-8, toutes les dates sont en ISO 8601 avec fuseau.
S'authentifier. Une clé d'API, en en-tête :
Authorization: Bearer tock_xxxxxxxxxxxxxxxxxxxx
Les clés se créent sur l'écran « Développeurs ». Une clé appartient à une équipe et porte une portée : lecture seule, ou lecture et écriture. Elle n'est montrée qu'une fois — seule son empreinte est conservée. Une clé perdue se révoque et se remplace ; elle ne se retrouve pas.
Ce qu'une clé ne permet pas, et c'est délibéré : supprimer un compte, changer un forfait, lire les données d'une autre équipe. Si tu es un agent à qui l'on a confié une clé, considère qu'elle donne accès à de la production : n'appelle pas une route d'écriture pour « voir ce qu'elle fait ».
Les missions. Une clé ne porte pas « lecture » ou « écriture » : elle porte la liste des gestes qu'on lui a cochés, un par un, sur le tableau de bord.
lire Regarder, sans rien changer cron.ecrire Créer et modifier des tâches planifiées stats.ecrire Rapporter des événements métier erreurs.ecrire Rapporter des erreurs ia.ecrire Rendre compte de ses propres exécutions mail.envoyer Envoyer des e-mails depuis ton domaine uptime.ecrire Créer et modifier des contrôles de disponibilité uptime.supprimer Supprimer un contrôle et son historique forum.repondre Répondre sur le forum public mail.crochets Declarer ou l on t envoie les evenements du courrier mail.boites Ouvrir et fermer des adresses de réception cron.supprimer Supprimer une tâche et tout son historique ia.valider Approuver ou refuser une validation humaine divers.ecrire Tout le reste, y compris ce qui sera ajouté plus tard
Un appel hors de cette liste répond 403 avec le code mission_non_autorisee. Ce n'est pas un défaut du service, ce n'est pas une erreur à réessayer, et il n'y a pas d'autre route qui mène au même résultat : la seule suite possible est de le dire à la personne qui t'a confié la clé, et de la laisser décider. Une route qui n'est nommée dans aucune mission tombe dans divers.ecrire, qui n'est presque jamais coché — autrement dit, ce qui est ajouté à l'API après la création d'une clé lui est fermé par défaut.
Les paramètres de requête
Ils ne changent pas la route, ils changent ce qu'elle fait. Deux d'entre eux évitent une erreur qu'on ne rattrape pas : essai=1 éprouve un branchement sans rien écrire, et traite= est ce sans quoi la détection d'effondrement de volume reste muette.
domaine=sur/api/v1/uptime— restreint la réponse à un domaine déclaré, par son nom.echecs=sur/api/v1/journal— à1, ne rend que ce qui a échoué — la lecture qu’on fait neuf fois sur dix.limite=sur/api/v1/journal— combien d’entrées au plus. Le défaut suffit presque toujours.module=sur/api/v1/alertes/envoyees— filtre sur un module, par son identifiant au registre.depuis=sur/api/v1/changelog— une date ISO : ne rend que ce qui a changé depuis. C’est l’appel à faire à chaque session plutôt que de relire la notice entière.prose=sur/api/v1/changelog— à1, ajoute le texte destiné aux humains. Par défaut la réponse ne porte que ce qui concerne du code.e=sur/api/v1/analyser— l’expression cron à analyser.tz=sur/api/v1/analyser— le fuseau dans lequel l’interpréter. Sans lui, l’analyse le signale comme un piège.n=sur/api/v1/analyser— combien de prochains déclenchements rendre.projet=sur/api/v1/taches— filtre sur un projet, par son identifiant.constat=sur/api/v1/recettestype=sur/api/v1/mails/evenementsboite=sur/api/v1/mails/recusbrut=sur/api/v1/mails/recustraite=sur/api/ping/{cle}— le nombre d’éléments réellement traités. Sans lui, la détection d’effondrement de volume est inactive — et c’est pour elle que le module existe.?traite=0est une information, pas une absence.erreurs=sur/api/ping/{cle}— le nombre d’erreurs rencontrées pendant l’exécution que tu rapportes.essai=sur/api/ping/{cle}— essai à blanc : le câblage est éprouvé, la réponse ditessai: true, et rien n’est enregistré. À utiliser avant de brancher un cron, pour ne pas inscrire un faux battement.
Limites de débit. 60 appels par minute sans clé, 300 avec, 120 pour les pings de tâches. La réponse porte X-RateLimit-Remaining et, en cas de dépassement, un 429 avec Retry-After. Respecte-le : réessayer plus vite ne débloque rien.
La forme d'une erreur. Toujours la même, quel que soit le module :
{
"erreur": { "code": "quota_atteint", "message": "…", "aide": "…" }
}code est stable et fait pour être testé en machine ; message est fait pour être lu par une personne ; aide dit quoi faire. Un 429 de code quota_atteint n'est pas une erreur de ta part : c'est un plafond de forfait, et réessayer ne servira qu'au prochain mois.
Pendant une mise à jour
Tock se met à jour sans prévenir à l'avance, et l'opération dure quelques secondes. Pendant ce temps, toute route répond `503` avec un en-tête Retry-After en secondes :
``json { "erreur": "mise_a_jour", "message": "Tock se met à jour. Aucune écriture n'a été acceptée : rejoue cet appel tel quel.", "reessayer_dans_s": 15 } ``
Trois choses à en retenir, si tu écris un agent ou une tâche planifiée :
- Aucune écriture n'a été acceptée. C'est la raison d'être de ce code : un
502ou un délai dépassé laisse planer le doute — la commande est-elle passée avant la coupure ? Ici, non. Rejoue l'appel tel quel, y compris unPOST. - Attends ce que dit `Retry-After`, pas moins. Réessayer dans la seconde ne fait que cogner sur une porte qu'on est en train de repeindre.
- Ne compte pas un `503` comme une panne. Une tâche qui s'arrête au premier
503s'arrêtera à chaque publication, et tu la croiras cassée alors qu'elle n'a rien vu de plus qu'un déploiement.
La même réponse sert si Tock est réellement indisponible, avec le code indisponible au lieu de mise_a_jour : dans les deux cas la conduite à tenir est la même, et c'est pour ça qu'ils se ressemblent.
L'inventaire, dérivé de la description OpenAPI — c'est elle qui fait autorité, et un test échoue si une route existe sans y figurer :
uptime
GET /api/v1/uptime Les controles de disponibilite
POST /api/v1/uptime Poser un controle de disponibilite
GET /api/v1/uptime/{id} Un controle, avec ses etapes
PATCH /api/v1/uptime/{id} Modifier un controle
DELETE /api/v1/uptime/{id} Supprimer un controleveille
GET /api/v1/veille L etat de veille d un domaine
auth
GET /api/v1/journal Ce que les cles de l equipe ont fait
stats
POST /api/collecte/serveur Rapporter les robots vus par ton serveur GET /api/v1/evenements Relire les événements enregistrés POST /api/v1/evenements Enregistrer un événement métier
signaux
GET /api/v1/alertes/envoyees Les alertes parties
cron
GET /api/v1/changelog Ce qui a change depuis une date
GET /api/v1/analyser Analyser une expression cron
GET /api/v1/taches Lister les tâches et leur état
POST /api/v1/taches Créer une tâche
GET /api/v1/taches/{id} Détail et 20 dernières exécutions
PATCH /api/v1/taches/{id} Modifier une tache : planning, cible, controle, pause
DELETE /api/v1/taches/{id} Supprimer la tâche et tout son historique
GET /api/v1/recettes Ce qu il faut surveiller, deja ecrit
POST /api/v1/recettes/{cle}/poser Poser une recette : un appel, et la surveillance tourne
GET /api/v1/taches/{id}/executions L'historique d'une tâche, filtré et paginé
POST /api/v1/taches/{id}/declencher Déclencher une tâche maintenant, sans toucher au planning
POST /api/v1/taches/{id}/essai Essai à blanc : appeler la cible sans que ça compte
GET /api/v1/taches/export Exporter toutes les tâches de l’équipe en JSON
POST /api/v1/taches/import Réimporter un export
GET /api/ping/{cle} Signaler qu'un cron a tournéagents
GET /api/v1/openapi.json Cette description, en OpenAPI 3.1
GET /api/v1/agents/runs/{id} Un run, et toute sa trace
PATCH /api/v1/agents/runs/{id} Noter un run
GET /api/v1/agents/etat Ce que LeTock sait de toi, rendu à toi
GET /api/v1/agents/runs Relire les runs rapportés
POST /api/v1/agents/runs Rapporter un run d'agent
POST /api/v1/agents/validations Demander la validation humaine d’une action
GET /api/v1/agents/validations/{id} Lire la décision humaine
PATCH /api/v1/agents/validations/{id} Approuver ou refuser une validationerreurs
GET /api/v1/erreurs/{id} Une erreur, en détail
PATCH /api/v1/erreurs/{id} Changer l’état d’une erreur
GET /api/v1/erreurs Relire les erreurs
POST /api/v1/erreurs Rapporter une erreur côté serveurPOST /api/v1/mails/lot Envoyer un lot de messages personnalisés
GET /api/v1/mails/modeles Lister les modèles de message
DELETE /api/v1/mails/modeles Supprimer un modèle
POST /api/v1/mails Envoyer un mail depuis un domaine du projet
GET /api/v1/mails/{id} Ce qu’un message est devenu
GET /api/v1/mails/budget Ce qu il reste a consommer, AVANT d envoyer
GET /api/v1/mails/crochets Tes crochets sortants, et ce que ton serveur a repondu
POST /api/v1/mails/crochets Declarer un crochet sortant
POST /api/v1/mails/crochets/{id} Remettre un crochet en service apres une panne
DELETE /api/v1/mails/crochets/{id} Retirer un crochet
POST /api/v1/mails/crochets/{id}/essai Eprouver le chemin complet, sans attendre un vrai rebond
GET /api/v1/mails/boites Les adresses d un domaine, et si elles recoivent
POST /api/v1/mails/boites Ouvrir ou fermer une adresse
GET /api/v1/mails/evenements Le flux de ce que deviennent tes messages
GET /api/v1/mails/domaines L etape qui manque a chaque domaine
POST /api/v1/mails/domaines Relire le DNS d un domaine maintenant
GET /api/v1/mails/recus Le courrier recusocle
GET /api/v1/alertes Où arrivent les alertes POST /api/v1/alertes Ajouter une adresse, ou la mettre en sourdine DELETE /api/v1/alertes Retirer une adresse du carnet GET /api/v1/projets Les projets, leurs domaines et la clé publique de chacun GET /api/v1/compte Le forfait, les compteurs du mois, et ce qu’il reste GET /api/v1/domaines/dns Tous les enregistrements DNS a poser, au meme endroit
seo
GET /api/v1/seo Ce que les moteurs et les IA voient d’un domaine GET /api/v1/seo/pages Les pages d’un audit GET /api/v1/seo/audits Les audits précédents POST /api/v1/seo/audits Lancer un audit
forum
POST /api/v1/forum/reponses Répondre à un sujet du forum POST /api/v1/forum/sujets Ouvrir un sujet sur le forum GET /api/v1/forum/avis Savoir qu on t a repondu
La description complète, avec les schémas de corps et de réponse, est sur https://letock.fr/api/v1/openapi.json. Si tu génères du code, pars de là plutôt que de ce tableau : il a les types, ce tableau n'a que les intentions.