# Next-gen API v1.28

## 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_accounts` shares it with direct sub-accounts, `descendants` shares it with every account below at any depth, and `accounts` shares it only with the accounts you list.
- `shared_with_account_ids`: the accounts allowed to use the sender, with `accounts` only. 1 to 100 account IDs.
- `excluded_account_ids`: the accounts denied the sender, with `sub_accounts` or `descendants` only. Up to 100 account IDs. Under `descendants`, 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}` accepts `remove_tags`. With `false`, the tags in `tags` are added and no existing tag is removed. The default, `true`, keeps today's behavior: `tags` replaces the contact's tags.
- `POST /lists/{list_id}/contacts/tag` with `contact_ids` now tags every ID that is a contact of the list, and returns the others in `skipped_contact_ids`. Before, one unknown ID failed the whole request with a `400`.
- `POST /lists/{list_id}/contacts/tag` and `POST /lists/{list_id}/contacts/untag` count a repeated ID in `contact_ids` once.

## 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 type `POST /v2/emails` accepts (`csv`, `doc`, `docx`, `calendar`, `jpeg`, `pdf`, `png`, `xls` and `xlsx`).

`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

- `GET` and `PATCH /brands/default/domains/default` now return the `forward` domain.
- `PATCH /brands/default/domains/default` accepts a `forward` domain 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 `400` response now includes `expected`: the DNS record to create (`host`, `type` and `value`).
- A bounce domain that contains a port or user information is now refused.

## Fixes

- `GET /v2/emails/{email_id}` no longer returns a `500` when an email's custom attributes or headers are missing or `null`.
