---
title: "Add a domain"
method: POST
path: "/domains"
tags: ["Domains"]
---

# Add a domain

`POST /domains`

## Request

- Base URL: `https://api.mepmail.dev`
- URL: `https://api.mepmail.dev/domains`
- Auth: HTTP bearer

Adds a sending domain and returns the DNS records to publish.

## Request body

- CreateDomainRequest
  - `name` string, required
  - `region` 'us-east-1': SES region of the identity, one of the regions this deployment serves (the values listed here; the first is the default). Any other region is rejected with 422. A domain has one region: to move it, delete and re-add it.
  - `custom_return_path` string
  - `open_tracking` boolean: Inject a tracking pixel served from the tracking subdomain and record email.opened events. Off by default.
  - `click_tracking` boolean: Rewrite links to redirect through the tracking subdomain and record email.clicked events. Off by default.
  - `tracking_subdomain` string: DNS label of the branded tracking host, e.g. "links" for links.<domain>. Setting it adds a Tracking CNAME to records[]; links are tracked through it once that CNAME resolves. Required on MepMail Cloud to turn tracking on.

## Response `200`

Domain created

- CreateDomainResponse
  - `id` string, uuid, required
  - `name` string, required
  - `status` string, required
  - `created_at` string, required
  - `region` string, required
  - `open_tracking` boolean, required
  - `click_tracking` boolean, required
  - `tracking_subdomain` string, nullable, required
  - `capabilities` object, required
    - `sending` string, required
    - `receiving` string, required
  - `records` object[], required
    - `record` string, required: Which record this is: DKIM, SPF (the MAIL FROM MX and TXT rows), DMARC, or Tracking (the branded tracking CNAME, present once a tracking subdomain is set). Only the DKIM and SPF rows gate sending.
    - `name` string, required
    - `type` string, required
    - `ttl` string, required
    - `status` string, required: not_started | pending | verified | failed. DKIM and SPF rows combine public DNS with the provider's verification: found in DNS but not yet confirmed reads pending, a different published value reads failed, no record reads not_started. DMARC reads verified when a policy covers the domain — its own or a parent domain's (see inherited_from) — and not_started when none does. Tracking reads verified once its CNAME resolves.
    - `value` string, required
    - `priority` number
    - `live` 'found' | 'missing' | 'mismatch' | 'unknown': What public DNS answers for this record right now: found, missing, mismatch (a different value is published) or unknown (the lookup did not conclude). Omitted when no live check ran (the create response).
    - `detail` string: One sentence explaining a row that is not verified: found but awaiting the provider, the value that is published instead, no record at the name, or which parent DMARC policy covers the domain. Omitted when there is nothing to add.
    - `inherited_from` string: DMARC only: the _dmarc name whose policy covers this domain when it has no record of its own (RFC 7489 organizational-domain fallback).
    - `policy` 'none' | 'quarantine' | 'reject': DMARC only, alongside inherited_from: the inherited policy's p= value.

## Other responses

- `401`: Missing, malformed or invalid API key
- `403`: Plan domain limit reached
- `409`: Domain already added
- `422`: Validation error
- `429`: Too many domains created recently, or the rate limit was exceeded (see Retry-After)

---

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