Référence de l'API d'ingestion
Voici l'API HTTP neutre que chaque client intègre. Si vous construisez ou maintenez un package client, implémentez-le contre ce contrat. Toutes les routes sont en JSON sur HTTPS.
Chemin de base et versionnage
Les points d'entrée d'ingestion se trouvent sous /api/v1. Envoyez et acceptez application/json (le téléversement de sauvegarde est la seule exception en multipart/form-data).
Authentification
Chaque requête s'authentifie avec une clé d'API de projet (lm_...). Deux styles d'en-tête sont acceptés ; la forme bearer est recommandée :
La clé est mise en correspondance par son hachage SHA-256 et se résout vers un seul projet. Les échecs d'authentification renvoient 401 :
Limites de débit
- Ingestion (
/ingest,/logs,/dependencies,/heartbeats/*) : 300 requêtes par minute, indexées par jeton de projet. - Sauvegardes (
/encryption-key,/backups*) : 60 requêtes par minute.
Dépasser une limite renvoie 429 Too Many Requests.
Quand l'ingestion est suspendue
Tant qu'un paiement reste dû sur l'abonnement de l'équipe, /ingest, /logs et /dependencies répondent 402 Payment Required et ne stockent rien :
Les pings de heartbeat continuent d'être enregistrés pendant cette période, pour qu'une équipe suspendue ne voie pas ses tâches planifiées passer pour cassées. Traitez un 402 comme un état à journaliser et à afficher, non comme une erreur à réessayer : il se lève de lui-même quand le paiement passe.
Un point d'entrée du coffre répond 402 dans la même période, avec son propre message : POST /backups. La lecture reste ouverte, matériel de clé compris, pour qu'une restauration de ce que vous avez déjà payé continue de fonctionner.
Lister, télécharger et supprimer une sauvegarde restent ouverts : une archive déjà stockée peut toujours être récupérée. Le point d'entrée de clé est celui à remarquer : il sert aussi le matériel dont monitor:restore a besoin, si bien que le déchiffrement côté client attend le paiement, là où le blob lui-même n'attend pas.
POST /api/v1/ingest, rapporter une exception
Rapporte une seule occurrence d'exception.
Corps de la requête
Règles des champs
| Champ | Requis | Type / limite |
|---|---|---|
exception.class | oui | chaîne, max 255 |
exception.message | non | chaîne, max 8192 |
exception.code | non | quelconque |
exception.file | non | chaîne, max 1024 |
exception.line | non | entier ≥ 0 |
exception.trace | non | tableau |
context.environment | non | chaîne, max 100 |
context.release | non | chaîne, max 255 (un SHA hex active la corrélation de commit) |
context.occurred_at | non | chaîne, max 64 (date analysable) |
Réponses
202 Accepted: stockée :
``json { "message": "accepted", "stored": true, "issue_id": "01kw6tkrd8wjbfv2pktr7ssw43" } ``
202 Accepted: quota dépassé, accusée mais non stockée :
``json { "message": "accepted", "stored": false } ``
422 Unprocessable Entity: échec de validation.
issue_id est l'identifiant public de l'issue, un ULID. C'est la valeur que porte l'URL du tableau de bord, vous pouvez donc la journaliser et la coller dans la barre d'adresse. Ce n'est pas un numéro de ligne, et la réponse ne contient aucun compteur d'occurrences : ces nombres auraient indiqué à chaque projet combien d'exceptions la plateforme entière avait stockées.
POST /api/v1/logs, rapporter des logs applicatifs (lot)
Stocke un lot d'entrées de log. Conditionné à la fonctionnalité de plan logs.
Corps de la requête
Règles des champs
| Champ | Requis | Type / limite |
|---|---|---|
logs | oui | tableau, 1 à 500 entrées |
logs.*.level | non | chaîne, max 20 |
logs.*.message | oui | chaîne, max 8192 |
logs.*.context | non | tableau |
logs.*.channel | non | chaîne, max 100 |
logs.*.environment | non | chaîne, max 100 |
logs.*.release | non | chaîne, max 255 |
logs.*.logged_at | non | chaîne, max 64 |
Réponses
202 Accepted:
``json { "message": "accepted", "stored": 137 } ``
stored indique combien d'entrées ont réellement été enregistrées (un lot partiel est stocké lorsque le quota est presque plein).
403 Forbidden: le plan n'inclut pas les logs :
``json { "message": "Application logs are not available on your current plan." } ``
POST /api/v1/dependencies, rapporter le composer.lock
Remplace l'instantané de dépendances du projet et déclenche un scan de vulnérabilités en arrière-plan.
Corps de la requête
Règles des champs
| Champ | Requis | Type / limite |
|---|---|---|
packages | oui | tableau, 1 à 5000 entrées |
packages.*.name | oui | chaîne, max 255 |
packages.*.version | oui | chaîne, max 100 |
packages.*.is_dev | non | booléen |
Réponse
202 Accepted:
``json { "message": "accepted", "dependencies": 142 } ``
POST /api/v1/heartbeats/{slug}, pinguer une tâche planifiée
Signale qu'une tâche planifiée vient de s'exécuter. La requête ne porte aucun corps.
{slug} est normalisé en minuscules, chiffres et tirets. Le premier ping sur un slug inconnu enregistre le heartbeat non armé : il est consigné et n'alerte jamais tant qu'une période attendue n'a pas été définie dans le tableau de bord. Voir Heartbeats.
Réponses
202 Accepted:
``json { "message": "pong", "armed": true } ``
armed indique si une période attendue est définie, pour qu'un client distingue un ping consigné d'un ping surveillé.
422 Unprocessable Entity: le slug se normalise en chaîne vide, ou le projet détient déjà le nombre maximal de heartbeats.
Points d'entrée du coffre de sauvegardes
Ceux-ci alimentent le coffre de sauvegardes chiffrées. Tous requièrent la fonctionnalité de plan backups. Tant qu'un paiement reste dû, POST /backups répond 402 Payment Required ; récupérer le matériel de clé, lister, télécharger et supprimer restent ouverts, pour que monitor:restore continue de fonctionner sur les archives déjà en place.
GET /api/v1/encryption-key
Sert le matériel de clé de l'équipe pour que le client puisse sceller et (avec la phrase secrète, en local) désenvelopper.
403si le plan n'inclut pas les sauvegardes.404si l'équipe n'a pas configuré de clés de chiffrement.
GET /api/v1/backups
POST /api/v1/backups
Téléversement multipart/form-data d'un blob déjà chiffré.
| Champ | Requis | Remarques |
|---|---|---|
type | oui | database ou files |
name | non | chaîne, max 255 |
file | oui | l'archive chiffrée |
201 Createdrenvoie les métadonnées de la sauvegarde stockée (même forme qu'une entrée de liste).403si le plan n'inclut pas les sauvegardes.413 Request Entity Too Largesi le téléversement dépasserait le quota de stockage :
``json { "message": "Backup storage quota exceeded.", "used_bytes": 5012345678, "limit_bytes": 5000000000 } ``
GET /api/v1/backups/{uuid}
Diffuse le blob chiffré en téléchargement (<nom>.enc).
DELETE /api/v1/backups/{uuid}
Supprime la sauvegarde. Renvoie 204 No Content.
Récapitulatif des erreurs
| Statut | Signification |
|---|---|
202 Accepted | Ingéré (consultez stored pour savoir ce qui a été conservé). |
201 Created | Sauvegarde téléversée. |
204 No Content | Sauvegarde supprimée. |
401 Unauthorized | Clé d'API manquante ou invalide. |
402 Payment Required | Ingestion, matériel de clé et téléversements de sauvegarde suspendus tant qu'un paiement reste dû. |
403 Forbidden | Fonctionnalité absente du plan de l'équipe. |
404 Not Found | Clés de chiffrement non configurées (point d'entrée de clé). |
413 Payload Too Large | Quota de stockage des sauvegardes dépassé. |
422 Unprocessable Entity | Échec de validation. |
429 Too Many Requests | Limite de débit dépassée. |
Vous lisez la documentation Quiet Guard v1.0.