Pre-release. v0.1 is not out yet, so there is nothing to install and no public source to clone — the quickstart builds from a checkout.
Endpoints
Every route the control plane serves. The contract for each is in the v0.1 API surface.
Public
Section titled “Public”No credential.
| Method | Path | Returns |
|---|---|---|
GET |
/.well-known/openid-configuration |
Discovery: the issuer, the three OAuth endpoints, the JWKS URL, the grant types and the one client authentication method |
GET |
/.well-known/jwks.json |
The public keys task tokens and audit checkpoints are signed with. Every configured key is published; only the active one signs |
GET |
/agents/{agent_id}/jwks.json |
An agent’s inline public keys. 404 when the registration uses jwks_uri instead |
A disabled agent still publishes its keys, so tokens it was already issued can still be checked.
Tokens
Section titled “Tokens”| Method | Path | Authenticated by | Does |
|---|---|---|---|
POST |
/oauth2/token |
The agent’s private_key_jwt assertion |
Exchange a user’s token for a task token, or refresh with a task grant |
POST |
/oauth2/introspect |
The token itself | Whether the token is active, answered from storage |
POST |
/oauth2/revoke |
The agent’s private_key_jwt assertion |
Revoke a task token by jti, or a task grant, which revokes its task |
grant_type=urn:ietf:params:oauth:grant-type:token-exchangestarts a task;grant_type=refresh_tokenrenews one. Your first exchange describes the response.- Introspection asks for no client credential in v0.1. It tells the holder nothing the token does not already say, except whether it has been revoked.
- Revocation follows RFC 7009. Only the agent a token was issued to can revoke it. Any other
token, including one that does not exist, gets the same empty
200.
Every admin route takes Authorization: Bearer <admin API key>. If SubactId:Admin:ApiKey is not
set, every admin route answers 503. A wrong key gets 401 and writes admin.denied. See
the admin API.
| Method | Path | Result |
|---|---|---|
POST |
/admin/agents |
201 with the agent; 400 with per-field errors; 409 if the id exists |
GET |
/admin/agents |
200 with every agent |
GET |
/admin/agents/{agent_id} |
200; 404 |
PATCH |
/admin/agents/{agent_id} |
200 with the updated agent, validated as a whole; 400; 404 |
DELETE |
/admin/agents/{agent_id} |
204; 404; 409 while any of the agent’s tasks is still stored |
DELETE |
/admin/agents/{agent_id}/tasks |
200 with {"revoked_tasks": n}; 404 |
DELETE |
/admin/tasks/{task_id} |
200 with {"revoked_tasks": n}; 404 |
GET |
/admin/sponsors/{sponsor_key} |
200 with the block on that human; 404 if not blocked |
PUT |
/admin/sponsors/{sponsor_key}/block |
200 with the block and revoked_tasks: live tasks end and no new one starts until the block is lifted |
DELETE |
/admin/sponsors/{sponsor_key}/block |
204; 404 if not blocked; 409 if another source placed the block |
DELETE |
/admin/sponsors/{sponsor_key}/tasks |
200 with {"revoked_tasks": n}: ends live tasks without blocking |
GET |
/audit |
200 with one page of the ledger; 400 with per-field errors |
GET |
/audit/checkpoints |
200 with one page of checkpoints, oldest first |
GET |
/audit/records/{seq}/proof |
200 with one record’s proof; 404 until sealed; 410 once archived |
A sponsor_key is the value of the claim named by SubactId:UpstreamIdp:SponsorKeyClaim, sub by
default. Kill switches are idempotent; see revocation.
Signals from the identity provider
Section titled “Signals from the identity provider”Each receiver exists only when it is configured. Otherwise its path answers 404.
| Method | Path | Authenticated by | Does |
|---|---|---|---|
POST |
/backchannel-logout |
The identity provider’s signature on the logout token | Back-channel logout: ends the tasks a session started, or all of a person’s tasks. Does not block |
| various | /scim/v2/Users |
A SCIM bearer credential (SubactId:Scim:BearerToken) |
SCIM 2.0 provisioning: a deactivated or deleted user is blocked and their tasks end |
POST |
/events |
A push credential and the transmitter’s signature on the event | Shared Signals: CAEP and RISC events end tasks, and account events block or unblock the person |
Health
Section titled “Health”| Method | Path | Meaning |
|---|---|---|
GET |
/healthz |
The process is up |
GET |
/readyz |
200 once the database answers, the signing key is loaded, the identity provider’s keys have been fetched, and this month’s ledger partition exists; 503 until then |
Point a load balancer at /readyz and a restart policy at /healthz.
If the identity provider stops answering after the instance is ready, /readyz stays 200,
because the instance still holds the provider’s keys and can keep serving. Once the last
successful key fetch is more than fifteen minutes old, the body reads Degraded. Do not route on
Degraded. Operating it covers what to alert on.
Rate limits
Section titled “Rate limits”Every route except /healthz and /readyz is rate-limited per source and can answer
429 slow_down with Retry-After. Introspection, the signal receivers and everything else use
separate buckets. See configuration.
© 2026 Nikola Živković PR Agencija za programerske usluge Novi Sad. Subact ID is its product.