Every API here is available over the APIs.io API and to AI agents over MCP.
{
"openapi": "3.1.0",
"info": {
"title": "Agent Rails public MCP and OAuth HTTP API",
"version": "2026-09-25",
"description": "Public HTTP envelope for admitted agent apps. OAuth issuer is rails.so; each MCP resource has its own audience. Tool names and schemas are release-bound and come from authenticated tools/list, not this static document.",
"x-release": {
"sha": "230ddc0a19e0f419c5f4ff27c9d421c5d62cb7e0"
}
},
"externalDocs": {
"url": "https://rails.so/docs"
},
"servers": [
{
"url": "https://rails.so"
}
],
"tags": [
{
"name": "Discovery"
},
{
"name": "OAuth"
},
{
"name": "MCP"
},
{
"name": "Health"
}
],
"paths": {
"/.well-known/oauth-authorization-server": {
"get": {
"tags": [
"Discovery"
],
"summary": "Authorization server metadata",
"operationId": "authorizationServerMetadata",
"responses": {
"200": {
"description": "RFC 8414 authorization server metadata",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthorizationServerMetadata"
}
}
}
}
}
}
},
"/oauth/register": {
"post": {
"tags": [
"OAuth"
],
"summary": "Dynamic public-client registration (RFC 7591)",
"description": "No client secret is issued. Client ID Metadata Documents are not supported on the source floor of this document.",
"operationId": "registerClient",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegistrationRequest"
}
}
}
},
"responses": {
"201": {
"description": "Registered public client",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegistrationResponse"
}
}
}
},
"400": {
"description": "OAuth error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OAuthError"
}
}
}
},
"429": {
"description": "OAuth error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OAuthError"
}
}
}
}
}
}
},
"/oauth/authorize": {
"get": {
"tags": [
"OAuth"
],
"summary": "Begin authorization-code + PKCE consent",
"description": "Browser navigation. A signed-out user is redirected to sign-in. The selected resource is bound to the issued code. Errors the registered redirect_uri can receive are returned as a 303 redirect to it with error, error_description, state and iss.",
"operationId": "authorize",
"parameters": [
{
"name": "client_id",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "redirect_uri",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "response_type",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "code_challenge",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "code_challenge_method",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "resource",
"in": "query",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "scope",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "state",
"in": "query",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "HTML consent page"
},
"303": {
"description": "Redirect: to sign-in (signed out or re-verification needed), or an OAuth error redirect to the exact registered redirect_uri with error, error_description, state and iss."
},
"400": {
"description": "Error the client cannot be sent back for (unknown client, unregistered redirect_uri, stale or invalid form): an HTML error page, not JSON.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
}
}
},
"post": {
"tags": [
"OAuth"
],
"summary": "Submit signed-in consent decision",
"description": "Same-origin, CSRF-protected browser form; not a machine approval endpoint. On allow, redirects to the exact registered redirect_uri with code, state and iss.",
"operationId": "submitAuthorizationDecision",
"responses": {
"303": {
"description": "Redirect to the exact registered redirect_uri: code, state and iss on allow; error, error_description, state and iss on deny or a redirectable error. Also a redirect to sign-in when the session lapsed."
},
"400": {
"description": "Error the client cannot be sent back for (unknown client, unregistered redirect_uri, stale or invalid form): an HTML error page, not JSON.",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
}
}
}
},
"/oauth/token": {
"post": {
"tags": [
"OAuth"
],
"summary": "Redeem authorization code or rotate refresh token",
"operationId": "token",
"requestBody": {
"required": true,
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"type": "object",
"properties": {
"grant_type": {
"type": "string",
"enum": [
"authorization_code",
"refresh_token"
]
},
"client_id": {
"type": "string"
},
"code": {
"type": "string"
},
"redirect_uri": {
"type": "string"
},
"code_verifier": {
"type": "string"
},
"refresh_token": {
"type": "string"
},
"resource": {
"type": "string"
},
"scope": {
"type": "string"
}
},
"required": [
"grant_type",
"client_id"
]
}
}
}
},
"responses": {
"200": {
"description": "Resource-bound token response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenResponse"
}
}
}
},
"400": {
"description": "OAuth error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OAuthError"
}
}
}
},
"401": {
"description": "OAuth error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OAuthError"
}
}
}
}
}
}
},
"/oauth/revoke": {
"post": {
"tags": [
"OAuth"
],
"summary": "Revoke an access or refresh token",
"description": "Unknown tokens also return 200 to avoid existence disclosure.",
"operationId": "revokeToken",
"requestBody": {
"required": true,
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"type": "object",
"properties": {
"token": {
"type": "string"
},
"client_id": {
"type": "string"
}
},
"required": [
"token"
]
}
}
}
},
"responses": {
"200": {
"description": "Empty JSON object",
"content": {
"application/json": {
"schema": {
"type": "object",
"maxProperties": 0
}
}
}
}
}
}
}
},
"components": {
"securitySchemes": {
"BearerAuth": {
"type": "http",
"scheme": "bearer"
}
},
"schemas": {
"ProtectedResourceMetadata": {
"type": "object",
"required": [
"resource",
"authorization_servers"
],
"properties": {
"resource": {
"type": "string",
"format": "uri"
},
"authorization_servers": {
"type": "array",
"items": {
"type": "string",
"format": "uri"
}
},
"scopes_supported": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": true
},
"AuthorizationServerMetadata": {
"type": "object",
"required": [
"issuer",
"authorization_endpoint",
"token_endpoint",
"registration_endpoint"
],
"properties": {
"issuer": {
"type": "string",
"format": "uri"
},
"authorization_endpoint": {
"type": "string",
"format": "uri"
},
"token_endpoint": {
"type": "string",
"format": "uri"
},
"registration_endpoint": {
"type": "string",
"format": "uri"
},
"revocation_endpoint": {
"type": "string",
"format": "uri"
}
},
"additionalProperties": true
},
"RegistrationRequest": {
"type": "object",
"required": [
"redirect_uris"
],
"properties": {
"client_name": {
"type": "string"
},
"redirect_uris": {
"type": "array",
"minItems": 1,
"maxItems": 10,
"items": {
"type": "string",
"format": "uri"
}
},
"grant_types": {
"type": "array",
"items": {
"type": "string"
}
},
"response_types": {
"type": "array",
"items": {
"type": "string"
}
},
"token_endpoint_auth_method": {
"type": "string",
"const": "none"
},
"scope": {
"type": "string"
}
},
"additionalProperties": true
},
"RegistrationResponse": {
"type": "object",
"required": [
"client_id",
"redirect_uris",
"token_endpoint_auth_method"
],
"properties": {
"client_id": {
"type": "string"
},
"client_id_issued_at": {
"type": "integer"
},
"client_name": {
"type": "string"
},
"redirect_uris": {
"type": "array",
"items": {
"type": "string"
}
},
"token_endpoint_auth_method": {
"type": "string",
"const": "none"
}
},
"additionalProperties": true
},
"TokenResponse": {
"type": "object",
"required": [
"access_token",
"token_type",
"expires_in"
],
"properties": {
"access_token": {
"type": "string"
},
"token_type": {
"type": "string"
},
"expires_in": {
"type": "integer"
},
"refresh_token": {
"type": "string"
},
"scope": {
"type": "string"
}
},
"additionalProperties": true
},
"OAuthError": {
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string"
},
"error_description": {
"type": "string"
}
},
"additionalProperties": true
},
"JsonRpcRequest": {
"type": "object",
"required": [
"jsonrpc",
"method"
],
"properties": {
"jsonrpc": {
"type": "string",
"const": "2.0"
},
"id": {
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
},
{
"type": "null"
}
]
},
"method": {
"type": "string"
},
"params": {
"type": "object",
"additionalProperties": true
}
},
"additionalProperties": true
},
"JsonRpcResponse": {
"type": "object",
"required": [
"jsonrpc",
"id"
],
"properties": {
"jsonrpc": {
"type": "string",
"const": "2.0"
},
"id": {
"oneOf": [
{
"type": "integer"
},
{
"type": "string"
},
{
"type": "null"
}
]
},
"result": {},
"error": {
"type": "object",
"properties": {
"code": {
"type": "integer"
},
"message": {
"type": "string"
}
},
"required": [
"code",
"message"
]
}
},
"additionalProperties": true
},
"Version": {
"type": "object",
"required": [
"sha",
"packages",
"env"
],
"properties": {
"sha": {
"type": "string"
},
"short": {
"type": "string"
},
"at": {
"type": "string"
},
"env": {
"type": "string"
},
"packages": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"verified": {
"type": [
"string",
"null"
]
},
"verified_at": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": true
},
"Health": {
"type": "object",
"required": [
"ok",
"apps_not_admitted"
],
"properties": {
"ok": {
"type": "boolean"
},
"apps_not_admitted": {
"type": "array",
"items": {
"type": "string"
}
},
"env": {
"type": "string"
}
},
"additionalProperties": true
}
}
}
}