Skip to content

API reference

The API is https://tormoni.ai/v1. Every route takes a tor_ API token as a bearer credential, and the token IS your account: it reaches exactly what you reach, and there is no scope below the account. Mint one on the API keys page.

Every route below answers about the token’s own account and takes no account selector — these are identity and billing lanes, and a member acts on somebody else’s project data, never on their identity or their bill.

Terminal window
export TORMONI_TOKEN="tor_..."
curl -H "Authorization: Bearer $TORMONI_TOKEN" https://tormoni.ai/v1/account

contract/openapi.json in the repository is the machine-readable version of this page. It is generated from the route tables the services’ routers are built from, so a route it does not describe is a route nothing serves.

Route What it answers
GET /v1/account Who this token is: the account id, the email, the display name.
GET /v1/members Everyone the owner invited who accepted, and the role each holds.
GET /v1/plan The tier in force, and whether the read was settled.
POST /v1/device/claim The desktop app collects its token after you approve its key. No bearer.
DELETE /v1/device The desktop app signs out: this token, and the device it belongs to, are revoked.

GET /v1/plan answers settled: false when our billing service could not be reached. The plan you are told is then the free tier, provisionally — an outage never blocks a read, and it never grants a paid entitlement either.

POST /v1/device/claim is the one route that takes no bearer: it is how the desktop app gets its first token, by proving it holds the private half of a key you approved on /connect. The body is the key, the Unix second the claim was signed at, and the base64 ed25519 signature over tormoni-device-claim:v1:<fingerprint>:<issued_at>. It answers 202 with {"status":"pending"} until you approve — and for a key nobody has ever approved, identically — 200 with the token exactly once, and 410 after that. A claim more than 60 seconds from now, or a signature presented twice, is a 400 that says which. Signing in the desktop app is the flow from your side.

DELETE /v1/device is the same flow ending. It takes no body and names no device: the bearer is the device, so the pairing that minted the token is revoked and the token dies with it, 204. Nothing else can be reached with it, which is why this is the one write on your account’s own lanes. A token you minted on the API keys page is not a device and answers 404 here, unrevoked; revoke that one on the page that made it.

Every non-success is an RFC 9457 problem document. Switch on type; Errors lists every one.

{
"type": "/errors/authz/forbidden",
"title": "forbidden",
"status": 403,
"detail": "you hold no role on @kendrick"
}

A 429 and a 503 carry Retry-After; wait that many seconds. The front door meters twice — once by source, once by token — before a request reaches a service.

  • It is additive only. A route is never removed from /v1; a removal would be a /v2.