Create or replace a contact
Full create-or-replace: if the contact exists it is fully replaced; if
it does not exist it is created. Returns 201 on creation and 200
on update.
All fields are replaced (not merged): omitted attributes are
cleared, omitted topic_preferences revert to the list default,
unsubscribe_all is set to the supplied value.
lists, when present, replaces the contact's static-List membership
exactly (an empty array clears all memberships). When lists is
absent, list membership is left unchanged.
Supports the Idempotency-Key header.
Path parameters
email string<email> required Recipient address. Percent-encode @ as %40. Matched case-insensitively.
Request body
Content type: application/json
attributes object optional Replaces the contact's attribute map entirely. Validated against the registry.
unsubscribe_all boolean optional Master opt-out. Defaults to false.
topic_preferences array<object> optional 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
lists array<string<uuid>> | null optional Exact static-List membership. A present empty array clears all
memberships; an absent (null) array leaves membership untouched.
Responses
Errors follow the RFC 7807 problem format — see the error reference.
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 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
lists array<string<uuid>> required Ids of the static Lists the contact currently belongs to. Always an array.
created_at string<date-time> required updated_at string<date-time> required 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.
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 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
lists array<string<uuid>> required Ids of the static Lists the contact currently belongs to. Always an array.
created_at string<date-time> required updated_at string<date-time> required 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.
code is internal_error. The
request_id field can be quoted to SendOps support to investigate.
application/problem+json code is
upstream_unavailable; the status is 503 when the call failed and
504 when it exceeded our deadline.
Retryable. Always accompanied by Retry-After. On a 504 the
outcome is genuinely unknown (the write may have reached SES), so
retries of a non-idempotent call should carry an Idempotency-Key.
The detail string is deliberately generic: the underlying AWS error
describes the customer's own account and is recorded in SendOps logs
against the request_id, not returned here.
application/problem+json code is
upstream_unavailable; the status is 503 when the call failed and
504 when it exceeded our deadline.
Retryable. Always accompanied by Retry-After. On a 504 the
outcome is genuinely unknown (the write may have reached SES), so
retries of a non-idempotent call should carry an Idempotency-Key.
The detail string is deliberately generic: the underlying AWS error
describes the customer's own account and is recorded in SendOps logs
against the request_id, not returned here.
application/problem+json