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.
export TORMONI_TOKEN="tor_..."curl -H "Authorization: Bearer $TORMONI_TOKEN" https://tormoni.ai/v1/accountcontract/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.
Your account
Section titled “Your account”| 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.
What a refusal looks like
Section titled “What a refusal looks like”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.
What this API does not do
Section titled “What this API does not do”- It is additive only. A route is never removed from
/v1; a removal would be a/v2.