List tickets
GET /tickets lists a project’s tickets one page at a time. This recipe asks for open tickets,
newest first, 50 per page, and follows nextCursor until the last page. See
Pagination for how cursors work.
// List tickets: page through every open ticket in a project, newest first.//// node list-tickets.ts (the first project)// SAW_PROJECT_ID=project-… node list-tickets.tsimport { createClient } from './saw.ts';
const saw = createClient();
const projectId = process.env.SAW_PROJECT_ID ?? (await saw.get('/projects'))[0]?.id;if (!projectId) throw new Error('This organization has no projects yet.');
let cursor: string | undefined;let listed = 0;do { const page = await saw.get('/tickets', { query: { projectId, open: true, sort: 'created', direction: 'desc', limit: 50, cursor }, }); if (listed === 0 && page.total !== undefined) console.log(`${page.total} open ticket(s):`); for (const ticket of page.items) { console.log(` ${ticket.identifier.padEnd(10)} ${ticket.priority.padEnd(11)} ${ticket.title}`); } listed += page.items.length; // `nextCursor` is null on the last page. cursor = page.nextCursor ?? undefined;} while (cursor);
console.log(`Listed ${listed} ticket(s).`);SAW_API_KEY=saw_live_… node --experimental-strip-types list-tickets.tsIt uses saw.ts and saw-api.d.ts from the
Quickstart.
Filters
Section titled “Filters”An API key must pass projectId, because it can’t list tickets across the whole organization.
The other filters are optional and combine:
- Board position:
statusId,open(leave out completed columns),includeArchived. - Planning:
cycleId,epicId,milestoneId,releaseId,parentTicketId. ForcycleId,epicIdandparentTicketId,nonemeans “not in any”. - People:
assigneeId. - Text:
q, which searches the identifier, title and description. - Order:
sort(manual,priority,created,updated,title) anddirection.
Find IDs for the filters with GET /projects, /statuses?projectId=…, /cycles and /users.
The API reference documents each one.