API reference

OAuth API

OAuth sign-in, tokens and revocation

HTTP reference. Generated from the backend contract. Browse endpoints below or download OpenAPI.

This group has 10 operations, generated from api/openapi.yaml. Filter by path, action, or authentication. Each endpoint lists its inputs; expand it for a request template and response codes. Templates need your own values and a schema-valid body.

Replace uppercase placeholders with your values. For a JSON request, save a body matching the schema in request.json. Cookie examples use a local cookie jar from an authenticated session.

OAuth sign-in, tokens and revocation

POST/oauth/token

Oauth Token

OAuth 2.0 token endpoint (RFC 6749 §3.2) for agent JWTs. grant_type refresh_token rotates an opaque refresh credential (RFC 9700): every use returns a new pair; a request_id (16 to 200 characters) makes an exact retry return the same response while its credential and grant are live and the successor is still current, without an elapsed-time retry deadline.

Any other reuse of a superseded refresh token revokes the whole family (invalid_grant). A removed selected membership or project returns invalid_scope with error_description beginning "project_selection_inactive:"; the refresh credential is not consumed.

Discover live memberships with GET /api/projects, intersect them with the previously consented selection, and retry with projects= and a new request_id. Never end the refresh family for this selection error.

Requested scope narrowing applies independently to every project and to identity authority; an explicit scope without identity excludes identity authority. grant_type urn:ietf:params:oauth:grant-type:token-exchange (RFC 8693) with subject_token_type urn:screenrig:token-type:identity-credential or urn:screenrig:token-type:project-token answers unsupported_token_type: legacy credentials are retired, and the installation signs in again with screenrig login. resource (RFC 8707) is https://api.<domain>/api or absent; projects selects up to 64 consented project IDs.

Omission selects all only when the set fits; otherwise the client must choose a subset. project_id selects one during the compatibility release. A connected app's grant has the single resource https://api.<domain>/mcp, which a refresh may omit.

Clients are public (client_id only), or a connected app whose metadata declares private_key_jwt authenticates with client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer and a client_assertion (iss and sub its client_id, aud the issuer or this endpoint as one string, exp within 5 minutes of iat, a jti used once, kid naming one of its keys; EdDSA, ES256 or RS256). grant_type authorization_code redeems a connected app's code within 60 seconds with the exact redirect_uri and the PKCE code_verifier; resource must be absent or the one authorized; a second redemption revokes the grant the code created. grant_type client_credentials is a service client's: it authenticates with a client assertion (one of its registered keys) or its secret by HTTP Basic (client_secret_basic; a secret in the body is refused) and receives a 15-minute service token for its project, audience api or (resource https://api.<domain>/mcp) mcp, scope within its capabilities and access level, and no refresh token; 600 per client per hour.

Errors are RFC 6749 JSON {error, error_description} with Cache-Control no-store; while the server does not issue it answers temporarily_unavailable (503).

Rate limits answer 429 rate_limited with Retry-After: 1200 requests per client address per hour on this and the revocation endpoint, 60 refreshes per grant per hour, 30 exchanges per legacy credential per hour. grant_type urn:ietf:params:oauth:grant-type:device_code (RFC 8628 §3.4) polls a device sign-in: authorization_pending until a person approves it, slow_down when polled sooner than the interval (which then grows by 5 seconds), access_denied when denied, expired_token after 10 minutes, then the token response.

A new installation receives a token pair; a sign-in started with an existing installation's access token adds the approved project to that grant and receives an access token only, without rotating the refresh token. Polling the same device_code again returns the same response until the grant first rotates or 10 minutes pass, then invalid_grant.

POST only, form-encoded, no query string.

Authentication
none
Request body
object
Operation ID
oauthToken

Request body fields

FieldDescription
grant_type (required, string)Allowed: "authorization_code", "client_credentials", "refresh_token", "urn:ietf:params:oauth:grant-type:token-exchange", "urn:ietf:params:oauth:grant-type:device_code"
client_id (optional, string)
client_assertion_type (optional, string)Allowed: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
client_assertion (optional, string)
code (optional, string)
redirect_uri (optional, string)
code_verifier (optional, string)minLength: 43 maxLength: 128
refresh_token (optional, string)
device_code (optional, string)
request_id (optional, string)minLength: 16 maxLength: 200
subject_token (optional, string)
subject_token_type (optional, string)Allowed: "urn:screenrig:token-type:identity-credential", "urn:screenrig:token-type:project-token"
scope (optional, string)
resource (optional, string)format: "uri"
projects (optional, string)Space- or comma-separated project IDs; omit for all consented projects up to the configured cap (default 64). Cannot be combined with project_id.
project_id (optional, string)
Request template and responses
shell · request template
curl --request POST --header 'Content-Type: application/x-www-form-urlencoded' --data-binary '@request.bin' 'https://api.screenrig.ai/oauth/token'

Responses

StatusMeaningBody and headers
200The token response (RFC 6749 §5.1).OAuthTokenResponse (application/json)
defaultAn RFC 6749 §5.2 error.OAuthError (application/json)
POST/oauth/device_authorization

Oauth Device Authorization

RFC 8628 §3.1 device authorization for `screenrig login`. scope is access:manage (the default), access:propose or access:read; project_id suggests the project the person approves; name, agent_type, platform and version describe the installation and are shown to the approver as reported by the device; install_source (optional) says where it was installed from and is kept on the agent the approval creates.

Without Authorization it starts a new installation. With Authorization: Bearer and an agent access token carrying identity scope it asks to add a project to that installation's grant, or to raise a Read only project to Manage.

The person enters user_code at verification_uri (or follows verification_uri_complete) and approves it in the dashboard; the device polls the token endpoint with the device_code every interval seconds.

Rate limits answer 429 rate_limited with Retry-After: 10 per client address per hour and 600 per hour fleet-wide, behind the endpoints' 1200 per address per hour. Errors are RFC 6749 JSON with Cache-Control no-store; while the server does not issue it answers temporarily_unavailable (503). POST only, form-encoded, no query string.

Authentication
none
Request body
object
Operation ID
oauthDeviceAuthorization

Request body fields

FieldDescription
client_id (required, string)
scope (optional, string)Allowed: "access:manage", "access:propose", "access:read"
project_id (optional, string)maxLength: 200
name (optional, string)maxLength: 80
agent_type (optional, string)maxLength: 32
platform (optional, string)maxLength: 80
version (optional, string)maxLength: 40
install_source (optional, string)

Optional where the integration was installed from: the host and, after a slash, the marketplace (claude/screenrig, codex/screenrig, grok/screenrig), or a bare host such as npm. A missing or wrongly shaped value is ignored and never fails the request. pattern: "^[a-z][a-z0-9-]{0,31}(/[a-z0-9][a-z0-9._-]{0,63})?$"

Request template and responses
shell · request template
curl --request POST --header 'Content-Type: application/x-www-form-urlencoded' --data-binary '@request.bin' 'https://api.screenrig.ai/oauth/device_authorization'

Responses

StatusMeaningBody and headers
200The device authorization response (RFC 8628 §3.2).object (application/json)
defaultAn RFC 6749 §5.2 error.OAuthError (application/json)
GET/oauth/authorize

Oauth Authorize

OAuth 2.0 authorization endpoint for connected apps (MCP clients). client_id is a client ID metadata document URL (https, port 443, fetched with no redirects, 64 KiB and 5 seconds at most, public addresses only) or a registered client id.

The request is validated in order: the client, the exact redirect_uri (an http loopback redirect of 127.0.0.1, [::1] or localhost matches on any port), response_type code, code_challenge with code_challenge_method S256, resource (https://api.<domain>/mcp, another MCP resource whose protected resource metadata names this server, or absent), then scope (access:read, the default, access:propose, access:manage and capability names).

An unknown client or redirect_uri answers an HTML error page and never redirects; any later error redirects to the redirect_uri with error, error_description, state and iss (RFC 9207).

Success answers 303 to the dashboard consent page, where a person chooses the project, the access level (Read only by default, Propose or Manage) and the capabilities; approval redirects with code, state and iss. 30 requests per client address per minute.

Authentication
none
Request body
none
Operation ID
oauthAuthorize

Parameters

NameSend inRequired?Description
client_idqueryrequired
redirect_uriqueryrequired
response_typequeryrequired
code_challengequeryrequired
code_challenge_methodqueryrequired
statequeryoptional
resourcequeryoptional
scopequeryoptional
Request template and responses
shell · request template
curl --request GET 'https://api.screenrig.ai/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=RESPONSE_TYPE&code_challenge=CODE_CHALLENGE&code_challenge_method=CODE_CHALLENGE_METHOD'

Responses

StatusMeaningBody and headers
303To the consent page, or back to the client's redirect_uri with error, state and iss.no body
400An HTML error page for an unknown client or redirect_uri; never a redirect.string (text/html)
429Too many authorization requests from this address.no body
POST/oauth/revoke

Oauth Revoke

RFC 7009 revocation. An opaque refresh credential (or a previous-release refresh JWT), or an agent access JWT, issued to the client revokes its grant; the grant's access tokens are refused within seconds. An unknown, expired or foreign token also answers 200. POST only, form-encoded.

Authentication
none
Request body
object
Operation ID
oauthRevoke

Request body fields

FieldDescription
client_id (optional, string)
client_assertion_type (optional, string)Allowed: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
client_assertion (optional, string)
token (required, string)
token_type_hint (optional, string)
Request template and responses
shell · request template
curl --request POST --header 'Content-Type: application/x-www-form-urlencoded' --data-binary '@request.bin' 'https://api.screenrig.ai/oauth/revoke'

Responses

StatusMeaningBody and headers
200Revoked, or nothing to revoke.no body
defaultAn RFC 6749 §5.2 error.OAuthError (application/json)
GET/.well-known/oauth-authorization-server

Oauth Authorization Server Metadata

RFC 8414 authorization server metadata for the agent authorization server.

Authentication
none
Request body
none
Operation ID
oauthAuthorizationServerMetadata
Request template and responses
shell · request template
curl --request GET 'https://api.screenrig.ai/.well-known/oauth-authorization-server'

Responses

StatusMeaningBody and headers
200The metadata document.object (application/json)
GET/.well-known/oauth-protected-resource/mcp

Oauth Protected Resource MCP

RFC 9728 protected resource metadata for /mcp, named by the resource_metadata of every /mcp 401.

Authentication
none
Request body
none
Operation ID
oauthProtectedResourceMCP
Request template and responses
shell · request template
curl --request GET 'https://api.screenrig.ai/.well-known/oauth-protected-resource/mcp'

Responses

StatusMeaningBody and headers
200The metadata document.object (application/json)
GET/.well-known/oauth-protected-resource/api

Oauth Protected Resource API

RFC 9728 protected resource metadata for /api.

Authentication
none
Request body
none
Operation ID
oauthProtectedResourceAPI
Request template and responses
shell · request template
curl --request GET 'https://api.screenrig.ai/.well-known/oauth-protected-resource/api'

Responses

StatusMeaningBody and headers
200The metadata document.object (application/json)
GET/api/oauth/authorizations/{id}

Get Dashboard OAuth Authorization

A pending connected-app authorization for the consent page: the client's name and domain as its metadata declares them (no logo is ever fetched), whether it is a registered client, the redirect host, and the access level and capabilities it asked for. Unknown, expired or settled authorizations are not_found.

Authentication
dashboardSession
Request body
none
Operation ID
getDashboardOAuthAuthorization

Parameters

NameSend inRequired?Description
idpathrequired
Request template and responses
shell · request template
curl --request GET --cookie cookies.txt --cookie-jar cookies.txt 'https://screenrig.ai/api/oauth/authorizations/RESOURCE_ID'

Responses

StatusMeaningBody and headers
200The authorization.OAuthAuthorization (application/json)
default

Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value.

Problem (application/problem+json)
POST/api/oauth/authorizations/{id}/approve

Approve Dashboard OAuth Authorization

Approves a connected app for one of the person's projects after a fresh proof (kind oauth_authorization_approval, subject the authorization id): it creates the app's agent identity (agent type mcp_client, the person responsible), its membership and its grant with the chosen access (read or manage; omitted keeps the requested level, which defaults to read) and capabilities (a subset of the requested), and answers the redirect_uri, carrying code, state and iss, that the page navigates to.

The code is valid for 60 seconds. A member limited to screens does not connect agents, issue credentials or manage the project's people: outside_screen_scope (ask the project owner).

Authentication
dashboardSession
Request body
DashboardAgentAction
Operation ID
approveDashboardOAuthAuthorization

Parameters

NameSend inRequired?Description
idpathrequired

Request body fields

FieldDescription
project_id (required, string)minLength: 1
proof (optional, DashboardProof)
capabilities (optional, array)

Optional on agent connection and connected-app approval only. Omitted approves the full requested set; a non-empty subset of the connection's capabilities narrows the granted credential; anything else is invalid_request.

user_code (optional, string)

Required when approving a device sign-in (flow device): the code the person confirms matches the terminal. A mismatch is agent_connection_code_mismatch; the fifth expires the sign-in (agent_connection_expired). Ignored otherwise. maxLength: 32

access (optional, string)

The access level a device sign-in or a connected app is approved with (Read only, Propose or Manage); omitted keeps the level asked for. Ignored for other connections. A person who cannot approve reviews may not approve Manage (403 approver_required). Allowed: "read", "propose", "manage"

Request template and responses
shell · request template
curl --request POST --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://screenrig.ai/api/oauth/authorizations/RESOURCE_ID/approve'

Responses

StatusMeaningBody and headers
200The redirect back to the application.OAuthAuthorizationRedirect (application/json)
403

outside_screen_scope - the caller is limited to screens and the screen, screen folder, selector or audience the request names or reaches is outside them (docs/screen-scope.md). An id outside the scope and an id that does not exist get the same answer; errors[0].screen_scope carries the caller's scope, and the write is refused whole, never narrowed.

Problem (application/problem+json)
default

Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value.

Problem (application/problem+json)
POST/api/oauth/authorizations/{id}/deny

Deny Dashboard OAuth Authorization

Denies a connected app after a fresh proof (kind oauth_authorization_denial) and answers the redirect_uri, carrying error=access_denied, state and iss, that the page navigates to. A member limited to screens does not connect agents, issue credentials or manage the project's people: outside_screen_scope (ask the project owner).

Authentication
dashboardSession
Request body
DashboardAgentAction
Operation ID
denyDashboardOAuthAuthorization

Parameters

NameSend inRequired?Description
idpathrequired

Request body fields

FieldDescription
project_id (required, string)minLength: 1
proof (optional, DashboardProof)
capabilities (optional, array)

Optional on agent connection and connected-app approval only. Omitted approves the full requested set; a non-empty subset of the connection's capabilities narrows the granted credential; anything else is invalid_request.

user_code (optional, string)

Required when approving a device sign-in (flow device): the code the person confirms matches the terminal. A mismatch is agent_connection_code_mismatch; the fifth expires the sign-in (agent_connection_expired). Ignored otherwise. maxLength: 32

access (optional, string)

The access level a device sign-in or a connected app is approved with (Read only, Propose or Manage); omitted keeps the level asked for. Ignored for other connections. A person who cannot approve reviews may not approve Manage (403 approver_required). Allowed: "read", "propose", "manage"

Request template and responses
shell · request template
curl --request POST --cookie cookies.txt --cookie-jar cookies.txt --header 'Content-Type: application/json' --data '@request.json' 'https://screenrig.ai/api/oauth/authorizations/RESOURCE_ID/deny'

Responses

StatusMeaningBody and headers
200The redirect back to the application.OAuthAuthorizationRedirect (application/json)
403

outside_screen_scope - the caller is limited to screens and the screen, screen folder, selector or audience the request names or reaches is outside them (docs/screen-scope.md). An id outside the scope and an id that does not exist get the same answer; errors[0].screen_scope carries the caller's scope, and the write is refused whole, never narrowed.

Problem (application/problem+json)
default

Stable RFC 9457 problem response. A 421 server_draining carries Retry-After of 1 second, a 500 not_ready or dependency_unavailable carries 5, and a 500 manifest_degraded carries 60, unless the handler set a more specific value.

Problem (application/problem+json)