API reference
Tokens and keys
API keys with scopes and expiry, agent tokens with a class, the audit of agent actions, SSH keys and the device login.
An API key belongs to an organization and is sent as a bearer token. Without scopes it is the whole organization; with scopes it can only do less (read, deploy, deploy:<app>, mail:send, mail:send:<domain>). An agent block makes it an agent token with a class (sandbox, twin or production) and an optional list of apps; the platform enforces both. See the guide Agents and tokens.
A key is shown exactly once, in the answer that creates it. Rytiv stores only a hash.
Endpoints
Section titled “Endpoints”POST /v1/tokens: Creates an API key. The value is in this answer onlyGET /v1/tokens: The organization’s keys, without their valuesDELETE /v1/tokens/:id: Revokes a key. Requests already using it are rejected right awayGET /v1/agent-actions: The audit of what agent tokens did: every judged request with its verdict.?token=narrows to one key,?limit=bounds the pageGET /v1/ssh: The SSH gateway’s address and host keyGET /v1/ssh-keys: The public keys that may open an SSH sessionPOST /v1/ssh-keys: Adds a public keyDELETE /v1/ssh-keys/:id: Removes a public keyGET /v1/ssh/tokens: The short-lived SSH tokens of the organizationPOST /v1/ssh/tokens: Creates a short-lived SSH tokenDELETE /v1/ssh/tokens/:id: Revokes an SSH tokenPOST /v1/device/lookup: Looks up a device login by its user code, for the console’s confirmation pagePOST /v1/device/approve: Approves a device login; the waiting CLI then receives a key for this organization
POST /v1/tokens
Section titled “POST /v1/tokens”Creates an API key. The value is in this answer only.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Request body
Section titled “Request body”JSON, the shape CreateTokenRequest of the contract.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | required | A name for the key, shown in lists. 1 to 120 characters. |
scopes |
array of string | optional | What the key may do: read, deploy, deploy:<app>, mail:send, mail:send:<domain>. Omitted: full access. 0 to 20 items. |
expiresAt |
string (ISO 8601) | optional | When the key stops working (a moment). Not together with ttlSeconds. |
ttlSeconds |
integer | optional | When the key stops working, as seconds from now. Never later than the key that creates it. 60 to 31536000. |
agent |
object | optional | Makes it an agent token. |
agent.class |
sandbox | twin | production |
required | sandbox and twin may do what the key may do; production may only read. |
agent.apps |
array of string | optional | The apps the token may touch. Omitted: the whole organization. 1 to 50 items. |
agent.prodDataRead |
boolean | optional | Class production only: may the agent read what production holds (files, a shell, query results), not only what it says about itself. |
Example request
Section titled “Example request”curl -X POST "https://api.rytiv.app/v1/tokens" \ -H "Authorization: Bearer $RYTIV_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"ci-deploy"}'Response
Section titled “Response”201 with a JSON object of these fields:
| Field | Type | Description |
|---|---|---|
id |
string | |
name |
string | |
prefix |
string | the first characters, shown in lists |
token |
string | the key itself; shown here only |
scopes |
array of string | if the key has scopes |
expiresAt |
string (ISO 8601) | if the key expires |
agent |
object | if it is an agent token: class, apps, prodDataRead |
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 400 | bad-request |
The request is malformed or a field is out of range. error names every field; issues lists them. |
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
GET /v1/tokens
Section titled “GET /v1/tokens”The organization’s keys, without their values.
Auth: API key with full access (a key with scopes cannot call this route). Every class of agent token may call it.
Example request
Section titled “Example request”curl -X GET "https://api.rytiv.app/v1/tokens" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”200 with a list of keys, each:
[ { "id": "<id>", "orgId": "<orgId>", "name": "my-app", "prefix": "UPLOADS", "createdAt": "2026-10-21T09:00:00Z" }]| Field | Type | Present | Description |
|---|---|---|---|
id |
string | always | The key’s id. |
orgId |
string | always | The organization that owns it. |
userId |
string | if set | The person who created it, if a person did. |
name |
string | always | Its name. |
prefix |
string | always | The first characters, to recognise it. |
createdAt |
string (ISO 8601) | always | When it was created. |
lastUsedAt |
string (ISO 8601) | if set | When it was last used. |
agent |
object | if set | Agent tokens: class, apps and prodDataRead. |
agent.class |
sandbox | twin | production |
always | sandbox and twin may do what the key may do; production may only read. |
agent.apps |
array of string | if set | The apps the token may touch. Omitted: the whole organization. |
agent.prodDataRead |
boolean | always | Class production only: may the agent read what production holds (files, a shell, query results), not only what it says about itself. |
scopes |
array of string | if set | The key’s scopes; absent means full access. |
expiresAt |
string (ISO 8601) | if set | When it stops working; absent means never. |
expired |
boolean | if set | Whether it has, as of this answer. |
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
DELETE /v1/tokens/:id
Section titled “DELETE /v1/tokens/:id”Revokes a key. Requests already using it are rejected right away.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Path parameters
Section titled “Path parameters”| Name | Description |
|---|---|
id |
The key’s id (tok-...). |
Example request
Section titled “Example request”curl -X DELETE "https://api.rytiv.app/v1/tokens/<id>" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”204 with no body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
| 404 | not-found |
Not found, or not yours. An object of another organization answers like one that does not exist. |
GET /v1/agent-actions
Section titled “GET /v1/agent-actions”The audit of what agent tokens did: every judged request with its verdict. ?token= narrows to one key, ?limit= bounds the page.
Auth: API key with full access (a key with scopes cannot call this route). Every class of agent token may call it.
Query parameters
Section titled “Query parameters”| Name | Description |
|---|---|
limit |
How many entries, at most. |
token |
Only the actions of this key. |
Example request
Section titled “Example request”curl -X GET "https://api.rytiv.app/v1/agent-actions" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”200 with a JSON body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
GET /v1/ssh
Section titled “GET /v1/ssh”The SSH gateway’s address and host key.
Auth: API key with full access or the scope read. Every class of agent token may call it.
Example request
Section titled “Example request”curl -X GET "https://api.rytiv.app/v1/ssh" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”200 with a JSON body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
GET /v1/ssh-keys
Section titled “GET /v1/ssh-keys”The public keys that may open an SSH session.
Auth: API key with full access (a key with scopes cannot call this route). Every class of agent token may call it.
Example request
Section titled “Example request”curl -X GET "https://api.rytiv.app/v1/ssh-keys" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”200 with a JSON body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
POST /v1/ssh-keys
Section titled “POST /v1/ssh-keys”Adds a public key.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Request body
Section titled “Request body”JSON, the shape SshKeyCreate of the contract.
| Field | Type | Required | Description |
|---|---|---|---|
publicKey |
string | required | 1 to 16384 characters. |
name |
string | optional | 1 to 100 characters. |
Example request
Section titled “Example request”curl -X POST "https://api.rytiv.app/v1/ssh-keys" \ -H "Authorization: Bearer $RYTIV_TOKEN" \ -H "Content-Type: application/json" \ -d '{"publicKey":"<publicKey>"}'Response
Section titled “Response”201 with a JSON body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 400 | invalid-key |
|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
| 409 | duplicate |
|
| 409 | limit |
DELETE /v1/ssh-keys/:id
Section titled “DELETE /v1/ssh-keys/:id”Removes a public key.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Path parameters
Section titled “Path parameters”| Name | Description |
|---|---|
id |
The object’s id. |
Example request
Section titled “Example request”curl -X DELETE "https://api.rytiv.app/v1/ssh-keys/<id>" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”204 with no body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
| 404 | not-found |
Not found, or not yours. An object of another organization answers like one that does not exist. |
GET /v1/ssh/tokens
Section titled “GET /v1/ssh/tokens”The short-lived SSH tokens of the organization.
Auth: API key with full access (a key with scopes cannot call this route). Every class of agent token may call it.
Example request
Section titled “Example request”curl -X GET "https://api.rytiv.app/v1/ssh/tokens" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”200 with a JSON body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
POST /v1/ssh/tokens
Section titled “POST /v1/ssh/tokens”Creates a short-lived SSH token.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Request body
Section titled “Request body”JSON, the shape SshTokenCreate of the contract.
| Field | Type | Required | Description |
|---|---|---|---|
app |
string | required | 1 to 63 characters. |
machine |
string | optional | 1 to 64 characters. |
ttlS |
integer | optional | How long the link opens a connection, in seconds. 60 to 259200. |
Example request
Section titled “Example request”curl -X POST "https://api.rytiv.app/v1/ssh/tokens" \ -H "Authorization: Bearer $RYTIV_TOKEN" \ -H "Content-Type: application/json" \ -d '{"app":"<app>"}'Response
Section titled “Response”201 with a JSON body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 400 | bad-request |
The request is malformed or a field is out of range. error names every field; issues lists them. |
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
DELETE /v1/ssh/tokens/:id
Section titled “DELETE /v1/ssh/tokens/:id”Revokes an SSH token.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Path parameters
Section titled “Path parameters”| Name | Description |
|---|---|
id |
The object’s id. |
Example request
Section titled “Example request”curl -X DELETE "https://api.rytiv.app/v1/ssh/tokens/<id>" \ -H "Authorization: Bearer $RYTIV_TOKEN"Response
Section titled “Response”204 with no body.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
| 404 | not-found |
Not found, or not yours. An object of another organization answers like one that does not exist. |
POST /v1/device/lookup
Section titled “POST /v1/device/lookup”Looks up a device login by its user code, for the console’s confirmation page.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Example request
Section titled “Example request”curl -X POST "https://api.rytiv.app/v1/device/lookup" \ -H "Authorization: Bearer $RYTIV_TOKEN" \ -H "Content-Type: application/json" \ -d '{"userCode":"BCDF-GHJK"}'Response
Section titled “Response”200 with a JSON object carrying client, version, requestedFrom, requestedAt, expiresAt.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 400 | bad-request |
The request is malformed or a field is out of range. error names every field; issues lists them. |
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |
POST /v1/device/approve
Section titled “POST /v1/device/approve”Approves a device login; the waiting CLI then receives a key for this organization.
Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).
Request body
Section titled “Request body”JSON, the shape DeviceApproveRequest of the contract.
| Field | Type | Required | Description |
|---|---|---|---|
userCode |
string | required | 1 to 40 characters. |
approve |
boolean | optional | default true. |
Example request
Section titled “Example request”curl -X POST "https://api.rytiv.app/v1/device/approve" \ -H "Authorization: Bearer $RYTIV_TOKEN" \ -H "Content-Type: application/json" \ -d '{"userCode":"<userCode>"}'Response
Section titled “Response”200 with a JSON object carrying ok, approved.
Errors
Section titled “Errors”| Status | Code | Meaning |
|---|---|---|
| 400 | bad-request |
The request is malformed or a field is out of range. error names every field; issues lists them. |
| 401 | unauthenticated |
No API key, or one that does not work. |
| 403 | token-scope |
The key’s scopes do not cover this route. |