List programs
List your community's programs, to find the programId the program XP requests need.
GET /v1/programs · requires programs:read
Query parameters
Prop
Type
Returns
data is a list of programs, by programId, lowest first. The response also includes page, with nextCursor and limit.
Prop
Type
Example
curl "https://ceejay.communitystudios.xyz/api/v1/programs?status=active" \
-H "Authorization: Bearer $CEEJAY_API_KEY"The TypeScript example uses ceejay.programs.list from the TypeScript SDK. It returns the full response below, with the list in data.
{
"success": true,
"data": [
{
"programId": 3,
"name": "Ambassadors",
"slug": "ambassadors",
"description": "Members who host events and welcome new players.",
"status": "active",
"type": "custom",
"memberCount": 24,
"maxMembers": 50,
"createdAt": "2026-08-12T10:00:00.000Z"
}
],
"page": {
"nextCursor": null,
"limit": 50
}
}Paging
Pass page.nextCursor as cursor to get the next page, and stop when it is null. A cursor is valid only for the list that returned it: a cursor from another list is rejected.
What the list is for
Grant program XP and Deduct program XP need a programId, and work only while the program's status is active. memberCount counts the members those two requests accept: the ones in the program with the status Accepted or Active.
The list never returns who created a program, its application form, its requirements, rewards and settings, its landing page, or anything about its members but how many there are.
Errors
| Status | code | error | When |
|---|---|---|---|
400 | bad_request | status must be one of active, draft, paused, archived or all | status is not active, draft, paused, archived or all |
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 | cursor is not one this request gave out | cursor is not a page.nextCursor value returned by this request |
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 |
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.

