List contacts

Search Documentation

Search across all developer documentation

contacts

List contacts

GET /v1/contacts
Auth required api.contacts.view

Returns the calling org's contacts, newest-first, with optional filters. Contacts mirror the recipients in your Amazon SES contact list; SendOps keeps them in sync but never sends on your behalf — sending stays on SendEmail with ListManagementOptions.

Recipient emails are returned in full: api.contacts.view is itself the PII gate, and the contact list is operator-managed by definition.

Filters compose with AND:

  • topic — only contacts with an explicit preference row for the named topic (use the name from /v1/topics).
  • subscription_status — OPT_IN or OPT_OUT, scoping the topic filter to that status. Requires topic; sent on its own it returns 422 validation_failed.
  • unsubscribe_all — true/false master opt-out flag.
  • attribute_key + attribute_value — JSONB containment match on a custom attribute (string equality on the value). Both must be sent together.

Cursors are opaque base64; stale or malformed cursors silently fall back to page 1. When no contact list is synced yet, an empty page is returned (use /v1/contact-list to detect that state explicitly).

Query parameters

limit integer optional

Page size (1–200). Default 50.

cursor string optional

Opaque cursor returned from the previous page.

topic string optional

Filter to contacts with a preference for this topic (topic name).

subscription_status string enum optional

Scope the topic filter to this status. Requires topic.

unsubscribe_all boolean optional

Filter by the contact's master opt-out flag.

attribute_key string optional

Custom attribute key to match. Must be sent with attribute_value.

attribute_value string optional

Custom attribute value to match (string equality). Must be sent with attribute_key.

ownership string enum optional

Contact ownership filter. probable_copy returns the contacts that the SES contact-list sync copied into this workspace from an SES contact list it shares with other workspaces on the same AWS account, and that nothing since shows this workspace using: not created in SendOps, no external_id, no attribute written, no activity, on none of your Lists, no topic preference or unsubscribe_all set in SendOps, never mailed by this workspace, no visitor id. owned returns every other contact. Every contact of the workspace linked to the SES contact list is owned. This only suggests; nothing is archived. Available only to workspaces on SendOps-owned contacts: any other gets 422 with code ownership_report_unavailable. A value other than the two below is 422 validation_failed. Each request classifies at most 50,000 probable copies. Past that, probable_copy returns the first 50,000 by contact id and owned also includes the rest.

Responses

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

200 Cursor-paginated list of contacts, newest-first application/json
data array<object> required

Each entry in data:

email string<email> required
unsubscribe_all boolean required

Master opt-out — when true the contact receives no topic email.

attributes object required

Custom attribute map as stored in SES. Always an object, never null.

topic_preferences array<object> required

The contact's explicit per-topic choices. Topics the contact has never set are absent — for those, the topic's default_subscription_status applies, and SendOps enforces it at send time. So an absent topic does not mean "will be mailed": on a topic defaulting to OPT_OUT, a contact with no entry here has not consented and will not be sent that topic's mail.

Each entry in topic_preferences:

topic_name string required

The topic's name (see /v1/topics).

subscription_status string enum required

One of: OPT_IN, OPT_OUT

created_at string<date-time> required
updated_at string<date-time> required
ses_absent_since string<date-time> optional

When the customer's SES contact list stopped reporting this contact. Set only for the workspace that owns the SES contact list. The contact is still active and mailable in SendOps; omitted when it is on the list, or was never on it.

ownership string enum optional

Whether this workspace uses the contact (owned) or it is probably just a copy from an SES contact list shared with other workspaces (probable_copy). See the ownership filter on GET /v1/contacts. Present only for workspaces on SendOps-owned contacts, on GET /v1/contacts and GET /v1/contacts/{email}.

One of: owned, probable_copy

ownership_reasons array<string enum> optional

Every signal behind ownership. [discovered_by_sync_only] for a probable copy; for an owned contact, each of ses_linked_org, created_here, external_id, attributes, activities, list_member, preference_set_here, sent_here and visitor_id that holds.

ses_sync object optional

Present ONLY while the contact has not reached the customer's SES account yet; absent means synced. A 2xx on a contact write means SendOps has accepted and durably stored the change, not that SES has it — writes are mirrored afterwards, paced against the AWS account-wide budget of one contact request per second. Everything user-visible (segments, consent filtering, exports, sends) reads SendOps' own copy, so a pending mirror holds nothing back.

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
422 A query parameter, path value or body field failed validation. The body is a validation_failed Problem. When the refusal is about a reference — a segment key, template slug, topic or attribute name the organization does not have — it additionally carries validation_code, field, line/column, missing, candidates and next_step, so a client can correct the call without a second round of guessing. See ValidationProblem. 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