Get one contact by email

Search Documentation

Search across all developer documentation

contacts

Get one contact by email

GET /v1/contacts/{email}
Auth required api.contacts.view

Returns one contact by email address, including its custom attributes and explicit per-topic preferences. Returns 404 not_found when the address is not a contact in this org (the same response is returned when no contact list is synced, so the endpoint never leaks which case applies). Match is case-insensitive. Percent-encode @ as %40 (e.g. user%40example.com).

Path parameters

email string<email> required

Recipient address. Percent-encode @ as %40. Matched case-insensitively.

Responses

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

200 The contact record application/json
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.

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 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