Skip to main content

Session

POST /session-handshake

Create a handshake token for secure authentication

Required scope: session:manage

Parameters

NameTypeRequiredSourceDescription
x-api-keystringheaderAPI key header
x-foundry-urlstringheaderFoundry URL header
x-usernamestringheaderUsername header
x-world-namestringheaderWorld name header

Returns

object - Handshake token and encryption details

Try It Out


POST /start-session

Start a headless Foundry session using puppeteer

Required scope: session:manage

Parameters

NameTypeRequiredSourceDescription
handshakeTokenstringbodyThe token received from session-handshake
encryptedPasswordstringbodyPassword encrypted with the public key
x-api-keystringheaderAPI key header
captureBrowserConsolestringbodyLog level for browser console capture ("error", "warn", or "debug")

Returns

object - Session information including sessionId and clientId

Try It Out

Code Examples

// Step 1: Get handshake credentials
const baseUrl = 'http://localhost:3010';
const apiKey = 'your-api-key';

const handshakeResponse = await fetch(`${baseUrl}/session-handshake`, {
method: 'POST',
headers: {
'x-api-key': apiKey,
'x-foundry-url': 'http://localhost:30000',
'x-world-name': 'my-world',
'x-username': 'Gamemaster'
}
});
const { token, publicKey, nonce } = await handshakeResponse.json();

// Step 2: Encrypt password using Web Crypto API (RSA-OAEP with SHA-256)
const password = 'your-password';
const payload = JSON.stringify({ password, nonce });

// Import the public key
const pemContents = publicKey
.replace('-----BEGIN PUBLIC KEY-----', '')
.replace('-----END PUBLIC KEY-----', '')
.replace(/\n/g, '');
const binaryKey = Uint8Array.from(atob(pemContents), c => c.charCodeAt(0));

const cryptoKey = await crypto.subtle.importKey(
'spki',
binaryKey,
{ name: 'RSA-OAEP', hash: 'SHA-256' },
false,
['encrypt']
);

// Encrypt the payload
const encrypted = await crypto.subtle.encrypt(
{ name: 'RSA-OAEP' },
cryptoKey,
new TextEncoder().encode(payload)
);
const encryptedPassword = btoa(String.fromCharCode(...new Uint8Array(encrypted)));

// Step 3: Start the session
const sessionResponse = await fetch(`${baseUrl}/start-session`, {
method: 'POST',
headers: {
'x-api-key': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ handshakeToken: token, encryptedPassword })
});
const { sessionId, clientId } = await sessionResponse.json();
console.log('Session started:', { sessionId, clientId });

Response

Status: 200

{
"clientId": "fvtt_099ad17ea199e7e3",
"sessionId": "030a1249-70e5-41a8-8bd3-26cfeb39faab",
"success": true
}

DELETE /end-session

Stop a headless Foundry session

Required scope: session:manage

Parameters

NameTypeRequiredSourceDescription
sessionIdstringqueryThe ID of the session to end
x-api-keystringheaderAPI key header

Returns

object - Status of the operation

Try It Out

Code Examples

const baseUrl = 'http://localhost:3010';
const path = '/end-session';
const params = {
sessionId: '030a1249-70e5-41a8-8bd3-26cfeb39faab'
};
const queryString = new URLSearchParams(params).toString();
const url = `${baseUrl}${path}?${queryString}`;

const response = await fetch(url, {
method: 'DELETE',
headers: {
'x-api-key': 'your-api-key-here'
}
});
const data = await response.json();
console.log(data);

Response

Status: 200

{
"message": "Session ended",
"status": "ok"
}

GET /session

Get all active headless Foundry sessions

Required scope: session:manage

Parameters

NameTypeRequiredSourceDescription
x-api-keystringheaderAPI key header

Returns

object - List of active sessions for the current API key

Try It Out

Code Examples

const baseUrl = 'http://localhost:3010';
const path = '/session';
const url = `${baseUrl}${path}`;

const response = await fetch(url, {
method: 'GET',
headers: {
'x-api-key': 'your-api-key-here'
}
});
const data = await response.json();
console.log(data);

Response

Status: 200

{
"activeSessions": [
0: {
"clientId": "fvtt_099ad17ea199e7e3",
"foundryUrl": "http://localhost:30013",
"foundryVersion": "13.348",
"lastActivity": 1778896411477,
"sessionId": "030a1249-70e5-41a8-8bd3-26cfeb39faab",
"startedAt": 1778896411477,
"systemId": "dnd5e",
"systemTitle": "Dungeons & Dragons Fifth Edition",
"systemVersion": "5.0.4",
"username": "tester",
"worldId": "testing",
"worldName": "testing",
"worldTitle": "testing"
}
]
}