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
appNamestring✓bodyName of the application requesting access
scopesarray✓bodyList 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
codestring✓paramsThe 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
codestring✓bodyThe 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"
]
}