---
title: Domain Validation Reference
path: reference/validation
status: published
---

# Domain Validation Reference

Validation endpoints for proving domain ownership before a zone goes active. For the concept, see [Domain Validation](../concepts/validation.md).

**Base path:** `/api/v1/domains/{domain_id}/validation`

## GET /api/v1/domains/{domain_id}/validation

Get the current pending validation for a domain (if any).

**Response when pending:**

```json
{
  "id": "v_abc123",
  "validation_type": "txt_record",
  "status": "pending",
  "challenge_value": "a1b2c3d4e5f6...",
  "dns_record": {
    "name": "_scaidns-verify.example.com",
    "type": "TXT",
    "value": "scaidns-verify=a1b2c3d4e5f6..."
  },
  "expires_at": "2026-04-26T10:42:00Z",
  "created_at": "2026-04-23T10:42:00Z"
}
```

**Response when no pending validation:**

```json
null
```

Zones with status `active` typically have no pending validation. Zones in `pending_validation` always do.

## POST /api/v1/domains/{domain_id}/validation

Create a new validation challenge. If one is already pending, it is superseded.

**Request:**

```json
{
  "validation_type": "txt_record"
}
```

Supported types:

| Type | Description |
|------|-------------|
| `txt_record` | Publish a TXT record at `_scaidns-verify.<domain>`. Default |
| `nameservers` | Delegate NS records to the ScaiDNS nameservers. Platform-dependent availability |

**Response:** New validation object with challenge details.

## POST /api/v1/domains/{domain_id}/validation/check

Trigger a DNS check for the current validation. ScaiDNS queries authoritative nameservers directly.

**Response on success:**

```json
{
  "is_valid": true,
  "message": "Domain validated",
  "validation_id": "v_abc123"
}
```

On failure:

```json
{
  "is_valid": false,
  "message": "TXT record found but value doesn't match. Expected: scaidns-verify=a1b2c3..."
}
```

On success, the domain's status flips to `active` and the PowerDNS zone is created.

## DELETE /api/v1/domains/{domain_id}/validation

Cancel the current pending validation.

**Response:** `204 No Content`.

## Validation lifecycle

```mermaid
stateDiagram-v2
    [*] --> pending : create
    pending --> verifying : check
    verifying --> validated : success
    verifying --> failed : failure
    failed --> verifying : retry check
    validated --> [*] : domain becomes active
```

## Status values

| Status | Meaning |
|--------|---------|
| `pending` | Challenge published; waiting for a check |
| `verifying` | Check in progress (transient) |
| `failed` | Last check failed; challenge still valid for retries |
| `validated` | Check succeeded; domain is now active |
| `expired` | Challenge exceeded its expiry; create a new one |
| `cancelled` | Validation was cancelled by the caller |

## Common failure messages

| Message | Cause |
|---------|-------|
| `No DNS record found for _scaidns-verify.<domain>` | TXT record not published or not propagated |
| `TXT record found but value doesn't match. Expected: ...` | Wrong value at the TXT record |
| `Domain <name> does not exist in DNS` | Domain not registered or NS delegation broken |
| `No nameservers available for query` | Unable to resolve authoritative nameservers |
| `DNS query timed out` | Authoritative nameserver unreachable |

## Bypass

Users with the `validation_bypass` permission can skip validation by creating domains with `?skip_validation=true` (platform admin only by default). Intended for:

- Internal zones not exposed on the public internet.
- Migrations from another ScaiDNS system with established ownership.
- Zones created by trusted automation.

## Related

- [Domain Validation concept](../concepts/validation.md)
- [Managing Domains](../tutorials/managing-domains.md)
