Skip to content

API reference

OAuth and device login

Markdown

How a hosted MCP client connects without a pasted key, and how the CLI signs in with a code.

Two flows need no key to start. The OAuth 2.1 authorization server of /v1/mcp lets a hosted client register itself, send the person to the console to approve, and exchange a code (with PKCE) for an access token and a refresh token; the discovery documents are at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource/v1/mcp. The device login is what ry login does: it asks for a code, the person confirms it in the console, and the CLI receives a key.

Scopes of the OAuth server: mcp and offline_access. There are no client secrets; every client is a public client bound to PKCE.

Registers a public OAuth client (dynamic client registration) and answers its client id. No secret.

Auth: No API key: this is an entrance of a login or OAuth flow.

JSON, the shape OAuthClientRegistration of the contract.

Field Type Required Description
redirect_uris array of string required 1 to 10 items.
client_name string optional 1 to 120 characters.
token_endpoint_auth_method string optional at most 40 characters.
grant_types array of string optional 0 to 4 items.
response_types array of string optional 0 to 4 items.
scope string optional at most 200 characters.
curl -X POST "https://api.rytiv.app/v1/oauth/register" \
-H "Content-Type: application/json" \
-d '{"redirect_uris":["<redirect_uri>"]}'

201 with a JSON object carrying client_id, client_name, redirect_uris, grant_types, response_types, token_endpoint_auth_method, client_id_issued_at.

Starts an authorization: answers a redirect into the console, where the person approves.

Auth: No API key: this is an entrance of a login or OAuth flow.

curl -X GET "https://api.rytiv.app/v1/oauth/authorize"

302 with a JSON body.

Exchanges an authorization code (with the PKCE verifier) for an access token and a refresh token, or rotates a refresh token.

Auth: No API key: this is an entrance of a login or OAuth flow.

curl -X POST "https://api.rytiv.app/v1/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "code=<code>" \
--data-urlencode "code_verifier=<verifier>" \
--data-urlencode "client_id=<client id>" \
--data-urlencode "redirect_uri=<redirect uri>"

A JSON body on success.

The console reads a pending authorization to show it.

Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).

JSON, the shape OAuthConsentLookupRequest of the contract.

Field Type Required Description
requestId string required 1 to 120 characters.
curl -X POST "https://api.rytiv.app/v1/oauth/consent/lookup" \
-H "Authorization: Bearer $RYTIV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"requestId":"<requestId>"}'

200 with a JSON body.

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.
404 not-found Not found, or not yours. An object of another organization answers like one that does not exist.
409 not-answerable

The console records the person’s decision.

Auth: API key with full access (a key with scopes cannot call this route). Refused for every agent token (agent-token-credential).

JSON, the shape OAuthConsentDecideRequest of the contract.

Field Type Required Description
requestId string required 1 to 120 characters.
approve boolean required
curl -X POST "https://api.rytiv.app/v1/oauth/consent/decide" \
-H "Authorization: Bearer $RYTIV_TOKEN" \
-H "Content-Type: application/json" \
-d '{"requestId":"<requestId>","approve":true}'

200 with a JSON object carrying redirectUrl.

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.
404 not-found Not found, or not yours. An object of another organization answers like one that does not exist.
409 not-answerable

Starts a device login: answers a device code and a user code to confirm in the console.

Auth: No API key: this is an entrance of a login or OAuth flow.

JSON, the shape DeviceCodeRequest of the contract.

Field Type Required Description
client string optional 1 to 120 characters.
version string optional 1 to 40 characters.
curl -X POST "https://api.rytiv.app/v1/device/code" \
-H "Content-Type: application/json" \
-d '{"client":"<client>"}'

201 with a JSON object carrying deviceCode, userCode, verificationUri, verificationUriComplete, expiresIn, interval.

Status Code Meaning
400 bad-request The request is malformed or a field is out of range. error names every field; issues lists them.

The CLI polls here until the login was confirmed, then receives a key.

Auth: No API key: this is an entrance of a login or OAuth flow.

JSON, the shape DeviceTokenRequest of the contract.

Field Type Required Description
deviceCode string required 1 to 200 characters.
curl -X POST "https://api.rytiv.app/v1/device/token" \
-H "Content-Type: application/json" \
-d '{"deviceCode":"<deviceCode>"}'

200 with a JSON object carrying token, org.