Skip to main content
id
string
required
Domain UUID
type
string
required
One of A, AAAA, CNAME, MX, TXT, CAA
value
string
required
Record value: IPv4 (A), IPv6 (AAAA), hostname (CNAME/MX), TXT string, or CAA value (0 issue "letsencrypt.org")
name
string
Record name. Use @ or omit for the zone apex. e.g. www for www.acme.com.
ttl
integer
TTL in seconds. Must be 60-86400.
priority
integer
MX priority (required for MX). Must be 0-65535.
mode
string
replace (default) PATCHes a single matching record at the same (type, name), or add-then-deletes when multiple match. append always creates a new row.
acknowledge_unowned
boolean
Required to overwrite an existing record that wasn’t created by Naive. Defaults to false.
curl -X POST https://api.usenaive.ai/v1/domains/dom-uuid-2/zone-records \
  -H "Authorization: Bearer nv_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "type": "A", "name": "@", "value": "76.76.21.21" }'
{
  "ok": true,
  "record": {
    "id": "rec_xyz",
    "type": "CNAME",
    "name": "www",
    "value": "shops.myshopify.com"
  },
  "mock": false,
  "ownership": "naive",
  "replaced_count": 1,
  "path": "patch"
}

Apex A/AAAA writes flip app_connect_status

When the request creates or replaces an apex A or AAAA record (i.e. name is empty, @, or the zone domain itself), the API atomically transitions the domain’s app_connect_status:
  1. Pre-flip to agent_managed_pending and clear connected_app_id.
  2. Write to the DNS zone.
  3. On success → flip to agent_managed and emit a domain.updated event with payload.action = "agent_managed" on the live event stream.
  4. On failure → roll back to the previous app_connect_status (best-effort).
After this, reapers and connect sweeps in either Naive product (SDK or paperclip on a shared DB) skip this domain. To re-enable Naive app routing, the user must explicitly disconnect and reconnect the domain from the dashboard; the agent cannot reverse this automatically.

Replace Semantics

When mode is replace (the default) and type is not CAA:
Existing matching recordsPathBehavior
0addA fresh record is created
1patchThe record is updated in place atomically — no race window
≥2add-then-deleteThe new authoritative record is added first; the old ones are best-effort deleted
CAA records always use add (multiple CAA rows at the same name are semantically valid).

Ownership

Records written by this endpoint carry a comment like naive:owned;company=<id>;agent=<id>;ts=<unix>. To overwrite a record that wasn’t created by Naive (e.g. legacy records left at the registrar), pass acknowledge_unowned: true. The response’s ownership field will be unowned-acknowledged in that case.

Validation Rules

The API enforces strict validation. Each rule maps to a reason code in the error response:
RuleReason
Allowed types only: A, AAAA, CNAME, MX, TXT, CAADISALLOWED_RECORD_TYPE
Wildcards (* or *.foo) are rejectedDISALLOWED_RECORD_TYPE
TTL must be 60-86400 secondsINVALID_TTL
Valid IPv4 for AINVALID_IPV4
Valid IPv6 for AAAAINVALID_IPV6
CNAME at apex is not permittedCNAME_AT_APEX
CNAME target must be a valid hostnameINVALID_HOSTNAME
MX priority required (0-65535)INVALID_MX_PRIORITY
MX target must be a valid hostnameINVALID_HOSTNAME
TXT must be ASCII and ≤4096 charsINVALID_TXT
CAA value must match &lt;flag&gt; (issue|issuewild|iodef) "&lt;value&gt;"INVALID_CAA
CAA flag must be 0 or 128INVALID_CAA
CAA issue/issuewild value must be in the CA allowlistCA_NOT_ALLOWED
CAA iodef must use mailto: or https://INVALID_CAA
CNAME cannot coexist with A/AAAA/MX/TXT at the same name (and vice versa)CNAME_COEXISTENCE
DMARC (_dmarc) and DKIM (*._domainkey) TXT records are protectedPROTECTED_RECORD
Inbound subdomain MX/TXT (e.g. agents.acme.com) is protectedPROTECTED_RECORD

Allowed CAs

ssl.com, letsencrypt.org, digicert.com, sectigo.com, globalsign.com, amazon.com, pki.goog, google.com.

Errors

StatuscodereasonCause
400invalid_inputDISALLOWED_RECORD_TYPE, INVALID_TTL, INVALID_IPV4, INVALID_IPV6, CNAME_AT_APEX, INVALID_HOSTNAME, INVALID_MX_PRIORITY, INVALID_TXT, INVALID_CAA, CA_NOT_ALLOWED, CNAME_COEXISTENCEInput failed validation
403forbiddenSYSTEM_DOMAIN, PROTECTED_RECORDSystem domain or protected record
404resource_not_foundDOMAIN_NOT_FOUNDDomain doesn’t exist or belongs to another company
409duplicate_recordUNOWNED_RECORD_REQUIRES_ACKExisting record at this (type, name) was not created by Naive — re-issue with acknowledge_unowned: true
429rate_limitedRATE_LIMITEDPer-company (5/min, 20/hr) or platform write budget exhausted. Includes Retry-After header.
501feature_not_configuredFEATURE_DISABLED, MOCK_MODE_REJECTEDFeature flag off or no DNS provider credentials configured
502provider_errorDNS_PROVIDER_ERRORThe DNS layer returned a non-429 error; details in the dns_provider field