---
title: "Assign a sending identity to a stream"
method: PATCH
path: "/api/domains/{id}"
tags: ["Domains"]
---

# Assign a sending identity to a stream

`PATCH /api/domains/{id}`

## Request

- Base URL: `https://api.sendly.now`
- URL: `https://api.sendly.now/api/domains/{id}`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `better-auth.session_token`
  - OAuth 2 (authorization code, authorization URL `https://app.sendly.now/api/auth/oauth2/authorize`, token URL `https://app.sendly.now/api/auth/oauth2/token`, scopes: `domains:write`)

Assign this identity to transactional or marketing traffic, make it the project's default for that stream, or give it the from-address a send on that stream uses when it names none.

Streams are enforced, not labelled: once an identity is assigned, a send of the other kind from it is refused with 403. That is what keeps a campaign's complaint rate off the identity your password resets go out on. An identity with no stream (`stream: null`, and the state of every domain added before this existed) carries both.

At most one identity per (project, stream) is the default; setting `streamDefault` demotes whichever held it. `defaultFromAddress` has to be an address on this identity's own host — a default pointing anywhere else would go out unsigned by the name in the From header.

`defaultFromName` is the sender name recipients see when a send from this identity names none. Unlike the other three it belongs to the identity rather than the stream, so it applies to every send leaving on this host and survives unassigning. Every field is optional and an omitted one is left alone.

Requires the `domains:write` scope — Add and remove sending domains, and trigger verification.

## Path parameters

- `id` string, uuid, required

## Request body

- AssignDomainStream: Body for PATCH /api/domains/{id}.
  - `defaultFromAddress` string, email, nullable: The address a send on this stream uses when it names none. Must be on this identity's own host — a default pointing elsewhere would go out unsigned by the name in the From header.
  - `defaultFromName` string, nullable: The name recipients see beside any address on this identity when a send names none, e.g. `Acme`. Independent of `stream`. An empty string or `null` clears it, and the project name is used instead.
  - `stream` 'TRANSACTIONAL' | 'MARKETING' | 'null', nullable: Which traffic this identity carries. `null` unassigns it, returning it to serving every stream and clearing its default flag and default address.
  - `streamDefault` boolean: Make this the project's default identity for its stream, demoting whichever held it.

## Response `200`

Updated sending identity

- object
  - `data` Domain, required: A sending identity: one domain registered with SES, with its own DKIM keys, its own MAIL FROM and its own reputation.
    - `createdAt` string, date-time, required: ISO 8601 datetime string
    - `defaultFromAddress` string, nullable: The address a send on this stream uses when it names none. Always on this identity's own host.
    - `defaultFromName` string, nullable: The display name recipients see beside any address on this identity when a send names none, e.g. `Acme` in `Acme <receipts@mail.example.com>`. A send's own `name` and its template's from-name both win over it; `null` falls back to the project name.
    - `dkimStatus` 'NOT_CHECKED' | 'PENDING' | 'VERIFIED' | 'FAILED' | 'null', nullable: Result of the last DNS check for this record type.
    - `dkimTokens` string[], nullable: SES DKIM tokens to publish as CNAME records before the domain can verify.
    - `dmarcStatus` 'NOT_CHECKED' | 'PENDING' | 'VERIFIED' | 'FAILED' | 'null', nullable: Result of the last DNS check for this record type.
    - `domain` string, required: The bare domain, e.g. `mail.acme.com`.
    - `id` string, uuid, required
    - `lastHealthCheckAt` string, date-time, nullable: ISO 8601 datetime string
    - `mailFromDomain` string, nullable: Custom MAIL FROM subdomain SES has on record (normally `sendly.<domain>`).
    - `mailFromDomainStatus` 'Pending' | 'Success' | 'Failed' | 'TemporaryFailure' | 'NotConfigured' | 'null', nullable: SES custom MAIL FROM setup state. Only `Success` means SES is using it.
    - `projectId` string, uuid, required
    - `receivingEnabled` boolean, required: Whether inbound mail for this domain is routed to Sendly mailboxes.
    - `region` string, nullable
    - `spfStatus` 'NOT_CHECKED' | 'PENDING' | 'VERIFIED' | 'FAILED' | 'null', nullable: Result of the last DNS check for this record type.
    - `stream` 'TRANSACTIONAL' | 'MARKETING' | 'null', nullable: Which traffic this identity carries. `null` means unassigned, and an unassigned identity carries every stream — the behaviour of every domain added before per-stream identities. A send whose stream does not match an ASSIGNED identity is refused.
    - `streamDefault` boolean: Whether this is the project's default identity for its stream — the one a send picks when it names no from-address. At most one per (project, stream).
    - `updatedAt` string, date-time, required: ISO 8601 datetime string
    - `verified` boolean, required
  - `success` true, required

## Other responses

- `400`: Validation error
- `401`: Unauthorized — missing or invalid auth
- `403`: Forbidden — insufficient permissions or project disabled
- `404`: Resource not found
- `429`: Rate limit or billing limit exceeded
- `500`: Internal server error

---

[API](https://skmtc.dev/sendly/apis/sendly-api.md) · [All operations](https://skmtc.dev/sendly/apis/sendly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sendly/apis/sendly-api/revisions/ce7cfb7f7c7e?raw)
