# verify_domain

Source: https://modulify.ai/docs/api/domains/verify-domain

Finishes a domain ownership check and adds the domain to the site once its TXT record matches.

- Title: Verify and connect a domain
- Scope: `config:write`
- Access: Makes changes
- Endpoint: `POST /v1/verify_domain`

It checks one thing: the TXT record at `_modulify-verification.<domain>` against the token `start_domain_verification` returned. Add that record, not the records `get_domain_status` lists, since the pending domain is not in `get_domain_status` until this call adds it.

When the TXT record matches, the domain joins the site's custom domains, with its www companion when it is a root domain and that hostname is free. It is added even while its A, AAAA and CNAME records are still missing, so it comes back with `IsConnected` false until those are in place. The answer carries the new `domainId`, so call `get_domain_status` with it afterwards to track that.

It is refused when no verification is pending, when the domain is already on this site or another one, and when the site already has 10 custom domains. When the domain is already on this site, the refusal also clears the pending verification. It needs a paid plan and the **Manage domains** permission.

DNS can take a while to propagate, so a failure here often just means not yet. Wait a few minutes and try again rather than changing anything. See [A domain waiting on verification](https://modulify.ai/docs/publish/custom-domains#a-domain-waiting-on-verification).

## Request

Call it with a `POST` to `https://api.modulify.ai/v1/verify_domain`, sending the inputs below as a JSON object. The token needs the `config:write` scope.

It makes changes, so send an [Idempotency-Key](https://modulify.ai/docs/api/idempotency) header whenever you might retry it. A retry with the same key gets the first answer back instead of running again.

```bash
curl -X POST https://api.modulify.ai/v1/verify_domain \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"PROJECT_ID"}'
```

Over MCP, the same method is the [verify_domain tool](https://modulify.ai/docs/mcp/domains/verify-domain).

## Inputs

| Input | Type | Required | Description |
| --- | --- | --- | --- |
| `projectId` | string | Yes | The site id. The domain being verified is the one `start_domain_verification` recorded. |

## Response

Every call answers with the [JSON envelope](https://modulify.ai/docs/api/requests-and-responses#the-response) of `success`, `message`, `data`, `code` and `version`. `data` holds the result described above, and on a method that returns a total, `count` carries it. The [response headers](https://modulify.ai/docs/api/requests-and-responses#headers-on-every-method-call) carry the call's `X-Request-Id` and what is left of your per-minute budget in `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. [Errors](https://modulify.ai/docs/api/errors) explains every status code a call can answer with.