External API
The External API lives at:
https://api.consortium.dev/external/v1A machine-readable spec is published (no auth required) at
GET /external/v1/openapi.json.
Install an SDK
Section titled “Install an SDK”No install required — the API is plain HTTP with a Bearer token.
export CONSORTIUM_PAT=csm_pat_xxxxxxxxxxxxxxxxxxxxnpm install @consortium/sdkNode 18+, Bun, Deno, or the browser with a supplied fetch.
pip install -e packages/consortium-sdk-pyPython 3.10+. Not yet published to PyPI — install from source.
Conventions
Section titled “Conventions”- Authenticate with
Authorization: Bearer <token>— see Authentication. - List endpoints return
{ "data": [...], "nextCursor": "..." }; cursors are opaque;limitcaps at 200. - Timestamps are Unix milliseconds.
Endpoints
Section titled “Endpoints”| Method | Path | Scope |
|---|---|---|
| GET | /me | — (any valid token) |
| GET | /sessions | sessions:read |
| GET | /sessions/{id} | sessions:read |
| GET | /sessions/{id}/messages | sessions:read |
| POST | /sessions/{id}/messages | sessions:write |
| GET | /sessions/{id}/messages/{msgId}/content | sessions:content |
| GET | /machines | machines:read |
| GET | /machines/{id} | machines:read |
| POST | /machines/{id}/invoke | machines:invoke (PAT-only) |
| GET | /artifacts · /artifacts/{id} | artifacts:read |
| GET | /artifacts/{id}/content | artifacts:content |
| GET | /usage | usage:read |
| GET/POST/DELETE | /webhooks · /webhooks/{id} | webhooks:manage |
Relay endpoints (write path)
Section titled “Relay endpoints (write path)”Writes are relayed to one of your online devices — the server brokers the call and returns what the device replied. Relay calls block up to 30 seconds and have a tighter rate bucket.
Send a message into an active session:
curl -X POST https://api.consortium.dev/external/v1/sessions/$SESSION_ID/messages \ -H "Authorization: Bearer $CONSORTIUM_PAT" \ -H "Content-Type: application/json" \ -d '{"content": "Run the test suite and summarize failures."}'import { ConsortiumClient } from '@consortium/sdk';
const client = ConsortiumClient.fromPat({ token: process.env.CONSORTIUM_PAT!, userAgent: 'my-integration/1.0',});
await client.sessions.sendMessage(sessionId, 'Run the test suite and summarize failures.');import osfrom consortium import ConsortiumClient, NoOnlineDeviceError, RateLimitError
client = ConsortiumClient.from_pat(os.environ["CONSORTIUM_PAT"])
try: client.sessions.send_message(session_id, "Run the test suite and summarize failures.")except NoOnlineDeviceError as e: print("no device online; retry in", e.retry_after, "seconds")except RateLimitError as e: print("rate limited; retry in", e.retry_after, "seconds")Run a command on a machine:
curl -X POST https://api.consortium.dev/external/v1/machines/$MACHINE_ID/invoke \ -H "Authorization: Bearer $CONSORTIUM_PAT" \ -H "Content-Type: application/json" \ -d '{"command": "git", "args": ["status"], "cwd": "/home/me/repo", "timeoutMs": 60000}'const result = await client.machines.invoke(machineId, { command: 'git', args: ['status'], cwd: '/home/me/repo', timeoutMs: 60_000,});result = client.machines.invoke( machine_id, command="git", args=["status"], cwd="/home/me/repo", timeout_ms=60_000,)Both return:
{ "requestId": "…", "result": { } }requestId is what to quote in support requests. If no device is online
you get 503 no_online_device with a Retry-After header; if the device
doesn’t answer in time, 504 timeout. See Errors.
Encrypted content
Section titled “Encrypted content”Session messages and artifacts are end-to-end encrypted; metadata endpoints
never include content. The …/content endpoints return content only after
you create a key grant for the resource from a signed-in device
(POST /v1/sessions/{id}/key-grants). Without one they return
403 no_content_grant. Message bodies you send via the relay do transit
the server; stored session history remains end-to-end encrypted.
Webhooks
Section titled “Webhooks”POST /external/v1/webhooks subscribes a URL to event types (the list
endpoint reports availableEvents). The response includes the signing
secret once. Delivery logs and replay are available in the app’s
developer settings.
Rate limits
Section titled “Rate limits”Per-account quotas, checked on every request and reported in headers
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
(plus Retry-After on 429):
| Bucket | Default |
|---|---|
| Metadata (reads) | 600 requests / minute |
| Relay (writes) | 60 requests / minute |
Versioning & deprecations
Section titled “Versioning & deprecations”/external/v1 is the stable prefix. Deprecations are announced in-band:
GET /me returns a deprecations array, and affected routes carry
deprecation headers ahead of any removal.