Skip to main content

Auth

POST /auth/key-request

Request a scoped API key

Initiates a key request that a user must approve in the dashboard. Supports two flows:

Device flow (no callbackUrl) — for CLI tools, scripts, and desktop apps. The response contains an approvalUrl to direct the user to. Poll GET /auth/key-request/{code}/status until status is approved, then read apiKey from the response.

Web flow (callbackUrl provided) — for web apps that can receive an HTTP redirect. After the user approves, the dashboard redirects to your callbackUrl with a code query parameter containing the exchange code. POST that code to POST /auth/key-request/exchange to retrieve the API key.

Parameters

NameTypeRequiredSourceDescription
appNamestringbodyName of the application requesting access
scopesarraybodyList of permission scopes the key requires
appDescriptionstringbodyShort description of what the application does
appUrlstringbodyHomepage or docs URL for the application
callbackUrlstringbodyEnables web flow: URL the dashboard redirects to after approval, with a code query parameter containing the exchange code
clientIdsarraybodyFoundry client IDs to restrict the key to
suggestedMonthlyLimitnumberbodySuggested per-key monthly request cap (user may override)
suggestedExpirystringbodySuggested expiry date ISO 8601 (user may override)

Returns

object - code, approvalUrl, expiresIn, expiresAt

Try It Out

Code Examples

const baseUrl = 'http://localhost:3010';
const path = '/auth/key-request';
const url = `${baseUrl}${path}`;

const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"appName": "Test Discord Bot",
"appDescription": "A test integration",
"scopes": [
"entity:read",
"roll:read",
"chat:read"
]
})
});
const data = await response.json();
console.log(data);

Response

Status: 201

{
"approvalUrl": "http://localhost:3010/approve/R76CTM",
"code": "R76CTM",
"expiresAt": "2026-05-15T21:04:05-05:00",
"expiresIn": 600
}

GET /auth/key-request/:code/status

Poll key request status

Returns the current status of a pending key request. When status is approved, the response includes the newly created apiKey. Once the key has been retrieved, the status becomes exchanged and the key is no longer returned.

Parameters

NameTypeRequiredSourceDescription
codestringparamsThe code returned by POST /auth/key-request

Returns

object - status (pending | approved | denied | expired | exchanged), apiKey, scopes, clientIds (when approved)

Try It Out

Code Examples

const baseUrl = 'http://localhost:3010';
const path = '/auth/key-request/R76CTM/status';
const url = `${baseUrl}${path}`;

const response = await fetch(url, {
method: 'GET'
});
const data = await response.json();
console.log(data);

Response

Status: 200

{
"apiKey": "your-api-key-here",
"clientIds": null,
"scopes": [
0: "entity:read",
1: "roll:read"
],
"status": "approved"
}

POST /auth/key-request/exchange

Exchange approval code for API key (web flow)

Web flow only. After the user approves the request in the dashboard, the relay redirects to the callbackUrl with a one-time code query parameter. POST that code here to receive the API key. The code is single-use — a second call returns 410.

Parameters

NameTypeRequiredSourceDescription
codestringbodyThe exchange code delivered to your callbackUrl

Returns

object - apiKey, scopes, clientIds

Try It Out

Code Examples

const baseUrl = 'http://localhost:3010';
const path = '/auth/key-request/exchange';
const url = `${baseUrl}${path}`;

const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"code": "your-exchange-code-here"
})
});
const data = await response.json();
console.log(data);

Response

Status: 200

{
"apiKey": "your-api-key-here",
"clientIds": null,
"scopes": [
0: "entity:read"
]
}