Docs/API reference

Events API

Browse delivery, open, click, bounce, and complaint events captured for the team's sent mail.

Every request needs a bearer token and goes to a path under https://api.anypost.com/v1. See API conventions for the shared request, error, and pagination rules.

List events

GET /v1/events

Page through delivery, open, click, bounce, and complaint events for the authenticated team, newest-first. Operational events (admin bounces, queue rebinds, …) are excluded.

Time window

The start / end query params accept ISO 8601 timestamps. The default window is the last 24 hours. The window is clamped to your plan's event retention — a request for 30 days of history on a 3-day-retention plan silently narrows to the last 3 days rather than erroring, so the same call works as customers upgrade.

Filters

All filters are exact-match on the indexed columns. A recipient or email_id that doesn't match any stored row returns an empty list; we do not support substring search because the events table holds billions of rows and wildcard scans would be prohibitively expensive.

Pagination

Cursor pagination on (occurred_at, event_id). Echo the response's next_cursor back as after to fetch the next page. Cursors are opaque — do not parse them.

Parameters

limitintegerin query[optional]

Number of items to return.

afterstringin query[optional]

Opaque cursor from a previous response's next_cursor. Do not parse.

startstring (date-time)in query[optional]

ISO 8601 timestamp marking the start of the window (inclusive). Defaults to 24 hours before end. Will be moved forward if it falls outside your plan's retention window.

endstring (date-time)in query[optional]

ISO 8601 timestamp marking the end of the window (exclusive). Defaults to now. Future timestamps are clamped to now.

event_typestringin query[optional]

Restrict to events of this customer-facing type.

One of: email.sent, email.delivered, email.delayed, email.bounced, email.complained, email.suppressed, email.unsubscribed, email.opened, email.clicked.

recipientstringin query[optional]

Restrict to events delivered to this exact recipient address (lowercased server-side).

email_idstringin query[optional]

Restrict to events for the email message with this id. The canonical shape is email_<uuidv7> in hyphenated form (e.g. email_019e1972-e87e-7000-bf74-ba09e0ed0d62) — minted identically by SMTP and HTTP submissions. A malformed value returns an empty list without hitting the data store.

message_idstringin query[optional]

Restrict to events whose Message-ID: header matches this value exactly.

domainstringin query[optional]

Restrict to events sent from this domain. Pass the domain hostname (not the internal domain_<uuid> public id). Unknown domains return 400.

topicstringin query[optional]

Restrict to events whose originating send was tagged with this topic. Exact match against the lowercase [a-z0-9_.-]{1,64} shape enforced at send time. Values that don't match the shape are dropped from the filter set server-side (no 400) — the call returns the unfiltered slice rather than an error a customer can't act on.

campaignstringin query[optional]

Restrict to events whose originating send set this campaign value. Exact match, case-sensitive — campaign values are stored verbatim. A value that doesn't match any stored row returns an empty list.

template_idstringin query[optional]

Restrict to events whose originating send used this stored template. Exact match against the template_id passed to POST /email. A value that doesn't match any stored row returns an empty list.

ip_poolstringin query[optional]

Restrict to events for mail that egressed from this named IP pool — the ip_pool passed to POST /email. Only meaningful on accounts with dedicated IPs; on any other account every event has a null ip_pool and this filter returns an empty list.

Exact match against the lowercase [a-z0-9]([a-z0-9-]*[a-z0-9])? pool-name shape. A value outside that shape returns an empty list rather than being dropped from the filter set — unlike topic, a mistyped pool name must not silently widen to "all pools", which would answer "which of my IPs sent this?" with mail from every one of them.

Retiring a pool does not make its history unqueryable: events keep the ip_pool they were sent with, so this filter still returns them after the pool is gone.

tagsarray of stringin query[optional]

Restrict to events whose originating send carried any of these tags (hasAny — an event matches if it has at least one of the listed values, not all of them). Pass a comma-separated list (tags=onboarding,welcome) or repeat the parameter (tags[]=onboarding&tags[]=welcome). Up to 10 tags; values outside [A-Za-z0-9_-]{1,64} are dropped from the filter rather than erroring.

Example request

curl https://api.anypost.com/v1/events \
  -H "Authorization: Bearer $ANYPOST_API_KEY"

Response body

On success (200), the response body is:

dataarray of Event
has_moreboolean
next_cursorstring

May be null.

{
  "data": [
    {
      "id": "evt_8f2c1b3e6a5d4f7c9a3e1d2b4c5e6f7a",
      "type": "email.sent",
      "occurred_at": "string",
      "email_id": "email_019e1972-e87e-7000-bf74-ba09e0ed0d62",
      "message_id": "string",
      "from": "string",
      "from_domain": "string",
      "recipient": "string",
      "subject": "string",
      "campaign": "string",
      "ip_pool": "marketing",
      "template_id": "template_019e2d74-df2a-72ed-a105-7ce7500ef2bc",
      "topic": "marketing",
      "tags": [
        "onboarding",
        "welcome"
      ],
      "smtp_code": 0,
      "bounce_type": "permanent",
      "bounce_classification": "string",
      "attempt": 0,
      "tracking": {
        "bot": {
          "source": "google",
          "kind": "proxy"
        }
      }
    }
  ],
  "has_more": true,
  "next_cursor": "string"
}

Responses

StatusDescription
200Paginated list of events.
400Request validation failed.
401Missing or invalid credentials.