Skip to content

HTTP API

RTC Agent’s HTTP API includes three categories of endpoints: OAuth2 Authentication handles user login and token management, Operational Endpoints provide health checks and metrics collection, and Business Endpoints support interrupt answers and memory export. The authentication flow follows the standard OAuth2 authorization code pattern, compatible with common Providers like GitHub and Google.

EndpointMethodFunctionWhen Called
/oauth2/authorizeGETGet authorization redirect URLUser clicks login
/oauth2/providersGETGet list of enabled OAuth ProvidersFrontend initializes login page
/oauth2/tokenPOSTExchange authorization code / RFC 8693 Token ExchangeAfter authorization callback / External JWT exchange
/oauth2/refreshPOSTRefresh access_tokenWhen token is about to expire

Admin-server Endpoints (Independent Service, Port 8081)

Section titled “Admin-server Endpoints (Independent Service, Port 8081)”
EndpointMethodFunctionAuthentication
/api/auth/loginPOSTAdmin email/password loginNone
/api/auth/refreshPOSTRefresh admin access_tokenNone
/api/auth/meGETGet current admin infoAdmin JWT
/api/auth/logoutPOSTLogout, revoke refresh_tokenAdmin JWT
/.well-known/jwks.jsonGETJWKS public key set (for Main Server JWT verification)None
/healthGETHealth checkNone

💡 Admin-server is an independent service that integrates with the Main Server via RFC 8693 Token Exchange. After an administrator logs in to admin-server, their JWT is recognized as a valid user identity by the Main Server. See Admin-server Authentication below.

Operational Endpoints (no JWT required): /healthz (health check), /readyz (readiness check), /metrics (Prometheus metrics).

📌 Security change: In production, /metrics and debug endpoints require authentication — the endpoints are disabled without credentials. The Server also automatically enables OAuth2 IP rate limiting (5 req/s per IP, burst 10), HSTS headers, and Permissions-Policy headers.

Business Endpoints (JWT required): /api/sessions/{sessionID}/interrupts/{interruptID}/answer (submit interrupt answer), /api/memories/export (export memory data), /api/credentials/temporary (get S3 temporary credentials), /api/presigned-url (generate presigned URL).

💡 Design note: The frontend (F-C) calls /oauth2/authorize to get the redirect URL, then navigates the user to the OAuth2 Provider’s authorization page. After authorization is complete, the Provider calls back to the frontend, which then calls /oauth2/token to complete the token exchange.


Get the redirect URL for the OAuth2 authorization page. The frontend uses this URL to navigate the user to the Provider’s authorization page.

ParameterLocationRequiredTypeDescription
providerquery✅stringOAuth2 Provider name (e.g., "github")
redirect_uriquery❌stringCallback URL after authorization (optional, required by some Providers)
code_challengequery❌stringPKCE code_challenge (RFC 7636), derived from code_verifier via SHA-256 + base64url encoding
code_challenge_methodquery❌stringPKCE challenge method, recommended S256 (default); also supports plain
{
"redirect_url": "https://github.com/login/oauth/authorize?client_id=xxx&state=yyy",
"state": "a1b2c3d4e5"
}
FieldTypeDescription
redirect_urlstringFull URL to the OAuth2 Provider’s authorization page
statestringCSRF protection random state parameter; must be returned as-is in the callback

Get the list of currently enabled OAuth2 Providers. The frontend calls this endpoint when initializing the login page to dynamically display available login options.

None.

{
"providers": ["github", "google"]
}
FieldTypeDescription
providersstring[]List of enabled provider names (e.g., "github", "google", "mock")

💡 The frontend dynamically renders login buttons based on the returned provider list. If only the mock provider is enabled, the list will be ["mock"].


Exchange an authorization code for an access_token and refresh_token. This is the core step of the OAuth2 authorization code flow.

{
"code": "auth_code_from_callback",
"redirect_uri": "https://your-app.com/callback",
"state": "a1b2c3d4e5",
"device_id": "uuid-generated-by-client",
"device_name": "Chrome on Mac",
"user_agent": "Mozilla/5.0 ..."
}
FieldRequiredTypeDescription
code✅stringAuthorization code, carried in the query parameters of the authorization callback URL
redirect_uri❌stringCallback URL, recommended to match the one from the authorization request
state✅stringCSRF protection state; must match the state from the authorization request and be used only once
device_id❌stringClient-generated device UUID, used to identify the client device
device_name❌stringDevice display name, e.g., "Chrome on Mac"
user_agent❌stringClient User-Agent, used for device identification
code_verifier❌stringPKCE code_verifier (RFC 7636); pass the original verifier when code_challenge was sent during authorization

📌 PKCE constraint: If code_challenge was included in the authorization request, code_verifier becomes required during token exchange. The server validates that code_verifier matches the stored code_challenge.

{
"access_token": "eyJhbGciOi...",
"refresh_token": "dGhpcyBpcyBh...",
"expires_in": 3600,
"user_id": "user-uuid"
}
FieldTypeDescription
access_tokenstringJWT access token, validity period specified by expires_in
refresh_tokenstringRefresh token, used to obtain a new token after the access_token expires
expires_inintegerAccess token expiration time (seconds), typically 3600 (1 hour)
user_idstringUnique ID of the authenticated user

💡 Refresh Token Reuse: The refresh_token can be reused multiple times within its validity period, returning a new access_token each time. The refresh_token itself is not replaced or revoked until it naturally expires (default 30 days).


POST /oauth2/token (Token Exchange — RFC 8693)

Section titled “POST /oauth2/token (Token Exchange — RFC 8693)”

POST /oauth2/token supports both authorization code exchange and RFC 8693 Token Exchange, dispatched by the grant_type parameter. When grant_type is urn:ietf:params:oauth:grant-type:token-exchange, the endpoint enters Token Exchange mode — exchanging an external JWT (e.g., an admin JWT issued by admin-server) for an RTC main-server access_token.

💡 Complete Integration Guide: This section only contains API protocol details. For a complete Token Exchange integration guide (including how to issue JWTs, configure JWKS endpoints, frontend configuration, etc.), please refer to Authentication & Authorization - Complete Token Exchange Integration Guide.

{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": "eyJhbGciOi...(external JWT)",
"subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
"device_id": "uuid-generated-by-client"
}
FieldRequiredTypeDescription
grant_type✅stringMust be urn:ietf:params:oauth:grant-type:token-exchange
subject_token✅stringExternal JWT (issued by a trusted issuer)
subject_token_type✅stringToken type, typically urn:ietf:params:oauth:token-type:access_token
device_id✅stringRTC Agent extension — client device UUID (embedded in the issued JWT)

💡 Both application/json and application/x-www-form-urlencoded Content-Types are supported.

{
"access_token": "eyJhbGciOi...(RTC JWT)",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600
}
FieldTypeDescription
access_tokenstringJWT issued by the RTC main server, validity specified by expires_in
issued_token_typestringFixed: urn:ietf:params:oauth:token-type:access_token
token_typestringFixed: Bearer
expires_inintegerAccess token expiration time (seconds), typically 3600 (1 hour)

Token Exchange error responses follow the standard OAuth2 error format:

{
"error": "invalid_grant",
"error_description": "Invalid subject_token"
}
HTTP Statuserror ValueMeaning
400invalid_requestMissing required fields or incorrect grant_type
400invalid_grantInvalid subject_token, JWT signature verification failed, or untrusted issuer
401invalid_grantJWT verification failed and JWKS could not be refreshed
500server_errorInternal server error
503temporarily_unavailableIdentity provider temporarily unavailable (JWKS endpoint unreachable)

💡 Error format note: The Token Exchange endpoint uses the standard OAuth2 error format (error + error_description), consistent with other modes of /oauth2/token. This differs from the unified response format (success + errorCode + errorMessage, always returning HTTP 200) used by Admin-server endpoints.

📌 Prerequisite: The main server must configure token_exchange.external_issuers in config.yaml to trust the corresponding JWT issuer. See Admin-server Authentication.


Exchange a refresh_token for a new access_token. The refresh_token can be reused within its validity period.

{
"refresh_token": "dGhpcyBpcyBh..."
}
FieldRequiredTypeDescription
refresh_token✅stringRefresh token, reusable within its validity period
{
"access_token": "eyJhbGciOi...(new)",
"expires_in": 3600
}
FieldTypeDescription
access_tokenstringNew JWT access token
expires_inintegerNew access token expiration time (seconds)

All endpoints return a unified error format when an error occurs:

{
"error": "invalid_grant",
"error_description": "Authorization code has expired"
}
Error CodeHTTP StatusDescriptionCommon Causes
invalid_request400Invalid request parametersMissing required fields, format errors
invalid_client400Client authentication failedProvider misconfiguration
invalid_grant401Authorization code invalid or expiredAuthorization code already used or past its validity period
server_error500Internal server errorServer-side exception

💡 Content-Type Support: POST endpoints (/oauth2/token and /oauth2/refresh) support both application/json and application/x-www-form-urlencoded request formats.


Operational endpoints do not require JWT authentication and are intended for infrastructure use.

Health check endpoint for load balancer and Kubernetes liveness probes.

Response:

{"status": "ok"}

Readiness check endpoint for Kubernetes readiness probes. Returns 200 only when the server is fully started and ready to accept requests. Checks database, Redis, and Centrifuge connection status.

Response (when ready):

{
"status": "ready",
"checks": {
"db": "ok",
"redis": "ok",
"centrifuge": "ok"
}
}

Response (when not ready, HTTP 503):

{
"status": "not ready",
"checks": {
"db": "ok",
"redis": "error",
"centrifuge": "not configured"
}
}
FieldTypeDescription
statusstringOverall status: "ready" or "not ready"
checksobjectCheck results for each dependency component
checks.dbstringDatabase connection status: "ok" or "error"
checks.redisstringRedis connection status: "ok" or "error"
checks.centrifugestringCentrifuge status: "ok", "error", or "not configured"

Prometheus metrics endpoint exposing runtime metrics for monitoring systems (Prometheus / Grafana).

Response: Prometheus metrics in text/plain format.

Authentication: Basic Auth via metrics.user and metrics.password configuration. Production requires authentication — the /metrics endpoint is disabled without credentials. Development environments remain accessible without auth.

💡 For a complete list of Prometheus metrics, Grafana dashboards, and alert rules, see Monitoring.


Business endpoints require JWT authentication (Authorization: Bearer <token> header). In development mode, X-User-ID / X-Device-ID headers are accepted as a bypass.

POST /api/sessions/{sessionID}/interrupts/{interruptID}/answer

Section titled “POST /api/sessions/{sessionID}/interrupts/{interruptID}/answer”

Submit an interrupt answer. When the AI encounters a question requiring user decision during execution, it pauses via the interrupt mechanism and sends the question to the frontend. The frontend collects the user’s answer and submits it through this endpoint.

Path Parameters:

ParameterTypeDescription
sessionIDUUIDSession ID
interruptIDstringInterrupt ID (carried by interrupt event)

Request Body:

{
"answer": "User's answer to the interrupt question"
}
FieldRequiredTypeDescription
answer✅stringThe user’s answer content

Response: Returns 202 Accepted on success with body {"status": "accepted"}.

💡 The internal implementation uses Redis SET+PUBLISH pattern to deliver the answer to the waiting interrupt handler goroutine, ensuring no answer is lost. See Interrupt Flow for details.

Export memory data as an OKF (Open Knowledge Format) bundle. Supports filtering by scope (session / user / global), type, and tags.

Request Body:

{
"scope": "user",
"scopeId": "user-uuid",
"format": "okf-bundle",
"types": ["user", "feedback"],
"tags": ["work"],
"includeLog": false
}
FieldRequiredTypeDescription
scope✅stringExport scope: session / user / global
scopeId✅stringID corresponding to scope (session UUID / user UUID / empty string)
format✅stringExport format, currently only okf-bundle is supported
types—string[]Filter by memory types (optional)
tags—string[]Filter by tags (optional)
includeLog—booleanGenerate log.md (default false)

Response: Content-Type: application/gzip, returns a gzip-compressed OKF bundle stream.

💡 Because this uses a streaming response, JSON error responses are no longer possible once writing to the response body begins. Clients should check HTTP status code and Content-Length to determine export success.

📌 Timestamps in the OKF bundle use UTC timezone, formatted as RFC 3339 (e.g., 2026-09-26T08:30:00Z).


Admin-server is an independent management service separate from the Main Server, providing administrator login, user management, and other features. After administrators log in to admin-server, they receive a JWT that can be recognized by the Main Server via the RFC 8693 Token Exchange mechanism.

💡 Complete Integration Guide: This section only contains Admin-server API protocol details. For a complete Token Exchange integration guide (including architecture, configuration, JWT signing, JWKS endpoints, etc.), please refer to Authentication & Authorization - Complete Token Exchange Integration Guide.

Configure token_exchange in the Main Server’s config.yaml to trust JWTs issued by admin-server:

token_exchange:
external_issuers:
- name: "admin-server"
issuer: "http://admin-server:8081" # admin-server address
jwks_uri: "http://admin-server:8081/.well-known/jwks.json"
allowed_algorithms: ["RS256", "ES256"]
cache_ttl: 3600
# admin-server uses standard JWT claim names (email, name, picture),
# which are covered by the default mapping — no explicit claims_mapping needed
FieldDescription
nameIdentifier name for the issuer
issuerValue that the JWT iss claim must match
jwks_uriJWKS public key endpoint address
allowed_algorithmsAllowed signature algorithms (ES256 or RS256 recommended)
cache_ttlJWKS public key cache time (seconds)
claims_mappingMapping from JWT claims to user fields

Admin-server uses asymmetric keys to sign JWTs, supporting algorithms such as RS256 / ES256 / EdDSA. The Main Server obtains public keys via the JWKS endpoint for verification, with no shared secrets required.

终端窗口
# Method 1: Using admin keygen subcommand (recommended)
./bin/rtc-agent admin keygen # Default: RS256
./bin/rtc-agent admin keygen --algorithm ES256 # ES256 (recommended for production)
./bin/rtc-agent admin keygen --algorithm EdDSA # EdDSA (Ed25519)
./bin/rtc-agent admin keygen --force # Force overwrite existing keys
# Method 2: Using script (legacy compatibility)
./scripts/generate-keys.sh all # RS256 + ES256
./scripts/generate-keys.sh es256 # ES256 only
# Auto mode (Docker deployments)
# On first startup, docker-entrypoint.sh auto-detects and generates an RS256 key pair
# Keys are stored in a Docker named volume (full-admin-server-keys), persisting across restarts
# Production environments should use persistent keys to avoid invalidating all JWTs after restart
EnvironmentKey Storage Recommendation
DevelopmentLocal etc/keys/ directory (already excluded *.pem in .gitignore)
DockerNamed volume full-admin-server-keys (auto-generated, persists across restarts)
ProductionKMS service (AWS KMS / Alibaba Cloud KMS / HashiCorp Vault)

💡 Rotate keys every 90 days. When rotating, retain old public keys for 24-48 hours to maintain compatibility with already-issued tokens. See etc/keys/README.md for details.

💡 Admin-server uses the Ant Design Pro unified response format: { "success": true, "data": {...} } on success, { "success": false, "errorCode": "...", "errorMessage": "..." } on failure (HTTP status code is always 200).

📌 Exception: The /health endpoint returns HTTP 503 (not 200) when the database is unavailable, so that load balancers and Kubernetes probes can correctly detect service status.

Administrator email/password login.

Request Body:

{
"email": "admin@example.com",
"password": "your-password"
}

Success Response (200):

{
"success": true,
"data": {
"access_token": "eyJhbGciOi...",
"refresh_token": "dGhpcyBpcyBh...",
"expires_in": 3600,
"token_type": "Bearer",
"user": {
"id": "uuid",
"email": "admin@example.com",
"name": "Admin",
"avatar_url": ""
}
}
}

Exchange a refresh_token for a new access_token. Each refresh returns a new refresh_token (rotation mechanism), and the old refresh_token is immediately invalidated.

Request Body:

{
"refresh_token": "previous-refresh-token"
}

Success Response (200):

{
"success": true,
"data": {
"access_token": "eyJhbGciOi...(new)",
"refresh_token": "rt_...(new)",
"expires_in": 3600,
"token_type": "Bearer"
}
}

Get current administrator information. Requires Authorization: Bearer <admin-jwt> header.

Success Response (200):

{
"success": true,
"data": {
"id": "uuid",
"email": "admin@example.com",
"name": "Admin",
"avatar_url": ""
}
}

Revoke a refresh_token. Requires JWT authentication.

Request Body:

{
"refresh_token": "refresh-token-to-revoke"
}

Success Response (200):

{
"success": true,
"data": {
"status": "ok"
}
}

Returns the admin-server’s JWK Set (RFC 7517). The Main Server uses this endpoint to obtain public keys for verifying JWT signatures.

Admin-server error responses always return HTTP 200, distinguishing error types via the errorCode field:

errorCodeTriggerDescription
invalid_requestMalformed request body, field validation failureClient should check request parameters
invalid_credentialsIncorrect email or passwordLogin credentials are wrong
invalid_grantrefresh_token is invalid, revoked, or expiredUser should re-login
unauthorizedMissing/invalid/expired Authorization headerJWT authentication failed
user_not_foundNo user found for the given user IDData consistency issue
server_errorInternal server error (key generation failure, database exception, etc.)Retryable; investigate if persistent