API reference

Domains API

Reference for creating, listing, retrieving, updating, verifying and deleting sending domains.

The domains API manages the sending domains of the project that owns your API key. Every endpoint needs a full_access key. For the concepts, see Add a domain and DNS records.

The domain object

JSON
{
  "object": "domain",
  "id": "jh7b2k4d9x1m5q8r3t6v0w2y",
  "name": "mail.yourcompany.com",
  "status": "verified",
  "region": "us-east-1",
  "created_at": "2026-11-14T10:30:00.000Z",
  "open_tracking": false,
  "click_tracking": true,
  "records": [
    {
      "record": "DKIM",
      "name": "<token>._domainkey.mail.yourcompany.com",
      "type": "CNAME",
      "ttl": "Auto",
      "status": "verified",
      "value": "<value from the API>"
    }
  ]
}

status is not_started, pending, verified, temporary_failure or failed. A record that has a priority, such as MX, also has a priority field. The list endpoint leaves out records.

Create a domain

POST/domains

Adds a domain and starts generating its DNS records. Returns 201.

FieldTypeRequiredDescription
namestringYesA valid domain name, 3 to 253 characters. Stored in lowercase.
regionstringNoLeave out unless support told you otherwise.
open_trackingbooleanNoDefault false.
click_trackingbooleanNoDefault false.
Shell
curl -X POST https://api.sooner.dev/domains \
  -H "Authorization: Bearer $SOONER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "mail.yourcompany.com", "click_tracking": true }'
JSON
{
  "object": "domain",
  "id": "jh7b2k4d9x1m5q8r3t6v0w2y",
  "name": "mail.yourcompany.com",
  "status": "not_started",
  "region": "us-east-1",
  "created_at": "2026-11-14T10:30:00.000Z",
  "open_tracking": false,
  "click_tracking": true,
  "records": []
}

records is empty until the records are generated, usually within a few seconds. Fetch the domain again to read them.

Notable errors: validation_error for an invalid name, a domain already registered by you or by another team, or the Free plan's limit of 10 domains.

List domains

GET/domains

Returns every domain in the project, without records. The list is not paginated.

Shell
curl https://api.sooner.dev/domains \
  -H "Authorization: Bearer $SOONER_API_KEY"
JSON
{
  "object": "list",
  "data": [
    {
      "object": "domain",
      "id": "jh7b2k4d9x1m5q8r3t6v0w2y",
      "name": "mail.yourcompany.com",
      "status": "verified",
      "region": "us-east-1",
      "created_at": "2026-11-14T10:30:00.000Z",
      "open_tracking": false,
      "click_tracking": true
    }
  ]
}

Retrieve a domain

GET/domains/{id}

Returns one domain with its records.

Shell
curl https://api.sooner.dev/domains/jh7b2k4d9x1m5q8r3t6v0w2y \
  -H "Authorization: Bearer $SOONER_API_KEY"

The response is the domain object above. Notable errors: not_found.

Update a domain

PATCH/domains/{id}

Turns open and click tracking on or off. See Open and click tracking.

FieldTypeRequiredDescription
open_trackingbooleanNoRecord opens.
click_trackingbooleanNoRecord clicks.
Shell
curl -X PATCH https://api.sooner.dev/domains/jh7b2k4d9x1m5q8r3t6v0w2y \
  -H "Authorization: Bearer $SOONER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "open_tracking": true }'
JSON
{ "object": "domain", "id": "jh7b2k4d9x1m5q8r3t6v0w2y" }

Verify a domain

POST/domains/{id}/verify

Asks Sooner to check the DNS records now instead of waiting for the next automatic check. The result arrives afterward in the domain's status and in the domain.verified or domain.failed webhook.

Shell
curl -X POST https://api.sooner.dev/domains/jh7b2k4d9x1m5q8r3t6v0w2y/verify \
  -H "Authorization: Bearer $SOONER_API_KEY"
JSON
{ "object": "domain", "id": "jh7b2k4d9x1m5q8r3t6v0w2y" }

Delete a domain

DELETE/domains/{id}

Removes a domain. You can no longer send from it.

Shell
curl -X DELETE https://api.sooner.dev/domains/jh7b2k4d9x1m5q8r3t6v0w2y \
  -H "Authorization: Bearer $SOONER_API_KEY"
JSON
{ "object": "domain", "id": "jh7b2k4d9x1m5q8r3t6v0w2y", "deleted": true }

Notable errors: validation_error if scheduled emails from this domain still exist. Cancel them first. See Scheduling.

With the Node SDK

TypeScript
import { Resend } from "resend";

const resend = new Resend(process.env.SOONER_API_KEY, { baseUrl: "https://api.sooner.dev" });

const { data: domain } = await resend.domains.create({ name: "mail.yourcompany.com" });
await resend.domains.verify(domain!.id);
const { data: domains } = await resend.domains.list();