Getting started
Pagination and filters
One scheme for every list: limit, an opaque cursor and next_cursor. How ordering works, what a keyset cursor guarantees, and the two documented exceptions.
Updated 4 September 2026
Every GET that returns a list answers with the same envelope:
{ "data": [ … ], "next_cursor": "eyJrIjoiMjAyNi0wOC0xOVQxMjowMDowMC4wMDArMDA6MDAiLCJpIjoiN2M5ZTY2NzktNzQyNS00MGRlLTk0NGItZTA3ZmMxZjkwYWU3In0" }
limit: 1 to 100, default 50. Anything else is400.cursor: the opaque string fromnext_cursorof the previous page. Do not build it yourself; a tampered cursor is400`cursor` is not valid.next_cursorisnullon the last page.
curl "https://app.seegnals.com/api/v1/prospects?status=replied&limit=100" -H "Authorization: Bearer $SEEGNALS_TOKEN"
curl "https://app.seegnals.com/api/v1/prospects?status=replied&limit=100&cursor=eyJr…" -H "Authorization: Bearer $SEEGNALS_TOKEN"
const res = await fetch("https://app.seegnals.com/api/v1/prospects?status=replied&limit=100&cursor=eyJr…", {
method: "GET",
headers: {
"Authorization": `Bearer ${process.env.SEEGNALS_TOKEN}`
}
});
const json = await res.json().catch(() => null);
console.log(res.status, json);
import os, requests
res = requests.get(
"https://app.seegnals.com/api/v1/prospects?status=replied&limit=100&cursor=eyJr…",
headers={"Authorization": f"Bearer {os.environ['SEEGNALS_TOKEN']}"},
timeout=20,
)
print(res.status_code, res.json() if res.content else None)
Ordering and stability
Lists are newest first: by created_at, received_at or sent_at descending, then by id. The cursor is a keyset over that pair, so a row inserted while you are paging does not shift the pages and never produces a duplicate. You can safely walk a whole list while the campaign keeps sending.
Two exceptions, documented on purpose
/companiesuses an offset cursor. Thetemperaturefilter works on a value computed from the last seven days of events rather than stored in a column, so the list is assembled in memory. A company created during your walk can shift a boundary row. The cursor is still opaque; only the guarantee differs./offers?status=is applied to the fetched page, because read status is derived from visits. A page can hold fewer thanlimitrows whilenext_cursoris notnull. Keep paging until it is.
/mailboxes does not paginate at all. Workspaces have tens of mailboxes, so a single response is enough. next_cursor is always null there.
Dates
Timestamps are ISO 8601 with an offset, as Postgres returns them: 2026-09-03T10:00:00.123456+00:00. Date filters (created_since, since) accept any ISO 8601 date or date-time: 2026-09-01 or 2026-09-01T00:00:00Z.
What a list does not offer
- No
updated_sinceon prospects or campaigns: those tables carry no modification timestamp, and the API refuses the parameter with400rather than pretend to filter. - No sorting parameters. Sort on your side after fetching.
- No total counts. Page until
next_cursorisnull.