All API access requires a valid Bearer token obtained through one of the two authentication methods described below. For a full, interactive reference of every API endpoint and its request/response schema, see the OpenAPI documentation published at /api-docs.
Quick Reference
What | Value |
Spec | OAuth 2.1 (draft) + RFC 8414 + RFC 9728 + RFC 7591 |
Token type | JWT Bearer |
Token lifetime | 15 minutes (900 s) |
Supported grant types |
|
Supported response types |
|
PKCE methods |
|
Token auth method |
|
Available scope |
|
Authentication Methods
ResQueServe supports two distinct ways to obtain a Bearer token:
| Method 1: Client Credentials | Method 2: Authorization Code + PKCE |
Best for | Automated scripts, server-side integrations, direct API access | Third-party applications and integrations that act on behalf of a logged-in user via a browser-based consent flow (includes OAuth 2.1 clients such as MCP-compatible tools) |
User login required | No | Yes - user authenticates interactively |
How to get credentials | Account settings page in the Dashboard | Dynamic client registration via |
Implementation effort | A single HTTP request for each token | Requires redirect handling, PKCE, and a callback endpoint |
Method 1: Client Credentials (Recommended for direct API access)
This is the straightforward method for integrations that run on a server or in automated pipelines. You register an API client in your ResQueServe account settings and then exchange the client credentials for a short-lived Bearer token with a single HTTP request.
Log in and open Account from the top-right menu, and scroll to the API Clients / Developer section. Enter a description and click Create. Copy the client_id and client_secret that are displayed. The secret is shown only once and cannot be retrieved again. A user account may have at most 10 API clients.
Post grant_type=client_credentials together with your client_id (the UUID from the account settings page) and client_secret (the value shown once at creation time) to the token endpoint:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<your-client-id>
&client_secret=<your-client-secret>
Success response (200 OK):
{
"access_token": "<JWT>",
"token_type": "Bearer",
"expires_in": 900
}The issued token carries the roles and permissions of the user account that owns the API client. Tokens expire after 15 minutes (900 seconds); simply repeat this request to obtain a fresh token. Include the token as a Bearer credential in every subsequent API request (Authorization: Bearer <access_token>). See the OpenAPI docs at /api-docs for the full list of available endpoints.
TOKEN=$(curl -sX POST https://dashboard.example.com/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=<your-client-id>" \
--data-urlencode "client_secret=<your-client-secret>" \
| jq -r '.access_token')
curl -H "Authorization: Bearer $TOKEN" https://dashboard.example.com/api/v1/...
Method 2: Authorization Code + PKCE (for third-party applications and redirect-based flows)
This method implements the full OAuth 2.1 authorization code flow and is intended for any third-party application that needs to act on behalf of a logged-in ResQueServe user, for example custom web or desktop apps, integrations that embed a consent screen, or OAuth 2.1 clients such as MCP-compatible tools that require interactive user authorization. The implementation is significantly more involved than Method 1 and is only necessary when a redirect-based consent flow is required. PKCE with S256 is mandatory. Plain code exchange without a code challenge is not accepted.
Client Dashboard User browser
| | |
|-- POST /oauth/register ----->| |
|<-- client_id, client_secret -| |
| | |
|-- redirect user to /oauth/authorize ---------------------->|
| |<-- user logs in ------------|
| |-- redirect with code ------>|
|<-- callback with ?code=... --------------------------------|
| | |
|-- POST /oauth/token (code + verifier) ->| |
|<-- access_token -------------------------------- |
Step 1: Register a dynamic client
Third-party applications using this flow must register before starting it. The server issues a client_id and client_secret that are valid for a limited time. If the server requires an initial access token, include it as Authorization: Bearer <initial-access-token>.
POST /oauth/register
Content-Type: application/json
{
"redirect_uris": ["https://your-app.example.com/callback"],
"grant_types": ["authorization_code"],
"client_name": "My MCP Client"
}
Field | Required | Description |
| Yes | One or more absolute URIs; must use HTTPS ( |
| No | Defaults to |
| No | Human-readable display name |
On success (201 Created) the response contains client_id and client_secret. The secret is shown only once. Store it securely immediately. Dynamically registered clients expire after a configurable period and must be re-registered. Rate limit: 5 requests per minute per IP address.
Step 2: Generate PKCE values
Before redirecting the user, generate a cryptographically random code_verifier (43–128 ASCII characters: [A-Z] [a-z] [0-9] - . _ ~) and derive code_challenge = BASE64URL(SHA-256(ASCII(code_verifier))) with no padding.
Step 3: Redirect the user to the authorization endpoint
GET /oauth/authorize
?response_type=code
&client_id=<your-client-id>
&redirect_uri=<your-redirect-uri>
&code_challenge=<BASE64URL(SHA-256(code_verifier))>
&code_challenge_method=S256
&scope=mcp:user
&state=<random-opaque-value>
Parameter | Required | Description |
| Yes | Must be |
| Yes | UUID issued during client registration |
| Yes | Must exactly match a URI registered for the client |
| Yes |
|
| Yes | Must be |
| No | Space-separated list of scopes; defaults to |
| No | Opaque value to protect against CSRF; returned unchanged in the callback |
The server redirects the user to the identity provider for login. After a successful login it redirects back to your redirect_uri with the authorization code and the original state value. Authorization codes expire after 5 minutes and are single-use.
Step 4: Exchange the code for a token
Rate limit: 10 requests per minute per IP on POST /oauth/token.
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id=<your-client-id>
&code=<authorization-code>
&code_verifier=<original-code-verifier>
&redirect_uri=<same-redirect-uri-as-step-3>
Parameter | Required | Description |
| Yes | Must be |
| Yes | UUID of the registered client |
| Yes | Authorization code from the callback |
| Yes | The original random string used in Step 2 |
| Yes | Must match the URI used in Step 3 |
On success the response is identical to the client credentials token response: a JSON object with access_token, token_type: "Bearer", and expires_in: 900.
# Generate PKCE values
CODE_VERIFIER=$(openssl rand -base64 64 | tr -d '=+/' | cut -c1-64)
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')
# Register a dynamic client (if not already registered)
REGISTRATION=$(curl -sX POST https://dashboard.example.com/oauth/register \
-H 'Content-Type: application/json' \
-d '{
"redirect_uris": ["https://your-app.example.com/callback"],
"client_name": "My Integration"
}')
CLIENT_ID=$(echo $REGISTRATION | jq -r '.client_id')
CLIENT_SECRET=$(echo $REGISTRATION | jq -r '.client_secret')
# Direct the user to the authorization URL (open in browser)
# https://dashboard.example.com/oauth/authorize?response_type=code
# &client_id=$CLIENT_ID&redirect_uri=...&code_challenge=$CODE_CHALLENGE
# &code_challenge_method=S256&scope=mcp:user&state=random-csrf-token
# After the user logs in, the browser is redirected to your callback with ?code=AUTH_CODE
# Exchange the code for a token
TOKEN=$(curl -sX POST https://dashboard.example.com/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "code=$AUTH_CODE" \
--data-urlencode "code_verifier=$CODE_VERIFIER" \
--data-urlencode "redirect_uri=https://your-app.example.com/callback" \
| jq -r '.access_token')
curl -H "Authorization: Bearer $TOKEN" https://dashboard.example.com/mcp/user
Discovery
The authorization server publishes machine-readable metadata at two well-known URLs used by OAuth 2.1 clients for automatic configuration.
GET /.well-known/oauth-authorization-server (RFC 8414) returns the issuer, endpoint URLs, supported grant types, PKCE methods, and available scopes. GET /.well-known/oauth-protected-resource (RFC 9728) advertises the resource and its authorization server.
Clients that receive a 401 Unauthorized from /mcp/* will also find a WWW-Authenticate header pointing to the protected resource metadata document:
WWW-Authenticate: Bearer realm="https://dashboard.example.com",
resource_metadata="https://dashboard.example.com/.well-known/oauth-protected-resource"
Example response for /.well-known/oauth-authorization-server:
{
"issuer": "https://dashboard.example.com",
"authorization_endpoint": "https://dashboard.example.com/oauth/authorize",
"token_endpoint": "https://dashboard.example.com/oauth/token",
"registration_endpoint": "https://dashboard.example.com/oauth/register",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "client_credentials"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["client_secret_post"],
"scopes_supported": ["mcp:user"]
}Access Token Format (JWT)
Tokens are signed JWTs. The payload structure for user-facing tokens:
{
"jti": "019723ab-...",
"sub": "550e8400-e29b-41d4-a716-446655440000",
"name": "dispatcher.name",
"iat": 1714300000,
"exp": 1714300900,
"iss": "https://dashboard.example.com",
"aud": "user-api-production",
"roles": ["rqs:user"],
"https://schemas.xenbit.app/rqs/claims/userid": "42",
"https://schemas.xenbit.app/rqs/claims/rank": "3",
"https://schemas.xenbit.app/rqs/claims/dispatchertag": "XY42",
"given_name": "Jane",
"family_name": "Doe"
}Standard claims:
Claim | Type | Description |
| string (UUID v7) | Unique token identifier |
| string (UUID) | Subject — the user's identity UUID |
| string | Username / login name |
| number | Issued-at timestamp (Unix epoch) |
| number | Expiration timestamp (Unix epoch) |
| string | Issuer — the Dashboard base URL |
| string | Audience — |
| string[] | Granted roles |
| string | First name |
| string | Last name |
Custom claims under the https://schemas.xenbit.app/rqs/claims/ namespace:
Claim | Type | Description |
| string | Internal numeric user ID |
| string | User rank level |
| string | Short dispatcher identification tag |
Error Responses
The OAuth endpoints (/oauth/authorize, /oauth/token, /oauth/register) return errors in the RFC 6749 JSON format. This is the only part of the API that does not follow the RFC 7807 Problem Details format used by all other API endpoints. Keep this in mind when writing error-handling code that covers both OAuth and regular API responses.
{
"error": "error_code",
"error_description": "Human-readable explanation."
}Endpoint |
| HTTP | Cause |
|
| 400 |
|
|
| 400 | Missing required parameter ( |
|
| 400 | One or more requested scopes are not supported |
|
| 400 |
|
|
| — | Redirected to |
|
| 400 |
|
|
| 400 | Missing required parameter |
|
| 401 | Authorization code not found, expired, or PKCE verification failed |
|
| 401 | Client credentials not found or secret is wrong |
|
| 400 | No |
|
| 400 | A URI is not an absolute URL, or uses HTTP outside of localhost |
|
| 401 | An initial access token is required and the provided token is missing or wrong |
