Support
DomainsManage Domains

Manage DNS records

View as Markdown

Manage DNS records and nameservers using the v3 API. Add, read, and delete individual DNS records, and replace authoritative nameservers with a single PUT request.

Overview

Create, read, and delete DNS records for domains hosted on GoDaddy's authoritative nameservers, and replace the authoritative nameservers themselves. All operations use the v3 API.

This page covers two related operations:

OperationDescription
DNS recordsCreate and retrieve A, AAAA, CNAME, MX, TXT, SRV, NS, and CAA records on a domain hosted by GoDaddy's authoritative DNS.
NameserversChange which authoritative nameservers the registry returns for a domain.

This page uses three OAuth scopes: domains.domain:read to list records, domains.dns:update to create and delete records, and domains.nameserver:update to replace nameservers. Go to Authentication for more information.

List DNS records

GET /v3/domains/zones/{zone}/dns-records returns a paginated collection of records for the zone. Use type and name query parameters to filter results.

The following procedure retrieves DNS records for a zone.

  • Run the following command for your preferred language:
# All records
curl -s "https://api.godaddy.com/v3/domains/zones/example.com/dns-records" \
  -H "Authorization: Bearer $GODADDY_PAT"

# Filter by type
curl -s "https://api.godaddy.com/v3/domains/zones/example.com/dns-records?type=A" \
  -H "Authorization: Bearer $GODADDY_PAT"

# Filter by type and name
curl -s "https://api.godaddy.com/v3/domains/zones/example.com/dns-records?type=TXT&name=_acme-challenge" \
  -H "Authorization: Bearer $GODADDY_PAT"
const pat = process.env.GODADDY_PAT;
const zone = "example.com";
const url = new URL(`https://api.godaddy.com/v3/domains/zones/${zone}/dns-records`);
url.searchParams.set("type", "TXT");
url.searchParams.set("name", "_acme-challenge");

const res = await fetch(url, {
  headers: { Authorization: `Bearer ${pat}` },
});
const records = await res.json();
console.log(records.items);
import os, requests

pat = os.environ["GODADDY_PAT"]
zone = "example.com"

res = requests.get(
    f"https://api.godaddy.com/v3/domains/zones/{zone}/dns-records",
    params={"type": "TXT", "name": "_acme-challenge"},
    headers={"Authorization": f"Bearer {pat}"},
)
res.raise_for_status()
for record in res.json()["items"]:
    print(record["name"], record["type"], record["data"])
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
    "os"
)

func main() {
    pat := os.Getenv("GODADDY_PAT")
    zone := "example.com"

    u, _ := url.Parse(fmt.Sprintf("https://api.godaddy.com/v3/domains/zones/%s/dns-records", zone))
    q := u.Query()
    q.Set("type", "TXT")
    q.Set("name", "_acme-challenge")
    u.RawQuery = q.Encode()

    req, _ := http.NewRequest("GET", u.String(), nil)
    req.Header.Set("Authorization", "Bearer "+pat)

    res, err := http.DefaultClient.Do(req)
    if err != nil { panic(err) }
    defer res.Body.Close()

    var body struct {
        Items []map[string]any `json:"items"`
    }
    json.NewDecoder(res.Body).Decode(&body)
    fmt.Println(body.Items)
}

The response is a DNSRecords object with an items array of DNSRecord entries. Each record includes a recordId needed for delete operations. Go to the DNSRecord schema for the full field reference.

DNSRecord schema

Every entry in items[] is a DNSRecord object.

FieldRequiredDescriptionNote
recordIdRead-onlyServer-assigned stable identifier for the record.
nameYesRecord name relative to the zone apex.Use @ for the apex. Wildcards (*) supported for A, AAAA, and CNAME.
typeYesRecord type: A, AAAA, CNAME, MX, TXT, SRV, NS, CAA, ALIAS, or SOA (SOA is read-only).
dataYesRecord value.Format depends on type: IP for A/AAAA, hostname for CNAME, text for TXT, etc.
ttlYesTime-to-live in seconds.Minimum 600 (10 min), maximum 86400 (24 hrs).
priorityMX, SRVPriority value.Lower value equals higher preference.
weightSRVRelative weight among equal-priority targets.
portSRVTarget port number.
serviceSRVService name.Prefixed with an underscore (for example, _http).
protocolSRVTransport protocol.Prefixed with underscore (for example, _tcp).
flagCAARestriction flags byte.Use 0 for non-critical, 128 for critical.
tagCAAProperty tag: issue, issuewild, or iodef.

Pagination

Results are page-based. Use page (1-based, default 1) and pageSize (1–100, default 25) to navigate.

The following procedure paginates through DNS records.

  • Navigate pages:
curl -s "https://api.godaddy.com/v3/domains/zones/example.com/dns-records?page=2&pageSize=50" \
  -H "Authorization: Bearer $GODADDY_PAT"

Add totalRequired=true to include totalItems and totalPages in the response — omitted by default to avoid count-query overhead on large zones. The response links array contains HATEOAS navigation links (self, first, last, next, prev) where applicable.

Add a record

POST /v3/domains/zones/{zone}/dns-records creates a single DNS record in the zone. Changes are applied synchronously — no polling required.

The following procedure adds a DNS record to a zone.

  • Create a record:
curl -s -X POST "https://api.godaddy.com/v3/domains/zones/example.com/dns-records" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "Content-Type: application/json" \
  -d '{ "type": "TXT", "name": "_acme-challenge", "data": "verification-string", "ttl": 600 }'
const pat = process.env.GODADDY_PAT;
const zone = "example.com";

const res = await fetch(
  `https://api.godaddy.com/v3/domains/zones/${zone}/dns-records`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${pat}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ type: "TXT", name: "_acme-challenge", data: "verification-string", ttl: 600 }),
  },
);
const record = await res.json();
console.log("Created record", record.recordId);
import os, requests

pat = os.environ["GODADDY_PAT"]
zone = "example.com"

res = requests.post(
    f"https://api.godaddy.com/v3/domains/zones/{zone}/dns-records",
    json={"type": "TXT", "name": "_acme-challenge", "data": "verification-string", "ttl": 600},
    headers={
        "Authorization": f"Bearer {pat}",
        "Content-Type": "application/json",
    },
)
res.raise_for_status()
print("Created record", res.json()["recordId"])
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
    "os"
)

func main() {
    pat := os.Getenv("GODADDY_PAT")
    zone := "example.com"

    body := bytes.NewReader([]byte(
        `{"type":"TXT","name":"_acme-challenge","data":"verification-string","ttl":600}`))
    req, _ := http.NewRequest("POST",
        fmt.Sprintf("https://api.godaddy.com/v3/domains/zones/%s/dns-records", zone), body)
    req.Header.Set("Authorization", "Bearer "+pat)
    req.Header.Set("Content-Type", "application/json")

    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()

    var record struct{ RecordID string `json:"recordId"` }
    json.NewDecoder(res.Body).Decode(&record)
    fmt.Println("Created record", record.RecordID)
}

A successful response returns 201 with the created DNSRecord in the body. The Location header contains the URL for the new record, with the recordId you'll need for deletes.

Not idempotent

Replaying a POST after a 5xx may create a duplicate record. Save the recordId from the Location header on success so you can clean up if needed. See Errors → Retry semantics.

Delete a record

DELETE /v3/domains/zones/{zone}/dns-records/{recordId} permanently removes a single record from the zone. Changes are applied synchronously.

The following procedure deletes a DNS record from a zone.

  • Delete a record:
curl -s -X DELETE "https://api.godaddy.com/v3/domains/zones/example.com/dns-records/$RECORD_ID" \
  -H "Authorization: Bearer $GODADDY_PAT"
const pat = process.env.GODADDY_PAT;
const zone = "example.com";
const recordId = process.env.RECORD_ID;

const res = await fetch(
  `https://api.godaddy.com/v3/domains/zones/${zone}/dns-records/${recordId}`,
  {
    method: "DELETE",
    headers: { Authorization: `Bearer ${pat}` },
  },
);
console.log(res.status); // expect 204
import os, requests

pat = os.environ["GODADDY_PAT"]
zone = "example.com"
record_id = os.environ["RECORD_ID"]

res = requests.delete(
    f"https://api.godaddy.com/v3/domains/zones/{zone}/dns-records/{record_id}",
    headers={"Authorization": f"Bearer {pat}"},
)
print(res.status_code)  # expect 204
package main

import (
    "fmt"
    "net/http"
    "os"
)

func main() {
    pat := os.Getenv("GODADDY_PAT")
    zone := "example.com"
    recordID := os.Getenv("RECORD_ID")

    req, _ := http.NewRequest("DELETE",
        fmt.Sprintf("https://api.godaddy.com/v3/domains/zones/%s/dns-records/%s", zone, recordID), nil)
    req.Header.Set("Authorization", "Bearer "+pat)

    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    fmt.Println(res.StatusCode) // expect 204
}

A successful response returns 204 with no body.

Not idempotent

A 404 is returned if the recordId does not exist — deleting an already-deleted record is not a no-op. GoDaddy-managed SOA and NS records cannot be deleted; attempting to do so returns 409 Conflict.

Manage nameservers

PUT /v3/domains/domain-names/{domain-name}/nameservers replaces the authoritative nameservers for a domain. Accepts a plain array of 2–13 nameserver hostnames.

The following procedure replaces the authoritative nameservers for a domain.

  • Replace a nameserver for a domain:
curl -s -X PUT "https://api.godaddy.com/v3/domains/domain-names/example.com/nameservers" \
  -H "Authorization: Bearer $GODADDY_PAT" \
  -H "Content-Type: application/json" \
  -d '["ns1.example-dns.com", "ns2.example-dns.com"]'
const pat = process.env.GODADDY_PAT;

const res = await fetch(
  "https://api.godaddy.com/v3/domains/domain-names/example.com/nameservers",
  {
    method: "PUT",
    headers: {
      Authorization: `Bearer ${pat}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(["ns1.example-dns.com", "ns2.example-dns.com"]),
  },
);
console.log(res.status); // expect 202
import os, requests

res = requests.put(
    "https://api.godaddy.com/v3/domains/domain-names/example.com/nameservers",
    json=["ns1.example-dns.com", "ns2.example-dns.com"],
    headers={
        "Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
        "Content-Type": "application/json",
    },
)
print(res.status_code)  # expect 202
package main

import (
    "bytes"
    "fmt"
    "net/http"
    "os"
)

func main() {
    body := bytes.NewReader([]byte(`["ns1.example-dns.com","ns2.example-dns.com"]`))
    req, _ := http.NewRequest("PUT",
        "https://api.godaddy.com/v3/domains/domain-names/example.com/nameservers", body)
    req.Header.Set("Authorization", "Bearer "+os.Getenv("GODADDY_PAT"))
    req.Header.Set("Content-Type", "application/json")

    res, _ := http.DefaultClient.Do(req)
    defer res.Body.Close()
    fmt.Println(res.StatusCode) // expect 202
}

A successful request returns 202 Accepted with a DomainOperation in the body and a Location header pointing to the operation URL. Propagation to the registry is asynchronous — poll the operation until it reaches a terminal state.

Authoritative DNS hand-off

Switching nameservers moves authoritative DNS off GoDaddy. Records you manage via /v3/domains/zones/{zone}/dns-records will no longer be served — make sure the new nameservers are fully configured before cutting over.

Use the CLI

After you set up the CLI, you can use it to list, add, replace, and delete DNS records on domains that use GoDaddy authoritative DNS.

The following procedure manages DNS records using the CLI.

  • Run the command for your operation:
gddy dns list example.com
gddy dns list example.com --type A --name www
gddy dns add example.com --type A --name www --data 192.0.2.10 --ttl 600
gddy dns set example.com --type A --name www --data 192.0.2.20 --ttl 600
gddy dns delete example.com --type A --name www

gddy dns add appends records. gddy dns set replaces every record for the type and name. gddy dns delete removes every record for the type and name; it does not delete GoDaddy-managed NS or SOA records. Use --dry-run with destructive commands when you want a preview.

Use the REST API for nameserver delegation; the CLI focuses on DNS record management.

Common errors

StatusMost likely cause
400Malformed request — missing required field, invalid field type, or unknown record type. Inspect fields[].
401Authentication credentials are missing or invalid.
403Caller is not authorized. Check that your token includes the required scope (domains.dns:update or domains.nameserver:update).
404Record or domain not found, or not owned by the authenticated account.
409Conflict — request cannot be completed in the current state. For DNS: attempting to delete a GoDaddy-managed SOA or NS record (dns_record_not_mutable).
422Valid structure but violates a business rule (e.g. CNAME at apex).
429Rate limit exceeded.

Full error envelope: Errors.

DNSRecord schema

FieldRequiredDescriptionNote
recordIdRead-onlyServer-assigned stable identifier for the record.
nameYesRecord name relative to the zone apex.Use @ for the apex. Wildcards (*) supported for A, AAAA, and CNAME.
typeYesRecord type: A, AAAA, CNAME, MX, TXT, SRV, NS, CAA, ALIAS, or SOA (SOA is read-only).
dataYesRecord value.Format depends on type (like IP for A/AAAA, hostname for CNAME, and text for TXT).
ttlYesTime-to-live in seconds.Minimum 600 (10 min), maximum 86400 (24 hrs).
priorityMX, SRVPriority value.Lower value equals higher preference.
weightSRVRelative weight among equal-priority targets.
portSRVTarget port number.
serviceSRVService name.Prefixed with an underscore (for example, _http).
protocolSRVTransport protocol.Prefixed with underscore (for example, _tcp).
flagCAARestriction flags byte.Use 0 for non-critical, 128 for critical.
tagCAAProperty tag: issue, issuewild, or iodef.

Reference

Next

Agent & Automation Notes

PermissionsDNS Management
Scopesdomains.domain:read, domains.dns:update, domains.nameserver:update
Rate limit60 req/min per credential
IdempotentNo
DestructiveYes — confirm before executing
On failureRead operations are safe to retry. Deletes are irreversible — confirm the recordId before calling DELETE. Re-read the zone after failures to verify state.

Last updated on

How is this guide?

On this page