Sender sharing
An account can now share a sender with the accounts below it. POST /brands/default/senders and PATCH /brands/default/senders/{sender_id} accept three new fields:
sharing: who, beyond the owning account, may use the sender.none(the default) keeps it to the owning account,sub_accountsshares it with direct sub-accounts,descendantsshares it with every account below at any depth, andaccountsshares it only with the accounts you list.shared_with_account_ids: the accounts allowed to use the sender, withaccountsonly. 1 to 100 account IDs.excluded_account_ids: the accounts denied the sender, withsub_accountsordescendantsonly. Up to 100 account IDs. Underdescendants, excluding an account also excludes every account below it.
Both lists can only name accounts below the owning account.
Sender responses now include sharing, both lists, and account_id, the account that owns the sender. A sub-account sees the senders shared with it in GET /brands/default/senders, can read them by ID, and can use them wherever a sender_id is accepted. Only the owning account can change or delete a sender.
A sender created before this release reports sharing: "legacy". You can't set legacy: set another mode with PATCH to choose who can use the sender.
Email API rate limit
POST /v2/emails now accepts a limited number of submissions per account in any 60-second window (currently 200). The account is the one the request acts on: the token's own account, or the one named in account_id. Over the limit, the request gets a 429 whose detail gives the limit, the window and retry_in, the number of seconds to wait.
Every 429 from a rate-limited endpoint now also carries a Retry-After header with the same number of seconds.
GET /v2/emails/{email_id} and GET /v2/emails/{email_id}/render now enforce the rate limits they already declared.
Contacts
PATCH /lists/{list_id}/contacts/{contact_id}acceptsremove_tags. Withfalse, the tags intagsare added and no existing tag is removed. The default,true, keeps today's behavior:tagsreplaces the contact's tags.POST /lists/{list_id}/contacts/tagwithcontact_idsnow tags every ID that is a contact of the list, and returns the others inskipped_contact_ids. Before, one unknown ID failed the whole request with a400.POST /lists/{list_id}/contacts/tagandPOST /lists/{list_id}/contacts/untagcount a repeated ID incontact_idsonce.
Transactional email and attachment settings
usage_limits in GET /accounts/{account_id} and PATCH /accounts/{account_id} has two new fields:
use_transactional_emails: whether the account can send transactional emails.attachment_types: one setting per attachment typePOST /v2/emailsaccepts (csv,doc,docx,calendar,jpeg,pdf,png,xlsandxlsx).
GET returns the value that applies to the account: its own, or else the nearest account above it that sets one. With PATCH, a partner can only change a setting that is turned on for its own account, and only on an account it manages. A refused request changes nothing.
Domains
GETandPATCH /brands/default/domains/defaultnow return theforwarddomain.PATCH /brands/default/domains/defaultaccepts aforwarddomain that has the same hostname as a tracking or bounce domain that passes verification.- When a tracking or bounce domain fails verification, each error in the
400response now includesexpected: the DNS record to create (host,typeandvalue). - A bounce domain that contains a port or user information is now refused.
Fixes
GET /v2/emails/{email_id}no longer returns a500when an email's custom attributes or headers are missing ornull.