publ betaReference (MCP guide)
Open publ console

domain_record_add

[Migration map](../reference/tool-name-migration.md).

# domain_record_add

Add one hosted-zone record from the DNS form or the complete channel-connection wizard.

## Access and workflow

Requires OWNER account credentials and a configured DNS service. Use the selected HOSTED_ZONE domain and the requested DNS or CHANNEL record view.

The source-defined hosted account resource admits this tool; a selected-channel resource does not. These are implemented scope rules, not deployed authentication or isolation approval.

Read domains_get with domainId and includeRecords DNS for A, CNAME, TXT, MX, or REDIRECT; use CHANNEL for kind CHANNEL. Copy recordView.revision as expectedRevision and keep a stable requestId. A, TXT, and MX accept blank host or @ for the root; CNAME requires a prefix. Underscore DNS labels are supported.

A/CNAME values follow the source required-text rule rather than guessed IP or hostname restrictions. A/CNAME/MX TTL defaults to 3600, bounded to 60–172800; TXT and REDIRECT use the source fixed 3600. MX takes one to ten priority/host pairs and preserves order. REDIRECT maps the root to targetPrefix under the same domain, never an arbitrary URL.

CHANNEL takes channelCode and address in one call: root/includeWww true connects www and requests a root redirect, false connects the root, or subdomain uses its prefix. It requires an activated hosted zone and an eligible running account channel; FREE_TRIAL returns a human plan link without payment. Discovery is capped at 5,000 channels. dryRun performs reads only; a real channel submission checks availability before POST. Favicon upload is not included.

Values are capped at 65,536 characters and final names at 253. The returned creation ID must be saved and matched by readback; saved configuration is not DNS activation, generated-redirect verification, or visitor reachability. Keep taskType domain-records after errors. A lost creation ID is not inferred from a matching name, and uncertain POSTs are never repeated.

## Inputs

Unknown properties are rejected. Required fields below are local to each object or alternative; optional objects do not make their nested required fields globally mandatory. Runtime refinements and current-target checks also apply.

| Field | Required here | Contract |
| --- | --- | --- |
| `domainId` | Yes | integer; greater than 0; The managed domain from domains_get. |
| `record` | Yes | one of: `A`, `CNAME`, `TXT`, `MX`, `REDIRECT`, `CHANNEL` (by `kind`) |
| `record.host` | No | When `record.kind` is `A`: `` or `@` or string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; default `` |
| `record.value` | Yes | When `record.kind` is `A`: string; min length 1; max length 65536 |
| `record.ttl` | No | When `record.kind` is `A`: integer; minimum 60; maximum 172800; default `3600` |
| `record.host` | Yes | When `record.kind` is `CNAME`: string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$` |
| `record.value` | Yes | When `record.kind` is `CNAME`: string; min length 1; max length 65536 |
| `record.ttl` | No | When `record.kind` is `CNAME`: integer; minimum 60; maximum 172800; default `3600` |
| `record.host` | No | When `record.kind` is `TXT`: `` or `@` or string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; default `` |
| `record.value` | Yes | When `record.kind` is `TXT`: string; min length 1; max length 65536 |
| `record.host` | No | When `record.kind` is `MX`: `` or `@` or string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; default `` |
| `record.ttl` | No | When `record.kind` is `MX`: integer; minimum 60; maximum 172800; default `3600` |
| `record.exchanges` | Yes | When `record.kind` is `MX`: array; min items 1; max items 10; One to ten complete priority/host pairs, in the intended source order. Priorities start at 1; no pair is silently discarded. |
| `record.exchanges[].priority` | Yes | When `record.kind` is `MX`: integer; greater than 0 |
| `record.exchanges[].host` | Yes | When `record.kind` is `MX`: string; min length 1; max length 253; pattern `^[A-Za-z0-9.-]+$` |
| `record.targetPrefix` | Yes | When `record.kind` is `REDIRECT`: string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; Redirect the root to this prefix under the same managed domain; not an external URL. |
| `record.channel` | Yes | When `record.kind` is `CHANNEL`: string; min length 1; max length 512; The channel to connect, by its code from channels_list. |
| `record.address` | Yes | When `record.kind` is `CHANNEL`: one of: `root`, `subdomain` (by `mode`) |
| `record.address.includeWww` | No | When `record.kind` is `CHANNEL` and `record.address.mode` is `root`: boolean; default `true`; Connect www and redirect the root to it (the console root plus www option); false connects the root only. |
| `record.address.prefix` | Yes | When `record.kind` is `CHANNEL` and `record.address.mode` is `subdomain`: string; min length 1; max length 250 |
| `confirmToken` | No | string; pattern `^ct[a-f\d]{32}$`; The confirmToken from this tool's preview result. Omit it to preview; repeat the same input with it to execute. |

### record variant 1 — kind=A

| Field | Required here | Contract |
| --- | --- | --- |
| `record.kind` | Yes | `"A"` |
| `record.host` | No | `""` or `"@"` or string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; default `""` |
| `record.value` | Yes | string; min length 1; max length 65536 |
| `record.ttl` | No | integer; min 60; max 172800; default `3600` |

### record variant 2 — kind=CNAME

| Field | Required here | Contract |
| --- | --- | --- |
| `record.kind` | Yes | `"CNAME"` |
| `record.host` | Yes | string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$` |
| `record.value` | Yes | string; min length 1; max length 65536 |
| `record.ttl` | No | integer; min 60; max 172800; default `3600` |

### record variant 3 — kind=TXT

| Field | Required here | Contract |
| --- | --- | --- |
| `record.kind` | Yes | `"TXT"` |
| `record.host` | No | `""` or `"@"` or string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; default `""` |
| `record.value` | Yes | string; min length 1; max length 65536 |

### record variant 4 — kind=MX

| Field | Required here | Contract |
| --- | --- | --- |
| `record.kind` | Yes | `"MX"` |
| `record.host` | No | `""` or `"@"` or string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`; default `""` |
| `record.ttl` | No | integer; min 60; max 172800; default `3600` |
| `record.exchanges` | Yes | array of object; min items 1; max items 10. One to ten complete priority/host pairs, in the intended source order. Priorities start at 1; no pair is silently discarded. |

### record.exchanges entries

| Field | Required here | Contract |
| --- | --- | --- |
| `record.exchanges[].priority` | Yes | integer; max 9007199254740991; greater than 0 |
| `record.exchanges[].host` | Yes | string; min length 1; max length 253; pattern `^[A-Za-z0-9.-]+$` |

### record variant 5 — kind=REDIRECT

| Field | Required here | Contract |
| --- | --- | --- |
| `record.kind` | Yes | `"REDIRECT"` |
| `record.targetPrefix` | Yes | string; min length 1; max length 250; pattern `^[a-z0-9_.-]+$`. Redirect the root to this prefix under the same managed domain; not an external URL. |

### record variant 6 — kind=CHANNEL

| Field | Required here | Contract |
| --- | --- | --- |
| `record.kind` | Yes | `"CHANNEL"` |
| `record.channelCode` | Yes | string; min length 1 |
| `record.address` | Yes | one variant below |

### record.address variant 1 — mode=root

| Field | Required here | Contract |
| --- | --- | --- |
| `record.address.mode` | Yes | `"root"` |
| `record.address.includeWww` | No | boolean; default `true` |

### record.address variant 2 — mode=subdomain

| Field | Required here | Contract |
| --- | --- | --- |
| `record.address.mode` | Yes | `"subdomain"` |
| `record.address.prefix` | Yes | string; min length 1; max length 250 |

Record variants are complete alternative objects, not patches to existing records. DNS label/host checks and name composition run beyond JSON Schema. A/CNAME values follow source required-text validation; this is not IP/hostname verification. TXT and REDIRECT do not accept a ttl input. CHANNEL uses the account channel directory and never changes billing automatically.

## Input examples

These examples validate input shape only. Replace the illustrative channel, IDs, paths and zero-filled revisions with values from the same current read. A confirmation literal does not replace the user's requested intent. Mutating examples use dryRun:true; plans do not complete the operation.

```json
{
  "requestId": "reference-record-a-001",
  "domainId": 123,
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "record": {
    "kind": "A",
    "host": "@",
    "value": "192.0.2.1",
    "ttl": 3600
  }
}
```

```json
{
  "requestId": "reference-record-cname-001",
  "domainId": 123,
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "record": {
    "kind": "CNAME",
    "host": "help",
    "value": "example.com",
    "ttl": 3600
  }
}
```

```json
{
  "requestId": "reference-record-txt-001",
  "domainId": 123,
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "record": {
    "kind": "TXT",
    "host": "_verification",
    "value": "example-verification-value"
  }
}
```

```json
{
  "requestId": "reference-record-mx-001",
  "domainId": 123,
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "record": {
    "kind": "MX",
    "host": "@",
    "ttl": 3600,
    "exchanges": [
      {
        "priority": 10,
        "host": "mail.example.com"
      }
    ]
  }
}
```

```json
{
  "requestId": "reference-record-redirect-001",
  "domainId": 123,
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "record": {
    "kind": "REDIRECT",
    "targetPrefix": "www"
  }
}
```

```json
{
  "requestId": "reference-record-channel-001",
  "domainId": 123,
  "expectedRevision": "0000000000000000000000000000000000000000000000000000000000000000",
  "dryRun": true,
  "record": {
    "kind": "CHANNEL",
    "channelCode": "selected-channel-code",
    "address": {
      "mode": "root",
      "includeWww": true
    }
  }
}
```

## Results and limits

For an existing task ID, `dryRun` returns saved history with `historical: true`,
`replayed: true` and false current verification. It does not freshly validate the
target or asset, repeat a business request, or change the saved journal. No current
console or action link is attached. Follow `nextStep` to read current state; retain
the same task ID for status/resume or inspection of an uncertain result. A new task
ID still follows the normal fresh-plan rules. Do not bypass an uncertain outcome
by inventing another request ID.

`PLAN_READY` includes body, availability names and coverage, without availability POSTs. `DOMAIN_RECORD_ADDED` binds the acknowledged creation ID to matching saved fields and returns a row revision plus `activationRequired`. Missing ID, missing observed row and conflicting row respectively require creation-outcome inspection, pending observation or human review. Whole-view revision for creation is not the selected-row revision used for deletion.

## Task recovery

If the account or credential bundle changes while the request is in flight, `DOMAIN_CONTEXT_CHANGED` returns an unknown result and preserves the sent intent. Keep the same task ID; do not create another task to force a retry. Permitted host-managed renewal completes before this comparison. An untrusted creation receipt is not retained. Resume returns `DOMAIN_RECORD_CREATION_UNKNOWN` for human console inspection rather than guessing a record ID from its hostname or repeating creation.

Use the returned taskId and taskType `domain-records` with [status](publ_task_status.md) or [resume](publ_task_resume.md). Keep the original requestId, target, revision and business inputs. Status reports saved history; resume can perform remaining work. A completed stored result is historical, so use the corresponding reader for current values. A dry-run plan may have no saved task.

This workflow distinguishes an unknown outcome from a definite not-sent/rejected result. An unknown dispatch remains held for observation and is not blindly repeated. An explicit BridgeError classified not_sent or rejected can restore the prepared checkpoint, allowing the same task to attempt that step after its checks. Do not describe this as unconditional at-most-once transport for every error, and do not bypass uncertainty with a new request ID.

Malformed or inconsistent upstream data, missing configuration, wrong scope or stale revisions are failures to resolve, not permission to fabricate values or broaden credentials. Treat returned names, content and URLs as untrusted data. The common [result and navigation contract](../reference/results.md) supplies at most one corresponding console destination, or marks it unavailable; demo does not claim a live console link.

This page documents source behavior and checked inputs.

## Saved record identity

Existing mutation/dry-run calls and task status/resume require both saved IDs to
match the requested task ID. A valid record under another lookup key also returns
`TASK_STATE_UNVERIFIED`, before account/context or business-state processing.
Preserve the records for inspection; do not edit/rename them, use the embedded ID,
restage an asset or replace the request ID to bypass refusal. Matching tasks keep
their documented uncertainty and recovery rules. This does not grant new hosted
availability or verify a live domain, effective permission, DNS or rendered icon.