Skip to the documentation
Python

nextmail.traffic

Every method in this namespace: its signature, its parameters, what it returns and an example.

Methods

What happened to every message at the edge of the workspace: where the mail that arrived for your addresses went, and what the receiving server said about the mail you sent.

traffic.list()

List one page of the traffic log

Scopesemails:readPages through results
Signature
def list(    *,    limit: int | None = None,    cursor: str | None = None,    domain_id: str | None = None,    direction: TrafficDirection | None = None,    outcomes: Sequence[TrafficOutcome] | None = None,    address: str | None = None,    recipient: str | None = None,    since: datetime | str | None = None,    until: datetime | str | None = None,    api_key: str | None = None,    timeout: float | None = None,) -> Page[TrafficEventResource]

Returns one page of the traffic log, newest first: one entry for each message and recipient at each step it took in or out of the workspace. list_all collects every page into one list and iterate walks them lazily.

Inbound, each recipient of a message that arrived gets an entry saying where it went: filed in the inbox, spam, routed to a webhook, forwarded without a copy kept, refused with a bounce back to the sender, or dropped without one, and reason says why mail was refused or dropped. Outbound, each recipient of a message you sent or forwarded gets an entry for each answer from the receiving server: delivered, deferred while it keeps trying, bounced, complained, suppressed when it was never tried, rejected when it was refused before it left, and failed for a forward that could not be relayed.

An entry never changes once it is written, and the same step keeps the same id. Entries are kept for 30 days. detail holds the reply of the receiving server and remoteMta, reportingMta and sendingIp the servers on each side, and inbound entries carry the SPF, DKIM, DMARC, spam and virus verdicts the message arrived with.

Parameters

limitint

Page size, from 1 to 100. The server defaults to 25.

cursorstr

The nextCursor of the previous page. Leave it out for the first page.

domain_idstr

Keeps one domain, by the id domains.list returns. A domain the key does not reach is a 404.

directionTrafficDirection

inbound for mail that arrived, outbound for mail the workspace sent or forwarded. Left out, both, as far as the key's scopes reach.

outcomesSequence[TrafficOutcome]

Keeps these outcomes, such as ['bounced', 'deferred'].

addressstr

Keeps one of your addresses: the one the mail arrived for, or the one it was sent from.

recipientstr

Keeps one recipient, matched whole: the person you wrote to on an outbound entry, the address in the envelope on an inbound one.

sincedatetime | str

Keeps entries at or after this instant: a datetime or an ISO 8601 string.

untildatetime | str

Keeps entries before this instant. It must be later than since.

api_keystr

Overrides the client API key for this call only.

timeoutfloat

Seconds this call may take, the response included, before it raises NextmailNetworkError with is_timeout. It overrides the client's timeout for this call, and 0 turns the limit off.

Returns

Page[TrafficEventResource], a dict with items, hasMore and nextCursor. Each item has direction, outcome, reason, status, detail, sender, recipient, address, domain, the ids of the email and thread it belongs to, the servers on each side, verdicts, size and createdAt.

Example

from datetime import datetime, timedelta, timezone from nextmail import nextmail page = nextmail.traffic.list(    direction='outbound',    outcomes=['bounced', 'deferred'],    since=datetime.now(timezone.utc) - timedelta(days=1),) for entry in page['items']:    print(        entry['createdAt'],        entry['recipient'],        entry['outcome'],        entry['status'],        entry['detail'],    )

Notes

  • Outbound entries need emails:read and inbound ones threads:read. A key with only one of them sees that direction alone, and asking for the other direction is a 403 insufficient_scope.

  • A key or an app narrowed to particular addresses or domains sees the entries of the addresses it reaches and, for a whole domain it holds, every entry of that domain, including mail for addresses that do not exist.

  • The sender and the reply are stored encrypted, so they cannot be searched. Filter by address, recipient, outcomes, direction, domain_id and the time.

  • The cursor is opaque and holds where the last row sat. A cursor this list did not hand out is a 400 invalid_cursor.

Also available in

API
GET /traffic
TypeScript
traffic.list()
Ruby
traffic.list
PHP
traffic->list
Go
Traffic.List
Java
traffic().list
C#
Traffic.ListAsync
CLI
nextmail traffic list

traffic.list_all()

Collect the traffic log into one list

Scopesemails:readPages through results
Signature
def list_all(    *,    limit: int | None = None,    cursor: str | None = None,    domain_id: str | None = None,    direction: TrafficDirection | None = None,    outcomes: Sequence[TrafficOutcome] | None = None,    address: str | None = None,    recipient: str | None = None,    since: datetime | str | None = None,    until: datetime | str | None = None,    api_key: str | None = None,    timeout: float | None = None,) -> builtins.list[TrafficEventResource]

Walks every page of list and returns every entry that matches in one list, newest first. One request per page, with the same filters on each, so narrow it with since, domain_id or outcomes before collecting a busy workspace.

Parameters

limitint

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstr

Starts the walk after this cursor instead of the first page.

domain_idstr

Keeps one domain, by the id domains.list returns. A domain the key does not reach is a 404.

directionTrafficDirection

inbound for mail that arrived, outbound for mail the workspace sent or forwarded. Left out, both, as far as the key's scopes reach.

outcomesSequence[TrafficOutcome]

Keeps these outcomes, such as ['bounced', 'deferred'].

addressstr

Keeps one of your addresses: the one the mail arrived for, or the one it was sent from.

recipientstr

Keeps one recipient, matched whole: the person you wrote to on an outbound entry, the address in the envelope on an inbound one.

sincedatetime | str

Keeps entries at or after this instant: a datetime or an ISO 8601 string.

untildatetime | str

Keeps entries before this instant. It must be later than since.

api_keystr

Overrides the client API key for every page of this walk.

timeoutfloat

Seconds this call may take, the response included, before it raises NextmailNetworkError with is_timeout. It overrides the client's timeout for this call, and 0 turns the limit off.

Returns

list[TrafficEventResource] holding every matching entry.

Example

from nextmail import nextmail bounced = nextmail.traffic.list_all(    outcomes=['bounced'], since='2026-10-01T00:00:00Z', limit=100) print({entry['recipient'] for entry in bounced})

Notes

  • If any page fails, the call raises and the entries already fetched are discarded.

  • Outbound entries need emails:read and inbound ones threads:read, as on list.

Also available in

API
GET /traffic
TypeScript
traffic.listAll()
Ruby
traffic.list_all
PHP
traffic->listAll
Go
Traffic.ListAll
Java
traffic().listAll
C#
Traffic.ListAllAsync

traffic.iterate()

Stream the traffic log one entry at a time

Scopesemails:readPages through results
Signature
def iterate(    *,    limit: int | None = None,    cursor: str | None = None,    domain_id: str | None = None,    direction: TrafficDirection | None = None,    outcomes: Sequence[TrafficOutcome] | None = None,    address: str | None = None,    recipient: str | None = None,    since: datetime | str | None = None,    until: datetime | str | None = None,    api_key: str | None = None,    timeout: float | None = None,) -> Iterator[TrafficEventResource]

Returns a generator that yields one entry at a time, newest first, and requests the next page only once the current one is used up. Nothing is fetched until the loop starts, and breaking out of it stops the requests.

Parameters

limitint

Page size for each request, from 1 to 100. The server defaults to 25.

cursorstr

Starts the walk after this cursor instead of the first page.

domain_idstr

Keeps one domain, by the id domains.list returns. A domain the key does not reach is a 404.

directionTrafficDirection

inbound for mail that arrived, outbound for mail the workspace sent or forwarded. Left out, both, as far as the key's scopes reach.

outcomesSequence[TrafficOutcome]

Keeps these outcomes, such as ['bounced', 'deferred'].

addressstr

Keeps one of your addresses: the one the mail arrived for, or the one it was sent from.

recipientstr

Keeps one recipient, matched whole: the person you wrote to on an outbound entry, the address in the envelope on an inbound one.

sincedatetime | str

Keeps entries at or after this instant: a datetime or an ISO 8601 string.

untildatetime | str

Keeps entries before this instant. It must be later than since.

api_keystr

Overrides the client API key for every page of this walk.

timeoutfloat

Seconds this call may take, the response included, before it raises NextmailNetworkError with is_timeout. It overrides the client's timeout for this call, and 0 turns the limit off.

Returns

Iterator[TrafficEventResource], a generator yielding one entry per step.

Example

from nextmail import nextmail for entry in nextmail.traffic.iterate(direction='inbound', outcomes=['refused', 'dropped']):    print(entry['recipient'], entry['reason'], entry['detail'])

Notes

  • The generator is lazy, so an abandoned loop costs only the pages you consumed.

  • Outbound entries need emails:read and inbound ones threads:read, as on list.

Also available in

API
GET /traffic
TypeScript
traffic.iterate()
Ruby
traffic.iterate
PHP
traffic->iterate
Go
Traffic.Iterate
Java
traffic().iterate
C#
Traffic.IterateAsync