# Create a DNS record

> Add a proxied DNS record from code with the SDK, simulating it first, reviewing the diff and confirming it against the zone version.

This adds `www.example.com` as a proxied A record, served through the OpenWAF edge, with the full simulate-then-confirm protocol. The token needs the **Tech** role.

**TypeScript**

```ts
import { OpenWAF, OpenWAFError, type Applied } from "./openwaf.ts";

const owf = new OpenWAF();

// 1. Find the zone's id.
const { items: zones = [] } = await owf.listZones();
const zone = zones.find((z) => z.name === "example.com");
if (!zone?.id) throw new Error("example.com not found");

const record = { type: "A", name: "www", content: "203.0.113.10", proxied: true } as const;
const reason = "Add www behind the WAF";

// 2. Simulate: nothing is applied.
const plan = (await owf.createRecord({ zone: zone.id, body: record }, { reason, dryRun: true })) as Applied;
for (const c of plan.diff?.changes ?? []) console.log(c.op, c.path);
console.log(`version ${plan.from_version} → ${plan.to_version}`, plan.warnings);

// 3. Confirm with the version the plan was made against.
try {
  const created = await owf.createRecord({ zone: zone.id, body: record }, { reason, ifMatch: plan.from_version! });
  console.log("created", created);
} catch (err) {
  if (err instanceof OpenWAFError && err.code === "version_conflict") {
    console.error("The zone changed in the meantime: run again and review the new plan.");
  } else {
    throw err;
  }
}
```
**Python**

```py
from openwaf import OpenWAF, OpenWAFError

owf = OpenWAF()

# 1. Find the zone's id.
zone = next(z for z in owf.list_zones()["items"] if z["name"] == "example.com")

record = {"type": "A", "name": "www", "content": "203.0.113.10", "proxied": True}
reason = "Add www behind the WAF"

# 2. Simulate: nothing is applied.
plan = owf.create_record(zone=zone["id"], body=record, reason=reason, dry_run=True)
for change in plan["diff"]["changes"]:
    print(change["op"], change["path"])
print("version %d -> %d" % (plan["from_version"], plan["to_version"]), plan["warnings"])

# 3. Confirm with the version the plan was made against.
try:
    created = owf.create_record(zone=zone["id"], body=record, reason=reason, if_match=plan["from_version"])
    print("created", created)
except OpenWAFError as e:
    if e.code != "version_conflict":
        raise
    print("The zone changed in the meantime: run again and review the new plan.")
```


The simulation prints one change, `add records[id=…]`, and the version the record would create. The confirmed call answers the new record with its `id`.

## Several records in one change

To create, update and delete several records as **one** version, use `batchRecords` / `batch_records` (up to 500 operations, all or nothing), with a body of `create`, `update` and `delete` lists. It takes the same `reason`, `dryRun` and `ifMatch` options.

## Record fields

`type` and `content` are required; `name`, `ttl`, `priority` (MX and SRV only), `proxied` (A, AAAA and CNAME only), `comment` and `tags` are optional. The [CLI records reference](https://developers.openwaf.dev/cli/reference/records/#records-add) describes each field; the [API reference](https://developers.openwaf.dev/api/) has the full schema.
