Getting started

Pagination

List endpoints return newest items first and use the limit and after parameters with a has_more flag.

List endpoints return one page at a time. Use limit to set the page size and after to ask for the next page.

Parameters

ParameterTypeDescription
limitintegerItems per page. Default 20, minimum 1, maximum 100. Values outside the range are clamped, and a value that is not a number falls back to 20.
afterstringThe ID of the last item you received. The response starts with the item just after it.

Response shape

JSON
{
  "object": "list",
  "data": [
    { "object": "email", "id": "01jcz8w3f2x9k4m7n6p5q2r1s0", "subject": "Welcome" }
  ],
  "has_more": true
}

Lists are ordered newest first. When has_more is true, pass the id of the last item in data as after to get the next page. When it is false, you have reached the end. An after value that does not match an existing item is ignored, and you get the first page again.

Paginated endpoints

EndpointNotes
GET /emailsFull-access key. List items have html and text set to null. Retrieve one email to read its body.
GET /contacts and GET /segments/{id}/contactsContacts in the project, or in one segment.
GET /segments and GET /audiencesSame data under both paths.
GET /broadcasts
GET /templates
GET /webhooks
GET /suppressionsSupports an origin filter.

These endpoints return everything in one response and ignore limit and after: GET /domains, GET /api-keys, GET /topics, GET /contact-properties, and the lists of a contact's segments and topics.

Example

Fetch every email, 100 at a time:

Shell
curl "https://api.sooner.dev/emails?limit=100" \
  -H "Authorization: Bearer $SOONER_API_KEY"

curl "https://api.sooner.dev/emails?limit=100&after=01jcz8w3f2x9k4m7n6p5q2r1s0" \
  -H "Authorization: Bearer $SOONER_API_KEY"
TypeScript
async function* allEmails() {
  let after: string | undefined;
  while (true) {
    const url = new URL("https://api.sooner.dev/emails");
    url.searchParams.set("limit", "100");
    if (after) url.searchParams.set("after", after);

    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.SOONER_API_KEY}` },
    });
    const page = await res.json();

    yield* page.data;
    if (!page.has_more) return;
    after = page.data[page.data.length - 1].id;
  }
}

for await (const email of allEmails()) {
  console.log(email.id, email.status);
}

Email logs are kept for 7 to 365 days depending on your plan, so GET /emails only returns emails inside your retention window. See Log retention.