API REST

Lea y escriba sus monitores, lea y actualice incidentes, y suba source maps. Todo esto usa las mismas comprobaciones de permisos y el mismo filtro de aislamiento entre clientes que el panel — no hay una implementación aparte para la API que pueda desviarse de él.

Incluida en todos los planes, también en el gratuito. No hay complemento que comprar ni nivel que la desbloquee.

URL base

https://vitrinaengine.com/api/v1

Descripción legible por máquinas

/openapi.json es un documento OpenAPI 3.1 que cubre todas las rutas de esta página. Apunte hacia él un generador de clientes, o entrégueselo a un agente que deba llamar a esta API sin que nadie se la explique.

Se genera a partir del servicio en lugar de escribirse a su lado: las rutas salen de la superficie que la propia API publica en GET /, las formas y su prosa de los mismos archivos .proto de /api/proto, y los límites de uso del código que los aplica. La compilación falla cuando el documento y la API discrepan, así que describe lo que se sirve y no lo que era cierto la última vez que alguien lo editó.

Describe las formas. Los motivos están en esta página — que un id de otra organización responde 404, que config nunca se devuelve — y eso no lo escribe ningún generador.

Para agentes: MCP

https://vitrinaengine.com/mcp es un servidor Model Context Protocol. Añádalo a un cliente MCP con una clave de API como token bearer y un agente podrá leer sus monitores, incidentes, errores y analíticas — y crear, modificar y eliminar monitores — sin que nadie le explique cómo funciona esta API.

{
  "mcpServers": {
    "vitrina-engine": {
      "type": "http",
      "url": "https://vitrinaengine.com/mcp",
      "headers": { "Authorization": "Bearer vte_your_key_here" }
    }
  }
}

Lee todo y escribe tres cosas. Cada operación GET de esta página es una herramienta, y también lo son POST /monitors, PATCH /monitors/{id} y DELETE /monitors/{id}. No hay ninguna otra escritura al alcance — ni un espacio de trabajo, ni un miembro, ni una clave de API, ni una página de estado, ni su cuenta — porque no existe herramienta para ninguna de ellas, y la lista de las que sí están permitidas son tres líneas que alguien tiene que añadir a propósito.

Una clave que no puede escribir sigue siendo rechazada. Una llamada a una herramienta es la misma petición que haría la clave directamente, con la misma comprobación de permisos y el mismo filtro de inquilino: un agente con una clave de solo lectura lee. Déle una, salvo que quiera que cambie su monitorización — y cuente con que un cliente le pregunte antes de borrar: al eliminar un monitor se va con él su historial y no hay vuelta atrás. Para callar un monitor sin perderlo, páuselo con PATCH.

Como es la misma petición, ve exactamente lo que ve la clave, escribe la misma entrada en el registro de auditoría que el panel y cuenta contra el mismo límite de uso, dos veces: una por la llamada y otra por la petición que contiene. Una escritura consume el límite de escritura.

Conviene saber una cosa antes de que un agente edite un monitor: config se reemplaza entero, no se fusiona. Lea primero el monitor, cambie ese campo y devuelva el objeto completo. Una configuración parcial descarta en silencio las cabeceras y las credenciales de las que depende la comprobación, y la deja funcionando.

Autenticación

Cree una clave en Ajustes → Claves de API y envíela como token bearer. La clave se muestra una sola vez, al crearla, y se guarda solo como hash — si la pierde, cree otra.

curl https://vitrinaengine.com/api/v1/summary \
  -H "Authorization: Bearer vte_your_key_here"

Una clave nunca otorga más de lo que tenía quien la creó. Está ligada a su membresía, así que lleva su rol: una clave creada por alguien con un rol de solo lectura no puede escribir, envíe lo que envíe. Una clave también puede confinarse a un solo espacio de trabajo, y en ese caso cada respuesta se filtra a ese espacio y lo que quede fuera no existe para esa clave.

Quitar a alguien de su organización revoca las claves que creó, en la misma operación. Revocar el acceso tiene que llevarse las credenciales con él, o la persona conserva una que funciona.

Convenciones

Toda respuesta correcta es un objeto JSON con una propiedad data. Todo fallo es un objeto JSON con una propiedad error que contiene una frase pensada para una persona.

{ "data": { "id": "8f14e45f-…", "name": "Marketing site" } }

{ "error": "This key cannot create monitors." }

Las respuestas se envían con Cache-Control: private, no-store. Son datos propios de una clave sobre un origen compartido y no deben quedar guardados en ningún proxy.

Protobuf y gzip

Todos los endpoints bajo /api/v1 hablan también Protocol Buffers. Con Accept: application/x-protobuf la respuesta llega en protobuf; si envía un body en protobuf con Content-Type: application/x-protobuf, la respuesta vuelve en el mismo formato. Sin ninguno de los dos, es JSON, igual que siempre.

curl https://vitrinaengine.com/api/v1/monitors \
  -H "Authorization: Bearer vte_your_key_here" \
  -H "Accept: application/x-protobuf" \
  --compressed -o monitors.pb

Los mensajes están publicados: /api/proto enumera todos los archivos. Descárguelos conservando sus rutas y apunte protoc -I a ese directorio. Tres cosas difieren de lo que se esperaría en protobuf: un campo que puede estar vacío es null en JSON y está ausente en protobuf; algunos campos cuya forma varía —como el config de un monitor o de un canal— son documentos JSON dentro de un string; y StringList envuelve una lista que a su vez puede ser null.

Gzip funciona en ambos sentidos: Accept-Encoding: gzip para las respuestas y Content-Encoding: gzip para las peticiones. Como dos clientes pueden recibir ahora bytes distintos de la misma URL, todas las respuestas llevan Vary: Accept, Content-Type.

Códigos de estado

CódigoSignifica
200Todo bien. 201 cuando se creó algo.
400El cuerpo no era JSON, falta un campo, o no se pidió ningún cambio.
401Sin clave, o con una que no es válida. Deliberadamente nunca dice cuál de las dos — un mensaje que las distinguiera sería una forma de probar claves.
403Una clave válida sin permiso para esta acción. El mensaje lo nombra.
404No existe ese registro para usted. Vea más abajo.
413Un source map por encima del límite de tamaño.
429Superó un límite de peticiones. Lleva Retry-After. Vea más abajo.

Códigos de rechazo

Todo cuerpo que no sea 2xx lleva un code junto a la frase — not_found, limit_reached, rate_limited — y ese es el campo sobre el que ramificar. La cadena error es prosa para alguien que lee un registro y puede reescribirse en cualquier momento; el código es estable. Cuando la frase nombra un valor, vars lleva esos valores como cadenas, de modo que puedas colocarlos donde los quiera tu propia gramática en vez de extraerlos del inglés.

{
  "error": "The Pro plan includes 50 monitors, and you have 50.",
  "code": "limit_reached",
  "vars": { "plan": "pro", "limit": "50", "current": "50", "resource": "monitors" }
}

Es de aquí de donde nuestras propias aplicaciones sacan un rechazo en el idioma de quien lee. Trata un código que no reconozcas igual que ellas — recurre a error — porque se añaden códigos sin cambiar la versión.

Límites de peticiones

Por organización, no por clave — crear otra clave no los sube.

BucketLímite
Lecturas (GET)120 por minuto
Escrituras (POST, PATCH, DELETE)30 por minuto
Subidas de source maps300 por hora

Pasarse responde 429 con una cabecera Retry-After que indica los segundos enteros que faltan para que la ventana se reinicie. Respétela en lugar de reintentar de inmediato.

Están puestos donde una integración normal nunca llega: un panel de pared que consulta cada diez segundos gasta seis de las 120 lecturas. Son iguales en todos los planes, porque los endpoints de colección devuelven todo en una sola respuesta — una cuenta con quinientos monitores no necesita más peticiones que una con veinte. Los source maps tienen una ventana por hora porque llegan en bloque al desplegar, donde un front end puede tener cien chunks.

404 en lugar de 403, a propósito

Un id que pertenece a otro cliente responde «Not found.», no «Forbidden.». Un 403 confirmaría que el registro existe, lo que convertiría al endpoint en una forma de averiguar si un id es real. No lea un 404 como prueba de que algo no existe en ninguna parte — solo de que no existe nada que esta clave pueda ver.

Endpoints

Todo lo que coincide con ?q= en la cuenta: monitores, incidencias y sus análisis posteriores, servidores, páginas de estado, espacios de trabajo, canales de notificación, ventanas de mantenimiento, proyectos de errores y problemas, sitios de analítica, miembros e invitaciones, claves de API, agentes y sondas privadas. Una sola petición en lugar de una por tipo.

?type= limita a una lista de tipos separada por comas y ?limit= limita los resultados de cada tipo entre 1 y 20 (5 por defecto). Cada tipo exige el mismo permiso que su propio endpoint; un tipo que su clave no puede leer está ausente igual que un tipo sin coincidencias. No se busca ni se devuelve nada sellado, cifrado ni secreto.

Parámetros y respuestas
NombreUbicaciónTipo
limitqueryinteger
qquerystring
typequerystring
RespuestaSearchResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /summary

Conteos, para un panel de pared o un resumen diario. Requiere monitor:read.

{
  "data": {
    "total": 42, "up": 39, "degraded": 1, "down": 1,
    "paused": 1, "pending": 0,
    "openIncidents": 2, "suppressedIncidents": 1
  }
}

suppressedIncidents cuenta los incidentes retenidos por ser el alcance de otro. Son reales, y no son caídas separadas.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaGetSummaryResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /setup

Lo que a una cuenta nueva le queda por hacer: las mismas cuatro preguntas que hace la lista de puesta en marcha del panel, derivadas en cada lectura. Requiere monitor:read.

{
  "data": {
    "hasMonitor": true,
    "hasConfirmedChannel": false,
    "hasStatusPage": false,
    "hasColleague": false,
    "dismissedAt": null
  }
}

hasConfirmedChannel pregunta si una alerta podría llegar de verdad, no si existe un canal. Las dos cosas se separaron feamente una vez, y una lista que diera la alerta por montada con un canal al que no servimos repetiría aquel fallo en forma de tranquilidad.

hasColleague cuenta pertenencias y nunca invitaciones: una invitación enviada y no aceptada no ha añadido a nadie.

No está plegado en /summary porque ese endpoint son recuentos por estado y nada más: un panel de pared que lo consulta cada pocos segundos no quiere cinco consultas de más para pintar un aviso dirigido a quien montó la cuenta hace meses.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaGetSetupResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

DELETE /setup

Omite la lista. Requiere org:update, porque descartarla es una fila de toda la organización y no una preferencia de cada persona: a quien llegue después no se le vuelve a mostrar.

Nada más cambia en la cuenta y no se escribe entrada de auditoría: ocultar un aviso no cambia nada de cómo se comporta el producto, ni de cómo alerta, ni de cómo factura.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaDismissedResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /monitors

Todos los monitores que la clave puede ver. Requiere monitor:read. Cada uno lleva id, name, kind, status, statusSince, enabled, intervalSeconds, tags, workspace, lastCheckedAt, lastResponseTimeMs, lastMessage, uptime24h, uptime30d y openIncidentId.

?tag=prod,eu reduce la lista a los monitores que llevan todas las etiquetas nombradas — Y, no O, de modo que nombrar una segunda etiqueta siempre devuelve menos monitores en lugar de más. El filtro del panel se lee igual. Las etiquetas se guardan en minúsculas, y aquí el valor se convierte del mismo modo antes de compararlo, así que ?tag=Prod las encuentra. Una entrada que no podría ser una etiqueta —vacía, o más larga de lo que una etiqueta admite— se descarta y el resto del filtro sigue aplicándose, en vez de rechazar la llamada: un enlace no debería dejar de funcionar porque se renombró una de sus etiquetas.

config nunca se devuelve. En algunos tipos contiene cabeceras de solicitud y credenciales, y una clave de solo lectura no debería ser una forma de recuperar los secretos que alguien escribió en un formulario.

Parámetros y respuestas
NombreUbicaciónTipo
tagquerystring
RespuestaListMonitorsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /monitors

Requiere monitor:create. Necesita name, kind, workspaceId y config. Opcionales: intervalSeconds (por defecto 300), 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" }]
    }
  }'

Responde 201 con el id nuevo. El intervalo se ajusta al mínimo de su plan en lugar de rechazarse, así que pedir 10 segundos en un plan cuyo mínimo es 60 le da 60 — si le importa, vuelva a leerlo.

Parámetros y respuestas
NombreUbicaciónTipo
namebodystring
kindbodystring
workspaceIdbodystring
configbodystring
intervalSecondsbodyinteger
confirmationsbodyinteger
dependsOnbodystring[]
probeIdbodystring
tagsbodystring[]
RespuestaCreatedResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

GET /monitors/{id}

Un monitor, con todo lo que da la lista más paused. Requiere monitor:read.

Para mail_posture, tls_audit y snmp incluye además lastCheckDetail, el resultado de la última comprobación: los hallazgos detrás del estado, cada uno con un code estable y una severity, más una nota TLS o las lecturas SNMP. Es null hasta la primera comprobación y no aparece en los demás tipos.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetMonitorResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PATCH /monitors/{id}

Envíe solo lo que quiera cambiar: name, intervalSeconds, confirmations, enabled, config o paused.

paused se comprueba contra monitor:pause y todo lo demás contra monitor:update, por separado — una clave que puede pausar pero no editar todavía puede pausar. Enviar un cambio vacío es un 400.

El monitor se vuelve a leer y se devuelve, en lugar de repetirle lo que envió, así que lo que ve es lo que quedó guardado.

# 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}'
Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
namebodystring
intervalSecondsbodyinteger
confirmationsbodyinteger
enabledbodyboolean
pausedbodyboolean
configbodystring
tagsbodyStringList
RespuestaUpdatedMonitorResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /monitors/{id}

Requiere monitor:delete. Responde { "data": { "id": "…", "deleted": true } }.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /hosts · POST /hosts

Los servidores son la segunda forma de agrupar monitores: el espacio de trabajo dice de quién es un monitor, el servidor dice dónde corre. Totalmente opcional: una cuenta que nunca cree uno no pierde nada, y la mayoría de los monitores no nombran ningún servidor.

Cada servidor trae status, pinned y spanning. status se deriva solo de los monitores que corren únicamente en ese servidor. Un monitor que corre en varias máquinas cuenta en spanning y no colorea a ninguna, porque cuando falla un endpoint balanceado eso dice que el servicio está roto, no qué máquina lo rompió. Un servidor sin nada propio responde "status": null en lugar de up.

POST requiere monitor:create y un name. Los campos opcionales provider, address y notes son suyos: nada en el producto los usa. Un nombre que coincide con uno que ya tiene — ignorando mayúsculas y el punto final — responde 409.

Parámetros y respuestas

GET /hosts

Sin parámetros ni campos de cuerpo declarados.

RespuestaListHostsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /hosts

NombreUbicaciónTipo
namebodystring
providerbodystring
addressbodystring
notesbodystring
RespuestaCreatedResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

GET /hosts/{id} · PATCH /hosts/{id} · DELETE /hosts/{id}

El detalle trae el servidor y sus monitores, cada uno marcado con pinned y, cuando no lo está, con alsoOn: las otras máquinas desde las que responde, que es lo que usted lee antes de reiniciar una. DELETE retira el servidor y todos sus monitores siguen funcionando: un servidor no tiene horario ni historial propios.

Parámetros y respuestas

GET /hosts/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetHostResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PATCH /hosts/{id}

NombreUbicaciónTipo
id obligatoriopathstring
namebodystring
providerbodystring
addressbodystring
notesbodystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /hosts/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /hosts/{id}/monitors · DELETE /hosts/{id}/monitors

Un monitor dentro o fuera de un servidor, con monitorId en el cuerpo o ?monitorId=. Deliberadamente no es una lista completa: en una cuenta de agencia un servidor lleva monitores de varios espacios de trabajo, y quien reemplazara “la lista” estaría reemplazando filas que nunca vio. Ambas direcciones son idempotentes.

Parámetros y respuestas

POST /hosts/{id}/monitors

NombreUbicaciónTipo
id obligatoriopathstring
monitorIdbodystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /hosts/{id}/monitors

NombreUbicaciónTipo
id obligatoriopathstring
monitorIdquerystring
monitorIdbodystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /monitors/{id}/hosts · PUT /monitors/{id}/hosts

El otro lado de la misma relación, y este sí es una lista completa: estos vínculos pertenecen a un solo monitor, así que no hay nada del otro lado que otro espacio de trabajo pueda ver. Envíe hostIds; un arreglo vacío es una petición real y significa que el monitor no corre en ningún servidor en particular. Los ids que no son suyos se descartan en vez de rechazarse. Toda respuesta de monitor trae además hosts, vacío cuando no hay ninguno.

Parámetros y respuestas

GET /monitors/{id}/hosts

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaListMonitorHostsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PUT /monitors/{id}/hosts

NombreUbicaciónTipo
id obligatoriopathstring
hostIdsbodystring[]
RespuestaListMonitorHostsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /incidents

Requiere incident:read. Acepta ?status= — uno de open, acknowledged, resolved o suppressed — y ?open=true para los tres que no están resueltos. Un estado que no se reconoce se ignora en lugar de rechazarse, igual que ?limit= (por defecto 50) se ajusta a 200 en vez de rechazarse.

Cada uno lleva id, monitorId, monitorName, title, cause, status, severity, startedAt, resolvedAt, durationSeconds, acknowledgedAt y rootIncidentId.

rootIncidentId es el campo que mirar si arma un feed de alertas. Cuando está presente, este incidente es el alcance de otro — se cayó el servidor de base de datos y este es uno de los doce servicios que están detrás. Sáltelos y recibe una alerta en lugar de trece.

Parámetros y respuestas
NombreUbicaciónTipo
limitqueryinteger
openqueryboolean
statusquerystring
RespuestaListIncidentsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /incidents/{id}

Un incidente. Requiere incident:read. Los mismos campos que la lista, más workspaceId.

No devuelve la cronología del incidente — los comentarios y los cambios de estado que se ven en el panel no están en este endpoint. Si los necesita, dígalo y se pueden agregar; documentarlos aquí sin que existan sería peor que la ausencia.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetIncidentResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PATCH /incidents/{id}

Envíe status con valor "acknowledged" o "resolved", o un comment, o ambos. Cada uno se comprueba contra su propio permiso: incident:acknowledge, incident:resolve, incident:comment. Agregar "publish": true a un comentario lo publica en la página de estado y requiere además 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}'
Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
statusbodystring
commentbodystring
publishbodyboolean
RespuestaGetIncidentResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

PUT /incidents/{id}/postmortem

Escribe o reemplaza el análisis posincidente del incidente. Requiere incident:resolve, y el incidente debe estar ya resuelto; si no, 409 con el código incident_not_resolved. Envíe body en Markdown, de 1 a 50.000 caracteres tras recortar espacios (postmortem_required, postmortem_too_long). Hay uno por incidente, así que cada llamada reemplaza el anterior. La respuesta es el incidente, tal como lo devuelve GET /incidents/{id}.

GET /incidents/{id} lo incluye como postmortem: { body, authorName, updatedAt }, o null, y la lista incluye hasPostmortem. Muestre body como Markdown y nunca como HTML: es texto que escribió una persona. Un análisis posincidente es interno y nunca aparece en una página de estado.

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."}'
Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
bodybodystring
RespuestaGetIncidentResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /probes

Las sondas privadas de su organización: id, name, lastSeenAt, version, hostname, monitorCount, revoked y createdAt. Requiere agent:read. Es lo que ofrece el selector de sonda de un monitor.

No hay campo de región, ni lo habrá. Usted elige una sonda por su nombre; dónde se ejecuta una comprobación detrás de ella lo decidimos y cambiamos nosotros. Las sondas revocadas aparecen con revoked: true y ya no reciben trabajo, así que no las ofrezca.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaListProbesResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /monitors/{id}/push-url

La URL de ping de un monitor heartbeat, mostrada de nuevo. Requiere monitor:read. url es null para un tipo que no recibe pings y para un token que ya no se puede descifrar; el monitor sigue funcionando, y renovar el token en el panel genera una URL que sí se puede mostrar.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetPushUrlResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /organizations · PUT /organizations/active

Las organizaciones a las que pertenece la persona que ha iniciado sesión, cada una con su role allí y active en la que está en uso, y el cambio entre ellas. Envíe organizationId; la respuesta es la membresía que queda en uso.

Solo con sesión iniciada. Una clave pertenece a una única membresía y recibe 403 con session_required. Cambiar mueve todas las sesiones de esa persona, incluido el panel, y una organización a la que no pertenece responde 404.

Parámetros y respuestas

GET /organizations

Sin parámetros ni campos de cuerpo declarados.

RespuestaListOrganizationsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PUT /organizations/active

NombreUbicaciónTipo
organizationIdbodystring
RespuestaActiveOrganizationResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /sms/enrolment · POST /sms/enrolment/confirm

Registre su propio número de móvil para alertas por SMS: envíe phone (y opcionalmente name) y le enviaremos un código de seis dígitos; envíe ese code a la segunda ruta para confirmar. Requiere notification_channel:manage y una sesión iniciada: un número lo añade la persona que tiene el teléfono, nunca una clave.

El número se guarda sin confirmar y no recibe nada hasta que vuelve el código. Registrarse de nuevo reemplaza su número anterior. Rechazos: sms_not_included (402, el plan no incluye SMS), not_a_phone_number, sms_country_unsupported, sms_route_not_open, verification_code_not_sent (502; vuelva a llamar para recibir un código nuevo), verification_code_malformed y verification_code_incorrect. Un inicio correcto incluye country y caveat (sender-replaced, registration-pending, unverified o null), que conviene mostrar antes de que alguien dependa del número.

Parámetros y respuestas

POST /sms/enrolment

NombreUbicaciónTipo
phonebodystring
namebodystring
RespuestaSmsEnrolmentResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

POST /sms/enrolment/confirm

NombreUbicaciónTipo
codebodystring
RespuestaSmsConfirmedResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /channels/{id}/confirmation

Reenvía el mensaje de confirmación de un canal de correo. Requiere notification_channel:manage. Cada llamada emite un enlace nuevo y el anterior deja de funcionar. sent: false significa que no había nada que enviar (la dirección ya confirmó), y por esta vía nunca se vuelve a escribir a una dirección confirmada. Un envío rechazado por el proveedor de correo responde 502 con confirmation_not_sent.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaChannelConfirmationResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

PATCH /workspaces/{id}

Cambia el nombre de un espacio de trabajo. Requiere workspace:update. name es obligatorio (de 1 a 80 caracteres) y clientReference, opcional: null lo borra. El slug nunca cambia, porque figura en las URL de las páginas de estado. La respuesta es el espacio de trabajo tal como queda.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
namebodystring
clientReferencebodyrequests.NullableString
RespuestaUpdatedWorkspaceResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /sourcemaps

Suba un source map para que las trazas minificadas se resuelvan. Requiere monitor:create. Necesita projectRef (un número) y filename, más el mapa en sí como map (JSON) o mapGzipBase64. Opcionales: debugId y release.

Envíe un debug id o un release. Un mapa sin ninguno de los dos no se puede asociar a una traza y quedará ahí sin hacer nada. La correspondencia se busca primero por debugId y después por release más nombre de archivo.

Los mapas se resuelven cuando se lee un problema, no al subirlos, así que uno subido después de que llegaran los errores igual sirve — que es el orden habitual.

Parámetros y respuestas
NombreUbicaciónTipo
projectRefbodyinteger
filenamebodystring
debugIdbodystring
releasebodystring
mapbodystring
mapGzipBase64bodystring
RespuestaUploadedSourceMapResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones300 por hora

POST /symbols

La misma idea para una aplicación nativa: suba un .dSYM de iOS o un mapping.txt de R8 en Android para que las trazas de los fallos se resuelvan. Requiere monitor:create. Veinte subidas por hora, y se conservan veinte compilaciones por proyecto.

A diferencia de /sourcemaps, el cuerpo es el propio archivo comprimido con gzip y los metadatos van en cabeceras: X-Vitrina-Project-Ref, X-Vitrina-Platform (ios o android), X-Vitrina-Symbol-Name y X-Vitrina-Release. Un dSYM pesa decenas de megabytes, y ponerlo en base64 dentro de un campo JSON cuesta un tercio más de transferencia.

Las dos plataformas se asocian de forma distinta. Un frame de iOS nombra el UUID Mach-O de la imagen a la que pertenece, así que una subida de iOS debe llevar X-Vitrina-Debug-Ids y se asocia exactamente por él. R8 no emite ningún id de ese tipo, así que un mapping de Android se asocia solo por el release — que debe ser exactamente el que reporta la aplicación, <applicationId>@<versionName>+<versionCode>. Un dígito de diferencia y los frames se resuelven a líneas que parecen plausibles y son falsas.

Volver a subir la misma compilación reemplaza sus símbolos en lugar de fallar, así que un trabajo de publicación reintentado no es un error. Igual que con los source maps, la resolución ocurre cuando se lee un problema.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaUploadedSymbolsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones20 por hora

GET /errors/projects

Los proyectos de seguimiento de errores de esta cuenta. Requiere monitor:read. Cada uno lleva ref — el número que va en el DSN — más publicKey, unresolved y eventsLast24h. Es de solo lectura: un proyecto se crea con una clave que todavía hay que pegar en la configuración de una aplicación, así que no hay nada aquí que un endpoint pudiera terminar.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaListErrorProjectsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /errors/issues

Errores agrupados, primero los de actividad más reciente. Requiere monitor:read. Un problema es una huella y no un evento, así que mil apariciones de una misma excepción son una sola fila con timesSeen en mil. ?status= vale unresolved por defecto y acepta también resolved, ignored o all; ?project= filtra por id de proyecto, ?q= busca en el tipo, el valor y el culpable, y ?limit= tiene un tope de 200. spark son veinticuatro conteos por hora, del más antiguo al más reciente.

Parámetros y respuestas
NombreUbicaciónTipo
limitqueryinteger
projectquerystring
qquerystring
statusquerystring
RespuestaListIssuesResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /errors/issues/{id}

Un problema con su traza. Requiere monitor:read. exceptions es la cadena propia del SDK, con el error lanzado al final y sus causas antes, y sus frames se resuelven contra cualquier source map que haya subido — la misma resolución que hace el panel, para que un script y la persona con quien habla nunca estén mirando trazas distintas. Un mapa que no se puede aplicar vuelve a los frames originales en lugar de hacer fallar la petición.

lastEvent lleva dos marcas de tiempo a propósito. occurredAt es lo que reportó el SDK y receivedAt es cuándo lo escribió la ingesta; un dispositivo que estaba sin conexión, o una cola que se atascó, son exactamente la diferencia entre las dos.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetIssueResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PATCH /errors/issues/{id}

Resolver, ignorar o reabrir: { "status": "resolved" }. Requiere monitor:update. ignoreHours puede acompañar a ignored para dejar de ignorarlo más adelante, y tiene un tope de 90 días.

Al resolver se registra el release en el que se resolvió, así que un rezagado de un despliegue anterior no reabre el problema. Cuando el SDK no envió ningún release no hay nada con qué comparar y cualquier evento posterior sí lo reabre — sin forma de distinguir un rezagado de una regresión, lo seguro es suponer que el fallo volvió.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
statusbodystring
ignoreHoursbodyinteger
RespuestaIssueStatusResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /analytics

Los sitios web que mide esta cuenta. Requiere monitor:read. Lleva publicId — el valor que va en la etiqueta del script, que es público por diseño — más viewsLast24h y trafficAlerting, que es verdadero mientras el tráfico de un sitio está por debajo de lo que esa hora ve normalmente.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaListAnalyticsSitesResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /analytics/{id}

Los números de un sitio, para una hoja de cálculo o un reporte. Requiere monitor:read. ?days= vale 7 por defecto y tiene un tope de 365. ?dimensions= acepta una lista separada por comas de path, referrer, country, browser, os, device, utm_source, utm_medium, utm_campaign y event; una desconocida es un 400 y no una respuesta vacía, porque un error de escritura que no devuelve nada se lee como «no hubo tráfico».

La cifra de visitantes se llama dailyUniqueVisitors, y eso es exactamente lo que es. Es la suma de los únicos diarios y no puede ser otra cosa: el secreto detrás del hash de un visitante se destruye al terminar su día UTC, así que alguien que visitó en dos días cuenta dos veces y no hay ninguna clave que los una. Eso es el diseño de privacidad funcionando y no una aproximación — pero un campo llamado visitors junto a un rango de 30 días le invitaría a reportar un número que significa otra cosa.

curl "https://vitrinaengine.com/api/v1/analytics/$ID?days=30&dimensions=path,referrer" \
  -H "Authorization: Bearer vte_…"
Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
daysqueryinteger
RespuestaGetAnalyticsSiteResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /billing

El plan, y dónde se factura. Requiere billing:read. Lleva plan, status, cadence, currentPeriodEnd, cancelAt, addOnPacks y los últimos doce comprobantes.

source es paddle, apple, manual o none. Importa: una suscripción comprada en la aplicación de iOS le corresponde a Apple, y el plan, la tarjeta y la cancelación viven en los ajustes de la App Store del cliente y no aquí. canCheckoutOnWeb y canPurchaseInApp dicen qué ofertas es seguro mostrar, para que un cliente no tenga que volver a deducir esa regla y equivocarse en la dirección que le cobra dos veces a alguien.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaGetBillingResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /monitors/{id}/history

Disponibilidad diaria de un monitor. Requiere monitor:read. Acepta days, hasta la retención de historial de su plan.

Se calcula a partir de los resúmenes diarios y no de los resultados individuales de cada verificación, que es por lo que sigue respondiendo para periodos cuyos resultados en bruto ya borró la retención.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
daysqueryinteger
RespuestaGetMonitorHistoryResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /monitors/{id}/graph · GET /monitors/graphs

Las últimas horas de un monitor, hora a hora, o de todos los monitores que ve esta clave en una sola respuesta — lo que el panel dibuja en la fila y la página de un monitor. Requiere monitor:read. Acepta hours, 24 por defecto y 168 como máximo.

Un gráfico uptime lleva la proporción de verificaciones superadas en cada hora, con null para una hora sin ninguna; un gráfico value, para los tipos cuantitativos, lleva sus lecturas como series con su unidad. Cada hora de la ventana está presente se registrara algo o no, de modo que un hueco se ve como hueco. Las lecturas se envían tal como se midieron: una serie raw no tiene escala conocida, así que dibújela frente a su propia lectura más alta y nunca muestre esa proporción como si fuera la lectura.

Parámetros y respuestas

GET /monitors/{id}/graph

NombreUbicaciónTipo
id obligatoriopathstring
hoursqueryinteger
RespuestaGetMonitorGraphResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /monitors/graphs

NombreUbicaciónTipo
hoursqueryinteger
RespuestaListMonitorGraphsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /monitors/{id}/channels · PUT /monitors/{id}/channels

A qué canales alerta este monitor, y cómo fijarlos. Leer requiere notification_channel:read; escribir requiere monitor:update.

PUT reemplaza el conjunto entero — envíe todos los ids de canal que quiera, no solo los que está agregando. Un arreglo vacío significa que el monitor no alerta a nadie, lo que es algo válido de querer y algo malo de hacer por descuido.

Parámetros y respuestas

GET /monitors/{id}/channels

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetMonitorChannelsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PUT /monitors/{id}/channels

NombreUbicaciónTipo
id obligatoriopathstring
channelIdsbodyStringList
RespuestaGetMonitorChannelsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /incidents/{id}/events

La cronología de un incidente: cambios de estado, acuses de recibo, comentarios y pasos de escalamiento. Requiere incident:read. Esta es la cronología que GET /incidents/{id} no incluye.

Parámetros y respuestas
NombreUbicaciónTipo
id obligatoriopathstring
RespuestaListIncidentEventsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /channels · POST /channels

Leer requiere notification_channel:read; crear requiere notification_channel:manage. Cada uno lleva id, kind, name, target y workspaceId.

secret se devuelve solo al crear un canal, y nunca más. Es la clave de firma de un webhook; guardarla donde pudiera volver a leerse convertiría una clave de solo lectura en una forma de falsificar peticiones firmadas.

Puede crear los tipos que una persona puede crear en el panel: email, webhook, telegram, slack, teams, discord, pagerduty y jsm. SMS, WhatsApp, satélite y push los registra la persona que los recibe y no pueden crearse por la API — eso es lo que los hace consentimiento y no un campo que alguien escribió.

Un canal de correo se crea sin confirmar y recibe un solo mensaje preguntándole si quiere alertas. No se envía nada más hasta que acepte, así que crear uno por la API no pone por sí solo una dirección en su rotación de avisos.

Parámetros y respuestas

GET /channels

Sin parámetros ni campos de cuerpo declarados.

RespuestaListChannelsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /channels

NombreUbicaciónTipo
kindbodystring
namebodystring
targetbodystring
workspaceIdbodyrequests.NullableString
RespuestaCreatedChannelResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

PATCH /channels/{id} · DELETE /channels/{id} · POST /channels/{id}/test

Todos requieren notification_channel:manage. El envío de prueba se rechaza para una dirección que no ha confirmado — de lo contrario sería una forma ilimitada de escribirle a una dirección sin consentimiento, con una etiqueta servicial encima.

Parámetros y respuestas

PATCH /channels/{id}

NombreUbicaciónTipo
id obligatoriopathstring
enabledbodyboolean
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /channels/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /channels/{id}/test

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaTestDeliveryResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /status-pages · POST /status-pages

Leer requiere status_page:read; escribir requiere status_page:manage. Cada una lleva id, name, slug, visibility, customDomain, domainVerifiedAt, subscribersEnabled, componentCount, workspace y createdAt.

Parámetros y respuestas

GET /status-pages

Sin parámetros ni campos de cuerpo declarados.

RespuestaListStatusPagesResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /status-pages

NombreUbicaciónTipo
namebodystring
workspaceIdbodystring
RespuestaCreatedResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

GET /status-pages/{id} · PATCH /status-pages/{id} · DELETE /status-pages/{id}

Leer requiere status_page:read; cambiar o eliminar requiere status_page:manage.

Parámetros y respuestas

GET /status-pages/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaGetStatusPageResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

PATCH /status-pages/{id}

NombreUbicaciónTipo
id obligatoriopathstring
namebodystring
headlinebodyrequests.NullableString
descriptionbodyrequests.NullableString
logoUrlbodyrequests.NullableString
themeAccentbodystring
languagebodystring
historyDaysbodyinteger
showResponseTimesbodyboolean
showIncidentHistorybodyboolean
subscribersEnabledbodyboolean
visibilitybodystring
passwordbodyrequests.NullableString
customCssbodyrequests.NullableString
hideVitrinaBrandingbodyboolean
groupByHostbodyboolean
RespuestaUpdatedStatusPageResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /status-pages/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /status-pages/{id}/components · DELETE /status-pages/{id}/components

Agregar o quitar un monitor de una página. Requiere status_page:manage.

El monitor tiene que estar en el mismo espacio de trabajo que la página, no solo en la misma organización. En una cuenta de agencia eso es lo que impide que el monitor de un cliente se publique en la página de otro.

Parámetros y respuestas

POST /status-pages/{id}/components

NombreUbicaciónTipo
id obligatoriopathstring
monitorIdbodystring
displayNamebodystring
RespuestaComponentAckResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /status-pages/{id}/components

NombreUbicaciónTipo
id obligatoriopathstring
componentquerystring
componentIdbodystring
RespuestaComponentAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /workspaces · POST /workspaces · DELETE /workspaces/{id}

Leer requiere workspace:read, y el resto sus propios permisos. Cada uno lleva id, name, slug, clientReference e isDefault.

La clave de un miembro confinado ve solo los espacios de trabajo a los que ese miembro está confinado. El espacio de trabajo predeterminado no se puede eliminar.

Parámetros y respuestas

GET /workspaces

Sin parámetros ni campos de cuerpo declarados.

RespuestaListWorkspacesResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /workspaces

NombreUbicaciónTipo
namebodystring
clientReferencebodystring
RespuestaCreatedResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /workspaces/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /members · POST /members

Leer requiere member:read; invitar requiere member:invite. La respuesta trae members e invitations por separado — una invitación que nadie ha aceptado no ha agregado a nadie, y juntarlas daría un recuento de puestos que no coincide con lo que se le factura.

POST envía una invitación en lugar de crear una cuenta. Acepta un correo, un rol y, si quiere, workspaceIds para confinar a esa persona.

Parámetros y respuestas

GET /members

Sin parámetros ni campos de cuerpo declarados.

RespuestaListMembersResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /members

NombreUbicaciónTipo
emailbodystring
rolebodystring
workspaceIdsbodystring[]
RespuestaAckResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

PATCH /members/{id} · DELETE /members/{id} · DELETE /invitations/{id}

Cambiar un rol requiere member:update_role; quitar a alguien requiere member:remove; revocar una invitación requiere member:invite.

Quitar a un miembro elimina sus canales de alerta personales — su teléfono, su chat privado, su número móvil — junto con sus claves de API. Los canales compartidos no se tocan. Al último propietario no se le puede quitar ni bajar de rol.

Parámetros y respuestas

PATCH /members/{id}

NombreUbicaciónTipo
id obligatoriopathstring
rolebodystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /members/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /invitations/{id}

NombreUbicaciónTipo
id obligatoriopathstring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /maintenance · POST /maintenance · DELETE /maintenance

Ventanas durante las cuales nada avisa a nadie. Por omisión las verificaciones siguen corriendo y registrando, así que esos minutos cuentan para la disponibilidad como cualquier otro; con keepChecking en false no se comprueba nada mientras la ventana está abierta, lo que deja un hueco en el historial en lugar de un bajón. Leer requiere incident:read; escribir requiere maintenance:manage.

Lleva title, startsAt, endsAt, timezone, monitorIds, recurrenceRule, keepChecking, showOnStatusPage y notifySubscribers. Una ventana periódica es una sola fila, no muchas.

Una regla repite la ventana a la misma hora local en su propia timezone, así que una ventana que cruza un cambio de hora se mantiene en la hora prevista. FREQ=DAILY, FREQ=WEEKLY y FREQ=MONTHLY se expanden, opcionalmente con INTERVAL, COUNT, UNTIL y un BYDAY o BYMONTHDAY que nombre el día en que empieza la propia ventana. Cualquier otra regla se guarda y se devuelve sin cambios y solo retiene las alertas en su primera ocurrencia: nunca se adivina.

Parámetros y respuestas

GET /maintenance

NombreUbicaciónTipo
pastqueryboolean
RespuestaListMaintenanceResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /maintenance

NombreUbicaciónTipo
titlebodystring
descriptionbodystring
workspaceIdbodystring
monitorIdsbodystring[]
startsAtbodystring
endsAtbodystring
recurrenceRulebodystring
timezonebodystring
keepCheckingbodyboolean
showOnStatusPagebodyboolean
notifySubscribersbodyboolean
RespuestaCreatedResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /maintenance

NombreUbicaciónTipo
idquerystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /on-call

Horarios, políticas de escalamiento, reemplazos y quién está de guardia ahora mismo. Requiere oncall:read.

onCallNow se resuelve en el momento en que pregunta, con viaOverride indicando si salió de la rotación o de alguien que está cubriendo. unreachable nombra a los participantes que no tienen ningún canal por el que se les pueda alcanzar de verdad, que es la falla que conviene detectar antes de un incidente y no durante.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaGetOnCallResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /agents · POST /agents · DELETE /agents · GET /agents/{id}/metrics

Los agentes de servidor reportan CPU, memoria y disco desde sus propias máquinas. Registrarlos requiere agent:enroll, leerlos requiere agent:read, quitarlos requiere agent:delete.

Registrar uno devuelve un token, una sola vez. Es con lo que el agente se autentica, así que después ya no se puede leer.

Parámetros y respuestas

GET /agents

Sin parámetros ni campos de cuerpo declarados.

RespuestaListAgentsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /agents

NombreUbicaciónTipo
namebodystring
workspaceIdbodyrequests.NullableString
RespuestaEnrolledAgentResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /agents

NombreUbicaciónTipo
idquerystring
idbodystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /agents/{id}/metrics

NombreUbicaciónTipo
id obligatoriopathstring
hoursqueryinteger
limitqueryinteger
RespuestaGetAgentMetricsResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /api-keys · POST /api-keys · DELETE /api-keys

Leer requiere api_key:read; crear y revocar requieren api_key:manage. Cada una lleva id, name, prefix, scopes, workspaceIds, owner, createdAt, lastUsedAt, expiresAt y revokedAt.

token se devuelve solo al crearla. prefix es la parte que se puede mostrar, que es lo que le permite distinguir dos claves en una lista sin que ninguna sea legible.

Una clave hereda el rol y el confinamiento a espacios de trabajo de la membresía que la creó, así que una clave no puede ser una forma de rodear un límite que tiene quien la creó.

Parámetros y respuestas

GET /api-keys

Sin parámetros ni campos de cuerpo declarados.

RespuestaListApiKeysResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

POST /api-keys

NombreUbicaciónTipo
namebodystring
scopesbodystring[]
workspaceIdsbodystring[]
expiresInDaysbodyrequests.NullableInt64
RespuestaCreatedApiKeyResponse
Códigos de estado201 400 401 403 404 429
Límite de peticiones30 por minuto

DELETE /api-keys

NombreUbicaciónTipo
idquerystring
idbodystring
RespuestaAckResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /audit

Cambios de configuración, con quién los hizo y qué cambió. Requiere audit_log:read, que es del plan Business en adelante.

Se pagina con nextBefore y no por número de página, así que el corte entre páginas no se mueve mientras las está leyendo. Las entradas se registran en todos los planes — el plan controla la lectura, así que subir de nivel abre todo el historial en lugar de empezar uno.

Nunca se escriben credenciales, hashes ni secretos en changes.

Parámetros y respuestas
NombreUbicaciónTipo
limitqueryinteger
RespuestaListAuditResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

GET /me

Quién es esta clave, a qué alcanza y qué permite el plan. No requiere permiso alguno — toda clave puede describirse a sí misma.

Lleva user, organization, membership(rol y confinamiento a espacios de trabajo), entitlements (los límites del plan ya resueltos, con los paquetes adicionales ya incorporados) y usage. Úselo para comprobar un límite antes de intentar crear algo, en lugar de después de que se lo rechacen.

Una sesión recibe además organizations, con todas las organizaciones a las que pertenece la persona. Una clave de API no: una clave se emite contra una sola membresía y queda confinada a ella, así que listar las demás anunciaría organizaciones a las que esa credencial no llega.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaGetMeResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones120 por minuto

DELETE /account

Elimina la organización y todo lo que hay dentro. Ninguna constante de permiso protege esta ruta porque la comprobación es la propiedad: se rechaza para quien no sea propietario.

Esto no se puede deshacer y no es una pausa. Úselo de forma deliberada.

Parámetros y respuestas

Sin parámetros ni campos de cuerpo declarados.

RespuestaAccountDeletedResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

POST /billing/apple/verify

Confirma una compra dentro de nuestra propia aplicación móvil. Requiere billing:manage.

Está documentado por completitud y no para usarlo: solo se puede llamar con un comprobante que Apple emitió para nuestra aplicación, así que no hay nada que una integración de terceros pueda hacer con él. Aparece aquí porque una ruta que existe y no se describe en ninguna parte es indistinguible de una que a alguien se le olvidó.

Parámetros y respuestas
NombreUbicaciónTipo
transactionIdbodystring
RespuestaAppleVerifyResponse
Códigos de estado200 400 401 403 404 429
Límite de peticiones30 por minuto

GET /

El índice. Lista las rutas que sirve este despliegue, que es la versión legible por máquinas de esta página y siempre está al día — se genera a partir de lo que de verdad está montado.

Canal de incidentes (RSS y Atom)

Todos los incidentes de su cuenta como canal, para un lector y no para una biblioteca cliente. Cree la URL en el panel, en Ajustes → Notificaciones:

https://vitrinaengine.com/feeds/incidents/vtf_…/feed.xml
https://vitrinaengine.com/feeds/incidents/vtf_…/atom.xml

La URL es la credencial. No hay ninguna cabecera que enviar: quien tenga el enlace puede leer todos los incidentes de la cuenta, de todos los espacios de trabajo. Se muestra en el panel siempre que la necesite otra vez, porque vive en un lector de canales que alguien acabará reinstalando — y puede sustituirse o revocarse, con efecto en la siguiente petición y no cuando caduque una caché.

Lleva solo hechos del incidente: el nombre del monitor, la causa, la gravedad, el estado, cuándo se abrió y se cerró, y las novedades marcadas como públicas. Nunca un análisis posterior, nunca la configuración del monitor y nunca desde dónde se ejecutó una comprobación. La mayoría de los lectores sincronizan a través de servidores ajenos, así que el documento está escrito como si saliera de su edificio, porque sale.

Consultarlo una vez por minuto es lo previsto. A partir de sesenta peticiones por minuto para una URL responde 429, y una URL que nunca fue válida, que se ha sustituido o que se ha revocado responde 404 — la misma respuesta para los tres casos, de modo que no sirva para averiguar qué tokens fueron reales.

Lo que esta API deliberadamente no devuelve

  • El config de un monitor. Puede contener credenciales.
  • Desde qué región se ejecutó una verificación. Dónde verificamos es decisión nuestra y podemos cambiarlo a medida que colocamos y movemos sondas. Sería una promesa sobre nuestra infraestructura sobre la que usted no podría actuar, y tampoco se muestra en ninguna otra parte del producto.

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 tipo de filas, en CSV o JSON. entity es uno de monitors, hosts, status-pages, notification-channels, members, incidents, incident-events, postmortems, audit-log, error-issues, uptime-daily, uptime-hourly o analytics-hourly. Cualquier otro responde 404.

format es csv (por defecto) o json. from y to son marcas de tiempo RFC 3339. bom añade una marca de orden de bytes UTF-8 al CSV: Excel la necesita para los nombres con caracteres no ASCII, y la mayoría de los lenguajes de scripting la leen como parte del primer encabezado de columna, así que está desactivada salvo que la pidas.

Parámetros y respuestas
NombreUbicaciónTipo
entity obligatoriopathstring
bomqueryboolean
formatquerystring
fromquerystring
toquerystring
Códigos de estado200 400 401 403 404 429
Límite de peticiones6 por hora

GET /export

Todo lo que la clave puede leer, en un zip: un archivo por entidad más manifest.json, que indica qué contiene, cuántas filas tiene cada archivo y qué entidades faltan. Lo que el rol de la clave no puede leer se omite en vez de rechazar la petición entera, y el manifiesto evita que eso ocurra en silencio.

Parámetros y respuestas
NombreUbicaciónTipo
bomqueryboolean
formatquerystring
fromquerystring
toquerystring
Códigos de estado200 400 401 403 404 429
Límite de peticiones6 por hora

What an export does not contain

Una exportación no contiene nada que autentique: ni configuración de canales, ni tokens de heartbeat, ni hashes de contraseñas. La configuración de un monitor sí va incluida, sin nada con forma de credencial — cuerpo de la petición, cabeceras, cadena de comunidad SNMP, credenciales de buzón. Los resultados de comprobación en bruto tampoco están: la retención los elimina, así que la disponibilidad procede de los agregados.

Size, and the one refusal you may meet

Las series horarias están limitadas a 92 días por petición; una ventana mayor se rechaza con export_window_too_wide en lugar de recortarse en silencio. Límite propio: 6 exportaciones por hora y organización.

Versionado

La versión va en la ruta. Se agregarán campos a las respuestas — trate los desconocidos como algo a ignorar y no como un error — pero nada se quitará de v1 ni cambiará de significado dentro de ella.

¿Falta algo?

La superficie es deliberadamente pequeña: cubre un panel de pared, un resumen en un chat y un script de despliegue que silencia un monitor mientras dura una publicación. Si está construyendo algo que no alcanza, escriba a support@vitrinaengine.com — saber qué quiere la gente de verdad es como se elige el siguiente endpoint.

Precios · Términos