Vigilia Incidents API
Diagnosed problems, in plain language, with a fix prompt.
Diagnosed problems, in plain language, with a fix prompt.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/getvigilia-com:getvigilia-com-incidents-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Vigilia Incidents API
version: 1.0.0
summary: Read your apps and incidents, and mark incidents fixed — the same things the Vigilia dashboard does.
description: 'Vigilia watches your live app, explains every problem in plain language and writes a fix prompt for your AI builder. This API gives your own scripts and AI agents the same view.
**Authentication.** Create a personal access token in the dashboard under Settings → API tokens, and send it as `Authorization: Bearer vgs_…`. A token acts as you across every app you own, so keep it secret. Read-only tokens can call every `GET`; changing an incident needs a read & write token.
**The fix loop.** List your open incidents (worst first), read one — its `fixPrompt` is written for your builder and its `evidence` carries the technical detail — fix it, then `POST …/resolve`. Resolving opens a fix watch: if the error stays away through real traffic for 24 hours, Vigilia confirms the fix (`fix.watch` becomes `verified`).
**Rate limits.** Per token, per minute: Free 60, Pro 300, Team 600. Free accounts also have 2,000 requests a day across all their tokens (API and MCP together), reset at midnight UTC. Over either limit you get `429` with a `Retry-After` header; the daily one has the code `daily_limit`.
**Conventions.** Timestamps are epoch milliseconds. Errors are always `{ "error": { "code", "message" } }`. Something that exists but belongs to another account is reported as `404`, never `403`.'
contact:
name: Vigilia support
email: support@getvigilia.com
url: https://getvigilia.com
servers:
- url: https://app.getvigilia.com/v1
description: Production
security:
- bearerAuth: []
tags:
- name: Incidents
description: Diagnosed problems, in plain language, with a fix prompt.
paths:
/incidents:
get:
tags:
- Incidents
summary: List incidents — open ones worst first
description: 'Open incidents come back by severity, then most recent: the order to fix them in.'
operationId: listIncidents
parameters:
- name: appId
in: query
description: Only this app's incidents.
schema:
type: string
- name: status
in: query
schema:
type: string
enum:
- open
- resolved
- ignored
- all
default: open
- name: severity
in: query
description: Comma-separated, e.g. `critical,high`.
schema:
type: string
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 25
responses:
'200':
description: Incidents.
content:
application/json:
schema:
type: object
required:
- incidents
- hasMore
properties:
incidents:
type: array
items:
$ref: '#/components/schemas/Incident'
hasMore:
type: boolean
'400':
$ref: '#/components/responses/InvalidRequest'
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
/incidents/{incidentId}:
get:
tags:
- Incidents
summary: One incident, with its fix prompt and the evidence behind it
operationId: getIncident
parameters:
- $ref: '#/components/parameters/IncidentId'
responses:
'200':
description: The incident.
content:
application/json:
schema:
type: object
required:
- incident
properties:
incident:
$ref: '#/components/schemas/IncidentDetail'
'401':
$ref: '#/components/responses/Unauthenticated'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
/incidents/{incidentId}/resolve:
post:
tags:
- Incidents
summary: Mark an incident fixed — and start verifying it
description: Resolving a diagnosed error opens a fix watch. After 24 hours, if the error has stayed away through enough traffic that it would very likely have shown again (`fix.evidence.expectedErrors` of 3 or more), `fix.watch` becomes `verified` and the owner gets a "your fix worked" email. With less traffic the watch keeps going for up to 7 days, then closes as `not_enough_traffic`. If the error comes back, the incident reopens flagged as a regression.
operationId: resolveIncident
parameters:
- $ref: '#/components/parameters/IncidentId'
responses:
'200':
$ref: '#/components/responses/IncidentChanged'
'401':
$ref: '#/components/responses/Unauthenticated'
'403':
$ref: '#/components/responses/InsufficientScope'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
/incidents/{incidentId}/ignore:
post:
tags:
- Incidents
summary: Ignore an incident
description: Ignored errors don't reopen and aren't verified.
operationId: ignoreIncident
parameters:
- $ref: '#/components/parameters/IncidentId'
responses:
'200':
$ref: '#/components/responses/IncidentChanged'
'401':
$ref: '#/components/responses/Unauthenticated'
'403':
$ref: '#/components/responses/InsufficientScope'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
/incidents/{incidentId}/reopen:
post:
tags:
- Incidents
summary: Reopen an incident
operationId: reopenIncident
parameters:
- $ref: '#/components/parameters/IncidentId'
responses:
'200':
$ref: '#/components/responses/IncidentChanged'
'401':
$ref: '#/components/responses/Unauthenticated'
'403':
$ref: '#/components/responses/InsufficientScope'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
components:
responses:
NotFound:
description: No such thing on your account.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
RateLimited:
description: Too many requests for this token (`rate_limited`), or a Free account's daily requests are used up (`daily_limit`) — wait `Retry-After` seconds.
headers:
Retry-After:
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InvalidRequest:
description: A parameter has a value that isn't allowed.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthenticated:
description: No token, or not a valid one.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InsufficientScope:
description: The token is read-only.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
IncidentChanged:
description: The incident after the change.
content:
application/json:
schema:
type: object
required:
- incident
properties:
incident:
$ref: '#/components/schemas/Incident'
message:
type: string
description: Present when a fix watch started.
parameters:
IncidentId:
name: incidentId
in: path
required: true
schema:
type: string
schemas:
Incident:
type: object
properties:
id:
type: string
appId:
type: string
kind:
type: string
enum:
- error
- downtime
- health
description: 'error: errors from real visitors, diagnosed. downtime: the uptime checker. health: a recurring check of the app itself (secret keys in its public code, its certificate).'
check:
type:
- string
- 'null'
enum:
- secrets
- certificate
- domain
- speed
- null
description: 'Health incidents: which check raised it. `speed`: the app answers several times slower than its usual.'
details:
type: array
items:
type: string
description: 'Health incidents: the specifics, e.g. each exposed key, masked, and where it was found. Empty otherwise.'
endpoint:
type:
- object
- 'null'
description: Downtime incidents about one of the app's extra check URLs (a page such as checkout, or an API), rather than the whole app. Null otherwise.
properties:
url:
type: string
label:
type:
- string
- 'null'
description: The owner's name for it, e.g. Checkout.
required:
- url
- label
sentry:
type:
- object
- 'null'
description: The Sentry issue this incident explains, when it came through the Sentry bridge (Team). Null otherwise.
properties:
url:
type: string
required:
- url
issue:
type:
- object
- 'null'
description: The issue opened for this incident in GitHub Issues, Linear or Jira (Team plan), by hand or automatically. Null when there is none.
properties:
tracker:
type: string
enum:
- github
- linear
- jira
url:
type: string
key:
type: string
description: '#123, ENG-45, SHOP-7'
required:
- tracker
- url
- key
related:
type:
- object
- 'null'
description: 'The same problem seen from the other side: for a request that failed with a 5xx in visitors'' browsers, the server error behind it (side: server); for a server error, the failed request visitors saw (side: browser). Null when there is none.'
properties:
side:
type: string
enum:
- server
- browser
incidentId:
type:
- string
- 'null'
title:
type: string
count:
type: integer
required:
- side
- incidentId
- title
- count
severity:
type: string
enum:
- critical
- high
- medium
- low
status:
type: string
enum:
- open
- resolved
- ignored
title:
type: string
summary:
type: string
description: What broke, in plain language.
userImpact:
type: string
description: Who is affected and how.
occurrences:
type:
- integer
- 'null'
sessions:
type:
- integer
- 'null'
isRegression:
type: boolean
description: It was marked fixed and came back.
createdAt:
type: integer
updatedAt:
type: integer
resolvedAt:
type:
- integer
- 'null'
fix:
type: object
properties:
watch:
type:
- string
- 'null'
enum:
- watching
- verified
- not_enough_traffic
- unverified
- null
description: '`watching` until there is a verdict. `verified`: the error stayed away through enough traffic that it would very likely have shown again. `not_enough_traffic`: watched for 7 days without enough traffic to say either way. `unverified` is the same outcome as recorded before October 2026.'
verifiedAt:
type:
- integer
- 'null'
evidence:
type:
- object
- 'null'
description: The traffic behind the verdict, or behind the wait so far. Null until the watch is first examined, 24 hours after the incident is resolved.
properties:
expectedErrors:
type: number
description: 'How many times the error would have shown up since the fix, had the fix done nothing: its rate per visit in the week before the fix, times the visits since. A fix is confirmed at 3 or more.'
visits:
type: integer
description: Production page loads since the incident was resolved.
baselineHits:
type: integer
description: Sessions the error hit in the 7 days before the incident was resolved.
baselineVisits:
type: integer
description: Production page loads in those 7 days.
measured:
type: boolean
description: False when traffic for this error cannot be counted yet (errors from the app's backend). Its fix then cannot be confirmed.
countedAt:
type: integer
dashboardUrl:
type: string
afterDeploy:
type:
- object
- 'null'
description: The deploy this problem first appeared after, within a day. Timing, not blame.
properties:
at:
type: integer
label:
type:
- string
- 'null'
providerOutage:
type:
- object
- 'null'
description: A platform the app depends on (Supabase, Vercel, OpenAI…) was reporting its own incident when this began, from its public status page. There may be nothing to fix in the app. `resolvedAt` is set once the provider marks it resolved; if the problem continues after that, the cause is likely the app's.
properties:
provider:
type: string
examples:
- Supabase
incident:
type: string
description: The provider's own title for its incident.
level:
type: string
enum:
- outage
- degraded
url:
type: string
description: The provider's status page for this incident.
startedAt:
type: integer
resolvedAt:
type:
- integer
- 'null'
IncidentDetail:
allOf:
- $ref: '#/components/schemas/Incident'
- type: object
properties:
builder:
type: string
confidence:
type: number
minimum: 0
maximum: 1
fixPrompt:
type: string
description: A paste-ready prompt for the app's builder, or for any coding agent.
evidence:
type:
- object
- 'null'
properties:
type:
type: string
message:
type: string
normalizedMessage:
type: string
page:
type:
- string
- 'null'
description: Where the visitor was — not necessarily where the fault is.
pagePattern:
type: string
source:
type:
- string
- 'null'
description: Script, or for a failed request the endpoint that failed.
line:
type:
- integer
- 'null'
column:
type:
- integer
- 'null'
httpStatus:
type:
- integer
- 'null'
stack:
type: array
items:
type: string
sourceStack:
type:
- array
- 'null'
items:
type: string
description: The top frames in the app's original code, resolved through its published source maps (e.g. `at src/pages/Checkout.tsx:42:7` with a few lines of source). Null when the app publishes no source maps.
breadcrumbs:
type: array
items:
type: object
properties:
at:
type: integer
type:
type: string
message:
type: string
userAgent:
type:
- string
- 'null'
environment:
type: string
enum:
- production
- development
count:
type: integer
sessions:
type: integer
firstSeenAt:
type: integer
lastSeenAt:
type: integer
Error:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
properties:
code:
type: string
enum:
- unauthenticated
- insufficient_scope
- not_found
- invalid_request
- rate_limited
- internal
message:
type: string
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: A personal access token (`vgs_…`) from Settings → API tokens.