> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sequenzy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrade Sending Domain DNS

> Move a verified domain onto the current DNS records without removing it

Start a one-time, optional upgrade of a sending domain to our new DNS
structure. It is recommended: it improves deliverability and security, and
Sequenzy can later change keys and sending infrastructure without you editing
DNS again. The domain is
not removed: it keeps sending on its current records while the upgrade is in
progress, and sender profiles, sequences and tracking stay as they are.

`website.dnsUpgrade.status` tells you whether a domain can start. The upgrade
is being offered to domains gradually; until it reaches yours, `status` is
`unavailable`. It is
`available` for a verified domain on the previous record set (a DKIM TXT at
`sequenzy._domainkey` and a `send` return path, for example), including older
domains that only sent through Amazon SES. Such a domain needs a working DMARC
record first: without one, this endpoint answers `400` with "Add a DMARC record
for this domain before upgrading its DNS records." and the status is
`unavailable`. Domains that use Amazon's three-CNAME DKIM records, and domains
in the middle of an earlier records migration, are `unavailable` too. Every
`unavailable` domain gets a `400` from this endpoint.

## How it works

1. Call this endpoint. The response lists four CNAMEs in
   `website.dnsUpgrade.records`.
2. Publish them next to your current records. Remove nothing yet: your current
   records keep the domain verified and sending until the switch.
3. Sequenzy checks the new records with each verification. Call [Verify
   Sending Domain](./verify) to check right away.
4. About an hour after the required records (`dkim` and `return_path`) are
   visible on public DNS (Google and Cloudflare resolvers), the domain
   switches by itself. The wait lets cached "does not exist" answers expire;
   verifying checks right away but does not skip it. Sequenzy prepares the
   domain's sending setup separately and switches only once it is confirmed, so
   sending is normally not interrupted and no emails are held. If that isn't
   possible for a domain, emails sent through Amazon SES can be held for a few
   minutes while SES confirms the new setup, then they go out. Some domains get
   a new DKIM key during the upgrade; you still add the same four CNAMEs.
5. `website.dnsUpgrade.status` becomes `completed` and `oldRecords` lists the
   records the domain no longer uses. Keep them until `deleteOldRecordsAfter`,
   8 days after the switch; deleting them after that is optional. Before the switch,
   `replacedRecords` lists the same records. Each verification marks a record
   `removed` once it is gone from public DNS. For an older SES-only domain
   these include the old return path records (MX and TXT at
   `send.mail.example.com`) and the DKIM TXT; your DMARC record stays.

| Purpose | Example name | Example value | Required |
| - | - | - | - |
| `dkim` | `sq1._domainkey.mail.example.com` | `sq1.k7f3q2ab.d.sequenzydns.com` | Yes |
| `dkim_spare` | `sq2._domainkey.mail.example.com` | `sq2.k7f3q2ab.d.sequenzydns.com` | No |
| `return_path` | `rp.mail.example.com` | `r1.k7f3q2ab.d.sequenzydns.com` | Yes |
| `ses_return_path` | `rp2.mail.example.com` | `r2.k7f3q2ab.d.sequenzydns.com` | No |

Publish all four, and set every CNAME to DNS only on Cloudflare. The values
differ for each domain; always publish the ones returned. Once started, an
upgrade can't be cancelled: until the switch it changes nothing, and the
domain keeps sending on its current records.

This endpoint requires the `websites:write` scope.

CLI: `sequenzy websites upgrade-dns mail.example.com`.
MCP: `upgrade_sending_domain_dns`.

## Request

<ParamField path="domain" type="string" required>
  Configured sending domain.
</ParamField>

<ParamField body="mailFromPrefix" type="string">
  Return-path subdomain label for the new records, 1 to 63 characters.
  Defaults to `rp`; if `rp` is taken or already has DNS records, `rp1`, then
  `sqrp`. A label that already has DNS records, or is the current return path
  or the tracking domain label, is rejected with `400`, and `inbound` is not
  allowed. The SES return path is this label followed by `2` (`rp2` by
  default), moving to `bounces` or `sesbounces` if that name is in use. The
  body is optional.
</ParamField>

```bash theme={null}
curl -X POST "https://api.sequenzy.com/api/v1/websites/mail.example.com/dns-upgrade" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

## Responses

<ResponseField name="website.dnsUpgrade" type="object">
  `status` is `in_progress`, `startedAt` is set and `records` lists the CNAMEs
  to publish, each with `purpose`, `type`, `name`, `value`, `required`,
  `status` (`pending`, `verified` or `misconfigured`) and, when known, a
  `diagnostic` explaining why it is not verified yet.
</ResponseField>

| Status | When |
| - | - |
| `400` | The domain is not verified, verification is paused, it already uses the current records, its record set can't be upgraded in place, an older SES-only domain has no working DMARC record, or `mailFromPrefix` is invalid or already in use |
| `404` | The domain is not a sending domain of this company |
| `409` | An upgrade is already in progress, or the domain changed during the request; read the website and retry |
| `422` | `mailFromPrefix` is not a string of 1 to 63 characters |
| `500` | The new records could not be prepared; nothing changed, try again in a few minutes |

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "website": {
      "id": "domain_abc123",
      "domain": "mail.example.com",
      "status": "verified",
      "dnsVerified": true,
      "readyToSend": true,
      "dnsUpgrade": {
        "status": "in_progress",
        "startedAt": "2026-10-16T10:00:00.000Z",
        "records": [
          {
            "purpose": "dkim",
            "type": "CNAME",
            "name": "sq1._domainkey.mail.example.com",
            "value": "sq1.k7f3q2ab.d.sequenzydns.com",
            "required": true,
            "status": "pending"
          },
          {
            "purpose": "dkim_spare",
            "type": "CNAME",
            "name": "sq2._domainkey.mail.example.com",
            "value": "sq2.k7f3q2ab.d.sequenzydns.com",
            "required": false,
            "status": "pending"
          },
          {
            "purpose": "return_path",
            "type": "CNAME",
            "name": "rp.mail.example.com",
            "value": "r1.k7f3q2ab.d.sequenzydns.com",
            "required": true,
            "status": "pending"
          },
          {
            "purpose": "ses_return_path",
            "type": "CNAME",
            "name": "rp2.mail.example.com",
            "value": "r2.k7f3q2ab.d.sequenzydns.com",
            "required": false,
            "status": "pending"
          }
        ],
        "completedAt": null,
        "replacedRecords": [
          { "type": "TXT", "name": "sequenzy._domainkey.mail.example.com", "removed": false },
          { "type": "CNAME", "name": "send.mail.example.com", "removed": false }
        ],
        "oldRecords": null,
        "deleteOldRecordsAfter": null
      }
    }
  }
  ```

  ```json 400 theme={null}
  {
    "success": false,
    "error": "Verify this domain before upgrading its DNS records."
  }
  ```

  ```json 400 (no DMARC record) theme={null}
  {
    "success": false,
    "error": "Add a DMARC record for this domain before upgrading its DNS records."
  }
  ```

  ```json 404 theme={null}
  {
    "success": false,
    "code": "SENDING_DOMAIN_NOT_CONFIGURED",
    "error": "Sending domain not configured",
    "title": "Sending domain not configured",
    "description": "The domain \"mail.example.com\" has not been added as a sending domain for this company, so it cannot be checked or verified yet.",
    "resolution": "Call add_sending_domain with domain \"mail.example.com\" first, publish the DNS records it returns (DKIM, the bounce records described by website.bounceRecords, and DMARC when present), then call verify_sending_domain after DNS changes propagate.",
    "docsUrl": "https://docs.sequenzy.com/api-reference/websites/create",
    "details": {
      "domain": "mail.example.com"
    }
  }
  ```

  ```json 409 theme={null}
  {
    "success": false,
    "error": "This domain's DNS upgrade is already in progress."
  }
  ```
</ResponseExample>

## After the switch

`GET /api/v1/websites/{domain}` then returns:

```json theme={null}
{
  "dnsUpgrade": {
    "status": "completed",
    "startedAt": null,
    "records": null,
    "completedAt": "2026-10-16T12:00:00.000Z",
    "replacedRecords": null,
    "oldRecords": [
      { "type": "TXT", "name": "sequenzy._domainkey.mail.example.com", "removed": true },
      { "type": "CNAME", "name": "send.mail.example.com", "removed": false }
    ],
    "deleteOldRecordsAfter": "2026-10-24T12:00:00.000Z"
  }
}
```

The new records now appear in `website.dnsRecords.platformDnsRecords` and
`website.bounceRecords`. `completed` is shown for 30 days after the switch;
after that, `status` is `unavailable` because the domain already uses the
current records.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.