HTTP API

Manage sources and rules, read source events and findings, and drive Leak Alarm from your own code.

Advanced Available on every plan, with read only or read and write keys Updated 25 October 2026

These pages describe ShellOrbit as it runs today. Breaking changes to the HTTP API are announced before they ship, and existing request and response shapes stay supported.

Authenticate

Bearer token. Create a key in the dashboard, store it as a secret, and send it on every request.

bash
curl https://api.shellorbit.com/v1/sources \
  -H "authorization: Bearer $SHELLORBIT_API_KEY"

Keys are read only or read and write. A revoked key stops working at once.

Sources and rules

HTTP API: Method and path, What it does
Method and pathWhat it does
GET /v1/sourcesList sources
POST /v1/sourcesCreate one: {"name":"AWS production","kind":"aws","silent_hours":24}; kind github, aws, okta, auth0, app, or custom, with signature_format and inbound_secret for a custom source
GET /v1/sources/{id}Read one source with its configuration
PATCH /v1/sources/{id}Update its name, silent hours, IP allowlist, masked fields, or switched off rules
DELETE /v1/sources/{id}Delete a source; its URL stops accepting events at once
POST /v1/sources/{id}/secret/rotateA new secret, shown once
POST /v1/sources/{id}/testRun a sample event of the source’s kind through its rules
GET /v1/sources/{id}/eventsThe source’s events, newest first, with a cursor
GET /v1/events/{id}One source event with headers, body, and signature result, masked fields hidden
GET /v1/rules/catalogThe ready-made rules: id, kind, title, severity, description
GET /v1/rulesYour custom rules
POST /v1/rulesCreate one, as below
PATCH /v1/rules/{id}Change a rule, or turn it off with {"enabled":false}
DELETE /v1/rules/{id}Delete a rule
GET /v1/usageThis month’s source events (fair use, never charged), log volume, tripwires, and optional overages
PUT /v1/usage/log-overageOwners and admins, signed in: {"on": true} keeps scanning logs past the allowance, billed per whole GB
GET /v1/alertsRead alert settings, with channel URLs masked
PATCH /v1/alertsUpdate alert settings
POST /v1/alerts/testSend a test alert down every saved channel and report each result

A custom rule:

json
{
  "name": "Lots of new Stripe disputes",
  "source_id": "",
  "severity": "high",
  "conditions": [
    { "path": "body.type", "op": "eq", "value": "charge.dispute.created" }
  ],
  "threshold": { "count": 5, "minutes": 60 },
  "enabled": true
}

source_id empty means any source. op is eq, ne, contains, exists, or in; threshold is optional. See rules.

Leak Alarm and Incident Alerts

Auth: Read is a session or any API key. Write needs a read and write key or a signed-in member. Member and Admin need a signed-in member, admin or owner; API keys are refused.

API keys can never create or delete API keys, schedule a revoke, or change a person’s own account (password, email, two-step verification, sessions). A leaked key cannot mint another key or act on your other providers.

HTTP API: Method and path, Auth, What it does
Method and pathAuthWhat it does
GET /v1/leak/overviewReadOpen findings by severity, tripwire hits, coverage, and limits
GET /v1/leak/findingsReadFindings from every source, with masked values and fixes, up to 200
POST /v1/leak/findings/{id}/statusWrite{"status":"acknowledged"}, "resolved", or "open". See findings
POST /v1/leak/findings/{id}/revokeMemberSchedule a revoke ten minutes out
POST /v1/leak/findings/{id}/revoke/cancelWriteCancel a scheduled revoke
GET /v1/leak/assetsReadWatched domains and log drains with their last scan
POST /v1/leak/scansWriteScan a verified domain now: {"hostname":"app.example.com"}, three times an hour per domain
GET /v1/leak/tripwiresReadList tripwires
POST /v1/leak/tripwiresWriteCreate one: {"name":"Users table","type":"database_row"}; type link, email, database_row, or aws_key
DELETE /v1/leak/tripwires/{id}WriteDelete a tripwire
GET /v1/leak/tripwires/hitsReadRecent hits
GET /v1/leak/drainsReadList log drains
POST /v1/leak/drainsWriteCreate one: {"name":"Prod","provider":"vercel","secret":"…","verify":"…"}; provider vercel, netlify, supabase, cloudflare, or cloudwatch
DELETE /v1/leak/drains/{id}WriteDelete a drain
GET /v1/leak/sdk/projectsReadList SDK projects with their DSNs
POST /v1/leak/sdk/projectsWriteCreate one: {"name":"Checkout API"}
POST /v1/leak/sdk/projects/{id}/rotateWriteNew key and DSN; the old one stops at once
DELETE /v1/leak/sdk/projects/{id}WriteDelete a project and its tripwire
GET /v1/leak/accountsReadConnected accounts for revoke
PUT /v1/leak/accounts/{provider}AdminConnect aws, openai, supabase, or github
PATCH /v1/leak/accounts/{provider}AdminTurn automatic revoke on or off: {"auto_revoke":true}
DELETE /v1/leak/accounts/{provider}AdminDisconnect and delete the credential
GET /v1/leak/incidentsReadIncidents affecting you, and the last 90 days of advisories with their state
GET /v1/leak/incidents/{id}ReadOne advisory and every match
GET /v1/leak/stackReadYour stack, declared and detected
GET /v1/leak/stack/catalogReadProducts you can declare
POST /v1/leak/stackWriteDeclare: {"product":"php","version":"8.1","label":"billing API"}
DELETE /v1/leak/stack/{id}WriteRemove a declared item, or dismiss a detected one

Intake

Used by the SDK and logging platforms, not by API keys.

HTTP API: Method and path, Auth, What it does
Method and pathAuthWhat it does
POST /v1/intake/{project}/findingsAuthorization: DSN <key>Report masked findings, up to 50 a request
POST /v1/intake/{project}/fingerprintsDSNRegister salted fingerprints of your keys
GET /v1/intake/{project}/saltDSNThe project’s fingerprint salt
GET /v1/intake/{project}/tripwireDSNA fake AWS key to plant
POST /v1/intake/{project}/runtimeDSNNode.js and OpenSSL versions, platform, and architecture
POST /v1/intake/{project}/outboundDSNHostnames the app and its packages connect to, up to 200 a request. See outbound traffic watch
POST /v1/drains/{token}The token in the URL, plus the drain’s secretOne log batch from a platform

Pagination

Cursor based. A response carries next_cursor when more rows exist.

json
{
  "data": [ { "id": "evt_9c41f0", "received_at": "2026-10-25T06:12:04Z", "signature_verified": true } ],
  "next_cursor": "ZXZ0Xzk1MmEx"
}

Pass it back as cursor. Cursors are stable across inserts, so no row is skipped or repeated.

Errors

json
{
  "error": {
    "type": "invalid_request",
    "message": "Choose a kind: github, aws, okta, auth0, app, or custom.",
    "param": "kind"
  }
}
HTTP API: Status, Meaning
StatusMeaning
400Bad request
401Missing or revoked key
403Scope or role problem
404Unknown id
429Rate limited; retry with backoff
5xxOur failure; retry reads with backoff, and check a write took effect before repeating it