---
title: Domains Reference
path: reference/domains
status: published
---

# Domains Reference

All endpoints for managing forward and reverse zones. For the conceptual model, see [Zones and Records](../concepts/zones-and-records.md). For task walkthroughs, see [Managing Domains](../tutorials/managing-domains.md).

**Base path:** `/api/v1/domains/`

## GET /api/v1/domains/

List zones in the current tenant.

**Query parameters:**

| Param | Type | Notes |
|-------|------|-------|
| `page` | integer | 1-based, default 1 |
| `page_size` | integer | 1–100, default 50 |
| `status` | string | `pending_validation`, `active`, `inactive`, `deleted` |
| `domain_type` | string | `primary`, `secondary`, `reverse_ipv4`, `reverse_ipv6` |
| `dnssec_enabled` | boolean | |
| `search` | string | Substring match on `name` |
| `include_deleted` | boolean | Include soft-deleted zones |

**Response:**

```json
{
  "data": [
    {
      "id": "d_abc123",
      "name": "example.com",
      "domain_type": "primary",
      "status": "active",
      "default_ttl": 3600,
      "description": "Main production zone",
      "dnssec_enabled": true,
      "created_at": "2026-04-01T10:00:00Z",
      "updated_at": "2026-04-15T14:30:00Z"
    }
  ],
  "total": 42,
  "page": 1,
  "page_size": 50,
  "total_pages": 1
}
```

## POST /api/v1/domains/

Create a zone.

**Request:**

| Field | Type | Required | Notes |
|-------|------|---------|-------|
| `name` | string | Yes | Zone apex |
| `domain_type` | string | Yes | `primary`, `secondary`, `reverse_ipv4`, `reverse_ipv6` |
| `default_ttl` | integer | No | Seconds, default 3600 |
| `description` | string | No | Free-form |
| `cidr` | string | No | For reverse zones; prefer `/api/v1/reverse-zones/` |
| `template_id` | string | No | Apply template after validation |
| `template_variables` | object | No | Variables for template |

**Response:** `DomainDetailResponse` (see schema below).

Status: `pending_validation` initially. Records are stored but not served.

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

Get a single zone.

**Response:**

```json
{
  "id": "d_abc123",
  "name": "example.com",
  "domain_type": "primary",
  "status": "active",
  "default_ttl": 3600,
  "description": "Main production zone",
  "dnssec_enabled": true,
  "pdns_zone_id": "example.com.",
  "tenant_id": "t_xyz789",
  "settings": {},
  "created_at": "2026-04-01T10:00:00Z",
  "updated_at": "2026-04-15T14:30:00Z",
  "deleted_at": null,
  "record_count": 17,
  "current_validation": null
}
```

## PATCH /api/v1/domains/{domain_id}

Update zone metadata. Only `description`, `default_ttl`, and `settings` are editable.

**Request:**

| Field | Type | Notes |
|-------|------|-------|
| `description` | string | |
| `default_ttl` | integer | |
| `settings` | object | |

**Response:** Updated zone.

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

Delete a zone. Soft by default (recoverable); add `?hard=true` for permanent deletion.

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

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

Restore a soft-deleted zone.

**Response:** Zone with status set back to its prior value.

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

Get the zone's SOA record in a structured shape.

**Response:**

```json
{
  "primary_ns": "ns1.scaidns.scailabs.ai.",
  "hostmaster": "hostmaster.example.com.",
  "serial": 2026042301,
  "refresh": 3600,
  "retry": 600,
  "expire": 604800,
  "minimum": 600,
  "ttl": 3600
}
```

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

Export zone as BIND format. See [Import and Export](../tutorials/import-export.md).

**Response:**

```json
{
  "domain_id": "d_abc123",
  "domain_name": "example.com",
  "format": "bind",
  "zone_file": "..."
}
```

## Validation sub-resource

See [Domain Validation](./validation.md) for `/validation` endpoints under each domain.

## Records sub-resource

See [Records](./records.md) for `/records/*` endpoints under each domain.

## DNSSEC sub-resource

See [DNSSEC](./dnssec.md) for `/dnssec/*` endpoints under each domain.

## Access grants sub-resource

See [Access Grants](../tutorials/access-grants.md) for `/access-grants/*` endpoints under each domain.

## Schemas

### DomainResponse

| Field | Type |
|-------|------|
| `id` | string (UUID) |
| `name` | string |
| `domain_type` | string |
| `status` | string |
| `default_ttl` | integer |
| `description` | string or null |
| `dnssec_enabled` | boolean |
| `tenant_id` | string (UUID) |
| `created_at` | ISO 8601 timestamp |
| `updated_at` | ISO 8601 timestamp |
| `deleted_at` | ISO 8601 timestamp or null |

### DomainDetailResponse

Everything in `DomainResponse` plus:

| Field | Type |
|-------|------|
| `pdns_zone_id` | string |
| `settings` | object |
| `record_count` | integer |
| `current_validation` | object or null — see [Validation](./validation.md) |

## Error codes

| Status | Meaning |
|--------|---------|
| `400` | Invalid domain name, unsupported type, malformed CIDR |
| `403` | Caller lacks `domains:*` permission on this tenant |
| `404` | Domain not found (or in a different tenant) |
| `409` | Domain name already exists in this tenant |

## Related

- [Managing Domains](../tutorials/managing-domains.md) — task-oriented guide.
- [Records](./records.md) — record CRUD.
- [Domain Validation](./validation.md) — ownership proof.
