End-to-end workflow
View as MarkdownComplete workflow for buying and configuring a domain — search, quote, register, add DNS, verify. Runnable start-to-finish in under 5 minutes.
What you'll build
A complete end-to-end workflow: search for an available domain, lock a price with a quote, register it (with idempotency for retry safety), add a DNS record, and verify. Every step is copy-paste runnable in curl, Node, Python, or Go.
Overview
Prerequisites: a GoDaddy account with a payment method on file, a Personal Access Token with domains.domain:read, domains.registration:write, and domains.dns:update scopes, and the CLI or curl. Export the token:
export GODADDY_PAT="<YOUR_TOKEN>"
export BASE="https://api.godaddy.com" # or api.ote-godaddy.com for testingCheck availability
GET /v3/domains/check-availability returns availability and indicative pricing for a domain.
curl -s "$BASE/v3/domains/check-availability?domain=example.com" \
-H "Authorization: Bearer $GODADDY_PAT"const res = await fetch(`${process.env.BASE}/v3/domains/check-availability?domain=example.com`, {
headers: { Authorization: `Bearer ${process.env.GODADDY_PAT}` },
});
const { available, prices } = await res.json();
if (!available) throw new Error("Domain not available");
console.log("Available at", prices[0].price.value / 100, prices[0].price.currencyCode);import os, requests
res = requests.get(
f"{os.environ['BASE']}/v3/domains/check-availability",
params={"domain": "example.com"},
headers={"Authorization": f"Bearer {os.environ['GODADDY_PAT']}"},
)
data = res.json()
assert data["available"], "Domain not available"
price = data["prices"][0]["price"]
print(f"Available at {price['value'] / 100} {price['currencyCode']}")package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type Price struct {
Value int `json:"value"`
CurrencyCode string `json:"currencyCode"`
}
func main() {
req, _ := http.NewRequest("GET",
os.Getenv("BASE")+"/v3/domains/check-availability?domain=example.com", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("GODADDY_PAT"))
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
var data struct {
Available bool `json:"available"`
Prices []struct{ Price Price } `json:"prices"`
}
json.NewDecoder(res.Body).Decode(&data)
if !data.Available { panic("not available") }
fmt.Printf("Available at %d %s\n", data.Prices[0].Price.Value/100, data.Prices[0].Price.CurrencyCode)
}Response shape:
{
"domain": "example.com",
"available": true,
"prices": [
{ "term": "YEAR", "period": 1, "price": { "currencyCode": "USD", "value": 1199 } }
]
}Get a registration quote
POST /v3/domains/registration-quotes locks the price. The returned quoteToken guarantees the price you see is the price you'll pay when you execute registration.
curl -s -X POST "$BASE/v3/domains/registration-quotes" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com", "period": 1}'const res = await fetch(`${process.env.BASE}/v3/domains/registration-quotes`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GODADDY_PAT}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ domain: "example.com", period: 1 }),
});
const { quoteToken, expiresAt } = await res.json();
console.log("Quote locked until", expiresAt);import os, requests
res = requests.post(
f"{os.environ['BASE']}/v3/domains/registration-quotes",
json={"domain": "example.com", "period": 1},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
quote = res.json()
print("Quote locked until", quote["expiresAt"])body := strings.NewReader(`{"domain": "example.com", "period": 1}`)
req, _ := http.NewRequest("POST",
os.Getenv("BASE")+"/v3/domains/registration-quotes", 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()
var quote struct {
QuoteToken string `json:"quoteToken"`
ExpiresAt string `json:"expiresAt"`
}
json.NewDecoder(res.Body).Decode("e)
fmt.Println("Quote locked until", quote.ExpiresAt)Register the domain
POST /v3/domains/registrations executes the registration. Send an Idempotency-Key header — if the request times out or returns 5xx, replay with the same key and the server dedupes.
Charges real money
This call charges the account's payment profile. Verify the domain name and quoted price before executing.
curl -s -X POST "$BASE/v3/domains/registrations" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"quoteToken": "qt_abc123...",
"domain": "example.com",
"period": 1,
"consent": {
"agreedAt": "2026-07-07T10:30:00.000Z",
"agreementTypes": ["API_DPA"]
}
}'import { randomUUID } from "node:crypto";
const res = await fetch(`${process.env.BASE}/v3/domains/registrations`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GODADDY_PAT}`,
"Content-Type": "application/json",
"Idempotency-Key": randomUUID(),
},
body: JSON.stringify({
quoteToken: "qt_abc123...",
domain: "example.com",
period: 1,
consent: {
agreedAt: new Date().toISOString(),
agreementTypes: ["API_DPA"]
},
}),
});
if (res.status !== 201) throw new Error(`Registration failed: ${res.status}`);
console.log("Registered:", (await res.json()).domain);import os, uuid, requests
from datetime import datetime, timezone
res = requests.post(
f"{os.environ['BASE']}/v3/domains/registrations",
json={
"quoteToken": "qt_abc123...",
"domain": "example.com",
"period": 1,
"consent": {
"agreedAt": datetime.now(timezone.utc).isoformat(),
"agreementTypes": ["API_DPA"]
},
},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
)
res.raise_for_status()
print("Registered:", res.json()["domain"])import "github.com/google/uuid"
body := map[string]any{
"quoteToken": "qt_abc123...",
"domain": "example.com",
"period": 1,
"consent": map[string]any{
"agreedAt": time.Now().UTC().Format(time.RFC3339),
"agreementTypes": []string{"API_DPA"},
},
}
b, _ := json.Marshal(body)
req, _ := http.NewRequest("POST",
os.Getenv("BASE")+"/v3/domains/registrations", bytes.NewReader(b))
req.Header.Set("Authorization", "Bearer "+os.Getenv("GODADDY_PAT"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
if res.StatusCode != 201 { panic(fmt.Sprint("registration failed: ", res.StatusCode)) }Returns 201 Created with the order ID and domain metadata.
Add a DNS record
POST /v3/domains/zones/{zone}/dns-records adds a record. Common first step: an A record pointing the apex at your web server.
curl -s -X POST "$BASE/v3/domains/zones/example.com/dns-records" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"type": "A", "name": "@", "data": "192.0.2.1", "ttl": 600}'const res = await fetch(
`${process.env.BASE}/v3/domains/zones/example.com/dns-records`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.GODADDY_PAT}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ type: "A", name: "@", data: "192.0.2.1", ttl: 600 }),
},
);
const record = await res.json();
console.log("Created record", record.recordId);import os, requests
res = requests.post(
f"{os.environ['BASE']}/v3/domains/zones/example.com/dns-records",
json={"type": "A", "name": "@", "data": "192.0.2.1", "ttl": 600},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
res.raise_for_status()
print("Created record", res.json()["recordId"])body := strings.NewReader(`{"type": "A", "name": "@", "data": "192.0.2.1", "ttl": 600}`)
req, _ := http.NewRequest("POST",
os.Getenv("BASE")+"/v3/domains/zones/example.com/dns-records", 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()Verify propagation
Confirm the record was accepted by the API, then confirm it's answering at a public resolver.
-
Read the zone back through the API. The new record should appear in
items[].curl -s "$BASE/v3/domains/zones/example.com/dns-records?type=A" \ -H "Authorization: Bearer $GODADDY_PAT" -
Query a public resolver. Global propagation completes within seconds; the delay end-users see depends on their local resolver's TTL cache.
dig +short A example.com # 192.0.2.1
What's next
- Add more DNS records (CNAME, MX, TXT) via the same endpoint — see the DNS how-to
- Set up domain forwarding to redirect apex-www or subdomains — see Forwarding
- Manage renewals and auto-renew — see Renewals
- Lock the domain against unauthorized transfer — see Registry lock
Agent & Automation Notes
domains.domain:read, domains.registration:write, domains.dns:updateRelated
Last updated on
How is this guide?