Skip to main content

Roll

GET /rolls​

Get recent rolls

Retrieves a list of up to 20 recent rolls made in the Foundry world.

Required scope: roll:read

Parameters​

NameTypeRequiredSourceDescription
clientIdstringqueryClient ID for the Foundry world
limitnumberqueryOptional limit on the number of rolls to return (default is 20)
userIdstringquery, bodyFoundry user ID or username to scope permissions (omit for GM-level access)

Returns​

array - An array of recent rolls with details

Try It Out​

Code Examples​

const baseUrl = 'http://localhost:3010';
const path = '/rolls';
const params = {
clientId: 'fvtt_099ad17ea199e7e3',
limit: '20'
};
const queryString = new URLSearchParams(params).toString();
const url = `${baseUrl}${path}?${queryString}`;

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

{
"type": "rolls-result",
"requestId": "rolls_1778896424608",
"data": [
0: {
"id": "manual_1778896424102_l0jfemg94sh",
"messageId": "manual_1778896424102_l0jfemg94sh",
"user": null,
"speaker": {},
"flavor": "Test Roll",
"rollTotal": 16,
"formula": "2d20kh",
"isCritical": false,
"isFumble": false,
"dice": [ 1 item ],
"timestamp": 1778896424102
},
1: {
"id": "manual_1778896413186_z1jrn5ycr6",
"messageId": null,
"user": null,
"speaker": {},
"flavor": "",
"rollTotal": 11,
"formula": "1d20",
"isCritical": false,
"isFumble": false,
"dice": [ 1 item ],
"timestamp": 1778896413186
}
]
}

GET /lastroll​

Get the last roll

Retrieves the most recent roll made in the Foundry world.

Required scope: roll:read

Parameters​

NameTypeRequiredSourceDescription
clientIdstringqueryClient ID for the Foundry world
userIdstringquery, bodyFoundry user ID or username to scope permissions (omit for GM-level access)

Returns​

object - The most recent roll with details

Try It Out​

Code Examples​

const baseUrl = 'http://localhost:3010';
const path = '/lastroll';
const params = {
clientId: 'fvtt_099ad17ea199e7e3'
};
const queryString = new URLSearchParams(params).toString();
const url = `${baseUrl}${path}?${queryString}`;

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

{
"type": "last-roll-result",
"requestId": "last-roll_1778896424612",
"data": {
"id": "manual_1778896424102_l0jfemg94sh",
"messageId": "manual_1778896424102_l0jfemg94sh",
"user": null,
"speaker": {},
"flavor": "Test Roll",
"rollTotal": 16,
"formula": "2d20kh",
"isCritical": false,
"isFumble": false,
"dice": [
0: { 2 keys }
],
"timestamp": 1778896424102
}
}

POST /roll​

Make a roll

Executes a roll with the specified formula.

Required scope: roll:execute

Parameters​

NameTypeRequiredSourceDescription
formulastring✓bodyThe roll formula to evaluate (e.g., "1d20 + 5")
clientIdstringqueryClient ID for the Foundry world
flavorstringbodyOptional flavor text for the roll
createChatMessagebooleanbodyWhether to create a chat message for the roll
speakerstringbodyThe speaker for the roll
whisperarraybodyUsers to whisper the roll result to
userIdstringquery, bodyFoundry user ID or username to scope permissions (omit for GM-level access)

Returns​

object - Result of the roll operation

Try It Out​

Code Examples​

const baseUrl = 'http://localhost:3010';
const path = '/roll';
const params = {
clientId: 'fvtt_099ad17ea199e7e3'
};
const queryString = new URLSearchParams(params).toString();
const url = `${baseUrl}${path}?${queryString}`;

const response = await fetch(url, {
method: 'POST',
headers: {
'x-api-key': 'your-api-key-here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
"formula": "2d20kh",
"flavor": "Test Roll",
"createChatMessage": true
})
});
const data = await response.json();
console.log(data);

Response​

Status: 200

{
"type": "roll-result",
"requestId": "roll_1778896424096",
"success": true,
"data": {
"id": "manual_1778896424102_l0jfemg94sh",
"chatMessageCreated": true,
"roll": {
"formula": "2d20kh",
"total": 16,
"isCritical": false,
"isFumble": false,
"dice": [ 1 item ],
"timestamp": 1778896424102
}
}
}

GET /rolls/subscribe​

Subscribe to real-time roll events via Server-Sent Events (SSE)

Opens a persistent SSE connection that streams roll events as they occur.

Required scope: events:subscribe

Parameters​

NameTypeRequiredSourceDescription
clientIdstringqueryClient ID for the Foundry world
userIdstringqueryFoundry user ID or username to scope permissions (omit for GM-level access)

Returns​

SSE stream - SSE event stream

Try It Out​

Code Examples​

const { EventSource } = require('eventsource'); // npm install eventsource

const baseUrl = 'http://localhost:3010';
const apiKey = 'your-api-key-here';
const url = `${baseUrl}/rolls/subscribe?clientId=your-client-id`;

// eventsource v4 uses a custom fetch function to inject headers
const eventSource = new EventSource(url, {
fetch: (input, init) => fetch(input, {
...init,
headers: { ...init?.headers, 'x-api-key': apiKey }
})
});

eventSource.addEventListener('connected', (event) => {
const data = JSON.parse(event.data);
console.log('Connected:', data.clientId);
});

eventSource.addEventListener('roll', (event) => {
const roll = JSON.parse(event.data);
const dice = roll.dice?.map(d =>
`${d.results.map(r => `${r.result}${r.active ? '' : '(dropped)'}`).join(', ')} (d${d.faces})`
).join(' + ') || '';
console.log(`[${roll.user?.name}] ${roll.formula} = ${roll.rollTotal}${roll.isCritical ? ' CRITICAL!' : ''}${roll.isFumble ? ' FUMBLE!' : ''}`);
if (roll.flavor) console.log(` Flavor: ${roll.flavor}`);
if (dice) console.log(` Dice: ${dice}`);
});

eventSource.onerror = (error) => {
console.error('SSE error:', error);
};

// To disconnect later:
// eventSource.close();

Response​

Status: 200

{
"event": "connected",
"data": {
"clientId": "fvtt_099ad17ea199e7e3"
}
}