API REST
Lisez et écrivez vos moniteurs, lisez et mettez à jour vos incidents, et téléversez des source maps. Tout ici passe par les mêmes vérifications de permissions et le même filtre de cloisonnement entre clients que le tableau de bord — il n’existe pas d’implémentation séparée du côté de l’API qui pourrait s’en écarter.
Incluse dans tous les forfaits, y compris le gratuit. Il n’y a pas de module à acheter ni de palier qui la déverrouille.
URL de base
https://vitrinaengine.com/api/v1Description exploitable par un programme
/openapi.json est un document OpenAPI 3.1 qui couvre toutes les routes de cette page. Pointez-y un générateur de client, ou confiez-le à un agent qui doit appeler cette API sans qu’on lui explique comment.
Il est généré depuis le service plutôt qu’écrit à côté : les routes proviennent de la surface que l’API publie elle-même sur GET /, les structures et leurs explications des mêmes fichiers .proto sur /api/proto, et les limites de débit du code qui les applique. Une compilation échoue lorsque le document et l’API divergent : il décrit donc ce qui est servi, et non ce qui était vrai lors de la dernière modification.
Il décrit les structures. Les raisons sont sur cette page — qu’un identifiant appartenant à une autre organisation répond 404, que config n’est jamais renvoyé — et aucun générateur ne sait les écrire.
Pour les agents : MCP
https://vitrinaengine.com/mcp est un serveur Model Context Protocol. Ajoutez-le à un client MCP avec une clé d’API comme jeton bearer, et un agent peut lire vos moniteurs, incidents, erreurs et statistiques — et créer, modifier et supprimer des moniteurs — sans qu’on lui explique le fonctionnement de cette API.
{
"mcpServers": {
"vitrina-engine": {
"type": "http",
"url": "https://vitrinaengine.com/mcp",
"headers": { "Authorization": "Bearer vte_your_key_here" }
}
}
}Il lit tout et n’écrit que trois choses. Chaque opération GET de cette page est un outil, ainsi que POST /monitors, PATCH /monitors/{id} et DELETE /monitors/{id}. Rien d’autre qui écrive n’est accessible — ni un espace de travail, ni un membre, ni une clé d’API, ni une page de statut, ni votre compte — parce qu’aucun outil n’existe pour cela, et que la liste des écritures autorisées tient en trois lignes que quelqu’un doit ajouter délibérément.
Une clé sans droit d’écriture reste refusée. Un appel d’outil est la même requête que la clé ferait directement, soumise au même contrôle de permission et au même filtre de cloisonnement : un agent muni d’une clé en lecture seule lit. Donnez- lui-en une, sauf si vous voulez qu’il modifie votre supervision — et attendez-vous à ce qu’un client vous demande confirmation avant de supprimer : supprimer un moniteur emporte son historique et il n’y a pas de retour en arrière. Pour faire taire un moniteur sans le perdre, mettez-le en pause avec PATCH.
Puisque c’est la même requête, elle voit exactement ce que voit la clé, écrit la même entrée au journal d’audit que le tableau de bord, et compte dans la même limite de débit — deux fois, une pour l’appel et une pour la requête qu’il contient. Une écriture est décomptée de la limite d’écriture.
Une chose à savoir avant qu’un agent ne modifie un moniteur : config est remplacé en entier, jamais fusionné. Lisez d’abord le moniteur, changez le champ voulu et renvoyez l’objet complet. Une configuration partielle supprime silencieusement les en-têtes et les identifiants dont dépend la vérification, et la laisse tourner.
Authentification
Créez une clé sous Paramètres → Clés d’API, puis envoyez-la comme jeton bearer. La clé n’est affichée qu’une fois, à sa création, et n’est conservée que sous forme d’empreinte — si vous la perdez, créez-en une autre.
curl https://vitrinaengine.com/api/v1/summary \
-H "Authorization: Bearer vte_your_key_here"Une clé n’accorde jamais plus que ce qu’avait la personne qui l’a créée. Elle est liée à son adhésion et porte donc son rôle : une clé créée par quelqu’un dont le rôle est en lecture seule ne peut pas écrire, quoi que vous lui envoyiez. Une clé peut aussi être confinée à un seul espace de travail, auquel cas chaque réponse est filtrée à cet espace et tout ce qui est en dehors n’existe pas pour cette clé.
Retirer quelqu’un de votre organisation révoque les clés qu’il a créées, dans la même opération. Révoquer un accès doit emporter les identifiants avec lui, sinon la personne en conserve un qui fonctionne.
Conventions
Toute réponse réussie est un objet JSON doté d’une propriété data. Tout échec est un objet JSON doté d’une propriété error contenant une phrase destinée à un être humain.
{ "data": { "id": "8f14e45f-…", "name": "Marketing site" } }
{ "error": "This key cannot create monitors." }Les réponses sont envoyées avec Cache-Control: private, no-store. Ce sont des données propres à une clé sur une origine partagée, et elles ne doivent jamais être conservées par un mandataire.
Protobuf et gzip
Chaque point d’accès sous /api/v1 parle aussi Protocol Buffers. Avec Accept: application/x-protobuf, la réponse arrive en protobuf ; si vous envoyez un body en protobuf avec Content-Type: application/x-protobuf, la réponse revient dans le même format. Sans l’un ni l’autre, c’est du JSON, comme avant.
curl https://vitrinaengine.com/api/v1/monitors \
-H "Authorization: Bearer vte_your_key_here" \
-H "Accept: application/x-protobuf" \
--compressed -o monitors.pbLes messages sont publiés : /api/proto liste chaque fichier. Téléchargez-les en conservant leurs chemins et pointez protoc -I sur ce répertoire. Trois points diffèrent de ce qu’on attend de protobuf : un champ qui peut être vide vaut null en JSON et est absent en protobuf ; quelques champs dont la forme varie — le config d’un moniteur ou d’un canal, par exemple — sont des documents JSON portés dans une chaîne ; et StringList enveloppe une liste qui peut elle-même valoir null.
Gzip fonctionne dans les deux sens : Accept-Encoding: gzip pour les réponses, Content-Encoding: gzip pour les requêtes. Comme deux clients peuvent désormais recevoir des octets différents pour la même URL, chaque réponse porte Vary: Accept, Content-Type.
Codes d’état
| Code | Signification |
|---|---|
200 | Tout va bien. 201 quand quelque chose a été créé. |
400 | Le corps n’était pas du JSON, un champ manque, ou rien n’a été demandé. |
401 | Aucune clé, ou une clé invalide. Ne dit délibérément jamais laquelle des deux — un message qui les distinguerait serait un moyen de tester des clés. |
403 | Une clé valide, sans la permission pour cette action. Le message la nomme. |
404 | Aucun enregistrement de ce genre pour vous. Voir plus bas. |
413 | Une source map au-delà de la taille maximale. |
429 | Au-delà d’une limite de débit. Porte Retry-After. Voir plus bas. |
Codes de refus
Tout corps non-2xx porte un code à côté de la phrase — not_found, limit_reached, rate_limited — et c’est le champ sur lequel brancher. La chaîne error est de la prose pour quelqu’un qui lit un journal et peut être reformulée à tout moment ; le code, lui, est stable. Là où la phrase nomme une valeur, vars porte ces valeurs sous forme de chaînes, pour que vous les placiez là où votre propre grammaire les veut plutôt que de les extraire de l’anglais.
{
"error": "The Pro plan includes 50 monitors, and you have 50.",
"code": "limit_reached",
"vars": { "plan": "pro", "limit": "50", "current": "50", "resource": "monitors" }
}C’est de là que nos propres applications tirent un refus dans la langue de qui le lit. Traitez un code que vous ne connaissez pas comme elles le font — repliez-vous sur error — car des codes sont ajoutés sans changement de version.
Limites de débit
Par organisation, et non par clé — créer une clé de plus ne les augmente pas.
| Catégorie | Limite |
|---|---|
Lectures (GET) | 120 par minute |
Écritures (POST, PATCH, DELETE) | 30 par minute |
| Téléversements de source maps | 300 par heure |
Au-delà de la limite, la réponse est 429 avec un en-tête Retry-After donnant le nombre entier de secondes avant la réinitialisation de la fenêtre. Respectez-le plutôt que de réessayer immédiatement.
Elles sont fixées là où une intégration normale ne les atteint jamais : un tableau mural qui interroge toutes les dix secondes dépense six des 120 lectures. Elles sont les mêmes sur tous les forfaits, parce que les points d’accès de collection renvoient tout dans une seule réponse — un compte avec cinq cents moniteurs n’a pas besoin de plus de requêtes qu’un compte qui en a vingt. Les source maps ont une limite horaire parce qu’elles arrivent en lot au moment du déploiement, où une interface peut facilement compter une centaine de fragments.
404 plutôt que 403, délibérément
Un identifiant appartenant à un autre client obtient « Not found. », et non « Forbidden. » Un 403 confirmerait que l’enregistrement existe, ce qui transformerait le point d’accès en moyen de vérifier si un identifiant est réel. Ne lisez pas un 404 comme la preuve que rien n’existe nulle part — seulement que rien n’existe que cette clé ait le droit de voir.
Points d’accès
GET /search
Tout ce qui correspond à ?q= dans le compte : moniteurs, incidents et leurs analyses post-incident, serveurs, pages de statut, espaces de travail, canaux de notification, fenêtres de maintenance, projets d’erreurs et problèmes, sites d’analyse, membres et invitations, clés d’API, agents et sondes privées. Une seule requête au lieu d’une par type.
?type= restreint à une liste de types séparés par des virgules et ?limit= plafonne les résultats de chaque type entre 1 et 20 (5 par défaut). Chaque type exige la même permission que son propre point d’accès ; un type que votre clé ne peut pas lire est absent exactement comme un type sans correspondance. Rien de scellé, de haché ni de secret n’est recherché ni renvoyé.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
limit | query | integer |
q | query | string |
type | query | string |
| Réponse | SearchResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /summary
Des décomptes, pour un tableau mural ou un résumé quotidien. Requiert monitor:read.
{
"data": {
"total": 42, "up": 39, "degraded": 1, "down": 1,
"paused": 1, "pending": 0,
"openIncidents": 2, "suppressedIncidents": 1
}
}suppressedIncidents compte les incidents retenus parce qu’ils sont la conséquence d’un autre. Ils sont réels, et ce ne sont pas des pannes distinctes.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | GetSummaryResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /setup
Ce qu’il reste à faire sur un compte neuf — les quatre mêmes questions que la liste de mise en route du tableau de bord, recalculées à chaque lecture. Nécessite monitor:read.
{
"data": {
"hasMonitor": true,
"hasConfirmedChannel": false,
"hasStatusPage": false,
"hasColleague": false,
"dismissedAt": null
}
}hasConfirmedChannel demande si une alerte pourrait réellement arriver, et non si un canal existe. Les deux se sont dissociés une fois, salement, et une liste qui cocherait l’alerte comme configurée pour un canal que nous refusons de servir répéterait ce défaut en guise de réassurance.
hasColleague compte les adhésions et jamais les invitations : une invitation envoyée et non acceptée n’a ajouté personne.
Pas replié dans /summary, parce que cet endpoint n’est que des décomptes par statut — un mur d’écrans qui l’interroge toutes les quelques secondes ne veut pas cinq requêtes de plus pour afficher un rappel destiné à quelqu’un qui a configuré le compte il y a des mois.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | GetSetupResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
DELETE /setup
Passe la liste. Nécessite org:update, car la mise de côté est une ligne à l’échelle de l’organisation et non une préférence individuelle — la personne qui arrive ensuite ne la revoit pas.
Rien d’autre ne change sur le compte, et aucune entrée d’audit n’est écrite : masquer un rappel ne change rien à la façon dont le produit se comporte, alerte ou facture.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | DismissedResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /monitors
Tous les moniteurs que la clé peut voir. Requiert monitor:read. Chacun porte id, name, kind, status, statusSince, enabled, intervalSeconds, tags, workspace, lastCheckedAt, lastResponseTimeMs, lastMessage, uptime24h, uptime30d et openIncidentId.
?tag=prod,eu restreint la liste aux moniteurs portant toutes les étiquettes nommées — ET, pas OU, si bien qu’une deuxième étiquette renvoie toujours moins de moniteurs plutôt que plus. Le filtre du tableau de bord se lit de la même façon. Les étiquettes sont stockées en minuscules, et la valeur est convertie de la même façon avant comparaison : ?tag=Prod les trouve donc. Une entrée qui ne pourrait pas être une étiquette — vide, ou plus longue qu’une étiquette ne peut l’être — est ignorée et le reste du filtre s’applique quand même, plutôt que de refuser l’appel : un lien ne doit pas cesser de fonctionner parce qu’une de ses étiquettes a été renommée.
config n’est jamais renvoyé. Pour certains genres, il contient des en-têtes de requête et des identifiants, et une clé en lecture seule ne doit pas être un moyen de relire les secrets que quelqu’un a saisis dans un formulaire.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
tag | query | string |
| Réponse | ListMonitorsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /monitors
Requiert monitor:create. Exige name, kind, workspaceId et config. Facultatifs : intervalSeconds (300 par défaut), confirmations, dependsOn.
curl -X POST https://vitrinaengine.com/api/v1/monitors \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing site",
"kind": "http",
"workspaceId": "…",
"intervalSeconds": 60,
"config": {
"url": "https://example.com",
"assertions": [{ "type": "status_code", "operator": "lt", "value": "400" }]
}
}'Répond 201 avec le nouvel identifiant. L’intervalle est ramené au plancher de votre forfait plutôt que refusé : demander 10 secondes sur un forfait dont le plancher est de 60 vous en donne 60 — relisez-le si cela compte.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
name | body | string |
kind | body | string |
workspaceId | body | string |
config | body | string |
intervalSeconds | body | integer |
confirmations | body | integer |
dependsOn | body | string[] |
probeId | body | string |
tags | body | string[] |
| Réponse | CreatedResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /monitors/{id}
Un moniteur, avec tout ce que donne la liste plus paused. Requiert monitor:read.
Pour mail_posture, tls_audit et snmp, il porte aussi lastCheckDetail, le résultat de la dernière vérification : les constats derrière le statut, chacun avec un code stable et une severity, plus une note TLS ou les relevés SNMP. Il vaut null jusqu’à la première vérification et est absent pour les autres types.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetMonitorResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PATCH /monitors/{id}
N’envoyez que ce que vous voulez changer : name, intervalSeconds, confirmations, enabled, config, ou paused.
paused est vérifié contre monitor:pause et tout le reste contre monitor:update, séparément — une clé autorisée à mettre en pause mais pas à modifier peut quand même mettre en pause. Envoyer une modification vide donne un 400.
Le moniteur est relu puis renvoyé, au lieu que l’entrée soit répétée telle quelle : ce que vous voyez est ce qui a été enregistré.
# Silence a monitor for the length of a deploy.
curl -X PATCH https://vitrinaengine.com/api/v1/monitors/$ID \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{"paused": true}'Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
name | body | string |
intervalSeconds | body | integer |
confirmations | body | integer |
enabled | body | boolean |
paused | body | boolean |
config | body | string |
tags | body | StringList |
| Réponse | UpdatedMonitorResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /monitors/{id}
Requiert monitor:delete. Répond { "data": { "id": "…", "deleted": true } }.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /hosts · POST /hosts
Les serveurs sont la seconde façon de regrouper les moniteurs : l’espace de travail dit à qui appartient un moniteur, le serveur dit où il tourne. Entièrement facultatif — un compte qui n’en crée jamais ne perd rien, et la plupart des moniteurs ne nomment aucun serveur.
Chaque serveur porte status, pinned et spanning. status ne vient que des moniteurs qui tournent sur ce serveur et nulle part ailleurs. Un moniteur réparti sur plusieurs machines compte dans spanning et n’en colore aucune : une panne sur un point d’entrée réparti indique que le service est cassé, pas quelle machine l’a cassé. Un serveur sans moniteur propre répond "status": null plutôt que up.
POST exige monitor:create et un name. Les champs facultatifs provider, address et notes sont les vôtres : rien dans le produit ne les utilise. Un nom identique à un nom existant — la casse et le point final sont ignorés — répond 409.
Paramètres et réponses
GET /hosts
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListHostsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /hosts
| Nom | Emplacement | Type |
|---|---|---|
name | body | string |
provider | body | string |
address | body | string |
notes | body | string |
| Réponse | CreatedResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /hosts/{id} · PATCH /hosts/{id} · DELETE /hosts/{id}
Le détail porte le serveur et ses moniteurs, chacun marqué pinned et, quand il ne l’est pas, alsoOn : les autres machines depuis lesquelles il répond, ce que l’on lit avant de redémarrer l’une d’elles. DELETE retire le serveur et tous ses moniteurs continuent de tourner — un serveur n’a ni planning ni historique propre.
Paramètres et réponses
GET /hosts/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetHostResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PATCH /hosts/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
name | body | string |
provider | body | string |
address | body | string |
notes | body | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /hosts/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /hosts/{id}/monitors · DELETE /hosts/{id}/monitors
Un moniteur ajouté ou retiré d’un serveur, via monitorId dans le corps ou ?monitorId=. Délibérément pas une liste entière : sur un compte d’agence un serveur porte des moniteurs de plusieurs espaces de travail, et remplacer « la liste » reviendrait à remplacer des lignes jamais montrées. Les deux sens sont idempotents.
Paramètres et réponses
POST /hosts/{id}/monitors
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
monitorId | body | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /hosts/{id}/monitors
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
monitorId | query | string |
monitorId | body | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /monitors/{id}/hosts · PUT /monitors/{id}/hosts
L’autre côté de la même relation, et celui-ci est bien une liste entière : ces liens appartiennent à un seul moniteur, donc rien à l’autre bout n’est visible par un autre espace de travail. Envoyez hostIds ; un tableau vide est une vraie demande et signifie que le moniteur ne tourne sur aucun serveur en particulier. Les identifiants qui ne sont pas les vôtres sont ignorés plutôt que refusés. Toute réponse de moniteur porte aussi hosts, vide s’il n’y en a aucun.
Paramètres et réponses
GET /monitors/{id}/hosts
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | ListMonitorHostsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PUT /monitors/{id}/hosts
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
hostIds | body | string[] |
| Réponse | ListMonitorHostsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /incidents
Requiert incident:read. Accepte ?status= — l’une des valeurs open, acknowledged, resolved ou suppressed — et ?open=true pour les trois qui ne sont pas résolus. Un statut inconnu est ignoré plutôt que refusé, de la même manière que ?limit= (50 par défaut) est ramené à 200 plutôt que rejeté.
Chacun porte id, monitorId, monitorName, title, cause, status, severity, startedAt, resolvedAt, durationSeconds, acknowledgedAt et rootIncidentId.
rootIncidentId est le champ à regarder quand vous construisez un fil d’alertes. Lorsqu’il est renseigné, cet incident est la conséquence d’un autre — l’hôte de la base de données est tombé et voici l’un des douze services qui se trouvent derrière. Ignorez-les et vous obtenez une alerte au lieu de treize.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
limit | query | integer |
open | query | boolean |
status | query | string |
| Réponse | ListIncidentsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /incidents/{id}
Un incident. Requiert incident:read. Les mêmes champs que la liste, plus workspaceId.
Il ne renvoie pas la chronologie de l’incident — les commentaires et les changements d’état affichés dans le tableau de bord ne sont pas sur ce point d’accès. Si vous en avez besoin, dites-le et ils pourront être ajoutés; les documenter ici alors qu’ils n’existent pas serait pire que le manque.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetIncidentResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PATCH /incidents/{id}
Envoyez un status valant "acknowledged" ou "resolved", ou un comment, ou les deux. Chacun est vérifié contre sa propre permission : incident:acknowledge, incident:resolve, incident:comment. Ajouter "publish": true à un commentaire le place sur la page d’état et requiert en plus status_page:manage.
# A runbook that fixed the thing itself can close its own incident.
curl -X PATCH https://vitrinaengine.com/api/v1/incidents/$ID \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{"status": "resolved", "comment": "Restarted by runbook.", "publish": true}'Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
status | body | string |
comment | body | string |
publish | body | boolean |
| Réponse | GetIncidentResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
PUT /incidents/{id}/postmortem
Rédige ou remplace le post-mortem de l’incident. Nécessite incident:resolve, et l’incident doit déjà être résolu — sinon 409 avec le code incident_not_resolved. Envoyez body en Markdown, de 1 à 50 000 caractères après suppression des espaces (postmortem_required, postmortem_too_long). Il y en a un par incident : chaque appel remplace donc le précédent. La réponse est l’incident, tel que GET /incidents/{id} le renvoie.
GET /incidents/{id} le porte sous la forme postmortem: { body, authorName, updatedAt }, ou null, et la liste porte hasPostmortem. Affichez body comme du Markdown et jamais comme du HTML : c’est un texte saisi par une personne. Un post-mortem est interne et n’apparaît jamais sur une page de statut.
curl -X PUT https://vitrinaengine.com/api/v1/incidents/$ID/postmortem \
-H "Authorization: Bearer vte_…" \
-H "Content-Type: application/json" \
-d '{"body": "## What happened\n\nThe connection pool ran dry after a deploy."}'Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
body | body | string |
| Réponse | GetIncidentResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /probes
Les sondes privées de votre organisation : id, name, lastSeenAt, version, hostname, monitorCount, revoked et createdAt. Nécessite agent:read. C’est ce que propose le sélecteur de sonde d’un moniteur.
Il n’y a pas de champ de région, et il n’y en aura pas. Vous choisissez une sonde par son nom ; l’endroit où s’exécute une vérification derrière elle, c’est à nous de le décider et de le changer. Les sondes révoquées apparaissent avec revoked: true et ne reçoivent plus de travail : ne les proposez pas.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListProbesResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /monitors/{id}/push-url
L’URL de ping d’un moniteur heartbeat, affichée à nouveau. Nécessite monitor:read. url vaut null pour un type qui ne reçoit pas de ping, et pour un jeton qui ne peut plus être déchiffré — le moniteur continue de fonctionner, et renouveler le jeton dans le tableau de bord fournit une URL affichable.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetPushUrlResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /organizations · PUT /organizations/active
Les organisations dont la personne connectée est membre, chacune avec son role et active sur celle en cours, et le passage de l’une à l’autre. Envoyez organizationId ; la réponse est l’adhésion désormais utilisée.
Session connectée uniquement. Une clé appartient à une seule adhésion et reçoit 403 avec session_required. Changer d’organisation déplace toutes les sessions de cette personne, tableau de bord compris, et une organisation dont elle n’est pas membre renvoie 404.
Paramètres et réponses
GET /organizations
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListOrganizationsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PUT /organizations/active
| Nom | Emplacement | Type |
|---|---|---|
organizationId | body | string |
| Réponse | ActiveOrganizationResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /sms/enrolment · POST /sms/enrolment/confirm
Enregistrez votre propre numéro de mobile pour les alertes SMS : envoyez phone (et éventuellement name), et nous y envoyons un code à six chiffres ; envoyez ce code à la seconde route pour confirmer. Nécessite notification_channel:manage et une session connectée — un numéro est ajouté par la personne qui tient le téléphone, jamais par une clé.
Le numéro est enregistré non confirmé et ne reçoit rien tant que le code n’est pas revenu. Un nouvel enregistrement remplace votre numéro précédent. Refus : sms_not_included (402, l’offre n’inclut pas de SMS), not_a_phone_number, sms_country_unsupported, sms_route_not_open, verification_code_not_sent (502 ; rappelez pour obtenir un nouveau code), verification_code_malformed et verification_code_incorrect. Un démarrage réussi porte country et caveat — sender-replaced, registration-pending, unverified ou null —, à montrer avant que quelqu’un compte sur ce numéro.
Paramètres et réponses
POST /sms/enrolment
| Nom | Emplacement | Type |
|---|---|---|
phone | body | string |
name | body | string |
| Réponse | SmsEnrolmentResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /sms/enrolment/confirm
| Nom | Emplacement | Type |
|---|---|---|
code | body | string |
| Réponse | SmsConfirmedResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /channels/{id}/confirmation
Renvoie le message de confirmation d’un canal e-mail. Nécessite notification_channel:manage. Chaque appel émet un nouveau lien et le précédent cesse de fonctionner. sent: false signifie qu’il n’y avait rien à envoyer — l’adresse a déjà confirmé — et une adresse confirmée n’est jamais relancée par ce biais. Un envoi refusé par le fournisseur de messagerie renvoie 502 avec confirmation_not_sent.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | ChannelConfirmationResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
PATCH /workspaces/{id}
Renomme un espace de travail. Nécessite workspace:update. name est obligatoire (1 à 80 caractères), clientReference facultatif — null l’efface. Le slug ne change jamais, car il figure dans les URL des pages de statut. La réponse est l’espace de travail tel qu’il est désormais.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
name | body | string |
clientReference | body | requests.NullableString |
| Réponse | UpdatedWorkspaceResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /sourcemaps
Téléversez une source map pour que les traces d’appels minifiées se résolvent. Requiert monitor:create. Exige projectRef (un nombre) et filename, ainsi que la carte elle-même sous forme de map (JSON) ou de mapGzipBase64. Facultatifs : debugId et release.
Envoyez un debug id ou une release. Une carte qui n’a ni l’un ni l’autre ne peut être appariée à aucune trace d’appels et restera là sans rien faire. L’appariement se fait par debugId d’abord, puis par release et nom de fichier.
Les cartes sont résolues à la lecture d’un problème et non au téléversement : une carte envoyée après l’arrivée des erreurs sert donc quand même — et c’est l’ordre habituel.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
projectRef | body | integer |
filename | body | string |
debugId | body | string |
release | body | string |
map | body | string |
mapGzipBase64 | body | string |
| Réponse | UploadedSourceMapResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 300 par heure |
POST /symbols
La même idée pour une application native : téléversez un .dSYM iOS ou un mapping.txt R8 d’Android pour que les piles de plantage se résolvent. Requiert monitor:create. Vingt téléversements par heure, et l’équivalent de vingt versions conservé par projet.
Contrairement à /sourcemaps, le corps est le fichier gzippé lui-même et les métadonnées sont dans les en-têtes : X-Vitrina-Project-Ref, X-Vitrina-Platform (ios ou android), X-Vitrina-Symbol-Name et X-Vitrina-Release. Un dSYM pèse des dizaines de mégaoctets, et le base64 dans un champ JSON coûte un tiers de plus en transfert.
Les deux plateformes ne sont pas appariées de la même façon. Une trame iOS nomme l’UUID Mach-O de l’image à laquelle elle appartient : un téléversement iOS doit donc porter X-Vitrina-Debug-Ids et est apparié dessus, exactement. R8 n’émet aucun identifiant de ce genre, si bien qu’un mapping Android est apparié sur la seule release — qui doit être très exactement ce que l’application rapporte, <applicationId>@<versionName>+<versionCode>. Un chiffre d’écart et les trames se résolvent vers des lignes qui paraissent plausibles et qui sont fausses.
Reléverser la même version remplace ses symboles au lieu d’échouer : une tâche de publication relancée n’est donc pas une erreur. Comme pour les source maps, la résolution a lieu à la lecture d’un problème.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | UploadedSymbolsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 20 par heure |
GET /errors/projects
Les projets de suivi d’erreurs que détient ce compte. Requiert monitor:read. Chacun porte ref — le nombre présent dans le DSN — ainsi que publicKey, unresolved et eventsLast24h. En lecture seule : un projet est créé avec une clé qu’il faut encore coller dans la configuration d’une application, il n’y a donc rien ici qu’un point d’accès viendrait achever.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListErrorProjectsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /errors/issues
Les erreurs regroupées, l’activité la plus récente d’abord. Requiert monitor:read. Un problème est une empreinte et non un événement : mille occurrences d’une même levée forment une seule ligne, avec timesSeen à mille. ?status= vaut unresolved par défaut et accepte aussi resolved, ignored ou all ; ?project= filtre par identifiant de projet, ?q= cherche dans le type, la valeur et le coupable, et ?limit= est plafonné à 200. spark contient vingt-quatre décomptes horaires, du plus ancien au plus récent.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
limit | query | integer |
project | query | string |
q | query | string |
status | query | string |
| Réponse | ListIssuesResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /errors/issues/{id}
Un problème avec sa pile. Requiert monitor:read. exceptions est la chaîne que fournit le SDK lui-même, l’erreur levée en dernier et ses causes avant elle, et ses trames sont résolues avec les source maps que vous avez téléversées — la même résolution que celle du tableau de bord, de sorte qu’un script et la personne à qui vous parlez ne regardent jamais des piles différentes. Une carte qui ne peut pas s’appliquer retombe sur les trames d’origine plutôt que de faire échouer la requête.
lastEvent porte deux horodatages à dessein. occurredAt est ce que le SDK a rapporté et receivedAt le moment où l’ingestion l’a écrit ; un appareil qui était hors ligne, ou une file qui a pris du retard, c’est exactement l’écart entre les deux.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetIssueResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PATCH /errors/issues/{id}
Résoudre, ignorer ou rouvrir : { "status": "resolved" }. Requiert monitor:update. ignoreHours peut accompagner ignored pour cesser de l’ignorer plus tard, et est plafonné à 90 jours.
Résoudre enregistre la release dans laquelle la résolution a eu lieu : un retardataire venu d’un déploiement plus ancien ne rouvre donc pas le problème. Lorsque le SDK n’a envoyé aucune release, il n’y a rien à quoi comparer et tout événement ultérieur le rouvre bel et bien — faute de pouvoir distinguer un retardataire d’une régression, l’hypothèse prudente est que le bogue est de retour.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
status | body | string |
ignoreHours | body | integer |
| Réponse | IssueStatusResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /analytics
Les sites web que ce compte mesure. Requiert monitor:read. Porte publicId — la valeur qui va dans la balise de script, publique par conception — ainsi que viewsLast24h et trafficAlerting, vrai tant que le trafic d’un site reste sous ce que cette heure-là voit d’habitude.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListAnalyticsSitesResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /analytics/{id}
Les chiffres d’un site, pour un tableur ou un rapport. Requiert monitor:read. ?days= vaut 7 par défaut et est plafonné à 365. ?dimensions= prend une liste séparée par des virgules parmi path, referrer, country, browser, os, device, utm_source, utm_medium, utm_campaign et event ; une dimension inconnue donne un 400 plutôt qu’une réponse vide, parce qu’une faute de frappe qui ne renvoie rien se lit comme « aucun trafic ».
Le chiffre des visiteurs s’appelle dailyUniqueVisitors, et c’est bien ce qu’il est. C’est la somme des uniques quotidiens et il ne peut être rien d’autre : le secret derrière une empreinte de visiteur est détruit à la fin de sa journée UTC, si bien que quelqu’un venu deux jours compte deux fois et qu’aucune clé ne permettrait de les réunir. C’est la conception de la confidentialité qui fonctionne, et non une approximation — mais un champ nommé visitors à côté d’une plage de 30 jours vous inviterait à rapporter un nombre qui veut dire autre chose.
curl "https://vitrinaengine.com/api/v1/analytics/$ID?days=30&dimensions=path,referrer" \
-H "Authorization: Bearer vte_…"Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
days | query | integer |
| Réponse | GetAnalyticsSiteResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /billing
Le forfait, et où il est facturé. Requiert billing:read. Porte plan, status, cadence, currentPeriodEnd, cancelAt, addOnPacks et la douzaine de reçus les plus récents.
source vaut paddle, apple, manual ou none. Cela compte : un abonnement acheté dans l’application iOS appartient à Apple, et le forfait, la carte et l’annulation vivent tous dans les réglages App Store du client plutôt qu’ici. canCheckoutOnWeb et canPurchaseInApp disent quelles offres peuvent être affichées sans risque, pour qu’un client n’ait pas à redériver cette règle et à se tromper dans le sens qui facture quelqu’un deux fois.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | GetBillingResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /monitors/{id}/history
La disponibilité quotidienne d’un moniteur. Requiert monitor:read. Accepte days, jusqu’à la durée de conservation de l’historique de votre forfait.
Calculée à partir des agrégats quotidiens plutôt que des résultats de vérification un à un : c’est pourquoi elle continue de répondre pour des périodes dont la conservation des résultats bruts a déjà supprimé les données.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
days | query | integer |
| Réponse | GetMonitorHistoryResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /monitors/{id}/graph · GET /monitors/graphs
Les dernières heures d’un moniteur, heure par heure, ou de tous les moniteurs que voit cette clé en une seule réponse — ce que le tableau de bord dessine sur la ligne et la page d’un moniteur. Requiert monitor:read. Accepte hours, 24 par défaut et 168 au plus.
Un graphique uptime porte la part des vérifications réussies de chaque heure, avec null pour une heure sans vérification ; un graphique value, pour les types quantitatifs, porte ses mesures en séries avec leur unité. Chaque heure de la fenêtre est présente, qu’il y ait eu un enregistrement ou non, pour qu’un trou reste visible. Les mesures sont envoyées telles quelles : une série raw n’a pas d’échelle connue, dessinez-la par rapport à sa propre mesure la plus haute et n’affichez jamais cette part comme si c’était la mesure.
Paramètres et réponses
GET /monitors/{id}/graph
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
hours | query | integer |
| Réponse | GetMonitorGraphResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /monitors/graphs
| Nom | Emplacement | Type |
|---|---|---|
hours | query | integer |
| Réponse | ListMonitorGraphsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /monitors/{id}/channels · PUT /monitors/{id}/channels
Les canaux que ce moniteur alerte, et la façon de les définir. La lecture requiert notification_channel:read ; l’écriture requiert monitor:update.
PUT remplace l’ensemble complet — envoyez tous les identifiants de canaux que vous voulez, et non ceux que vous ajoutez. Un tableau vide veut dire que le moniteur n’alerte personne, ce qui est une chose valable à vouloir et une mauvaise chose à faire par accident.
Paramètres et réponses
GET /monitors/{id}/channels
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetMonitorChannelsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PUT /monitors/{id}/channels
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
channelIds | body | StringList |
| Réponse | GetMonitorChannelsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /incidents/{id}/events
La chronologie d’un incident : changements d’état, acquittements, commentaires, étapes d’escalade. Requiert incident:read. C’est la chronologie que GET /incidents/{id} n’inclut pas.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | ListIncidentEventsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /channels · POST /channels
La lecture requiert notification_channel:read ; la création requiert notification_channel:manage. Chacun porte id, kind, name, target et workspaceId.
secret n’est renvoyé qu’à la création d’un canal, et plus jamais ensuite. C’est la clé de signature d’un webhook ; la conserver quelque part où vous pourriez la relire ferait d’une clé en lecture seule un moyen de forger des requêtes signées.
Vous pouvez créer les genres qu’une personne peut créer dans le tableau de bord : email, webhook, telegram, slack, teams, discord, pagerduty et jsm. Les canaux SMS, WhatsApp, satellite et push sont enrôlés par la personne qui les reçoit et ne peuvent pas être créés par l’API — c’est ce qui en fait un consentement plutôt qu’un champ que quelqu’un a rempli.
Un canal courriel est créé non confirmé et reçoit un seul message lui demandant s’il veut des alertes. Rien d’autre n’est envoyé tant qu’il n’a pas accepté : créer un canal par l’API ne met donc pas à lui seul une adresse dans votre rotation d’astreinte.
Paramètres et réponses
GET /channels
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListChannelsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /channels
| Nom | Emplacement | Type |
|---|---|---|
kind | body | string |
name | body | string |
target | body | string |
workspaceId | body | requests.NullableString |
| Réponse | CreatedChannelResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
PATCH /channels/{id} · DELETE /channels/{id} · POST /channels/{id}/test
Tous requièrent notification_channel:manage. L’envoi de test est refusé pour une adresse qui n’a pas confirmé — autrement ce serait un moyen illimité d’écrire à une adresse qui n’a rien accepté, sous une étiquette avenante.
Paramètres et réponses
PATCH /channels/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
enabled | body | boolean |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /channels/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /channels/{id}/test
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | TestDeliveryResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /status-pages · POST /status-pages
La lecture requiert status_page:read ; l’écriture requiert status_page:manage. Chacune porte id, name, slug, visibility, customDomain, domainVerifiedAt, subscribersEnabled, componentCount, workspace et createdAt.
Paramètres et réponses
GET /status-pages
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListStatusPagesResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /status-pages
| Nom | Emplacement | Type |
|---|---|---|
name | body | string |
workspaceId | body | string |
| Réponse | CreatedResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /status-pages/{id} · PATCH /status-pages/{id} · DELETE /status-pages/{id}
La lecture requiert status_page:read ; modifier ou supprimer requiert status_page:manage.
Paramètres et réponses
GET /status-pages/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | GetStatusPageResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
PATCH /status-pages/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
name | body | string |
headline | body | requests.NullableString |
description | body | requests.NullableString |
logoUrl | body | requests.NullableString |
themeAccent | body | string |
language | body | string |
historyDays | body | integer |
showResponseTimes | body | boolean |
showIncidentHistory | body | boolean |
subscribersEnabled | body | boolean |
visibility | body | string |
password | body | requests.NullableString |
customCss | body | requests.NullableString |
hideVitrinaBranding | body | boolean |
groupByHost | body | boolean |
| Réponse | UpdatedStatusPageResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /status-pages/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /status-pages/{id}/components · DELETE /status-pages/{id}/components
Ajouter un moniteur à une page, ou l’en retirer. Requiert status_page:manage.
Le moniteur doit être dans le même espace de travail que la page, et pas seulement dans la même organisation. Dans un compte d’agence, c’est ce qui empêche le moniteur d’un client d’être publié sur la page d’un autre.
Paramètres et réponses
POST /status-pages/{id}/components
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
monitorId | body | string |
displayName | body | string |
| Réponse | ComponentAckResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /status-pages/{id}/components
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
component | query | string |
componentId | body | string |
| Réponse | ComponentAckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /workspaces · POST /workspaces · DELETE /workspaces/{id}
La lecture requiert workspace:read, et le reste leurs propres permissions. Chacun porte id, name, slug, clientReference et isDefault.
Une clé appartenant à un membre confiné ne voit que les espaces de travail auxquels ce membre est confiné. L’espace de travail par défaut ne peut pas être supprimé.
Paramètres et réponses
GET /workspaces
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListWorkspacesResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /workspaces
| Nom | Emplacement | Type |
|---|---|---|
name | body | string |
clientReference | body | string |
| Réponse | CreatedResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /workspaces/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /members · POST /members
La lecture requiert member:read ; inviter requiert member:invite. La réponse comporte members et invitations séparément — une invitation que personne n’a acceptée n’a ajouté personne, et fusionner les deux donnerait un nombre de sièges en désaccord avec ce qui vous est facturé.
POST envoie une invitation plutôt que de créer un compte. Il prend une adresse courriel, un rôle et, facultativement, workspaceIds pour confiner la personne.
Paramètres et réponses
GET /members
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListMembersResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /members
| Nom | Emplacement | Type |
|---|---|---|
email | body | string |
role | body | string |
workspaceIds | body | string[] |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
PATCH /members/{id} · DELETE /members/{id} · DELETE /invitations/{id}
Changer un rôle requiert member:update_role ; retirer quelqu’un requiert member:remove ; révoquer une invitation requiert member:invite.
Retirer un membre supprime ses canaux d’alerte personnels — son combiné, sa conversation privée, son numéro de mobile — en même temps que ses clés d’API. Les canaux partagés ne sont pas touchés. Le dernier propriétaire ne peut être ni retiré ni rétrogradé.
Paramètres et réponses
PATCH /members/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
role | body | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /members/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /invitations/{id}
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /maintenance · POST /maintenance · DELETE /maintenance
Des fenêtres pendant lesquelles rien ne réveille personne. Par défaut, les vérifications continuent de s’exécuter et d’être enregistrées : ces minutes comptent dans le taux de disponibilité comme les autres ; avec keepChecking à false, rien n’est vérifié tant que la fenêtre est ouverte, ce qui laisse un trou dans l’historique plutôt qu’un creux. La lecture requiert incident:read ; l’écriture requiert maintenance:manage.
Porte title, startsAt, endsAt, timezone, monitorIds, recurrenceRule, keepChecking, showOnStatusPage et notifySubscribers. Une fenêtre récurrente est une seule ligne et non plusieurs.
Une règle répète la fenêtre à la même heure locale dans son propre timezone : une fenêtre qui traverse un changement d’heure reste à l’heure prévue. FREQ=DAILY, FREQ=WEEKLY et FREQ=MONTHLY sont développées, éventuellement avec INTERVAL, COUNT, UNTIL et un BYDAY ou BYMONTHDAY nommant le jour où la fenêtre elle-même commence. Toute autre règle est stockée et renvoyée telle quelle et ne retient les alertes que pour sa première occurrence — rien n’est deviné.
Paramètres et réponses
GET /maintenance
| Nom | Emplacement | Type |
|---|---|---|
past | query | boolean |
| Réponse | ListMaintenanceResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /maintenance
| Nom | Emplacement | Type |
|---|---|---|
title | body | string |
description | body | string |
workspaceId | body | string |
monitorIds | body | string[] |
startsAt | body | string |
endsAt | body | string |
recurrenceRule | body | string |
timezone | body | string |
keepChecking | body | boolean |
showOnStatusPage | body | boolean |
notifySubscribers | body | boolean |
| Réponse | CreatedResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /maintenance
| Nom | Emplacement | Type |
|---|---|---|
id | query | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /on-call
Les horaires, les politiques d’escalade, les remplacements, et qui est d’astreinte en ce moment. Requiert oncall:read.
onCallNow est résolu au moment où vous posez la question, viaOverride indiquant si la réponse vient de la rotation ou de quelqu’un qui remplace. unreachable nomme les participants qui n’ont aucun canal capable de les joindre réellement, ce qui est la défaillance qu’il vaut mieux découvrir avant un incident que pendant.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | GetOnCallResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /agents · POST /agents · DELETE /agents · GET /agents/{id}/metrics
Les agents serveur rapportent le processeur, la mémoire et le disque depuis vos propres machines. L’enrôlement requiert agent:enroll, la lecture requiert agent:read, le retrait requiert agent:delete.
L’enrôlement renvoie un jeton, une seule fois. C’est ce avec quoi l’agent s’authentifie : il n’est donc jamais relisible ensuite.
Paramètres et réponses
GET /agents
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListAgentsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /agents
| Nom | Emplacement | Type |
|---|---|---|
name | body | string |
workspaceId | body | requests.NullableString |
| Réponse | EnrolledAgentResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /agents
| Nom | Emplacement | Type |
|---|---|---|
id | query | string |
id | body | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /agents/{id}/metrics
| Nom | Emplacement | Type |
|---|---|---|
id obligatoire | path | string |
hours | query | integer |
limit | query | integer |
| Réponse | GetAgentMetricsResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /api-keys · POST /api-keys · DELETE /api-keys
La lecture requiert api_key:read ; créer et révoquer requièrent api_key:manage. Chacune porte id, name, prefix, scopes, workspaceIds, owner, createdAt, lastUsedAt, expiresAt et revokedAt.
token n’est renvoyé qu’à la création. prefix est la partie affichable, celle qui permet de distinguer deux clés dans une liste sans qu’aucune des deux soit lisible.
Une clé hérite du rôle et du confinement aux espaces de travail de l’adhésion qui l’a créée : une clé ne peut donc pas servir à contourner une limite qui s’impose à son auteur.
Paramètres et réponses
GET /api-keys
Aucun paramètre ni champ de corps déclaré.
| Réponse | ListApiKeysResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
POST /api-keys
| Nom | Emplacement | Type |
|---|---|---|
name | body | string |
scopes | body | string[] |
workspaceIds | body | string[] |
expiresInDays | body | requests.NullableInt64 |
| Réponse | CreatedApiKeyResponse |
|---|---|
| Codes d’état | 201 400 401 403 404 429 |
| Limite de débit | 30 par minute |
DELETE /api-keys
| Nom | Emplacement | Type |
|---|---|---|
id | query | string |
id | body | string |
| Réponse | AckResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /audit
Les changements de configuration, avec qui les a faits et ce qui a changé. Requiert audit_log:read, soit Business et au-dessus.
Paginé par nextBefore plutôt que par numéro de page, de sorte qu’une limite de page ne se déplace pas pendant que vous la lisez. Les entrées sont enregistrées sur tous les forfaits — le forfait conditionne la lecture, si bien qu’une montée en gamme ouvre tout l’historique au lieu d’en commencer un.
Les identifiants, les empreintes et les secrets ne sont jamais écrits dans changes.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
limit | query | integer |
| Réponse | ListAuditResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
GET /me
Qui est cette clé, ce qu’elle peut atteindre et ce que le forfait permet. Aucune permission requise — toute clé peut se décrire elle-même.
Porte user, organization, membership(rôle et confinement aux espaces de travail), entitlements (les limites du forfait une fois résolues, les packs additionnels déjà intégrés) et usage. Servez-vous-en pour vérifier une limite avant de tenter une création plutôt qu’après un refus.
Une session reçoit en plus organizations, qui liste toutes les organisations auxquelles la personne appartient. Une clé d’API, non : une clé est émise pour une seule adhésion et confinée à celle-ci, si bien que lister les autres annoncerait des organisations que cet identifiant ne peut pas atteindre.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | GetMeResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 120 par minute |
DELETE /account
Supprime l’organisation et tout ce qu’elle contient. Aucune constante de permission ne garde celle-ci, parce que la propriété est la vérification : elle est refusée à quiconque n’est pas propriétaire.
Ce n’est pas réversible et ce n’est pas une mise en pause. À utiliser délibérément.
Paramètres et réponses
Aucun paramètre ni champ de corps déclaré.
| Réponse | AccountDeletedResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
POST /billing/apple/verify
Confirme un achat intégré effectué dans notre propre application mobile. Requiert billing:manage.
Documenté par souci d’exhaustivité plutôt que pour être utilisé : il n’est appelable qu’avec un reçu qu’Apple a émis pour notre application, il n’y a donc rien qu’une intégration tierce puisse en faire. Il figure ici parce qu’une route qui existe et n’est décrite nulle part est indiscernable d’une route que quelqu’un a oubliée.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
transactionId | body | string |
| Réponse | AppleVerifyResponse |
|---|---|
| Codes d’état | 200 400 401 403 404 429 |
| Limite de débit | 30 par minute |
GET /
L’index. Liste les routes que ce déploiement sert, ce qui est la version exploitable par un programme de cette page, et toujours à jour — elle est générée à partir de ce qui est réellement monté.
Flux des incidents (RSS et Atom)
Tous les incidents de votre compte sous forme de flux, pour un lecteur plutôt que pour une bibliothèque cliente. Créez l’URL dans le tableau de bord, sous Paramètres → Notifications :
https://vitrinaengine.com/feeds/incidents/vtf_…/feed.xml
https://vitrinaengine.com/feeds/incidents/vtf_…/atom.xmlL’URL est l’identifiant. Aucun en-tête à envoyer : quiconque détient le lien peut lire tous les incidents du compte, dans tous les espaces de travail. Elle est réaffichée dans le tableau de bord chaque fois que vous en avez besoin, parce qu’elle vit dans un lecteur de flux que quelqu’un réinstallera un jour — et elle peut être remplacée ou révoquée, avec effet dès la requête suivante et non à l’expiration d’un cache.
Elle ne porte que des faits au niveau de l’incident : le nom du moniteur, la cause, la gravité, l’état, l’ouverture et la clôture, et les mises à jour marquées publiques. Jamais de post-mortem, jamais la configuration d’un moniteur, jamais l’endroit d’où un contrôle a eu lieu. La plupart des lecteurs synchronisent via les serveurs d’un tiers : le document est donc écrit comme s’il sortait de chez vous, ce qu’il fait.
Une interrogation par minute est prévue. Au-delà de soixante requêtes par minute pour une URL, elle répond 429 ; une URL qui n’a jamais été valide, qui a été remplacée ou révoquée répond 404 — la même réponse dans les trois cas, pour qu’on ne puisse pas en déduire quels jetons ont existé.
Ce que cette API ne renvoie délibérément pas
- Le
configd’un moniteur. Il peut contenir des identifiants. - La région depuis laquelle une vérification s’est exécutée. D’où nous vérifions nous appartient, et il nous appartient de le changer à mesure que les sondes sont placées et déplacées. Ce serait une promesse sur notre infrastructure sur laquelle vous ne pourriez pas agir, et ce n’est affiché nulle part ailleurs dans le produit non plus.
Exporting your data
Two routes hand back a file rather than a message, so that taking your data out does not mean paging through a collection endpoint a thousand times. Both are on every plan, the free one included — what a plan changes is how much history there is to export, not whether you may.
GET /export/{entity}
Un type de lignes, en CSV ou en JSON. entity vaut monitors, hosts, status-pages, notification-channels, members, incidents, incident-events, postmortems, audit-log, error-issues, uptime-daily, uptime-hourly ou analytics-hourly. Toute autre valeur répond 404.
format vaut csv (par défaut) ou json. from et to sont des horodatages RFC 3339. bomajoute une marque d’ordre des octets UTF-8 au CSV : Excel en a besoin pour les noms non-ASCII, et la plupart des langages de script la lisent comme faisant partie du premier en-tête de colonne — elle est donc désactivée par défaut.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
entity obligatoire | path | string |
bom | query | boolean |
format | query | string |
from | query | string |
to | query | string |
| Codes d’état | 200 400 401 403 404 429 |
|---|---|
| Limite de débit | 6 par heure |
GET /export
Tout ce que la clé peut lire, dans un zip : un fichier par entité, plus manifest.json qui indique le contenu de l’archive, le nombre de lignes par fichier et les entités absentes. Ce que le rôle de la clé ne peut pas lire est omis plutôt que de faire échouer la requête entière, et le manifeste empêche que cela se produise en silence.
Paramètres et réponses
| Nom | Emplacement | Type |
|---|---|---|
bom | query | boolean |
format | query | string |
from | query | string |
to | query | string |
| Codes d’état | 200 400 401 403 404 429 |
|---|---|
| Limite de débit | 6 par heure |
What an export does not contain
Un export ne contient rien qui authentifie : ni configuration de canal, ni jeton de heartbeat, ni empreinte de mot de passe. La configuration d’un moniteur est incluse, débarrassée de tout ce qui ressemble à un identifiant — corps de requête, en-têtes, communauté SNMP, identifiants de boîte aux lettres. Les résultats de vérification bruts en sont absents : la rétention les supprime, la disponibilité provient donc des agrégats.
Size, and the one refusal you may meet
Les séries horaires sont plafonnées à 92 jours par requête ; une fenêtre plus large est refusée avec export_window_too_wide plutôt que réduite en silence. Limite dédiée : 6 exports par heure et par organisation.
Gestion des versions
La version est dans le chemin. Des champs seront ajoutés aux réponses — traitez ceux que vous ne connaissez pas comme quelque chose à ignorer plutôt que comme une erreur — mais rien ne sera retiré de v1 ni ne changera de sens à l’intérieur de celle-ci.
Il manque quelque chose ?
La surface est délibérément réduite : elle couvre un tableau mural, un résumé dans une messagerie et un script de déploiement qui met un moniteur en sourdine le temps d’une mise en production. Si vous construisez quelque chose qu’elle n’atteint pas, écrivez à support@vitrinaengine.com — savoir ce que les gens veulent vraiment, c’est ainsi que se choisit le prochain point d’accès.