BETA
Skip to content

Domains

Manage the sending domains used by your team. Emails can only be sent from addresses on a verified domain.

Base URL: https://app.krafter.dev/api/v1

Add Domain

Registers a new sending domain and returns the DNS records you must configure.

POST /domains

Required scope: domains:manage

Request Body

FieldTypeRequiredDescription
domainstringYesThe domain name (e.g. example.com).
return_pathstringNoSubdomain prefix used as the custom MAIL FROM (e.g. "send" produces send.example.com). Defaults to "send". Must start with a letter, contain only letters/digits/hyphens, and be at most 63 characters.

Example Request

bash
curl -X POST https://app.krafter.dev/api/v1/domains \
  -H "Authorization: Bearer kr_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "example.com",
    "return_path": "send"
  }'

Example Response

json
// 201 Created
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "status": "pending",
    "verified_at": null,
    "created_at": "2026-01-15T10:00:00Z",
    "dns_records": [
      {
        "type": "TXT",
        "name": "_amazonses.example.com",
        "value": "abc123...",
        "ttl": "Auto",
        "priority": null,
        "purpose": "Domain verification — proves you own this domain",
        "required": true,
        "category": "verification"
      },
      {
        "type": "CNAME",
        "name": "token1._domainkey.example.com",
        "value": "token1.dkim.amazonses.com",
        "ttl": "Auto",
        "priority": null,
        "purpose": "DKIM — cryptographic email signature",
        "required": true,
        "category": "delivery"
      },
      {
        "type": "CNAME",
        "name": "token2._domainkey.example.com",
        "value": "token2.dkim.amazonses.com",
        "ttl": "Auto",
        "priority": null,
        "purpose": "DKIM — cryptographic email signature",
        "required": true,
        "category": "delivery"
      },
      {
        "type": "CNAME",
        "name": "token3._domainkey.example.com",
        "value": "token3.dkim.amazonses.com",
        "ttl": "Auto",
        "priority": null,
        "purpose": "DKIM — cryptographic email signature",
        "required": true,
        "category": "delivery"
      },
      {
        "type": "MX",
        "name": "send.example.com",
        "value": "feedback-smtp.eu-central-1.amazonses.com",
        "ttl": "Auto",
        "priority": 10,
        "purpose": "Custom MAIL FROM — bounce handling",
        "required": true,
        "category": "delivery"
      },
      {
        "type": "TXT",
        "name": "send.example.com",
        "value": "v=spf1 include:amazonses.com ~all",
        "ttl": "Auto",
        "priority": null,
        "purpose": "SPF — authorizes SES to send on your behalf",
        "required": true,
        "category": "delivery"
      },
      {
        "type": "TXT",
        "name": "_dmarc.example.com",
        "value": "v=DMARC1; p=none;",
        "ttl": "Auto",
        "priority": null,
        "purpose": "DMARC — email authentication policy. Improves inbox placement.",
        "required": false,
        "category": "recommended"
      }
    ]
  }
}

The response includes seven DNS records: 1 SES verification TXT, 3 DKIM CNAMEs, 1 MX and 1 SPF TXT for the custom MAIL FROM subdomain, and 1 DMARC TXT (recommended only). Records with required: true must be added for the domain to work; required: false records are optional but improve deliverability.

DNS Record Fields

FieldTypeDescription
typestringTXT, CNAME, or MX.
namestringThe hostname to set.
valuestringThe record value.
ttlstringAlways "Auto" — set whatever your DNS provider's default is.
priorityintegerSet to 10 for the MX record; null for everything else.
purposestringHuman-readable description of why this record matters.
requiredbooleantrue for verification + DKIM + custom MAIL FROM records; false for DMARC.
categorystring"verification" (SES ownership), "delivery" (DKIM, MX, SPF), or "recommended" (DMARC).

TIP

DNS changes can take up to 72 hours to propagate but typically complete within a few minutes to a few hours.


List Domains

Returns every domain owned by the authenticated team. The list response does not include dns_records — call Get Domain for the full record list.

GET /domains

Required scope: domains:manage

Example Request

bash
curl https://app.krafter.dev/api/v1/domains \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
// 200 OK
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "domain": "example.com",
      "status": "verified",
      "verified_at": "2026-01-15T12:30:00Z",
      "created_at": "2026-01-15T10:00:00Z"
    },
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "domain": "anotherdomain.com",
      "status": "pending",
      "verified_at": null,
      "created_at": "2026-01-16T14:00:00Z"
    }
  ]
}

Get Domain

Returns a single domain by ID, including its full dns_records list and current verification status.

GET /domains/:id

Required scope: domains:manage

Example Request

bash
curl https://app.krafter.dev/api/v1/domains/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
// 200 OK
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "status": "verified",
    "verified_at": "2026-01-15T12:30:00Z",
    "created_at": "2026-01-15T10:00:00Z",
    "dns_records": [
      {
        "type": "TXT",
        "name": "_amazonses.example.com",
        "value": "abc123...",
        "ttl": "Auto",
        "priority": null,
        "purpose": "Domain verification — proves you own this domain",
        "required": true,
        "category": "verification"
      },
      {
        "type": "CNAME",
        "name": "token1._domainkey.example.com",
        "value": "token1.dkim.amazonses.com",
        "ttl": "Auto",
        "priority": null,
        "purpose": "DKIM — cryptographic email signature",
        "required": true,
        "category": "delivery"
      }
    ]
  }
}

Verify Domain

Triggers a verification check. Krafter enqueues a job that re-checks DNS and updates the domain's status based on what it finds.

POST /domains/:id/verify

Required scope: domains:manage

Example Request

bash
curl -X POST https://app.krafter.dev/api/v1/domains/550e8400-e29b-41d4-a716-446655440000/verify \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

The response is the domain object without dns_records:

json
// 200 OK
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "domain": "example.com",
    "status": "verifying",
    "verified_at": null,
    "created_at": "2026-01-15T10:00:00Z"
  }
}

The status will move to verified (or back to pending/failed) once the asynchronous verification job runs. Poll Get Domain to see the result.


Delete Domain

Removes a domain from your team. After deletion you can no longer send from addresses on this domain.

DELETE /domains/:id

Required scope: domains:manage

Example Request

bash
curl -X DELETE https://app.krafter.dev/api/v1/domains/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer kr_live_abc123def456"

Example Response

json
// 200 OK
{
  "data": { "deleted": true }
}

Domain Statuses

StatusDescription
pendingDomain has been added; DNS records have not been verified yet.
verifyingA verification check is in flight.
verifiedAll required DNS records are in place and the domain is ready to send.
failedVerification ran but at least one required DNS record was missing or wrong.

Built by Krafter Studio