Skip to content

REST API reference

Every operation of the Belvador API: path, required scope, which ones need a person's approval, retries and version checks; generated from the list the server runs.

Markdown
On this page

Status: live (beta). The REST API answers at https://api.belvador.dev. This page is generated from the same list of operations the gateway runs, so it changes only when the API does. Tools that support OAuth can connect by sign-in instead of a token. Coding agents can use the same operations through the MCP server.

Basics#

  • Base URL: https://api.belvador.dev/v1. JSON uses snake_case, times are RFC 3339 in UTC, ids are strings.

  • Authentication: send a personal token (blv_pat_…, from Account → API tokens) or a service token (blv_svc_…, from Workspace settings → Service accounts) in the Authorization header as Bearer blv_… (credentials). Tokens last at most 365 days. A token works only inside its workspace and the projects and environments it was given, and never above the current role of the person or service account behind it.

  • Sign in with OAuth: tools that support OAuth 2.1, such as MCP clients, find Belvador from https://api.belvador.dev/.well-known/oauth-protected-resource and https://belvador.dev/.well-known/oauth-authorization-server. They register themselves (RFC 7591, or a Client ID Metadata Document), send you to belvador.dev to pick a workspace and permissions, and must use PKCE with S256. Access tokens (blv_oat_…) last 60 minutes; refresh tokens (blv_ort_…) change on every use and stop after 30 days without use. A code or refresh token used twice ends that connection — two refreshes sent at the same moment count as reuse, so refresh one at a time. See and disconnect apps under Account → Connected apps.

  • Errors follow RFC 9457 (application/problem+json): code is the stable error code, request_id identifies the call, and errors[].pointer names each invalid field, for example /name.

  • Creating something needs an Idempotency-Key header. Sending the same key with the same body within 24 hours returns the first answer again, marked Idempotent-Replayed: true, and creates nothing new. A one-time secret in that answer (a ping token, a key) is never repeated: the replay shows null and names the field in Belvador-Secret-Withheld. The same key with a different body is refused with 422 IDEMPOTENCY_KEY_REUSED.

  • Changing or deleting a monitor, uptime check, SLO, project setting or alert rule needs If-Match with the ETag you last read. Without it the answer is 428; if someone changed it since, 412 — read it again and retry.

  • Lists return { "data": [...], "next_cursor": "...", "complete": true }. Pass cursor with the same filters for the next page; a cursor lasts 24 hours and only works for the list that made it.

  • Sensitive operations — keys, members, alert destinations, node changes — answer 403 APPROVAL_REQUIRED and wait for a person; see Approvals.

  • Data stored on your node (issues, events, traces, logs, monitor runs) is marked node data below. The gateway reads it from your node with a ticket that lasts a few minutes and passes the answer through; Belvador's servers neither store nor log it. If your node is offline the answer is 503 NODE_OFFLINE — nothing is served from a copy. Trace and log searches need start and end, at most 168 hours apart.

  • Rate limits: 300 calls per minute per token and 1200 per workspace, and 4 node-data calls in flight per token. Every answer carries the IETF RateLimit-Policy and RateLimit headers; over the limit the answer is 429 RATE_LIMITED with Retry-After.

  • Turning it off: revoking a token stops it within about 30 seconds. In an emergency Belvador can pause the API for one workspace or for everyone; calls then answer 503 PUBLIC_API_PAUSED and the app keeps working.

Approvals#

Sensitive operations never run straight from a token: DSN, upload and ingest keys, ping tokens, members and invites, tokens and service accounts, alert destinations and node changes. They are marked approval in the list below.

  1. The call answers 403 APPROVAL_REQUIRED with approval_id, approval_url (a page on belvador.dev), expires_at and state, and a Link: <…>; rel="approval" header. Nothing has changed yet.

  2. A person opens the link, sees exactly what will change, and approves with a code from their authenticator app no older than 10 minutes — or rejects. Most operations need an admin; deleting, rebuilding or recovering the node needs the owner; a new personal token can only be approved by the token's own holder. Requests from service accounts and OAuth apps are also emailed to the workspace's owners and admins.

  3. Send the same request again with the same Idempotency-Key, or poll GET /v1/approvals/{approval_id}, to read the outcome: executed with the ids it produced (200), rejected, expired after 15 minutes (410), or failed with the reason in code.

What always holds:

  • It runs exactly the request the person saw, once, as that person. If the stored request no longer matches, or the token was revoked or lost its rights meanwhile, it fails and nothing runs.

  • Secrets it creates — a new key, token or invite link — are shown once to the approving person, never to the caller.

  • What a person types themselves — the project or node name that confirms a deletion, a bot token, webhook URL or mail password — is never accepted from the caller.

  • At most 20 requests wait per workspace; more answer 429 RATE_LIMITED.

  • failed with APPROVAL_OUTCOME_UNKNOWN means it was approved but its result was never recorded. Check the resource before asking again.

Operations#

alert_deliveries#

CallScopeRoleNotes
POST /v1/alert-deliveries/{delivery_id}/replayalerts:writeadmin—

alert_rules#

CallScopeRoleNotes
GET /v1/alert-rulesalerts:readviewerpaged
POST /v1/alert-rulesalerts:writeadmin—
PUT /v1/alert-rules/{rule_id}/enabledalerts:writeadmin—
DELETE /v1/alert-rules/{rule_id}alerts:writeadminIf-Match

alerts#

CallScopeRoleNotes
GET /v1/alertsalerts:readviewerpaged

approvals#

CallScopeRoleNotes
GET /v1/approvals/{approval_id}org:readviewer—

audit#

CallScopeRoleNotes
GET /v1/audit-logaudit:readadminpaged

coverage#

CallScopeRoleNotes
GET /v1/coveragecoverage:readviewer—
PUT /v1/projects/{project_id}/coverage-expectationscoverage:writemember—

destinations#

CallScopeRoleNotes
GET /v1/destinationsalerts:readviewerpaged
POST /v1/destinationsdestinations:manageadminapproval · Idempotency-Key
PATCH /v1/destinations/{destination_id}destinations:manageadminapproval
POST /v1/destinations/{destination_id}/connectiondestinations:manageadminapproval
DELETE /v1/destinations/{destination_id}destinations:manageadminapproval
PUT /v1/destinations/{destination_id}/recipientsdestinations:manageadminapproval
POST /v1/destination-recipients/{recipient_id}/resenddestinations:manageadmin—
POST /v1/destinations/{destination_id}/testnotifications:writeadmin—

events#

CallScopeRoleNotes
GET /v1/issues/{issue_id}/eventsevents:readviewernode data · paged
GET /v1/issues/{issue_id}/events/{event_id}events:readviewernode data

incident_rules#

CallScopeRoleNotes
GET /v1/incident-rulesalerts:readviewer—
POST /v1/incident-rulesalerts:writeadmin—
DELETE /v1/incident-rules/{rule_id}alerts:writeadmin—

incidents#

CallScopeRoleNotes
GET /v1/incidentsincidents:readviewerpaged
GET /v1/incidents/{incident_id}incidents:readviewer—
POST /v1/incidents/{incident_id}/ackincidents:writemember—
POST /v1/incidents/{incident_id}/resolveincidents:writemember—
POST /v1/incidents/{incident_id}/notesincidents:writemember—
PATCH /v1/incidents/{incident_id}incidents:writemember—

ingest_keys#

CallScopeRoleNotes
POST /v1/projects/{project_id}/ingest-keyskeys:managememberapproval · Idempotency-Key
DELETE /v1/ingest-keys/{key_id}keys:managememberapproval

invites#

CallScopeRoleNotes
POST /v1/invitesmembers:manageadminapproval · Idempotency-Key
DELETE /v1/invites/{invite_id}members:manageadmin—

issues#

CallScopeRoleNotes
GET /v1/issuesissues:readviewernode data · paged
GET /v1/issues/{issue_id}issues:readviewernode data
GET /v1/issues/{issue_id}/statsissues:readviewernode data
GET /v1/issues/{issue_id}/tagsissues:readviewernode data
GET /v1/issues/{issue_id}/activityissues:readviewernode data
PATCH /v1/issues/{issue_id}issues:writemembernode data
POST /v1/issues/bulkissues:writemembernode data

logs#

CallScopeRoleNotes
GET /v1/logslogs:readviewernode data · start/end · paged
GET /v1/logs/histogramlogs:readviewernode data · start/end
GET /v1/logs/facetslogs:readviewernode data · start/end
GET /v1/logs/{log_id}/aroundlogs:readviewernode data

maintenance#

CallScopeRoleNotes
GET /v1/maintenance-windowsmonitors:readviewerpaged
POST /v1/maintenance-windowsmonitors:writememberIdempotency-Key
PATCH /v1/maintenance-windows/{window_id}monitors:writemember—
DELETE /v1/maintenance-windows/{window_id}monitors:writemember—

members#

CallScopeRoleNotes
GET /v1/membersmembers:readviewerpaged
PATCH /v1/members/{user_id}members:manageadminapproval
DELETE /v1/members/{user_id}members:manageadminapproval

metrics#

CallScopeRoleNotes
GET /v1/metrics/namesmetrics:readviewernode data
GET /v1/metrics/seriesmetrics:readviewernode data · paged
GET /v1/metrics/querymetrics:readviewernode data · start/end

monitors#

CallScopeRoleNotes
GET /v1/monitorsmonitors:readviewerpaged
GET /v1/monitors/{monitor_id}monitors:readviewer—
POST /v1/monitorsmonitors:writememberIdempotency-Key
PATCH /v1/monitors/{monitor_id}monitors:writememberIf-Match
DELETE /v1/monitors/{monitor_id}monitors:writememberIf-Match
PUT /v1/monitors/{monitor_id}/pausemonitors:writemember—
PUT /v1/monitors/{monitor_id}/mutemonitors:writemember—
DELETE /v1/monitor-discoveries/{discovery_id}monitors:writemember—
GET /v1/monitors/{monitor_id}/signalmonitors:readviewernode data
GET /v1/monitors/{monitor_id}/occurrencesmonitors:readviewernode data · paged
POST /v1/monitors/backtestmonitors:readviewernode data

node#

CallScopeRoleNotes
GET /v1/nodeorg:readviewer—
POST /v1/nodenode:operateadminapproval · Idempotency-Key
POST /v1/node/jobs/{job_id}/retrynode:operateadmin—
POST /v1/node/{node_id}/resizenode:operateadminapproval
POST /v1/node/{node_id}/upgradenode:operateadmin—
DELETE /v1/node/{node_id}node:operateadminapproval
POST /v1/node/{node_id}/restorenode:operateadmin—
POST /v1/node/backupsnode:operateadmin—
PUT /v1/node/backup-custodynode:operateadminapproval
POST /v1/node/{node_id}/rebuildnode:operateadminapproval · Idempotency-Key
POST /v1/node/jobs/{job_id}/recovery-kitnode:operateadminapproval

notification_policies#

CallScopeRoleNotes
GET /v1/notification-policiesalerts:readviewer—
POST /v1/notification-policiesalerts:writeadmin—
DELETE /v1/notification-policies/{policy_id}alerts:writeadmin—

occurrences#

CallScopeRoleNotes
POST /v1/occurrencesmonitors:writemembernode data
DELETE /v1/occurrences/{monitor_slug}/{occurrence_id}monitors:writemembernode data

ping_tokens#

CallScopeRoleNotes
POST /v1/monitors/{monitor_id}/ping-tokens/rotatekeys:managememberapproval
POST /v1/monitors/{monitor_id}/ping-tokens/revoke-previouskeys:managememberapproval
POST /v1/monitors/{monitor_id}/ping-tokens/resetkeys:managememberapproval

privacy#

CallScopeRoleNotes
GET /v1/projects/{project_id}/privacyprojects:readviewer—
PUT /v1/projects/{project_id}/privacyprivacy:writeadminapproval

project_keys#

CallScopeRoleNotes
POST /v1/projects/{project_id}/keyskeys:managememberapproval · Idempotency-Key
POST /v1/keys/{key_id}/rotatekeys:managememberapproval
DELETE /v1/keys/{key_id}keys:managememberapproval

projects#

CallScopeRoleNotes
GET /v1/projectsprojects:readviewerpaged
GET /v1/projects/{project_id}projects:readviewer—
POST /v1/projectsprojects:writememberIdempotency-Key
PATCH /v1/projects/{project_id}projects:writememberIf-Match
PATCH /v1/projects/{project_id}/intakeprojects:writememberIf-Match
PATCH /v1/projects/{project_id}/observabilityprojects:writememberIf-Match
PUT /v1/projects/{project_id}/scrub/{group}privacy:writeadminapproval
PUT /v1/projects/{project_id}/checkin-authkeys:managememberapproval
PUT /v1/projects/{project_id}/environments/{name}/hiddenprojects:writemember—
DELETE /v1/projects/{project_id}projects:deleteadminapproval
POST /v1/projects/{project_id}/restoreprojects:writemember—
POST /v1/projects/{project_id}/test-eventprojects:writemember—

service_principals#

CallScopeRoleNotes
POST /v1/service-accountstokens:manageadminapproval · Idempotency-Key
PATCH /v1/service-accounts/{id}tokens:manageadminapproval

slos#

CallScopeRoleNotes
GET /v1/slosmonitors:readviewerpaged
GET /v1/slos/{slo_id}monitors:readviewer—
POST /v1/slosmonitors:writememberIdempotency-Key
PATCH /v1/slos/{slo_id}monitors:writememberIf-Match
DELETE /v1/slos/{slo_id}monitors:writememberIf-Match
PUT /v1/slos/{slo_id}/holdmonitors:writemember—
POST /v1/slos/importmonitors:writemember—

spans#

CallScopeRoleNotes
GET /v1/spanstraces:readviewernode data · start/end · paged
GET /v1/spans/histogramtraces:readviewernode data · start/end

telemetry#

CallScopeRoleNotes
GET /v1/telemetry/usageusage:readviewernode data

tickets#

CallScopeRoleNotes
POST /v1/ticketsissues:readviewernode data

tokens#

CallScopeRoleNotes
POST /v1/tokenstokens:manageadminapproval · Idempotency-Key
POST /v1/service-accounts/{service_principal_id}/tokenstokens:manageadminapproval · Idempotency-Key
DELETE /v1/tokens/{id}tokens:manageadmin—
PUT /v1/token-policytokens:manageadminapproval

traces#

CallScopeRoleNotes
GET /v1/traces/{trace_id}traces:readviewernode data
GET /v1/traces/{trace_id}/spanstraces:readviewernode data
GET /v1/traces/{trace_id}/spans/{span_id}traces:readviewernode data

upload_tokens#

CallScopeRoleNotes
POST /v1/projects/{project_id}/upload-tokenskeys:managememberapproval · Idempotency-Key
DELETE /v1/upload-tokens/{token_id}keys:managememberapproval

uptime#

CallScopeRoleNotes
GET /v1/uptime-checksmonitors:readviewerpaged
GET /v1/uptime-checks/{check_id}monitors:readviewer—
POST /v1/uptime-checksmonitors:writememberIdempotency-Key
PATCH /v1/uptime-checks/{check_id}monitors:writememberIf-Match
DELETE /v1/uptime-checks/{check_id}monitors:writememberIf-Match
PUT /v1/uptime-checks/{check_id}/holdmonitors:writemember—
POST /v1/uptime-checks/{check_id}/runsmonitors:writemember—

usage#

CallScopeRoleNotes
GET /v1/usageusage:readviewer—

workspace#

CallScopeRoleNotes
GET /v1/workspaceorg:readviewer—

Spotted something wrong or missing? Tell us: hello@belvador.dev