---
title: "Add a sending domain"
method: POST
path: "/email-domains"
tags: ["Email"]
---

# Add a sending domain

`POST /email-domains`

## Request

- Base URL: `https://api.hypamoon.com/api/v1`
- URL: `https://api.hypamoon.com/api/v1/email-domains`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://app.hypamoon.com/oauth/authorize`, token URL `https://api.hypamoon.com/oauth/token`, scopes: `sites:write`)

Makes one of this project's domains (connected or purchased) a sending domain. When its DNS is hosted here, we add the records ourselves: an existing SPF record is merged (never a second one), an MX record of the user's mailbox is never touched, and nothing is deleted, so the user's mail keeps working. When the user manages DNS elsewhere, records lists what they need to add there (state add_yourself). A DMARC record is only suggested when there is none. Then call verify_email_domain. Adding the same domain again returns the existing one.

## Request body

- object
  - `domain` string, required: A domain of this project (connected with connect_domain or bought with register_domain), like example.com.

## Response `200`

Already a sending domain of this project.

- object
  - `id` string, uuid, required
  - `domain` string, required
  - `status` 'pending' | 'verified' | 'failed', required
  - `test` boolean, required
  - `dns` 'managed' | 'manual', required: managed: the domain's DNS is here and we set the records; manual: the user adds them at their own DNS provider.
  - `records` object[], required
    - `type` string, required
    - `name` string, required
    - `value` string, required
    - `priority` integer
    - `state` 'set' | 'merged' | 'exists' | 'conflict' | 'add_yourself' | 'test_only', required: set: we added it; merged: added to the existing SPF record; exists: already right; conflict: not added, see note; add_yourself: add it at your DNS provider; test_only: test mode, shown but not added anywhere.
    - `note` string
  - `dmarc_suggestion` object, nullable, required: Only when the domain has no DMARC record yet. A suggestion; we never set it ourselves.
    - `type` 'TXT', required
    - `name` string, required
    - `value` string, required
  - `next_step` string, required
  - `checked_at` string, nullable, required
  - `verified_at` string, nullable, required
  - `created_at` string, required

## Other responses

- `201`: The sending domain, with its records.
- `400`: Bad Request: invalid_json.
- `401`: Unauthorized: unauthorized, missing_api_key, invalid_api_key, api_key_revoked, project_deleted.
- `403`: Forbidden: project_not_enabled, key_mode_mismatch, missing_scope, verification_required, mail_not_enabled.
- `404`: Not Found: not_found.
- `409`: Conflict: conflict.
- `422`: Unprocessable Content: validation_failed.
- `429`: Too Many Requests: rate_limited.
- `500`: Internal Server Error: internal_error.
- `502`: Bad Gateway: upstream_error.
- `503`: Service Unavailable: service_unavailable.

---

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