---
title: "Verify domain DNS or apply DNS via Cloudflare, Vercel, or GoDaddy"
method: POST
path: "/domains/{id}"
tags: ["Domains"]
---

# Verify domain DNS or apply DNS via Cloudflare, Vercel, or GoDaddy

`POST /domains/{id}`

## Request

- Base URL: `https://api.groundmail.dev`
- URL: `https://api.groundmail.dev/domains/{id}`
- Auth: HTTP bearer

## Path parameters

- `id` string, required

## Request body

- object
  - `action` 'verify' | 'apply', required
  - `provider` 'cloudflare' | 'godaddy' | 'vercel': Required when action is apply
  - `credentials` RemoteApplyDnsCredentials
    - `apiToken` string: Inline Cloudflare API token instead of the stored dashboard integration
    - `zoneId` string: Optional Cloudflare zone id when using an inline token
    - `cloudflareApiToken` string: Alias for apiToken
    - `cloudflareZoneId` string: Alias for zoneId
    - `apiKey` string: GoDaddy API key
    - `apiSecret` string: GoDaddy API secret
    - `godaddyApiKey` string: Alias for apiKey
    - `godaddyApiSecret` string: Alias for apiSecret
    - `vercelApiToken` string: Alias for apiToken when provider is vercel
    - `vercelTeamId` string: Optional Vercel team id for team-scoped DNS
    - `teamId` string: Inline Vercel team id (alias for vercelTeamId)

## Response `200`

Domain verified, or DNS apply results

- union
  - VerifyDomainResponse
    - `domain` Domain, required
      - `id` string, required
      - `name` string, required
      - `status` 'pending' | 'verified' | 'failed', required
      - `created_at` string, date-time, required
      - `verified_at` string, date-time, nullable, required
      - `open_tracking` boolean, required: Open tracking preference for this domain.
      - `click_tracking` boolean, required: Click tracking preference for this domain.
      - `tracking_status` 'disabled' | 'pending' | 'active' | 'error', required: Whether open/click tracking is applied to outgoing mail. `disabled` when both preferences are off, `pending` until the tracking CNAME is accepted and a certificate is issued for the tracking hostname (links and opens are not tracked yet; this takes a few minutes after the CNAME is added), `active` once both are done, `error` when tracking or the certificate could not be set up. Re-checked when you verify the domain and when you read it.
      - `tracking_error` string, nullable, required: Why tracking is not active yet, when `tracking_status` is `pending` or `error`.
      - `tls_mode` 'opportunistic' | 'enforced', required: Preferred outbound TLS behavior for this domain.
      - `inbound_enabled` boolean, required: True when Groundmail should accept inbound mail for this domain.
      - `inbound_status` 'disabled' | 'pending' | 'active' | 'error', required: `pending` before verification, `active` once inbound receiving is configured, or `error` when setup fails.
      - `inbound_error` string, nullable, required: Last inbound configuration error, if any.
      - `inbound_spam_threshold` number, nullable: Received mail scoring at or above this is `spam` (and dropped when `inbound_spam_action` is `drop`). Null uses the default (10) and drops nothing.
      - `inbound_spam_action` 'flag' | 'drop': `flag` keeps spam with `spam_status: spam`; `drop` discards it (no stored email, no webhook).
      - `tenant` string: The `external_id` of the tenant that owns this domain. Present only on a tenant's domain.
    - `records` DnsRecord[], required
      - `type` string, required: DNS record type (`TXT`, `CNAME`, or `MX`)
      - `host` string, required
      - `value` string, required: Record content. For MX records, the mail server hostname (priority is in `priority`).
      - `priority` integer: MX preference when `type` is `MX` (lower is preferred).
      - `purpose` string, required: Human-readable purpose (`Domain ownership`, `DKIM`, `Return path`, `SPF`, `DMARC`, `Inbound receiving`)
    - `analysis` DomainDnsAnalysis
      - `dmarc` DomainDmarcAnalysis, required
        - `host` string, required
        - `configured` boolean, required
        - `record` string, nullable, required
        - `policy` string, nullable, required: Parsed DMARC `p=` policy when present (`none`, `quarantine`, or `reject`)
        - `rua` string[], required
        - `guidance` string, required
      - `bimi` DomainBimiAnalysis, required
        - `host` string, required
        - `configured` boolean, required
        - `record` string, nullable, required
        - `location` string, nullable, required: Parsed BIMI `l=` logo URL when present
        - `authority` string, nullable, required: Parsed BIMI `a=` VMC URL when present
        - `requires_dmarc_enforcement` boolean, required: True when BIMI is unlikely to work until DMARC is set to p=quarantine or p=reject
        - `guidance` string, required
    - `inbound_records` DnsRecord[], required
      - `type` string, required: DNS record type (`TXT`, `CNAME`, or `MX`)
      - `host` string, required
      - `value` string, required: Record content. For MX records, the mail server hostname (priority is in `priority`).
      - `priority` integer: MX preference when `type` is `MX` (lower is preferred).
      - `purpose` string, required: Human-readable purpose (`Domain ownership`, `DKIM`, `Return path`, `SPF`, `DMARC`, `Inbound receiving`)
    - `inbound_note` string, required
    - `verified` boolean, required
    - `auto` boolean
    - `checks` object
      - `ownership` boolean
      - `spf` boolean
      - `dkim` boolean
      - `dmarc` boolean
      - `return_path` boolean
    - `inbound_configured` boolean
    - `inbound_pending` boolean
    - `inbound_error` string, nullable
    - `signing_ready` boolean: True when the mail server will DKIM-sign with this domain's key (not the shared pool fallback).
    - `mail_server_signing` MailServerSigningStatus: Mail-server delivery DNS statuses recorded when verify re-checks the domain.
      - `dkim_ok` boolean
      - `return_path_ok` boolean
      - `dkim_status` string, nullable
      - `return_path_status` string, nullable
  - ApplyDomainDnsResponse
    - `provider` 'cloudflare' | 'godaddy' | 'vercel', required
    - `domain` string, required
    - `results` ApplyDnsRecordResult[], required
      - `purpose` string, required
      - `host` string, required
      - `action` 'created' | 'updated' | 'unchanged' | 'merged', required
      - `detail` string

## Other responses

- `400`: DNS not fully ready yet (propagation — response includes pending:true and checks), missing provider credentials, or invalid action
- `401`: Unauthorized
- `404`: Domain not found
- `502`: Domain registration failed, or DNS provider API error during apply
- `503`: Credentials encryption key not configured

---

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