List a domain's grouped sending sources

Search Documentation

Search across all developer documentation

domain-auth

List a domain's grouped sending sources

GET /v1/domain-auth/domains/{domain}/sources
Auth required api.domain_auth.view

Returns the sources sending as this domain, busiest first, each with its classification, confidence, review state and any open finding — including the literal DNS record that clears the finding where one exists.

The five effective classes are not five words for "suspicious", and conflating them is the most damaging mistake available on this surface. sendops is the org's own SES. sendops_unaligned is also their own SES, failing alignment — nearly always a missing custom MAIL FROM or a DKIM token rotated without republishing the CNAMEs, i.e. a configuration fault to fix rather than an intruder. sendops_relayed is their own mail arriving via a host that is not their SES, which is what a forwarder or a mail-security scanner looks like. known is a third party they have confirmed. Only unknown is a genuine stranger, and most of those are a third party nobody has registered yet.

review_state says why a row is outstanding and therefore what would end it. awaiting_decision is the only set a decision can clear; open_finding rows are already decided or were never the customer's to decide, and no decision will move them.

traffic_partial means the pass rates were computed from a capped scan of this domain's sending IPs, so a source reporting no traffic may still have some. Do not read an absent traffic as "sent nothing" while it is true.

Path parameters

domain string required

The domain, by NAME (acme.com). A UUID is also accepted. Matched case-insensitively, and scoped to the calling org — a domain belonging to another org is a 404, never a 403.

Query parameters

limit integer optional

Page size (1–200). Default 50.

cursor string optional

Opaque cursor returned from the previous page.

class string enum optional

Narrow to one effective class.

review_state string enum optional

Narrow to what is outstanding and why. Applied after the page is read, because review_state is derived rather than stored — so a filtered page may hold fewer rows than limit without meaning there are no more.

Responses

Errors follow the RFC 7807 problem format — see the error reference.

200 Cursor-paginated list of grouped sending sources application/json
data array<object> required

Each entry in data:

id string<uuid> required
display_name string required

The customer's label, else a provider name, else the raw group key. Never a bare IP.

group_kind string enum required

What the row is keyed on. provider is a fingerprint and survives IP churn; prefix is a /24 or /48 and will churn.

One of: provider, asn, prefix

group_key string required
class string enum required

What SendOps classified, before the customer's decision.

One of: sendops, sendops_relayed, sendops_unaligned, unknown

effective_class string enum required

The classification resolved against the decision — the field to reason with. sendops and sendops_unaligned cannot be overridden by a decision in either direction.

One of: sendops, sendops_relayed, sendops_unaligned, known, unknown

confidence string enum required

How strongly the evidence supports class. certain is reachable only by a DKIM selector match — nothing inferred from an IP range reaches it, because SES is shared infrastructure.

One of: certain, high, medium, low

status string enum required

One of: unreviewed, confirmed, rejected

review_state string enum required

One of: none, awaiting_decision, open_finding

alerts boolean required

Whether this source raises the customer's attention. A REJECTED source still alerts.

decided_at string<date-time> optional
first_seen_at string<date-time> optional
last_seen_at string<date-time> optional
volume_30d integer<int64> required
ip_count integer required
network_name string optional

DESCRIBES the group; never IDENTIFIES it. An AS name says who announces the route, so treating it as the sender's identity would scope a decision to an entire cloud provider.

top_host string optional
top_host_others integer optional
traffic object | null required
diagnosis object | null required
annotations array<object> optional

What we can say this source IS, as opposed to what is wrong with it (SND-1395). Absent or empty for most rows, and that is the correct answer rather than a gap: a group nothing matched has nothing said about it. Derived at read time, never stored, and it gates nothing — no verdict, alert, class or review state reads it.

Each entry in annotations:

kind string enum required

identity names what a sender is. infrastructure describes the machinery a message travelled over. caution warns that an identification is weaker than it looks and DEMANDS NO ACTION — it carries no doc_url on purpose, because the only way to "complete" it would be to confirm the source, which is the mistake it exists to prevent. gap names a configuration hole and links the vendor's fix.

One of: identity, infrastructure, caution, gap

title string required

A short noun phrase. Never an instruction.

body string required

One plain sentence, situation first, written for someone who has never heard the word "alignment".

doc_url string optional

The VENDOR's own page where one exists, empty otherwise. Empty is common, and on a caution it is deliberate.

confidence string enum required

confirmed means a vendor document or our own live DNS says it; strong means several credible secondary sources agree. Shown as-is — anything weaker is folklore and never reaches a table, so there is no third value and no rounding up.

One of: confirmed, strong

shared_pool object | null optional
traffic_partial boolean required

The pass rates were computed from a capped scan of this domain's sending IPs, so a source reporting no traffic may still have some. Do not read an absent traffic block as "sent nothing" while this is true.

pagination object required

Fields of pagination:

has_more boolean required
next_cursor string | null optional
401 Missing, malformed, or unknown API key application/problem+json
403 Key lacks the required scope or plan limit violated application/problem+json
404 Resource not found application/problem+json
422 Query parameter or path value failed validation application/problem+json
429 Per-org rate limit exceeded application/problem+json
500 Unexpected server-side failure. The code is internal_error. The request_id field can be quoted to SendOps support to investigate. application/problem+json