API reference
Every route under https://api.shiftlabs.org/v1, the role it needs, and the keys that call it.
API
Every route lives under https://api.shiftlabs.org/v1 and acts on your own workspace.
The workspace comes from the credential, never from the path or body, and another workspace's trigger or run answers 404. Send an API key as Authorization: Bearer slk_…. Bodies are JSON (16 KiB at most, except a deploy's source and a run's payload), and errors are {"error": "…"} with a 4xx or 5xx status.
A re-run starts a new run with the original payload, so it counts against your run quotas like any other run, and payloads older than 14 days answer 410. A full quota answers {"error": "quota exceeded", "limit", "max"}: with 429 for runs, and 403 for counts such as workflows, triggers, secrets, connections and API keys.
| Route | Method | Minimum role |
|---|---|---|
/v1/me principal, workspace, limits | GET | viewer |
/v1/workspace {"name"}, 1 to 64 characters; audited | PATCH | admin |
/v1/usage runs and egress in the last 24 h, counts, limits | GET | viewer |
/v1/workflows | GET | viewer |
/v1/workflows/:workflow body: the source | PUT | developer |
/v1/workflows/:workflow revokes its triggers, drops its vars and connection links; runs stay | DELETE | developer |
/v1/workflows/:workflow/versions | GET | viewer |
/v1/workflows/:workflow/versions/:hash/source {hash, language, source} | GET | developer |
/v1/workflows/:workflow/runs body: the payload, read like a webhook's, 256 KiB at most | POST | developer |
/v1/workflows/:workflow/rollback {"hash"}: new runs use that version | POST | developer |
/v1/deploys · /v1/deploys/:id deploys that waited on Python packages; ?status=building|live|failed | GET | viewer |
/v1/workflows/:workflow/connections {"connections": [...]} | GET · PUT | viewer · developer |
/v1/workflows/:workflow/vars/:NAME {"value"} | PUT · DELETE | developer |
/v1/triggers {"workflow", "signing"?: {"scheme", "secret"?}} | GET · POST | viewer · developer |
/v1/triggers/:id/rotate | POST | developer |
/v1/triggers/:id {"signing": {"scheme", "secret"?} | null}; the URL stays | PATCH | developer |
/v1/triggers/:id | DELETE | developer |
/v1/runs?status=&workflow=&limit=&before= newest first, cursor in nextBefore | GET | viewer |
/v1/runs/:id · /logs?limit= · /timeline · /egress | GET | viewer |
/v1/runs/:id/rerun same workflow and version, new run | POST | developer |
/v1/runs/:id/payload the delivered body; 410 after 14 days | GET | developer |
/v1/secrets metadata, never values | GET | viewer |
/v1/secrets/:NAME {"value", "hosts"?, "readable"?, "hmac"?} | PUT · DELETE | admin |
/v1/secrets/:NAME {"hosts"?, "readable"?, "hmac"?}; the value and its version stay | PATCH | admin |
/v1/connections | GET | viewer |
/v1/connections/:name {"hosts", "template"} | PUT · DELETE | admin |
/v1/vars | GET | viewer |
/v1/vars/:NAME {"value"} | PUT · DELETE | developer |
/v1/audit?limit= | GET | admin |
/v1/metrics/runs?hours= · /v1/metrics/egress?hours= | GET | viewer |
/v1/api-keys {"name", "role", "expiresInDays"?} | GET · POST | admin |
/v1/api-keys/:id | DELETE | admin |
/v1/members | GET | admin |
/v1/members/invitations {"email", "role"} | POST | admin |
/v1/members/:membershipId {"role"} | PATCH · DELETE | admin |
Roles
Roles rank viewer < developer < admin, and each role can do everything the roles below it can. They apply the same way to API keys and to members signed in to the dashboard.
- viewer
Read workflows, versions, runs, logs, timelines, egress, metrics, usage, vars, secret metadata (never a value), and connections with their hosts and templates. Trigger ids are shown masked and without URLs, because an unsigned trigger URL is enough to start a run.
- developer
Deploy, run, roll back and delete workflows and read their deployed source, set a workflow's connections and vars, set workspace vars, create, rotate and revoke triggers or change their signing, and re-run runs.
- admin
Set secrets (or change only their hosts and flags) and connections, read the audit log, manage API keys, and invite, re-role and remove members.
Members · ridgeline-ops
3| Member | Role |
|---|---|
| dana@ridgeline.example | admin |
| li@ridgeline.example | developer |
| sam@ridgeline.example | viewer |
The last active admin cannot be demoted or removed.
A caller below a route's minimum gets 403 {"error": "forbidden", "required": "<role>"}. The last active admin cannot be demoted or removed (409). A suspended workspace can still read and revoke triggers, API keys and members; every other write gets 403 {"error": "tenant suspended"}.
API keys
A key is shown once, when an admin creates it. We store its SHA-256, never the key.
Key created · deploy-bot
developerslk_7Qh2mZ0vYp4cN8xW1sR6tL3kJ9bF5dG0aE2uI7oP4yT
- Id
key_3f9a0c7e21b4d856- Prefix
slk_7Qh2mZ0v- Expires
- 2027-01-18, in 90 days
Copy it now. It will not be shown again.
- An admin creates a key with
POST /v1/api-keys {"name", "role", "expiresInDays"?}. The answer is{id, key, prefix, role, expiresAt}, and it is the only time the key is shown. - A key is 256 random bits, belongs to one workspace and one role, and expires after
expiresInDays(1–365, default 90). A key's role cannot exceed its creator's.
- A workspace holds at most 20 active keys.
GET /v1/api-keyslists metadata only, andlast_used_atmoves at most once a minute. Revoke a key withDELETE /v1/api-keys/:id. - Failed authentication counts against a per-IP limit: after 10 a minute, the API answers
429.