# DNS records

> List, create, update and delete the DNS records of a zone, in bulk or as one batch, and import existing records.

DNS records of a zone. A/AAAA/CNAME records can be proxied: the name then answers with the edge addresses and the record content becomes the origin. In an external zone only proxied A/AAAA/CNAME records are accepted (they are the sites served by the edge). Every write creates a new configuration version.

| Operation | Endpoint |
|---|---|
| [List records](https://developers.openwaf.dev/api/dns-records/#list-records) | `GET /v1/orgs/{org}/zones/{zone}/records` |
| [Create record](https://developers.openwaf.dev/api/dns-records/#create-record) | `POST /v1/orgs/{org}/zones/{zone}/records` |
| [Create records in bulk](https://developers.openwaf.dev/api/dns-records/#bulk-create-records) | `POST /v1/orgs/{org}/zones/{zone}/records/bulk` |
| [Batch records](https://developers.openwaf.dev/api/dns-records/#batch-records) | `POST /v1/orgs/{org}/zones/{zone}/records/batch` |
| [Get record](https://developers.openwaf.dev/api/dns-records/#get-record) | `GET /v1/orgs/{org}/zones/{zone}/records/{record}` |
| [Update record](https://developers.openwaf.dev/api/dns-records/#update-record) | `PATCH /v1/orgs/{org}/zones/{zone}/records/{record}` |
| [Delete record](https://developers.openwaf.dev/api/dns-records/#delete-record) | `DELETE /v1/orgs/{org}/zones/{zone}/records/{record}` |
| [Find existing records](https://developers.openwaf.dev/api/dns-records/#list-import-candidates) | `GET /v1/orgs/{org}/zones/{zone}/import` |
| [Read a BIND zone file](https://developers.openwaf.dev/api/dns-records/#parse-bind-zone) | `POST /v1/orgs/{org}/zones/{zone}/import/bind` |
| [Get edge DNS answers](https://developers.openwaf.dev/api/dns-records/#get-dns-answers) | `GET /v1/orgs/{org}/zones/{zone}/dns/answers` |

## List records

```http
GET /v1/orgs/{org}/zones/{zone}/records
```

Lists the DNS records of a zone with their ids.

**Required role:** `readonly` or higher.

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |

#### Response

- `200`: Returns `items`, an array of [Record](https://developers.openwaf.dev/api/schemas/#record).

| Field | Type | Description |
|---|---|---|
| `items[].id` | string (uuid) | Id. |
| `items[].org_id` | string (uuid) | Organization id. |
| `items[].zone_id` | string (uuid) | Zone id. |
| `items[].type` | string |  |
| `items[].name` | string | Full name without a trailing dot. |
| `items[].content` | string | Origin content. |
| `items[].ttl` | integer | TTL in seconds. |
| `items[].priority` | integer | MX and SRV priority (null for other types). |
| `items[].proxied` | boolean | Served through the OpenWAF edge. |
| `items[].comment` | string | Comment (empty if none). |
| `items[].tags` | array of string | Tags (empty list if none). |
| `items[].created_at` | string (date-time) | Creation time. |
| `items[].updated_at` | string (date-time) | Last change. |

#### Example

**curl**


```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.listRecords({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.list_records(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d")
```



```json
{
  "items": [
    {
      "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
      "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
      "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
      "type": "A",
      "name": "www.example.com",
      "content": "203.0.113.10",
      "ttl": 300,
      "priority": null,
      "proxied": true,
      "comment": "Web servers",
      "tags": [
        "web"
      ],
      "created_at": "2026-03-02T10:25:00Z",
      "updated_at": "2026-10-27T09:00:00Z"
    }
  ]
}
```

## Create record

```http
POST /v1/orgs/{org}/zones/{zone}/records
```

Creates a DNS record. In an external zone only proxied A/AAAA/CNAME records are accepted (they are the sites published to the edge); they are not published in DNS, which stays with the other provider.

**Required role:** `tech` or higher.

**Change controls:** [`dry_run`](https://developers.openwaf.dev/api/#configuration-changes) · [`If-Match`](https://developers.openwaf.dev/api/#configuration-changes) (optional) · [`X-Change-Reason`](https://developers.openwaf.dev/api/#configuration-changes) (required)

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `X-Change-Reason` | header | string | Yes | Reason of the change: 1-500 UTF-8 characters after trimming spaces, no control characters. If it is missing or invalid: 422 `reason_required`. 1 to 500 characters. |
| `If-Match` | header | string | No | Expected configuration version, e.g. `"12"` (`W/` accepted). If it is not the current one: 412 `version_conflict`. |
| `dry_run` | query | string | No | `1`/`true` simulates the change: answers 200 with the plan (`Applied`) and saves nothing. `0`/`false` accepted; any other value: 400. One of `1`, `true`, `0`, `false`. |

#### Request body

Content type `application/json`. Schema: [RecordInput](https://developers.openwaf.dev/api/schemas/#record-input).

| Field | Type | Required | Description |
|---|---|---|---|
| `type` | string | Yes | One of `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SRV`, `CAA`. |
| `name` | string | No | `@`, relative (`www`) or full name; `*` for a wildcard. Default `@`. |
| `content` | string | Yes | A/AAAA: address. CNAME/NS/MX: host name. TXT: text without quotes (split into 255-character strings). SRV: `weight port target`. CAA: `flags tag "value"`. |
| `ttl` | integer | No | TTL in seconds. Default `3600`. From 60 to 86400. |
| `priority` | integer | No | Required for MX and SRV; not allowed for other types. From 0 to 65535. |
| `proxied` | boolean | No | A/AAAA/CNAME only. The name answers with the edge addresses (TTL 300) and the content is kept as the origin. All A/AAAA/CNAME records of a name share the value. An unproxied CNAME at the apex is published flattened (ALIAS). Default `false`. |
| `comment` | string | No | Attribute of the record (not published in DNS; part of the zone's versions). No control characters. At most 100 characters. |
| `tags` | array of string | No | Attribute of the record, like the comment. Lowercased and deduplicated. At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |

#### Response

- `200`: With `dry_run=1`, the plan of the change ([Applied](https://developers.openwaf.dev/api/schemas/#applied)); nothing is saved.
- `201`: Created and published. Returns [Record](https://developers.openwaf.dev/api/schemas/#record).

| Field | Type | Description |
|---|---|---|
| `id` | string (uuid) | Id. |
| `org_id` | string (uuid) | Organization id. |
| `zone_id` | string (uuid) | Zone id. |
| `type` | string |  |
| `name` | string | Full name without a trailing dot. |
| `content` | string | Origin content. |
| `ttl` | integer | TTL in seconds. |
| `priority` | integer | MX and SRV priority (null for other types). |
| `proxied` | boolean | Served through the OpenWAF edge. |
| `comment` | string | Comment (empty if none). |
| `tags` | array of string | Tags (empty list if none). |
| `created_at` | string (date-time) | Creation time. |
| `updated_at` | string (date-time) | Last change. |

Response headers: `ETag`, `X-Config-Version`.

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `409` | Disabled zone, or `zone_merged`. |
| `412` | `version_conflict`: If-Match does not match the current version. |
| `422` | Validation error (`invalid`) or missing or invalid reason (`reason_required`). |

#### Example

**curl**


```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Add the API host" \
  -H 'If-Match: "12"' \
  -H "Content-Type: application/json" \
  --data '{
    "type": "A",
    "name": "api",
    "content": "203.0.113.20",
    "proxied": true
  }'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.createRecord({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  body: {
    type: "A",
    name: "api",
    content: "203.0.113.20",
    proxied: true
  }
}, {
  reason: "Add the API host",
  ifMatch: 12
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.create_record(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    body={
        "type": "A",
        "name": "api",
        "content": "203.0.113.20",
        "proxied": True
    },
    reason="Add the API host",
    if_match=12,
)
```



```json
{
  "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "type": "A",
  "name": "www.example.com",
  "content": "203.0.113.10",
  "ttl": 300,
  "priority": null,
  "proxied": true,
  "comment": "Web servers",
  "tags": [
    "web"
  ],
  "created_at": "2026-03-02T10:25:00Z",
  "updated_at": "2026-10-27T09:00:00Z"
}
```

## Create records in bulk

```http
POST /v1/orgs/{org}/zones/{zone}/records/bulk
```

Creates up to 1000 records atomically, all or none, as one version (for example a reviewed import). A validation error names the record in `field` (`records[i].field`).

**Required role:** `tech` or higher.

**Change controls:** [`dry_run`](https://developers.openwaf.dev/api/#configuration-changes) · [`If-Match`](https://developers.openwaf.dev/api/#configuration-changes) (optional) · [`X-Change-Reason`](https://developers.openwaf.dev/api/#configuration-changes) (required)

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `X-Change-Reason` | header | string | Yes | Reason of the change: 1-500 UTF-8 characters after trimming spaces, no control characters. If it is missing or invalid: 422 `reason_required`. 1 to 500 characters. |
| `If-Match` | header | string | No | Expected configuration version, e.g. `"12"` (`W/` accepted). If it is not the current one: 412 `version_conflict`. |
| `dry_run` | query | string | No | `1`/`true` simulates the change: answers 200 with the plan (`Applied`) and saves nothing. `0`/`false` accepted; any other value: 400. One of `1`, `true`, `0`, `false`. |

#### Request body

Content type `application/json`.

| Field | Type | Required | Description |
|---|---|---|---|
| `records` | array of [RecordInput](https://developers.openwaf.dev/api/schemas/#record-input) | Yes | At most 1000 items. |
| `records[].type` | string | Yes | One of `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SRV`, `CAA`. |
| `records[].name` | string | No | `@`, relative (`www`) or full name; `*` for a wildcard. Default `@`. |
| `records[].content` | string | Yes | A/AAAA: address. CNAME/NS/MX: host name. TXT: text without quotes (split into 255-character strings). SRV: `weight port target`. CAA: `flags tag "value"`. |
| `records[].ttl` | integer | No | TTL in seconds. Default `3600`. From 60 to 86400. |
| `records[].priority` | integer | No | Required for MX and SRV; not allowed for other types. From 0 to 65535. |
| `records[].proxied` | boolean | No | A/AAAA/CNAME only. The name answers with the edge addresses (TTL 300) and the content is kept as the origin. All A/AAAA/CNAME records of a name share the value. An unproxied CNAME at the apex is published flattened (ALIAS). Default `false`. |
| `records[].comment` | string | No | Attribute of the record (not published in DNS; part of the zone's versions). No control characters. At most 100 characters. |
| `records[].tags` | array of string | No | Attribute of the record, like the comment. Lowercased and deduplicated. At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |

#### Response

- `200`: With `dry_run=1`, the plan of the change ([Applied](https://developers.openwaf.dev/api/schemas/#applied)); nothing is saved.
- `201`: Created (one version). Returns `items`, an array of [Record](https://developers.openwaf.dev/api/schemas/#record).

| Field | Type | Description |
|---|---|---|
| `items[].id` | string (uuid) | Id. |
| `items[].org_id` | string (uuid) | Organization id. |
| `items[].zone_id` | string (uuid) | Zone id. |
| `items[].type` | string |  |
| `items[].name` | string | Full name without a trailing dot. |
| `items[].content` | string | Origin content. |
| `items[].ttl` | integer | TTL in seconds. |
| `items[].priority` | integer | MX and SRV priority (null for other types). |
| `items[].proxied` | boolean | Served through the OpenWAF edge. |
| `items[].comment` | string | Comment (empty if none). |
| `items[].tags` | array of string | Tags (empty list if none). |
| `items[].created_at` | string (date-time) | Creation time. |
| `items[].updated_at` | string (date-time) | Last change. |

Response headers: `ETag`, `X-Config-Version`.

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `409` | `zone_merged`: the zone is merged into another one (read-only until it is unmerged or purged). |
| `412` | `version_conflict`: If-Match does not match the current version. |
| `422` | Validation error (`field` names `records[i].field`) or `reason_required`. |

#### Example

**curl**


```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records/bulk" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Import reviewed records" \
  -H "Content-Type: application/json" \
  --data '{
    "records": [
      {
        "type": "A",
        "name": "@",
        "content": "203.0.113.10",
        "proxied": true
      },
      {
        "type": "MX",
        "name": "@",
        "content": "mail.example.com",
        "priority": 10
      }
    ]
  }'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.bulkCreateRecords({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  body: {
    records: [
      {
        type: "A",
        name: "@",
        content: "203.0.113.10",
        proxied: true
      },
      {
        type: "MX",
        name: "@",
        content: "mail.example.com",
        priority: 10
      }
    ]
  }
}, {
  reason: "Import reviewed records"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.bulk_create_records(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    body={
        "records": [
            {
                "type": "A",
                "name": "@",
                "content": "203.0.113.10",
                "proxied": True
            },
            {
                "type": "MX",
                "name": "@",
                "content": "mail.example.com",
                "priority": 10
            }
        ]
    },
    reason="Import reviewed records",
)
```



```json
{
  "items": [
    {
      "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
      "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
      "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
      "type": "A",
      "name": "www.example.com",
      "content": "203.0.113.10",
      "ttl": 300,
      "priority": null,
      "proxied": true,
      "comment": "Web servers",
      "tags": [
        "web"
      ],
      "created_at": "2026-03-02T10:25:00Z",
      "updated_at": "2026-10-27T09:00:00Z"
    }
  ]
}
```

## Batch records

```http
POST /v1/orgs/{org}/zones/{zone}/records/batch
```

Creates, updates and deletes records as one change, all or nothing, with one version, one reason and one audit entry per record. Turning the proxy on or off for an A/AAAA/CNAME also changes the other A/AAAA/CNAME records of the same name that are not in the batch. The answer (`200`) is the plan of the change plus the resulting records of the zone.

**Required role:** `tech` or higher.

**Change controls:** [`dry_run`](https://developers.openwaf.dev/api/#configuration-changes) · [`If-Match`](https://developers.openwaf.dev/api/#configuration-changes) (optional) · [`X-Change-Reason`](https://developers.openwaf.dev/api/#configuration-changes) (required)

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `X-Change-Reason` | header | string | Yes | Reason of the change: 1-500 UTF-8 characters after trimming spaces, no control characters. If it is missing or invalid: 422 `reason_required`. 1 to 500 characters. |
| `If-Match` | header | string | No | Expected configuration version, e.g. `"12"` (`W/` accepted). If it is not the current one: 412 `version_conflict`. |
| `dry_run` | query | string | No | `1`/`true` simulates the change: answers 200 with the plan (`Applied`) and saves nothing. `0`/`false` accepted; any other value: 400. One of `1`, `true`, `0`, `false`. |

#### Request body

Content type `application/json`. Schema: [RecordBatch](https://developers.openwaf.dev/api/schemas/#record-batch).

Up to 500 operations in total. Each record is updated or deleted at most once. Deletes are applied first, then updates, then creates; coexistence rules are checked on the final state.

| Field | Type | Required | Description |
|---|---|---|---|
| `create` | array of [RecordInput](https://developers.openwaf.dev/api/schemas/#record-input) | No |  |
| `create[].type` | string | Yes | One of `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SRV`, `CAA`. |
| `create[].name` | string | No | `@`, relative (`www`) or full name; `*` for a wildcard. Default `@`. |
| `create[].content` | string | Yes | A/AAAA: address. CNAME/NS/MX: host name. TXT: text without quotes (split into 255-character strings). SRV: `weight port target`. CAA: `flags tag "value"`. |
| `create[].ttl` | integer | No | TTL in seconds. Default `3600`. From 60 to 86400. |
| `create[].priority` | integer | No | Required for MX and SRV; not allowed for other types. From 0 to 65535. |
| `create[].proxied` | boolean | No | A/AAAA/CNAME only. The name answers with the edge addresses (TTL 300) and the content is kept as the origin. All A/AAAA/CNAME records of a name share the value. An unproxied CNAME at the apex is published flattened (ALIAS). Default `false`. |
| `create[].comment` | string | No | Attribute of the record (not published in DNS; part of the zone's versions). No control characters. At most 100 characters. |
| `create[].tags` | array of string | No | Attribute of the record, like the comment. Lowercased and deduplicated. At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |
| `update` | array of object | No |  |
| `update[].id` | string (uuid) | Yes | Id. |
| `update[].type` | string | No |  |
| `update[].name` | string | No | Name. |
| `update[].content` | string | No |  |
| `update[].ttl` | integer | No | TTL in seconds. |
| `update[].priority` | integer or null | No | MX and SRV priority (null for other types). |
| `update[].proxied` | boolean | No | Served through the OpenWAF edge. |
| `update[].comment` | string | No | At most 100 characters. |
| `update[].tags` | array of string | No | At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |
| `delete` | array of string (uuid) | No |  |

#### Response

- `200`: Applied (or simulated with `dry_run`). Returns [BatchResult](https://developers.openwaf.dev/api/schemas/#batch-result).

| Field | Type | Description |
|---|---|---|
| `dry_run` | boolean | `true` in a simulation. |
| `from_version` | integer | Current version before the change. |
| `to_version` | integer | Version the change creates (the same if nothing changes). |
| `diff` | [Diff](https://developers.openwaf.dev/api/schemas/#diff) | Changes. |
| `warnings` | array of string | Warnings (the change is still valid). |
| `records` | array of [Record](https://developers.openwaf.dev/api/schemas/#record) | Records of the zone after the change (simulated with `dry_run`). |

Response headers: `ETag`, `X-Config-Version`.

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `409` | Disabled zone, or `zone_merged`. |
| `412` | `version_conflict`: If-Match does not match the current version. |
| `422` | Validation error (`field` names the operation: `create[i].field`, `update[i].field`, `delete[i]`; empty if the batch is empty or has more than 500 operations) or `reason_required`. |

#### Example

**curl**


```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records/batch?dry_run=1" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Move the site to the new origin" \
  -H "Content-Type: application/json" \
  --data '{
    "create": [
      {
        "type": "CNAME",
        "name": "shop",
        "content": "shops.example.net",
        "proxied": true
      }
    ],
    "update": [
      {
        "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
        "content": "203.0.113.30"
      }
    ],
    "delete": [
      "1b3d5f7a-9c2e-4a6b-8d0f-2a4c6e8b0d2f"
    ]
  }'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.batchRecords({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  body: {
    create: [
      {
        type: "CNAME",
        name: "shop",
        content: "shops.example.net",
        proxied: true
      }
    ],
    update: [
      {
        id: "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
        content: "203.0.113.30"
      }
    ],
    delete: [
      "1b3d5f7a-9c2e-4a6b-8d0f-2a4c6e8b0d2f"
    ]
  }
}, {
  reason: "Move the site to the new origin",
  dryRun: true
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.batch_records(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    body={
        "create": [
            {
                "type": "CNAME",
                "name": "shop",
                "content": "shops.example.net",
                "proxied": True
            }
        ],
        "update": [
            {
                "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
                "content": "203.0.113.30"
            }
        ],
        "delete": [
            "1b3d5f7a-9c2e-4a6b-8d0f-2a4c6e8b0d2f"
        ]
    },
    reason="Move the site to the new origin",
    dry_run=True,
)
```



```json
{
  "dry_run": false,
  "from_version": 12,
  "to_version": 12,
  "diff": {
    "from": 0,
    "to": 0,
    "changes": [
      {
        "path": "rules[id=12]",
        "op": "add",
        "from": "example",
        "to": "example"
      }
    ]
  },
  "warnings": [],
  "records": [
    {
      "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
      "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
      "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
      "type": "A",
      "name": "www.example.com",
      "content": "203.0.113.10",
      "ttl": 300,
      "priority": null,
      "proxied": true,
      "comment": "Web servers",
      "tags": [
        "web"
      ],
      "created_at": "2026-03-02T10:25:00Z",
      "updated_at": "2026-10-27T09:00:00Z"
    }
  ]
}
```

## Get record

```http
GET /v1/orgs/{org}/zones/{zone}/records/{record}
```

Returns one record. For a proxied record, `content` is the origin.

**Required role:** `readonly` or higher.

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `record` | path | string (uuid) | Yes | Record id (see [List records](https://developers.openwaf.dev/api/dns-records/#list-records)). |

#### Response

- `200`: Returns [Record](https://developers.openwaf.dev/api/schemas/#record).

| Field | Type | Description |
|---|---|---|
| `id` | string (uuid) | Id. |
| `org_id` | string (uuid) | Organization id. |
| `zone_id` | string (uuid) | Zone id. |
| `type` | string |  |
| `name` | string | Full name without a trailing dot. |
| `content` | string | Origin content. |
| `ttl` | integer | TTL in seconds. |
| `priority` | integer | MX and SRV priority (null for other types). |
| `proxied` | boolean | Served through the OpenWAF edge. |
| `comment` | string | Comment (empty if none). |
| `tags` | array of string | Tags (empty list if none). |
| `created_at` | string (date-time) | Creation time. |
| `updated_at` | string (date-time) | Last change. |

#### Errors

| Status | Description |
|---|---|
| `404` | Not found, or not visible to the token (`not_found`). |

#### Example

**curl**


```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records/0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getRecord({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  record: "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.get_record(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    record="0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
)
```



```json
{
  "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "type": "A",
  "name": "www.example.com",
  "content": "203.0.113.10",
  "ttl": 300,
  "priority": null,
  "proxied": true,
  "comment": "Web servers",
  "tags": [
    "web"
  ],
  "created_at": "2026-03-02T10:25:00Z",
  "updated_at": "2026-10-27T09:00:00Z"
}
```

## Update record

```http
PATCH /v1/orgs/{org}/zones/{zone}/records/{record}
```

Changes fields of a record; fields left out keep their value.

**Required role:** `tech` or higher.

**Change controls:** [`dry_run`](https://developers.openwaf.dev/api/#configuration-changes) · [`If-Match`](https://developers.openwaf.dev/api/#configuration-changes) (optional) · [`X-Change-Reason`](https://developers.openwaf.dev/api/#configuration-changes) (required)

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `record` | path | string (uuid) | Yes | Record id (see [List records](https://developers.openwaf.dev/api/dns-records/#list-records)). |
| `X-Change-Reason` | header | string | Yes | Reason of the change: 1-500 UTF-8 characters after trimming spaces, no control characters. If it is missing or invalid: 422 `reason_required`. 1 to 500 characters. |
| `If-Match` | header | string | No | Expected configuration version, e.g. `"12"` (`W/` accepted). If it is not the current one: 412 `version_conflict`. |
| `dry_run` | query | string | No | `1`/`true` simulates the change: answers 200 with the plan (`Applied`) and saves nothing. `0`/`false` accepted; any other value: 400. One of `1`, `true`, `0`, `false`. |

#### Request body

Content type `application/json`. Schema: [RecordPatch](https://developers.openwaf.dev/api/schemas/#record-patch).

Fields that change; the others keep their value.

| Field | Type | Required | Description |
|---|---|---|---|
| `type` | string | No |  |
| `name` | string | No | Name. |
| `content` | string | No |  |
| `ttl` | integer | No | TTL in seconds. |
| `priority` | integer or null | No | MX and SRV priority (null for other types). |
| `proxied` | boolean | No | Served through the OpenWAF edge. |
| `comment` | string | No | At most 100 characters. |
| `tags` | array of string | No | At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |

#### Response

- `200`: Record changed (with X-Config-Version and ETag) or, with `dry_run`, the plan (`Applied`). Returns [Record](https://developers.openwaf.dev/api/schemas/#record) or [Applied](https://developers.openwaf.dev/api/schemas/#applied).

| Field | Type | Description |
|---|---|---|
| `id` | string (uuid) | Id. |
| `org_id` | string (uuid) | Organization id. |
| `zone_id` | string (uuid) | Zone id. |
| `type` | string |  |
| `name` | string | Full name without a trailing dot. |
| `content` | string | Origin content. |
| `ttl` | integer | TTL in seconds. |
| `priority` | integer | MX and SRV priority (null for other types). |
| `proxied` | boolean | Served through the OpenWAF edge. |
| `comment` | string | Comment (empty if none). |
| `tags` | array of string | Tags (empty list if none). |
| `created_at` | string (date-time) | Creation time. |
| `updated_at` | string (date-time) | Last change. |

Response headers: `ETag`, `X-Config-Version`.

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `409` | `zone_merged`: the zone is merged into another one (read-only until it is unmerged or purged). |
| `412` | `version_conflict`: If-Match does not match the current version. |
| `422` | Validation error (`invalid`) or missing or invalid reason (`reason_required`). |

#### Example

**curl**


```sh
curl -X PATCH "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records/0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Point www at the new origin" \
  -H 'If-Match: "12"' \
  -H "Content-Type: application/json" \
  --data '{
    "content": "203.0.113.30"
  }'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.updateRecord({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  record: "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
  body: {
    content: "203.0.113.30"
  }
}, {
  reason: "Point www at the new origin",
  ifMatch: 12
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.update_record(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    record="0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
    body={
        "content": "203.0.113.30"
    },
    reason="Point www at the new origin",
    if_match=12,
)
```



```json
{
  "id": "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
  "org_id": "1e7c9a3b-5d2f-4b8a-9c6e-0f2a4b6c8d1e",
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "type": "A",
  "name": "www.example.com",
  "content": "203.0.113.10",
  "ttl": 300,
  "priority": null,
  "proxied": true,
  "comment": "Web servers",
  "tags": [
    "web"
  ],
  "created_at": "2026-03-02T10:25:00Z",
  "updated_at": "2026-10-27T09:00:00Z"
}
```

## Delete record

```http
DELETE /v1/orgs/{org}/zones/{zone}/records/{record}
```

Deletes a record. Deleting a proxied record stops serving its site.

**Required role:** `tech` or higher.

**Change controls:** [`dry_run`](https://developers.openwaf.dev/api/#configuration-changes) · [`If-Match`](https://developers.openwaf.dev/api/#configuration-changes) (optional) · [`X-Change-Reason`](https://developers.openwaf.dev/api/#configuration-changes) (required)

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `record` | path | string (uuid) | Yes | Record id (see [List records](https://developers.openwaf.dev/api/dns-records/#list-records)). |
| `X-Change-Reason` | header | string | Yes | Reason of the change: 1-500 UTF-8 characters after trimming spaces, no control characters. If it is missing or invalid: 422 `reason_required`. 1 to 500 characters. |
| `If-Match` | header | string | No | Expected configuration version, e.g. `"12"` (`W/` accepted). If it is not the current one: 412 `version_conflict`. |
| `dry_run` | query | string | No | `1`/`true` simulates the change: answers 200 with the plan (`Applied`) and saves nothing. `0`/`false` accepted; any other value: 400. One of `1`, `true`, `0`, `false`. |

#### Response

- `200`: With `dry_run=1`, the plan of the change ([Applied](https://developers.openwaf.dev/api/schemas/#applied)); nothing is saved.
- `204`: Deleted. No body.

Response headers: `ETag`, `X-Config-Version`.

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `404` | Not found, or not visible to the token (`not_found`). |
| `409` | `zone_merged`: the zone is merged into another one (read-only until it is unmerged or purged). |
| `412` | `version_conflict`: If-Match does not match the current version. |
| `422` | Validation error (`invalid`) or missing or invalid reason (`reason_required`). |

#### Example

**curl**


```sh
curl -X DELETE "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/records/0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Remove an unused host" \
  -H 'If-Match: "12"'
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.deleteRecord({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  record: "0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d"
}, {
  reason: "Remove an unused host",
  ifMatch: 12
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.delete_record(
    zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
    record="0c9a7e4d-2b1f-4e6a-8d3c-5f7b9a1c3e5d",
    reason="Remove an unused host",
    if_match=12,
)
```



## Find existing records

```http
GET /v1/orgs/{org}/zones/{zone}/import
```

Queries the current authoritative servers (or public resolvers) for the apex, common names, mail TXT records, SRV records and names seen in Certificate Transparency logs, and returns them for review. Nothing is applied; send the reviewed list to [Create records in bulk](https://developers.openwaf.dev/api/dns-records/#bulk-create-records) or [Batch records](https://developers.openwaf.dev/api/dns-records/#batch-records).

**Required role:** `tech` or higher.

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |

#### Response

- `200`: Returns [ImportResult](https://developers.openwaf.dev/api/schemas/#import-result).

| Field | Type | Description |
|---|---|---|
| `domain` | string |  |
| `servers` | array of string |  |
| `wildcard` | boolean |  |
| `warnings` | array of string | Warnings (the change is still valid). |
| `candidates` | array of object |  |
| `candidates[].type` | string | One of `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SRV`, `CAA`. |
| `candidates[].name` | string | `@`, relative (`www`) or full name; `*` for a wildcard. Default `@`. |
| `candidates[].content` | string | A/AAAA: address. CNAME/NS/MX: host name. TXT: text without quotes (split into 255-character strings). SRV: `weight port target`. CAA: `flags tag "value"`. |
| `candidates[].ttl` | integer | TTL in seconds. Default `3600`. From 60 to 86400. |
| `candidates[].priority` | integer | Required for MX and SRV; not allowed for other types. From 0 to 65535. |
| `candidates[].proxied` | boolean | A/AAAA/CNAME only. The name answers with the edge addresses (TTL 300) and the content is kept as the origin. All A/AAAA/CNAME records of a name share the value. An unproxied CNAME at the apex is published flattened (ALIAS). Default `false`. |
| `candidates[].comment` | string | Attribute of the record (not published in DNS; part of the zone's versions). No control characters. At most 100 characters. |
| `candidates[].tags` | array of string | Attribute of the record, like the comment. Lowercased and deduplicated. At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |
| `candidates[].source` | string | One of `dns`, `crtsh`. |

#### Example

**curl**


```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/import" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.listImportCandidates({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.list_import_candidates(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d")
```



```json
{
  "domain": "example",
  "servers": [
    "example"
  ],
  "wildcard": false,
  "warnings": [],
  "candidates": [
    {
      "type": "A",
      "name": "example.com",
      "content": "203.0.113.10",
      "ttl": 3600,
      "priority": 0,
      "proxied": false,
      "comment": "Web servers",
      "tags": [
        "web"
      ],
      "source": "dns"
    }
  ]
}
```

## Read a BIND zone file

```http
POST /v1/orgs/{org}/zones/{zone}/import/bind
```

Reads a BIND zone file (up to 1 MiB) and returns the records it contains for review. Nothing is applied; apply the chosen candidates with [Batch records](https://developers.openwaf.dev/api/dns-records/#batch-records). Not available in external zones.

It understands `$ORIGIN`, `$TTL`, `@`, relative names, inherited owners, parentheses, comments and multi-string TXT records. It leaves out, with the reason, the SOA and the apex NS records (OpenWAF sets them), other directives, unsupported types or classes, names outside the zone, invalid records, records that already exist in the zone and duplicates.

**Required role:** `tech` or higher.

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |
| `proxied` | query | boolean | No | Proxy the A/AAAA/CNAME records whose name can be a site (no wildcards or `_`). Default `false`. |

#### Request body

Content type `text/plain`.

At most 1048576 characters.

#### Response

- `200`: Returns [BINDImport](https://developers.openwaf.dev/api/schemas/#bind-import).

| Field | Type | Description |
|---|---|---|
| `items` | array of object |  |
| `items[].type` | string | One of `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SRV`, `CAA`. |
| `items[].name` | string | `@`, relative (`www`) or full name; `*` for a wildcard. Default `@`. |
| `items[].content` | string | A/AAAA: address. CNAME/NS/MX: host name. TXT: text without quotes (split into 255-character strings). SRV: `weight port target`. CAA: `flags tag "value"`. |
| `items[].ttl` | integer | TTL in seconds. Default `3600`. From 60 to 86400. |
| `items[].priority` | integer | Required for MX and SRV; not allowed for other types. From 0 to 65535. |
| `items[].proxied` | boolean | A/AAAA/CNAME only. The name answers with the edge addresses (TTL 300) and the content is kept as the origin. All A/AAAA/CNAME records of a name share the value. An unproxied CNAME at the apex is published flattened (ALIAS). Default `false`. |
| `items[].comment` | string | Attribute of the record (not published in DNS; part of the zone's versions). No control characters. At most 100 characters. |
| `items[].tags` | array of string | Attribute of the record, like the comment. Lowercased and deduplicated. At most 10 items. Items match `^[a-z0-9][a-z0-9:_-]{0,31}$`. |
| `items[].source` | string | Always `file`. |
| `skipped` | array of object | At most 200 entries; skipped_total counts them all. |
| `skipped[].line` | integer | Line where the entry starts. |
| `skipped[].text` | string | Entry without comments (up to 200 bytes). |
| `skipped[].reason` | string | Reason of the change. |
| `skipped_total` | integer | Entries left out (all of them, even if skipped only lists the first 200). |
| `truncated` | boolean | The file had more than 5000 entries: only the first 5000 were read. |

#### Errors

| Status | Description |
|---|---|
| `400` | Malformed request (`bad_request`). |
| `404` | Not found, or not visible to the token (`not_found`). |
| `409` | External zone. |
| `413` | `too_large`: the file is larger than 1 MiB. |

#### Example

**curl**


```sh
curl -X POST "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/import/bind" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "Content-Type: text/plain" \
  --data-binary @example.com.zone
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.parseBindZone({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  body: ""
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.parse_bind_zone(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d", body="")
```



```json
{
  "items": [
    {
      "type": "A",
      "name": "example.com",
      "content": "203.0.113.10",
      "ttl": 3600,
      "priority": 0,
      "proxied": false,
      "comment": "Web servers",
      "tags": [
        "web"
      ],
      "source": "file"
    }
  ],
  "skipped": [
    {
      "line": 0,
      "text": "example",
      "reason": "Point www at the new origin"
    }
  ],
  "skipped_total": 128,
  "truncated": false
}
```

## Get edge DNS answers

```http
GET /v1/orgs/{org}/zones/{zone}/dns/answers
```

For a delegated zone, returns the addresses that OpenWAF DNS publishes for each proxied name (the edge addresses) and whether the published answer is up to date (`in_sync`; if not, it is corrected automatically).

**Required role:** `readonly` or higher.

#### Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `org` | path | string (uuid) | Yes | Organization id. Every route checks that it is the token's organization (otherwise `404`). |
| `zone` | path | string (uuid) | Yes | Zone id (see [List zones](https://developers.openwaf.dev/api/zones/#list-zones)). |

#### Response

- `200`: Returns [ZoneAnswers](https://developers.openwaf.dev/api/schemas/#zone-answers).

| Field | Type | Description |
|---|---|---|
| `ipv4` | array of string |  |
| `ipv6` | array of string |  |
| `names` | array of object |  |
| `names[].name` | string | Name. |
| `names[].in_sync` | boolean |  |
| `names[].rrsets` | array of object |  |

#### Errors

| Status | Description |
|---|---|
| `404` | Not found, or not visible to the token (`not_found`). |
| `409` | `conflict`: the zone is external (another provider serves its DNS). |
| `503` | The DNS service is not available right now. |

#### Example

**curl**


```sh
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/dns/answers" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
```

**TypeScript**


```ts
import { OpenWAF } from "./openwaf";

const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getDnsAnswers({
  zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});
```

**Python**


```py
from openwaf import OpenWAF

owf = OpenWAF(base_url="https://dash.openwaf.dev")  # token from OPENWAF_TOKEN
result = owf.get_dns_answers(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d")
```



```json
{
  "ipv4": [
    "example"
  ],
  "ipv6": [
    "example"
  ],
  "names": [
    {
      "name": "example.com",
      "in_sync": false,
      "rrsets": [
        {}
      ]
    }
  ]
}
```
