List quests
Retrieve the quests configured for your server, with their rewards and completion rules.
GET /v1/quests/list · requires quests:read
Query parameters
Prop
Type
Returns
data is a list of quests, in the order your community arranged them and then newest first. The response also includes page (nextCursor and limit), total (every quest that matches, not only this page), limit and offset.
Prop
Type
The response also includes the original field names. They contain the same values, and remain for as long as version 1 exists.
| Deprecated field, still sent | Same value as |
|---|---|
icon_emoji | iconEmoji |
quest_type | questType |
xp_reward | xpReward |
currency_reward | currencyReward |
role_reward_id | roleRewardId |
badge_id | badgeId |
is_repeatable | isRepeatable |
max_completions | maxCompletions |
max_completions_per_user | maxCompletionsPerMember |
starts_at | startsAt |
ends_at | endsAt |
verification_type | verificationType |
program_id | programId |
created_at | createdAt |
repeat_cooldown_hours | repeatCooldownHours |
required_level | requiredLevel |
required_role_id | requiredRoleId |
prerequisite_quest_id | prerequisiteQuestId |
required_season_xp | requiredSeasonXp |
status, startsAt, endsAt, isRepeatable, maxCompletions, maxCompletionsPerMember, programId, repeatCooldownHours, requiredLevel, requiredRoleId, prerequisiteQuestId and requiredSeasonXp are the quest's own rules. Complete a quest applies every one of them, so you can read them here before you call it. A rule that is 0 counts as not set, like one that is null. Your community's daily quest limit is not a field of a quest: Community details reports it.
Example
curl "https://ceejay.communitystudios.xyz/api/v1/quests/list?limit=20" \
-H "Authorization: Bearer $CEEJAY_API_KEY"The TypeScript example uses ceejay.quests.list from the TypeScript SDK. It returns the full response below, with the list in data.
{
"success": true,
"total": 1,
"limit": 20,
"offset": 0,
"data": [
{
"id": 42,
"title": "Join the weekend tournament",
"description": "Play one match in the weekend tournament.",
"icon_emoji": "🏆",
"category": "integrations",
"quest_type": "api_check",
"xp_reward": 500,
"currency_reward": 250,
"role_reward_id": "982371004827100394",
"badge_id": 7,
"is_repeatable": false,
"max_completions": null,
"max_completions_per_user": 1,
"starts_at": null,
"ends_at": null,
"status": "active",
"verification_type": "api",
"program_id": null,
"created_at": "2026-09-02T12:00:00.000Z",
"repeat_cooldown_hours": null,
"required_level": 5,
"required_role_id": null,
"prerequisite_quest_id": null,
"required_season_xp": null,
"iconEmoji": "🏆",
"questType": "api_check",
"xpReward": 500,
"currencyReward": 250,
"roleRewardId": "982371004827100394",
"badgeId": 7,
"isRepeatable": false,
"maxCompletions": null,
"maxCompletionsPerMember": 1,
"startsAt": null,
"endsAt": null,
"verificationType": "api",
"programId": null,
"createdAt": "2026-09-02T12:00:00.000Z",
"repeatCooldownHours": null,
"requiredLevel": 5,
"requiredRoleId": null,
"prerequisiteQuestId": null,
"requiredSeasonXp": null
}
],
"page": {
"nextCursor": null,
"limit": 20
}
}Paging
There are two ways to paginate. Use one of them.
- With
cursor. Pass thepage.nextCursorfrom the previous page ascursor, and stop when it isnull. Every quest is returned once, even when quests are added while you page. Use this to read the whole list. - With
offset. Skip a number of quests.totalgives the total count.
When both are sent, the page starts at cursor and offset is not used. The response's offset is then 0.
Errors
| Status | code | error | When |
|---|---|---|---|
400 | bad_request | limit must be a whole number of 0 or more | limit is negative, a fraction or text, or was sent more than once |
400 | bad_request | offset must be a whole number from 0 to 2147483647 | offset is negative, a fraction, text or above 2,147,483,647, or was sent more than once |
400 | bad_request | status cannot contain a null character | status contains a null character (U+0000, written %00 in the URL) |
400 | bad_request | category cannot contain a null character | category contains a null character (U+0000, written %00 in the URL) |
400 | bad_request | cursor cannot be read. Send page.nextCursor as it was answered | cursor is not a page.nextCursor value returned by List quests |
404 | not_available | This is not available on this instance yet. | This feature is not available on this instance yet. Community details reports the same under features. The body includes feature |
limit and offset must be plain integers, so 10.0, +10 and 1e2 are rejected as well.
Every error body also includes requestId, and a 400 with the code bad_request identifies the invalid field in field. Match on code; message text can change.
The errors every request shares (401, 403, 405, 429, 500) are on the Errors page.

