# Authenticate (https://developer.godaddy.com/en/docs/api-users/auth)
***
title: Authenticate
description: Authenticate API requests with a Personal Access Token (PAT). PATs are required for all Domains APIs. The classic GoDaddy developer key is supported through 2026 for other APIs.
agentNotes:
permissions: \["Any account"]
scopes: \["Not applicable — this page is credential setup"]
rateLimit: "PAT creation: interactive UI, not rate-limited. API calls with PAT: rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "PAT reveals once at creation — if lost, revoke and regenerate. Revocation is instant across all edges."
related:
guides:
* title: "Quickstart"
href: "/docs/api-users/quickstart"
* title: "Set up the CLI"
href: "/docs/api-users/cli-setup"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
## Overview
GoDaddy APIs use Bearer token authentication through a Personal Access Token (PAT) tied to specific capability scopes. PATs are required for all v3 Domains APIs. The classic GoDaddy developer key (`sso-key`) is still supported, but scheduled for deprecation. After you have a token, go to the [quickstart](https://developer.godaddy.com/docs/api-users/quickstart) to make your first call, or [set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup) for a command-line workflow.
### Account requirements
Some operations require the account to meet specific eligibility rules regardless of credential type. A valid credential on an ineligible account is still refused with a `403 Forbidden` response and an `Error` code that distinguishes the reason from a missing scope. Check the `code` field on the response body, not just the HTTP status, to determine the reason. Go to [Handle errors](https://developer.godaddy.com/docs/api-users/errors) for the full error envelope and status code reference.
| Operation group | Requirement |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Domain management — list, DNS, contacts, renewals, lock, privacy | Account holds at least one domain, OR is on a plan that grants management access. |
| Registration, renewal, transfer (any operation that costs money in production) | Account has a valid billing method on file or a funded [Good as Gold](https://www.godaddy.com/help/what-is-good-as-gold-3359) balance. Go to [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile). |
### PAT scopes
The following table lists the Domains API scopes you can assign when generating a PAT. Each scope enables specific operations. A write-scoped token satisfies read operations for the same resource; a read-scoped token is refused on writes.
When you generate a token, the **Domains & DNS** bundle in the scope picker selects all scopes below. You can expand it to grant a subset instead.
| Scope | Required to |
| --------------------------- | ---------------------------------------------------------------------- |
| `domains.domain:read` | Read domain records, availability, suggestions, quotes, and operations |
| `domains.domain:create` | Register domains |
| `domains.domain:update` | Modify domain settings |
| `domains.domain:delete` | Delete or cancel domains |
| `domains.dns:update` | Create, update, and delete DNS zone records |
| `domains.nameserver:update` | Replace authoritative nameservers for a domain |
| `domains.host:update` | Modify domain host records |
| `domains.forward:update` | Configure domain forwarding |
| `domains.contact:update` | Update registrant, admin, or tech contacts |
| `domains.transfer:execute` | Initiate an inbound domain transfer |
| `domains.transfer:update` | Modify a transfer in progress |
A PAT is a scoped Bearer token. Unlike `sso-key`, PATs are tied to specific capability scopes and can be revoked individually without rotating your account-wide key pair.
### Generate a PAT
The following describe how to generate a PAT.
1. Sign in to the [Personal Access Token](https://developer.godaddy.com/personal-access-token) page.
2. Click **+ Generate Token**.
3. In the **Generate personal access token** dialog, complete the following fields:
| Field | Description | Note |
| -------------- | --------------------------------------- | ------------------------------------------------------------ |
| **Name** | Name for the token. | |
| **Expiration** | Number of days until the token expires. | |
| **Scopes** | Scopes for the token. | Go to [PAT scopes](#pat-scopes) to see the available scopes. |
4. Click **Generate Token**.
### Store your token securely
After generating the token, it displays once. You can't retrieve it again from the [Personal Access Token page](https://developer.godaddy.com/personal-access-token) — store it in secure storage immediately.
1. In the **Copy your new token** dialog, click the copy icon.
2. Save the token in a password manager, secrets manager, or your application's secure credential store. Don't commit it to source control, check it into a repo, or paste it into chat.
3. Load the token at **runtime** when you need it:
* **Local scripts:** export it in the shell session you're about to use (not permanently in your shell profile):
```bash
export GODADDY_PAT=""
```
* **Apps and CI:** inject `GODADDY_PAT` from your platform's secret store (GitHub Actions secrets, AWS Secrets Manager, etc.) when the process starts.
`export GODADDY_PAT=...` makes the token available to the current shell — it is not a secure place to keep credentials long term. Store the value in a secrets manager first, then export or inject it only when running a command or starting your app.
### Use a token
The PAT is sent as a Bearer token in the `Authorization` header on every request.
* Add the header to every request:
```http
Authorization: Bearer ${GODADDY_PAT}
```
### Revoke a token
After a token isn't needed anymore, revoke it to prevent it from being used again.
1. Sign in to the [Personal Access Token](https://developer.godaddy.com/personal-access-token) page.
2. Next to the token you want to revoke, click the trash icon.
3. In the **Revoke token?** dialog, click **Revoke Token**.
This is the legacy way of generating a GoDaddy developer key. It's slated for retirement and won't work for v3 Domains APIs. Use a [Personal Access Token](#generate-a-pat) instead.
## Generate a key and secret
1. Sign in at .
2. Generate a new key for Production.
3. Copy both the **Key** and **Secret** immediately. The Secret is shown once.
* Export the credential:
```bash
export GODADDY_KEY=""
export GODADDY_SECRET=""
```
### Use the credential
* Add the header to every request:
```http
Authorization: sso-key ${GODADDY_KEY}:${GODADDY_SECRET}
```
# Building reliable integrations (https://developer.godaddy.com/en/docs/api-users/building-reliable-integrations)
***
title: Building reliable integrations
description: Error handling, rate limiting, idempotency, and retry patterns for the GoDaddy Domains API — the operational considerations that separate working code from production-ready code.
related:
guides:
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
* title: "Troubleshoot authentication"
href: "/docs/api-users/troubleshoot-authentication"
concepts:
* title: "How GoDaddy APIs work"
href: "/docs/api-users/how-godaddy-apis-work"
* title: "Domain management concepts"
href: "/docs/api-users/domain-management-concepts"
***
## Overview
This page covers the operational patterns for building an integration that holds up in production — how to handle errors correctly, manage rate limits, avoid duplicate charges through idempotency, and implement retry logic that doesn't make failures worse. The patterns here apply to the GoDaddy Domains API specifically but reflect general principles for working with any REST API.
## Error handling
The GoDaddy API returns a consistent JSON error envelope on every failure:
```json
{
"code": "DOMAIN_NOT_AVAILABLE",
"message": "The domain you requested is not available.",
"fields": [
{
"code": "REQUIRED",
"message": "is required",
"path": "contactRegistrant.email",
"pathRelated": ""
}
]
}
```
The `code` field is the key identifier. HTTP status codes alone are not sufficient — two `422` responses can require completely different handling depending on their `code`. Always read `code` before branching on a failure.
### Status code guide
The following table describes the different status codes.
| Status | What it means in practice |
| -------------------------- | ---------------------------------------------------------------------------------------------- |
| `200`, `201`, `202`, `204` | Success. `202 Accepted` means the operation is async — poll for completion. |
| `400` | Your request is malformed. Check `fields[]` for which field failed validation. |
| `401` | Token is missing, expired, or revoked. Regenerate and retry. |
| `403` | Token is valid but lacks the required scope, or the account isn't eligible. |
| `404` | The resource doesn't exist, or the account can't see it. Don't retry without verifying state. |
| `409` | Conflict — something about the current state prevents the operation. |
| `422` | Request structure is valid but violates a business rule. Check `code` to determine the reason. |
| `429` | Rate limit exceeded. Wait for `Retry-After` seconds. |
| `5xx` | Server error. Safe to retry with exponential backoff. |
### What to retry and what not to
The key distinction is safe vs. unsafe operations:
| Retry safety | Operations | Explanation |
| -------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| Safe to retry unconditionally | `GET` | Read-only. No side effects (a timeout can always be retried). |
| Safe to retry with idempotency | `PUT`, `PATCH` on domain settings (lock state, auto-renew, nameservers) | Idempotent (replaying with the same body produces the same result). |
| Unsafe to retry without checking state first | `POST` for registration, renewal, or transfer | These charge the account. A network timeout doesn't mean the operation failed. Always `GET` the resource before retrying. |
## Idempotency
Idempotency means that making the same request multiple times produces the same result as making it once. For read operations and most updates, this is automatic. For registrations, it requires explicit action.
### The `Idempotency-Key` header
The registration endpoint (`POST /v3/domains/registrations`) requires an `Idempotency-Key` header. Generate a UUID per request and include it on every registration call:
```bash
curl -X POST "https://api.godaddy.com/v3/domains/registrations" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ ... }'
```
If you send the same `Idempotency-Key` on a retry, the server returns the original response without creating a second order. This is the safe way to retry a registration after a network timeout.
### Checking state before retrying (transfer and renewal)
Transfer and renewal endpoints do not support `Idempotency-Key`. For those operations, check state before retrying any money-moving operation:
1. A request times out or returns a `5xx`.
2. Before retrying: call `GET /v1/domains/{domain}` (or the relevant read endpoint).
3. If the operation succeeded (domain is present, `renewAuto` changed, status is `PENDING_TRANSFER`), do not retry.
4. If the operation didn't happen, retry the original request.
This pattern avoids double-charges on endpoints where idempotency keys aren't available.
## Rate limiting
The API enforces per-credential rate limits (see [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for current values). When the limit is exceeded, the API returns:
```
HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 600
RateLimit-Remaining: 0
RateLimit-Reset: 1399
```
### Handling 429 in code
The only correct response to a `429` is to wait. The `Retry-After` header gives the exact number of seconds.
```js
async function callWithRetry(url, options, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const res = await fetch(url, options);
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get("Retry-After") ?? "10", 10);
await new Promise((r) => setTimeout(r, retryAfter * 1000));
continue;
}
return res;
}
throw new Error("Max retries exceeded");
}
```
### Staying within limits
The rate limit is generous for interactive use cases but can be consumed quickly by bulk operations. For batch jobs:
* Spread requests over time — don't send a burst of requests in the first second and then wait for the window to reset.
* Use the list endpoints with maximum `limit` values to reduce the number of calls needed.
* Cache read results where the underlying data changes slowly (for example, domain lock state rarely changes so there's no need to poll it every minute).
## Async operations
Some operations complete asynchronously. The API returns `202 Accepted` immediately with an operation object, and you poll until the operation reaches a terminal state.
Nameserver replacement is the primary async operation in the Domains v3 API. The response includes a `Location` header pointing to the operation URL. Poll that URL until `status` is `COMPLETE` or `FAILED`.
For domain registration, the operation completes synchronously in most cases, but the domain may briefly appear in `EXECUTING` status — particularly for first-time purchases on new accounts. Poll `GET /v1/domains/{domain}` until `status` is `ACTIVE`.
## Exponential backoff
For retryable errors (`5xx`, `429` after the wait period), use exponential backoff with jitter rather than fixed-interval retries. Fixed-interval retries from many clients simultaneously create retry storms that make server problems worse.
A simple backoff pattern:
```python
import time, random
def retry_with_backoff(fn, max_attempts=4, base_delay=1.0):
for attempt in range(max_attempts):
try:
return fn()
except RetryableError as e:
if attempt == max_attempts - 1:
raise
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)
```
The delays would be approximately: 1s, 2s, 4s — with up to 1 second of random jitter added to each. This spreads retry load across time and avoids synchronized retry waves.
## Secrets management
PATs are long-lived credentials that grant real access to real accounts. Treat them like passwords:
* Never hardcode tokens in source code or commit them to version control.
* Store tokens in environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.).
* Use separate tokens for separate environments — a production token should never appear in a development codebase.
* Rotate tokens on a regular schedule and immediately on suspected compromise.
* Scope tokens to the minimum permissions required for the integration.
Go to [Authenticate](https://developer.godaddy.com/docs/api-users/auth) for token generation steps and scope reference.
# Set up the CLI (https://developer.godaddy.com/en/docs/api-users/cli-setup)
***
title: Set up the CLI
description: Install the beta GoDaddy CLI as `gddy`, authenticate, and make a first call.
agentNotes:
permissions: \["Any account"]
scopes: \["Depends on invoked command — CLI wraps REST endpoints and inherits their scopes"]
rateLimit: "Rate-limited per credential per window (per underlying REST call). Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "CLI is a wrapper — same recovery semantics as the underlying REST endpoint. Config is stored in \~/.gddy/. Delete config to reset credentials."
related:
guides:
* title: "Quickstart"
href: "/docs/api-users/quickstart"
* title: "Authenticate"
href: "/docs/api-users/auth"
* title: "GoDaddy MCP server"
href: "/docs/api-users/mcp"
concepts:
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
## Overview
The CLI installer installs the beta GoDaddy CLI as `gddy`. If you prefer raw HTTP calls instead, go to the [quickstart](https://developer.godaddy.com/docs/api-users/quickstart). Go to the [MCP server](https://developer.godaddy.com/docs/api-users/mcp) for AI-assisted workflows.
The `gddy` binary tracks the tip of the `rust-port` branch, with a new versioned release cut on every push. It's still under active development — expect breaking changes between releases and update often.
The install scripts come from the public `godaddy/cli` repository. You don't need GitHub authentication to install or update the CLI.
## Install or update
Run the installer for your shell. Re-running the same command updates `gddy` to the latest release.
```bash
curl -fsSL https://github.com/godaddy/cli/releases/latest/download/install.sh | bash
```
This also works from Git Bash, MSYS2, or Cygwin on Windows.
```powershell
irm https://github.com/godaddy/cli/releases/latest/download/install.ps1 | iex
```
## Verify the install
Open a new terminal if the installer changed your `PATH`, then run:
```bash
gddy --version
gddy --help
```
If your shell can't find `gddy`, the install directory is not on your `PATH`.
## Authenticate
Use browser-based login to authenticate the CLI:
```bash
gddy auth login
```
Then confirm the CLI has an active session:
```bash
gddy auth status
```
## Add a payment method
Domain purchase requires a billing method on your GoDaddy account. Open the payment-methods page for your environment:
```bash
gddy payments add
```
See [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile) for account URLs, verification steps, and common billing errors.
## Make a first call
Ask the Domains API for available domain suggestions:
```bash
gddy domain suggest "coffee shop" --tlds com --limit 5
```
The response lists suggested domains. To check one suggestion directly, run:
```bash
gddy domain available
```
## Command reference
The following tables list the `gddy` commands available in the current beta release.
### Authentication
| Command | Description |
| ------------------ | ------------------------------------- |
| `gddy auth login` | Authenticate via browser-based login |
| `gddy auth status` | Show the current authentication state |
### Domain search and purchase
| Command | Description |
| ----------------------------------------------------------- | -------------------------------------------------------------------- |
| `gddy domain available ` | Check whether a single domain is available to register |
| `gddy domain available --check-type full` | Full registry check (slower, definitive result) |
| `gddy domain suggest "" --tlds com,net,io --limit 5` | Get domain name suggestions for a keyword or phrase |
| `gddy domain agreements --tld ` | Retrieve the ICANN agreements required for a registration |
| `gddy domain purchase --agree --confirm` | Register a domain (charges the account — use `--confirm` to proceed) |
| `gddy domain contacts init` | Write a `contacts.toml` template for reuse across purchases |
### Domain management
| Command | Description |
| ---------------------------------- | --------------------------------------------- |
| `gddy domain list` | List all domains on the authenticated account |
| `gddy domain list --status ACTIVE` | Filter domains by status |
| `gddy domain get ` | Get full detail for a single domain |
### DNS management
| Command | Description |
| ----------------------------------------------------------------------- | --------------------------------------- |
| `gddy dns list ` | List all DNS records on a domain |
| `gddy dns list --type A --name www` | Filter by record type and name |
| `gddy dns add --type A --name www --data 192.0.2.10 --ttl 600` | Add a DNS record |
| `gddy dns set --type A --name www --data 192.0.2.20 --ttl 600` | Replace all records for a type and name |
| `gddy dns delete --type A --name www` | Delete all records for a type and name |
`gddy dns add` appends records. `gddy dns set` replaces every record for the type and name combination. `gddy dns delete` removes every record for the type and name; it does not remove GoDaddy-managed `NS` or `SOA` records. Use `--dry-run` with destructive commands to preview changes.
### Payments
| Command | Description |
| ------------------- | --------------------------------------------------------- |
| `gddy payments add` | Open the payment-methods page for the current environment |
The `gddy` beta release covers domain search, purchase, list, and DNS management. Operations such as domain forwarding, registry lock, renewals, and contact updates are not yet available in the CLI — use the REST API directly for those operations. Run `gddy --help` at any time to see current commands.
# Domain management concepts (https://developer.godaddy.com/en/docs/api-users/domain-management-concepts)
***
title: Domain management concepts
description: The concepts behind domain registration, DNS, WHOIS, and the domain lifecycle — what the terms mean and why they matter when building with the GoDaddy Domains API.
related:
guides:
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
* title: "Manage renewals"
href: "/docs/api-users/manage-domains/renewals"
concepts:
* title: "How GoDaddy APIs work"
href: "/docs/api-users/how-godaddy-apis-work"
* title: "Building reliable integrations"
href: "/docs/api-users/building-reliable-integrations"
***
## Overview
This page explains the concepts behind domain registration and management — what registrars, registries, DNS, and the domain lifecycle mean at a technical level. Understanding these concepts makes the API's behavior more predictable and helps you build integrations that handle edge cases correctly.
## Domain registration
A domain name is a human-readable address registered in a global distributed database. When you register a domain, you're leasing the right to use that name for a fixed period (typically 1–10 years) from the registry \[the organization that manages a top-level domain (TLD)].
### Registrars and registries
Two distinct organizations are involved in every domain registration:
| Organization | Role | Example |
| ------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| **Registry** | Manages a TLD. Maintains the authoritative database of all registered domains under that TLD. Sets policy. | Verisign (`.com`, `.net`), Public Interest Registry (`.org`) |
| **Registrar** | An accredited middleman. Takes registration requests from customers and submits them to the registry. | GoDaddy, Namecheap, Cloudflare Registrar |
GoDaddy is an ICANN-accredited registrar. When you register a domain through the GoDaddy API, GoDaddy submits the registration to the appropriate registry on your behalf. The registry is the source of truth. A domain doesn't exist until the registry acknowledges it.
### What you own
When you register a domain, you don't own it in the traditional sense. You hold the right to use it for the registration period. The registry can reclaim domains that violate its policies (for example, trademark disputes decided by ICANN's UDRP process).
Registration creates a record in the registry's WHOIS database associating the domain with a registrant contact. The registrant contact is the legal owner for the duration of the registration.
## The domain lifecycle
Domains pass through defined states from registration to expiration and beyond.
| Status | Meaning |
| -------------------- | -------------------------------------------------------------------------------------------------------------- |
| `ACTIVE` | Registration is current. Domain resolves normally. |
| `EXPIRED` | Expiration date has passed but the domain is in the grace period. Renewal at standard price is still possible. |
| `PENDING_TRANSFER` | An inbound transfer is in progress. Registry is processing the move from another registrar. |
| `CANCELLED_TRANSFER` | A transfer was rejected or cancelled. The domain remains at the current registrar. |
### Grace periods
After expiration, GoDaddy provides a recovery window before the domain is permanently released. The exact timing varies by TLD, but the general pattern for gTLDs is:
* **0–12 days after expiration**: Standard renewal pricing applies. The domain is still in your account.
* **12–42 days after expiration**: Redemption period. The domain can be recovered but with additional fees. It's no longer visible in your account.
* **After redemption period**: The domain is released back to the registry and becomes available for registration by anyone.
ccTLDs (country-code TLDs like `.uk`, `.de`, `.ca`) have significantly different timelines — some expire immediately with no grace period. Always verify the TLD's expiration policy before building automated renewal logic.
## DNS and nameservers
DNS (Domain Name System) translates domain names into IP addresses (and other resource records). It's a distributed hierarchical system — no single server knows everything.
### Authoritative nameservers
Every domain has authoritative nameservers (the servers that hold the definitive DNS records for that domain). When a resolver looks up `example.com`, it eventually reaches `example.com`'s authoritative nameservers and gets the answer directly from them.
At registration, GoDaddy assigns its own authoritative nameservers to your domain by default. While GoDaddy's nameservers are authoritative, you manage DNS records through the GoDaddy API (`/v3/domains/zones/{zone}/dns-records`).
If you want to use a different DNS provider (like Cloudflare or Route 53.), you delegate authority by replacing the nameservers with that provider's servers (`PUT /v3/domains/domain-names/{domain-name}/nameservers`). After delegation, GoDaddy's API can no longer manage DNS records for the domain and the other provider's tools apply.
### DNS record types
The following table lists the different DNS record types.
| Type | Purpose | Example value |
| ------- | ------------------------------------------------------------------- | --------------------------------------- |
| `A` | Maps a hostname to an IPv4 address | `192.0.2.1` |
| `AAAA` | Maps a hostname to an IPv6 address | `2001:db8::1` |
| `CNAME` | Alias (maps a hostname to another hostname) | `www → example.com` |
| `MX` | Mail exchange (routes email for the domain) | `mail.example.com` (priority 10) |
| `TXT` | Arbitrary text (used for verification, SPF, DKIM) | `"v=spf1 include:_spf.google.com ~all"` |
| `NS` | Nameserver delegation (authoritative servers for a zone) | `ns1.domaincontrol.com` |
| `CAA` | Certificate Authority Authorization (which CAs may issue SSL certs) | `0 issue "letsencrypt.org"` |
| `SRV` | Service record (protocol-specific host and port) | `_http._tcp 0 5 80 www.example.com` |
### DNS propagation
When you change a DNS record, the new value doesn't appear instantly everywhere. DNS changes propagate through a cache hierarchy. Each record has a TTL (time-to-live) value that controls how long resolvers cache it before checking for updates.
With GoDaddy's authoritative DNS:
* Changes applied through the v3 API take effect synchronously on GoDaddy's nameservers.
* Cached copies elsewhere on the internet expire at the rate set by the record's TTL (minimum 600 seconds, maximum 86400 seconds on GoDaddy's v3 API).
* Resolvers that haven't cached the old value will see the new one immediately.
Propagation delay means there's a window after a DNS change where different users see different values depending on which resolver they use. For this reason, DNS changes for critical infrastructure (mail routing, SSL validation) should be planned and staged and not made under pressure.
## WHOIS and contact privacy
WHOIS is a protocol for querying the registry's public contact database. It exposes the registrant name, email, phone, and mailing address for every registered domain unless privacy protection is enabled.
### Contact roles
Every domain registration requires a registrant contact. Some registrations can require up to four contact roles. The following table lists the contact roles and their purposes:
| Role | Purpose |
| -------------- | ----------------------------------------------------------------------------- |
| **Registrant** | Legal owner of the domain. Required. |
| **Admin** | Administrative contact. Defaults to registrant if omitted. |
| **Billing** | Billing contact for renewal charges. Defaults to registrant if omitted. |
| **Tech** | Technical contact for DNS-related matters. Defaults to registrant if omitted. |
ICANN requires registrant contact information to be accurate. Providing false information can result in domain suspension. Use WHOIS privacy if you want to mask your contact details from the public database. Privacy services replace the real contact information with the privacy service's placeholder data in the WHOIS record.
## Domain locking
Registry lock (the `clientTransferProhibited` status flag) is a security feature that prevents other registrars from initiating a transfer out of GoDaddy without your explicit action. While locked, the registry will reject transfer requests from competing registrars.
Lock is enabled by default at registration. It has no effect on DNS resolution, email delivery, SSL certificates, or any service hosted on the domain. It should only be disabled for the duration of an outbound transfer or a registrant change on TLDs that require it, and re-enabled immediately after.
Go to [Lock a domain](https://developer.godaddy.com/docs/api-users/manage-domains/lock) for the API operations to read and toggle the lock state.
# Handle errors (https://developer.godaddy.com/en/docs/api-users/errors)
***
title: Handle errors
description: Error response shape, status code semantics, and retry guidance.
agentNotes:
scopes: \["Any — applies to all API operations"]
rateLimit: "N/A (informational reference)"
failureRecovery: "Match the 'code' field, not HTTP status, for programmatic handling. 4xx errors are client-fixable (check input, scopes, payment profile). 5xx errors are safe to retry with exponential backoff. 429 means wait for Retry-After header."
related:
guides:
* title: "Handle rate limits"
href: "/docs/api-users/rate-limits"
* title: "Authentication"
href: "/docs/api-users/auth"
* title: "Set up a payment profile"
href: "/docs/api-users/payment-profile"
apis:
* title: "Domains v3 reference"
href: "/docs/references/rest/domains/v3"
* title: "Domains v1 reference"
href: "/docs/references/rest/domains/v1"
***
## Overview
The Domains API returns a consistent error envelope across all version namespaces (v1, v2, and v3). Every error response includes a stable `code` field for programmatic handling, and optionally field-level validation details. This page covers the response shape, status code semantics, and retry guidance.
## Error response shape
`Error` schema (used for 4xx and 5xx responses):
```json
{
"code": "INVALID_BODY",
"message": "Request body did not match the expected schema.",
"fields": [
{
"path": "contactRegistrant.email",
"code": "INVALID_FORMAT",
"message": "Value must be a valid email address."
}
]
}
```
| Field | Required | Description |
| ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `code` | Yes | Stable, machine-readable error code. Match on this for programmatic handling. |
| `message` | No | Human-readable message. May change between releases. |
| `fields[]` | No | Per-field validation details when the error is body- or query-scoped. Each entry has its own `path` (JSONPath into the request), `code`, and `message`. |
`ErrorLimit` extends `Error` with one additional field for rate-limit (`429`) responses:
| Field | Required | Description |
| --------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `retryAfterSec` | Yes | Seconds the caller should wait before retrying the same operation. Mirrored in the `Retry-After` response header. |
## Status codes
| Status | Meaning | Caller action |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request` | Request was malformed (missing required field, invalid query parameter format). | Fix the request. Inspect `fields[]` for specifics. |
| `401 Unauthorized` | `Authorization` header missing, malformed, expired, or revoked. | Re-authenticate. See [Authentication](https://developer.godaddy.com/docs/api-users/auth). |
| `403 Forbidden` | Authenticated but unauthorized — usually a missing scope or insufficient role. | Issue a token with the required scope, or escalate the calling principal's authorization. |
| `404 Not Found` | The path doesn't exist, or the addressed resource (domain, contact, record) isn't visible to this caller. | Verify the path and confirm the caller owns or can access the resource. |
| `409 Conflict` | The request conflicts with current state (e.g. registering a name already taken; updating a record set that's mid-transfer). | Re-read state and retry only after resolving the conflict. |
| `422 Unprocessable Entity` | Request was syntactically valid but semantically rejected (e.g. invalid registrant data, TLD-specific constraint failure, `NO_PAYMENT_PROFILE`). | Inspect `code` and `fields[]`. For missing billing, see [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile). |
| `429 Too Many Requests` | Rate limit exceeded. Response is shaped as `ErrorLimit`. | Wait `retryAfterSec` seconds, then retry. Go to [Handle rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for strategies. |
| `5xx Server Error` | Upstream registry or service issue. | Retry idempotent operations with exponential backoff. See [Retry semantics](#retry-semantics) for non-idempotent ones. |
## Retry semantics
The following sections describe the retry semantics for read and write operations.
### Read operations
All `GET` operations on the Domains API are safe to retry. Examples:
* `GET /v3/domains/check-availability` — availability check
* `GET /v1/domains` — list your domains
* `GET /v1/domains/{domain}` — domain detail
* `GET /v1/domains/{domain}/records` — DNS records
### Write operations
Most writes can be retried after a 5xx, but **the API doesn't support an `Idempotency-Key` request header** — neither v1 nor v2 specs declare one. This affects retry strategy on a few specific operations:
| Operation | Retry-safe? |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `POST /v1/domains/purchase` | **Not idempotent without external coordination.** A retry can result in a duplicate registration if the first attempt actually succeeded server-side. Pair every retry with a fresh `GET /v1/domains/available` and a state check via `GET /v1/domains/{domain}`. |
| `POST /v1/domains/{domain}/renew` | Idempotent within a billing cycle in practice — the registry rejects duplicates — but treat the same as `purchase`: confirm state before retrying. |
| `POST /v1/domains/{domain}/transfer` | Same as `purchase`. |
| `PUT /v1/domains/{domain}/records` (replace) | Idempotent by shape — replaying the same request produces the same record set. |
| `PATCH /v1/domains/{domain}/records` (add) | **Not idempotent** — repeated calls add duplicate records. |
| `DELETE /v1/domains/{domain}/records/{type}/{name}` | Idempotent — deleting an already-deleted record is a no-op. |
## Programmatic error handling
Match on `code`, not `message`. Codes are stable across releases; messages may be refined.
```js
const res = await fetch(url, { headers });
if (!res.ok) {
const err = await res.json();
switch (err.code) {
case "DOMAIN_NOT_AVAILABLE":
// someone else registered the name first
break;
case "BILLING_DECLINED":
// payment method failed — surface to user
break;
case "NO_PAYMENT_PROFILE":
// no billing method on account — see payment profile setup
break;
default:
// log err.code and err.fields for debugging
throw new Error(err.code + ": " + err.message);
}
}
```
Reference: the `Error` and `ErrorLimit` schemas are defined in the OpenAPI specification.
# End-to-end workflow (https://developer.godaddy.com/en/docs/api-users/full-workflow)
***
title: End-to-end workflow
description: Complete workflow for buying and configuring a domain — search, quote, register, add DNS, verify. Runnable start-to-finish in under 5 minutes.
agentNotes:
permissions: \["Payment Profile", "DNS Management"]
scopes: \["domains.domain:read", "domains.registration:write", "domains.dns:update"]
idempotent: false
destructive: true
failureRecovery: "Registration is NOT idempotent without Idempotency-Key header. On any partial success, GET the domain first before retrying. Real money changes hands — be sure you want to do this before executing."
related:
guides:
* title: "Quickstart"
href: "/docs/api-users/quickstart"
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
concepts:
* title: "Authentication"
href: "/docs/api-users/auth"
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
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](https://developer.godaddy.com/docs/api-users/auth) with `domains.domain:read`, `domains.registration:write`, and `domains.dns:update` scopes, and the CLI or curl. Export the token:
```bash
export GODADDY_PAT=""
export BASE="https://api.godaddy.com" # or api.ote-godaddy.com for testing
```
## Check availability
`GET /v3/domains/check-availability` returns availability and indicative pricing for a domain.
```bash tab="curl"
curl -s "$BASE/v3/domains/check-availability?domain=example.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
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);
```
```python tab="Python"
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']}")
```
```go tab="Go"
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:
```json
{
"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.
```bash tab="curl"
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}'
```
```js tab="Node"
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);
```
```python tab="Python"
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"])
```
```go tab="Go"
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.
This call charges the account's payment profile. Verify the domain name and quoted price before executing.
```bash tab="curl"
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"]
}
}'
```
```js tab="Node"
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);
```
```python tab="Python"
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"])
```
```go tab="Go"
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.
```bash tab="curl"
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}'
```
```js tab="Node"
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);
```
```python tab="Python"
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"])
```
```go tab="Go"
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.
1. Read the zone back through the API. The new record should appear in `items[]`.
```bash
curl -s "$BASE/v3/domains/zones/example.com/dns-records?type=A" \
-H "Authorization: Bearer $GODADDY_PAT"
```
2. Query a public resolver. Global propagation completes within seconds; the delay end-users see depends on their local resolver's TTL cache.
```bash
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](https://developer.godaddy.com/docs/api-users/manage-domains/dns)
* Set up domain forwarding to redirect apex-www or subdomains — see [Forwarding](https://developer.godaddy.com/docs/api-users/manage-domains/forwarding)
* Manage renewals and auto-renew — see [Renewals](https://developer.godaddy.com/docs/api-users/manage-domains/renewals)
* Lock the domain against unauthorized transfer — see [Registry lock](https://developer.godaddy.com/docs/api-users/manage-domains/lock)
# Glossary (https://developer.godaddy.com/en/docs/api-users/glossary)
***
title: Glossary
description: Definitions for terms used throughout the GoDaddy Domains API documentation.
related:
guides:
* title: "Authenticate"
href: "/docs/api-users/auth"
* title: "Error handling"
href: "/docs/api-users/errors"
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
***
Learn about the terms used throughout this documentation.
* **async operation**: An API operation that returns `202 Accepted` immediately and continues processing in the background. The caller receives an operation ID and polls a status endpoint until the operation reaches `COMPLETED` or `FAILED`. Registration and domain transfers use async operations. See [status polling](#status-polling).
* **authoritative nameserver**: The nameserver that holds the definitive DNS records for a domain. When you update DNS records through the GoDaddy API, the change is applied to GoDaddy's authoritative nameservers. External resolvers cache the previous values until the TTL expires. See [TTL](#ttl).
* **CNAME (Canonical Name record)**: A DNS record type that aliases one domain name to another. A CNAME cannot coexist with other records at the same name — a CNAME at the apex (`@`) is invalid when other records (A, MX) are present.
* **domain status**: The lifecycle state of a registered domain. Common values: `ACTIVE` (in use), `CANCELLED` (registration lapsed), `PENDING_TRANSFER` (outbound transfer in progress), `EXPIRED` (past expiration, in grace period), `REDEMPTION` (past grace period, recoverable at higher cost). Status values affect which API operations are permitted.
* **domain transfer**: Moving a domain registration from one registrar to another. Outbound transfers require an authorization code (EPP code). Transfers take up to 5–7 days to complete and go through `PENDING_TRANSFER` status during that time.
* **grace period**: A period after domain expiration during which the domain can be renewed at normal pricing. After the grace period ends, the domain enters a redemption period and renewal costs increase significantly.
* **ICANN consent**: The Internet Corporation for Assigned Names and Numbers (ICANN) requires registrants to confirm that their contact information is accurate before a domain is registered. In the v3 API, you provide this as a consent object in the registration request. Providing false information can result in domain suspension.
* **idempotency key**: A client-generated value (typically a UUID) included in the `Idempotency-Key` request header. If the server already processed a request with the same key, it returns the original response without executing the operation again. Use idempotency keys on all non-idempotent write operations — particularly domain registration — to prevent duplicate charges on retries.
* **MX record (Mail Exchanger record)**: A DNS record type that specifies the mail servers responsible for accepting email for a domain. MX records include a priority value — lower numbers indicate higher priority.
* **nameserver**: A server that answers DNS queries for a domain. Nameservers are authoritative (hold the definitive records) or recursive (resolve queries by querying authoritative servers on behalf of clients). Changing a domain's nameservers delegates DNS management to a different provider.
* **NS record (Name Server record)**: A DNS record type that delegates a DNS zone to a set of nameservers. GoDaddy-managed NS records cannot be modified through the DNS records API — use the dedicated nameservers endpoint instead.
* **PAT (Personal Access Token)**: A scoped Bearer token used to authenticate API requests. Generated from the [developer dashboard](https://developer.godaddy.com/personal-access-token). PATs replace the legacy `sso-key` credential for new integrations and are required for v3 API access. A PAT includes one or more scopes (for example, `domains.domain:read`) that determine which operations it can authorize.
* **quote token**: A short-lived token returned by `POST /v3/domains/registration-quotes`. The token locks the price for a domain registration and must be included in the subsequent `POST /v3/domains/registrations` call. Quote tokens expire quickly — re-quote if you receive a `QUOTE_EXPIRED` error.
* **rate limit**: The maximum number of API requests allowed per credential per time window. The GoDaddy Domains API limits requests to 60 per minute per credential. Exceeding the limit returns `429 Too Many Requests` with a `Retry-After` header. Go to [Handle rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for retry guidance.
* **redemption period**: A period after the grace period ends during which a domain can still be recovered, but at significantly higher cost. After the redemption period, the domain is released for re-registration by anyone.
* **registrar**: A company accredited by ICANN to sell and manage domain registrations. GoDaddy is a registrar. The registrar manages the relationship with the registry on behalf of the registrant (the domain owner).
* **registry**: The organization that manages a top-level domain (TLD) on behalf of ICANN. For example, Verisign manages `.com` and `.net`; the Public Interest Registry manages `.org`. The registry maintains the authoritative database of all domains under the TLD.
* **registry lock**: A security feature that prevents unauthorized changes to a domain's nameservers, contact information, or transfer status by requiring out-of-band verification. Domains with registry lock cannot be updated programmatically until the lock is released.
* **scope**: A permission granted to a PAT that authorizes a specific category of API operations. For example, `domains.domain:read` allows read-only domain and availability queries; `domains.domain:create` allows registration. A PAT must include all scopes required for each operation it will perform. Go to [Authenticate — PAT scopes](https://developer.godaddy.com/docs/api-users/auth#pat-scopes) for the full reference.
* **shopper ID / customer ID**: GoDaddy's internal identifier for an account. In the v2 API, the `customerId` appears in operation paths (`/v2/customers/{customerId}/domains/...`). In the v3 API, the authenticated credential determines the account — no customer ID is required in the path.
* **SOA record (Start of Authority record)**: A DNS record that contains administrative information about a DNS zone, including the primary nameserver, zone serial number, and refresh intervals. SOA records are managed by GoDaddy and cannot be modified through the API.
* **sso-key**: A legacy credential format used by the v1 API. Format: `sso-key :`. The `sso-key` is not supported by the v3 API. New integrations should use a [PAT](#pat-personal-access-token) instead.
* **status polling**: The process of repeatedly calling a status endpoint to check whether an async operation has completed. The recommended pattern is exponential backoff: wait 1 second, then 2, then 4, up to a reasonable maximum. Stop polling when status reaches `COMPLETED` or `FAILED`. See [async operation](#async-operation).
* **TXT record**: A DNS record type that stores arbitrary text associated with a domain. TXT records are commonly used for domain ownership verification (Google, GitHub, Stripe), SPF email authentication, and DKIM keys.
* **TTL (Time to Live)**: The number of seconds a DNS record can be cached by resolvers before they must re-query the authoritative nameserver. Lower TTLs reduce propagation time for changes but increase query volume. The minimum TTL for GoDaddy-hosted DNS is 600 seconds (10 minutes).
* **v1 / v2 / v3 API**: The three versioned namespaces of the GoDaddy Domains API. `v1` (`/v1/domains/...`) covers DNS, contacts, renewals, lock, and transfers. `v2` (`/v2/customers/{customerId}/domains/...`) adds async operation tracking. `v3` (`/v3/domains/...`) is the preferred namespace for new integrations — it separates quoting from execution, supports async operations, and requires ICANN consent. Go to the [Domains API overview](https://developer.godaddy.com/docs/references/rest/domains) for the version comparison table.
* **zone**: The complete set of DNS records for a domain managed by a single authoritative nameserver. Managing DNS through the GoDaddy API operates on a domain's zone. If the domain uses external nameservers, GoDaddy's zone is inactive — DNS records must be managed at the external provider.
# How GoDaddy APIs work (https://developer.godaddy.com/en/docs/api-users/how-godaddy-apis-work)
***
title: How GoDaddy APIs work
description: The architecture, authentication model, environments, and versioning strategy behind the GoDaddy Domains API — what you need to know before you build.
related:
guides:
* title: "Authenticate"
href: "/docs/api-users/auth"
* title: "Make your first call"
href: "/docs/api-users/quickstart"
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
concepts:
* title: "Domain management concepts"
href: "/docs/api-users/domain-management-concepts"
* title: "Building reliable integrations"
href: "/docs/api-users/building-reliable-integrations"
***
## Overview
This page explains the architecture and design principles behind the GoDaddy Domains API (how authentication works, what the different API versions do, how environments are separated, and what to expect from the API's behavior). Read this before you build to ensure you have a full understanding of the GoDaddy Domain API.
## API architecture
The GoDaddy Domains API is a REST API that accepts JSON request bodies and returns JSON responses. All requests go to a single base URL (`api.godaddy.com` for production), and all API calls require an `Authorization` header carrying a Bearer token.
Every API call follows the same pattern:
1. Include `Authorization: Bearer ` in the request header.
2. The gateway validates the token and checks its scopes.
3. A valid request is routed to the correct API version and resource handler.
4. The handler returns a JSON response with a standard HTTP status code.
There is no API key rotation scheme, no HMAC signing, and no session management. Every request is independently authenticated with the Bearer token.
## Authentication model
GoDaddy uses Personal Access Tokens (PATs) for API authentication. A PAT is a long-lived credential tied to a GoDaddy account with a configurable set of capability scopes.
### Why scopes matter
Scopes determine what a token can do, not just who it belongs to. A token with only `domains.domain:read` can call read endpoints but will receive `403 Forbidden` on any write operation (even if the account itself has full access). Scopes are additive: a single token can carry multiple scopes.
The scope model exists so that integrations can be given the minimum permissions they need. A read-only analytics pipeline doesn't need write scopes. A DNS automation tool doesn't need purchase scopes. The following table describes the permissions each scope grants.
| Scope | What it grants |
| ---------------------------- | -------------------------------------------- |
| `domains.domain:read` | Read domains, DNS records, domain detail |
| `domains.domain:create` | Register domains (purchase) |
| `domains.domain:update` | Update domain settings, contacts, lock state |
| `domains.dns:update` | Create and delete DNS records |
| `domains.nameserver:update` | Replace authoritative nameservers |
| `domains.registration:write` | Transfer domains in |
Go to [Authenticate](https://developer.godaddy.com/docs/api-users/auth) for the full scope reference and token creation steps.
### Legacy credentials
The older `sso-key` credential format (`sso-key :`) is still supported for v1 API endpoints but is scheduled for deprecation in 2026. New integrations should use PATs exclusively. PATs are required for all v3 endpoints.
## API versions
GoDaddy exposes three major API versions simultaneously. They aren't interchangeable. Different capabilities live in different versions, and the versions have different authentication requirements. The following table provides information about the available versions.
| Version | Base path | Auth | Status | Primary use |
| ------- | ---------------------------------------- | -------------- | ------------------ | ------------------------------------------------- |
| v1 | `/v1/domains/...` | PAT or sso-key | Stable, maintained | List domains, renewals, contacts, transfers, lock |
| v2 | `/v2/customers/{customerId}/domains/...` | PAT or sso-key | Stable, maintained | Async operations, forwarding |
| v3 | `/v3/domains/...` | PAT only | Current | Registration, DNS records, availability checks |
### Why three versions exist
The API has evolved over years of product development. Rather than breaking existing integrations, GoDaddy maintains older versions alongside newer ones.
* **v3** is the current version for new capabilities. It uses resource-oriented paths and returns structured, consistent responses. New features land here first.
* **v1** covers operations that haven't migrated to v3 yet ( like domain listing, contacts, renewals, transfers, and lock management). Expect these to migrate to v3 over time.
* **v2** adds async operations.
The practical rule: use v3 where available; fall back to v1 or v2 where v3 doesn't cover the operation yet. The guide pages in this section note which version each operation uses.
## Environments
GoDaddy provides a single production environment for API development. Some API calls require a funded payment method, can incur costs, and create real domain records. Scope your calls carefully. Actions taken in production are real, billable, and often irreversible.
## Request and response format
All API requests and responses use JSON. A few conventions apply across the entire API surface:
**Content-Type**: Always send `Content-Type: application/json` on requests with a body.
**Accept**: Send `Accept: application/json` on read requests. The API defaults to JSON but specifying it is good practice.
**Monetary values**: Prices are expressed in currency micro-units — multiply by 10⁻⁶ to get the currency value. A `price` of `1199000` in `USD` is `$11.99`.
**Timestamps**: All timestamps are ISO 8601 in UTC (for example, `2026-03-15T00:00:00.000Z`).
**Pagination**: v1 list endpoints use `limit` and `marker` for cursor-based pagination. v3 list endpoints use `page` and `pageSize`. Go to [Pagination](https://developer.godaddy.com/docs/api-users/pagination) for examples.
## Rate limits
The API enforces per-credential rate limits. Exceeding the limit returns `429 Too Many Requests` with a `Retry-After` header indicating how many seconds to wait.
Rate limits apply per credential. If you have multiple integrations using the same PAT, their request rates are pooled. Use separate PATs for independent workloads if you expect them to approach the limit independently.
Go to [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for current limits and handling guidance.
## Error structure
All errors return a consistent JSON envelope regardless of the HTTP status code:
```json
{
"code": "DOMAIN_NOT_AVAILABLE",
"message": "The domain you requested is not available.",
"fields": []
}
```
The `code` field is the machine-readable identifier to branch on. The HTTP status code alone is not sufficient — a `422` with `DOMAIN_NOT_AVAILABLE` requires a different response than a `422` with `NO_PAYMENT_PROFILE`.
Go to [Handle errors](https://developer.godaddy.com/docs/api-users/errors) for the full error reference, status code guide, and retry semantics.
# Introduction (https://developer.godaddy.com/en/docs/api-users)
***
title: Introduction
description: Call GoDaddy APIs directly from your code or agent — domain registration, DNS, transfers, and more.
related:
guides:
* title: "Quickstart"
href: "/docs/api-users/quickstart"
* title: "Authenticate"
href: "/docs/api-users/auth"
* title: "Set up the CLI"
href: "/docs/api-users/cli-setup"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
## Overview
GoDaddy's REST APIs give you direct programmatic access to the same platform capabilities that power GoDaddy's own products. You can search and register domains, manage DNS, handle renewals and transfers, and more through standard HTTP calls from your code, scripts, or AI agents.
## Start here
New to the GoDaddy Domains API? Follow this path:
| Step | Time | What you'll do |
| -------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------ |
| [Generate a PAT](https://developer.godaddy.com/docs/api-users/auth) | 2 min | Create a scoped Personal Access Token from the developer dashboard |
| [Make your first call](https://developer.godaddy.com/docs/api-users/quickstart) | 3 min | Check domain availability with a single `curl` command — no account changes required |
| [Search for domains](https://developer.godaddy.com/docs/api-users/search-domains) | 5 min | Check availability and get suggestions for a domain name |
| [Register a domain](https://developer.godaddy.com/docs/api-users/purchase-domains/register) | 10 min | Walk through the v3 quote-and-register flow with billing consent |
Already up and running? Jump straight to [manage your domains](https://developer.godaddy.com/docs/api-users/manage-domains) or go to the [Domains v3 API reference](https://developer.godaddy.com/docs/references/rest/domains/v3).
## What you can do
Get Started
## Which API version?
The Domains API has three version namespaces. Pick the right one before you start.
| Operation | Version |
| ------------------------------------------------------------ | ------- |
| Check domain availability, get domain suggestions | v3 |
| Register a domain | v3 |
| DNS records and nameserver management | v3 |
| Change domain settings (auto-renew, registry lock, contacts) | v1 |
| Domain transfer | v1 |
| Domain forwarding | v2 |
## Base URL
All API calls target `https://api.godaddy.com`.
All requests and responses use JSON. Every call requires an `Authorization` header with a [Personal Access Token](https://developer.godaddy.com/docs/api-users/auth). Read operations also need `Accept: application/json`, and write operations (`POST`, `PATCH`, `PUT`) additionally need `Content-Type: application/json`.
```bash
curl -s "https://api.godaddy.com/v1/domains" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
The API is stateless — no sessions, no cookies. Each request is independently authenticated and authorized. See the [REST Reference](https://developer.godaddy.com/docs/references/rest) for the complete endpoint catalog.
## Credentials and access
Authentication uses a Personal Access Token (PAT) (a scoped Bearer token you generate from the [developer dashboard](https://developer.godaddy.com/personal-access-token)). PATs are tied to specific capability scopes, can be set to expire, and can be revoked individually without rotating any account-wide key. For most integrations, a PAT with the minimum required scopes is the right choice.
The legacy `sso-key` credential (a key/secret pair from ) is still supported for some APIs but is scheduled for deprecation. It doesn't work for v3 Domains APIs. New integrations should use a PAT.
**Account eligibility matters for write calls.** A valid credential isn't enough on its own. Some operations require the account to meet additional eligibility requirements:
* Read operations (availability search, domain listing, DNS reads) work with any valid credential on any account.
* Write operations that cost money (registration, renewal, transfer, and payment operations) require the account to have a valid billing method on file or a funded [Good as Gold](https://www.godaddy.com/help/what-is-good-as-gold-3359) balance.
If an account doesn't meet these requirements, the API returns `403 Forbidden`. To determine whether the failure is a scope problem or an account eligibility problem, check the `code` field in the response body. The HTTP status alone doesn't distinguish between the two.
Go to [Authenticate](https://developer.godaddy.com/docs/api-users/auth) for how to generate credentials and add them to your requests.
## API versions
The Domains API spans three version namespaces, each reflecting a different phase of the platform's evolution:
| Version | Base path | What's here |
| ------- | ---------------------------------------- | ----------------------------------------------------------------------------------- |
| v3 | `/v3/domains/...` | Availability checks and registration (the preferred namespace for new integrations) |
| v2 | `/v2/customers/{customerId}/domains/...` | v1 capabilities with async processing and operations tracking |
| v1 | `/v1/domains/...` | List, DNS, contacts, lock, and renewals |
v3 is where new capabilities are being added. For everything not yet in v3 (DNS, renewals, transfers, contacts, lock), use v1 or v2.
## In this section
## First call
Follow the [Quickstart](https://developer.godaddy.com/docs/api-users/quickstart) to generate a Personal Access Token and make your first call in under five minutes. If you prefer command-line workflows over raw `curl`, [set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup) first.
# GoDaddy MCP server (https://developer.godaddy.com/en/docs/api-users/mcp)
***
title: GoDaddy MCP server
description: Connect Claude or another MCP-compatible client to GoDaddy domain search and availability tools.
agentNotes:
permissions: \["Public — no account required"]
scopes: \["Not applicable — public data only"]
rateLimit: "Enforced per client-IP. Details TBD as service scales."
idempotent: true
destructive: false
failureRecovery: "Safe to retry on transient errors. MCP transport handles reconnection automatically."
related:
apis:
* title: "Domains v3 — Discovery"
href: "/docs/references/rest/domains/v3/discovery"
guides:
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
concepts:
* title: "Authentication"
href: "/docs/api-users/auth"
***
## Overview
The GoDaddy MCP server lets AI assistants search for domain names and check domain availability directly from a conversation. It is built on the [Model Context Protocol](https://modelcontextprotocol.io/), an open standard for connecting AI clients to external tools.
Current MCP capabilities use public domain data only. No GoDaddy account or API credential is required.
## What you can do
Example prompts:
* "Is `mycoolstartup.com` available?"
* "Find available domains related to sustainable fashion."
* "Suggest alternatives to `techcompany.io`."
## Set up Claude
Claude can connect to the GoDaddy MCP server through its connector directory.
1. Open Claude Desktop.
2. Go to **Settings**.
3. Open **Connectors**, then click **Browse connectors**.
4. Search for **GoDaddy**.
5. Click **Connect**.
6. Ask domain questions naturally in your conversation.
## Configure an MCP client
For a custom AI tool or any MCP-compatible client that supports streamable HTTP, add the GoDaddy server to your MCP configuration.
```json
{
"mcpServers": {
"godaddy": {
"url": "https://api.godaddy.com/v1/domains/mcp",
"transport": "streamable-http"
}
}
}
```
After the client loads the server, it can call GoDaddy's public domain search and availability tools.
## Limitations
* **Read-only:** The MCP server cannot register domains, modify DNS records, transfer domains, update account settings, or make purchases.
* **Public access only:** Domain registration and account-specific domain management still happen on [godaddy.com](https://www.godaddy.com/).
* **No authentication:** Current tools use public domain data and do not accept GoDaddy account credentials.
* **Rate limited:** Excessive requests may be temporarily throttled.
* **Availability can change:** Domain availability and pricing can change quickly. Re-check before sending a user to purchase.
## Privacy and security
* Searches use HTTPS/TLS.
* The public MCP tools do not require authentication.
* Searches are not linked to a GoDaddy account.
* Rate limits protect service availability.
## Support and terms
To report a bug or share feedback, [submit a support request](https://developer.godaddy.com/contact-support).
By using the GoDaddy MCP server, you agree to GoDaddy's [Universal Terms of Service](https://www.godaddy.com/legal/agreements/universal-terms-of-service-agreement), the [API Terms of Use](https://developer.godaddy.com/getstarted), and responsible use of the service.
## Related pages
# Paginate results (https://developer.godaddy.com/en/docs/api-users/pagination)
***
title: Paginate results
description: Cursor-based pagination on v1 list endpoints with limit and marker.
agentNotes:
permissions: \["Any account"]
scopes: \["Any scope that allows list operations — e.g. domains.domain:read for GET /v1/domains"]
rateLimit: "Rate-limited per credential per window. Page sequentially rather than in parallel to stay within limits. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "Cursor markers (marker query param) are stable. Safe to retry any page request with the same marker value. If a marker becomes invalid, restart pagination from the first page."
related:
guides:
* title: "List registered domains"
href: "/docs/api-users/manage-domains/list"
* title: "Handle rate limits"
href: "/docs/api-users/rate-limits"
concepts:
* title: "Error handling"
href: "/docs/api-users/errors"
***
## Overview
List endpoints return paginated results using cursor-based pagination. Use pagination to walk large result sets without hitting [rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) from parallel requests. The most common paginated endpoint is [list domains](https://developer.godaddy.com/docs/api-users/manage-domains/list).
## v1 cursor pagination
`GET /v1/domains` accepts two pagination query parameters:
| Parameter | Default | Description | Note |
| --------- | -------------- | ----------------------------------------------- | ------------------------------------------------------------- |
| `limit` | Server default | Maximum number of items to return in this page. | |
| `marker` | None | Cursor pointing to the start of the next page. | Set to the last item's identifier from the previous response. |
To page through all results, repeat the request with `marker` set to the last item's domain name from the previous page until the response array is shorter than `limit`.
```bash
# First page
curl -s "https://api.godaddy.com/v1/domains?limit=100" \
-H "Authorization: Bearer $GODADDY_PAT"
# Subsequent pages — marker is the last domain from the previous page
curl -s "https://api.godaddy.com/v1/domains?limit=100&marker=last-domain-from-previous-page.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
### Looping example
This pattern walks every page until the response is shorter than `limit`:
```js
const PAGE_SIZE = 100;
let marker = "";
const all = [];
while (true) {
const url = new URL("https://api.godaddy.com/v1/domains");
url.searchParams.set("limit", PAGE_SIZE);
if (marker) url.searchParams.set("marker", marker);
const res = await fetch(url, {
headers: {
Authorization: "Bearer " + process.env.GODADDY_PAT,
},
});
const page = await res.json();
all.push(...page);
if (page.length < PAGE_SIZE) break; // last page
marker = page[page.length - 1].domain;
}
```
## v2 list endpoints
v2 list endpoints (for example, domain forwarding lists, action lists) return the full collection in a single response and do not support `limit` or `marker` parameters.
## Pagination and retries
Cursor pagination is safe to interrupt and resume. The `marker` value remains valid as long as the underlying domain still exists in the account. If a request fails mid-walk, retry the same `(limit, marker)` pair.
# Set up a payment profile (https://developer.godaddy.com/en/docs/api-users/payment-profile)
***
title: Set up a payment profile
description: Add a billing method to your GoDaddy account before registering or renewing domains. Required for any operation that charges money.
agentNotes:
permissions: \["Billing"]
scopes: \["Not applicable — configured via UI"]
rateLimit: "Not applicable — one-time setup"
idempotent: true
destructive: false
failureRecovery: "Payment profile is configured through the account UI, not the API. If registration/renewal returns NO\_PAYMENT\_PROFILE (HTTP 422), the account has no billing method — direct the user to add one at godaddy.com."
related:
guides:
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Manage renewals"
href: "/docs/api-users/manage-domains/renewals"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
***
Domain registration, renewal, and transfer charge the billing method saved on your GoDaddy account. The Domains API does not accept card numbers or payment objects in the request body — v3 registration quotes and purchases draw from the account's **payment profile**.
If no billing method is on file, quote and purchase calls fail before registration logic runs. The API returns `NO_PAYMENT_PROFILE` (HTTP `422`) until billing is configured. Go to [Handle errors](https://developer.godaddy.com/docs/api-users/errors) for the full error envelope and other billing-related error codes.
## Add a payment method
You can add a payment method in the account UI or open the same page from the CLI.
### Using the CLI
The beta `gddy` CLI opens your browser to the payment-methods page for the active environment:
```bash
gddy payments add
```
Only a **credit card** or **Good as Gold** balance can be used for domain purchases. For built-in CLI environments, the command opens:
| CLI environment | Account payment URL |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Production (`gddy env set prod`) | [account.godaddy.com/payment-methods/add-payment](https://account.godaddy.com/payment-methods/add-payment) |
### Using the account UI
1. Sign in at [account.godaddy.com/payment-methods/add-payment](https://account.godaddy.com/payment-methods/add-payment).
2. Click **Add Payment Method**.
3. Complete the **Billing Information** and **Payment Method** sections.
4. Click **Save**.
Domain purchase also requires a complete registrant contact (phone and mailing address) on the account. If billing is set up but contact fields are missing, the API returns `MISSING_CONTACT` or validation errors on individual address fields. Update contacts at [account.godaddy.com/profile/contacts](https://account.godaddy.com/profile/contacts).
## Verify billing is ready
After adding a payment method, confirm the account can receive a registration quote. A successful quote returns a `quoteToken`; `NO_PAYMENT_PROFILE` means billing is still missing.
```bash
curl -s -X POST "https://api.godaddy.com/v3/domains/registration-quotes" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com", "period": 1}'
```
A `quoteToken` in the response confirms billing is configured. `NO_PAYMENT_PROFILE` means add a payment method first. `MISSING_CONTACT` means complete the registrant contact on the account before quoting or purchasing.
## Common errors
| Code | HTTP | Likely cause | What to do |
| ---------------------- | ----- | ---------------------------------------------------------------------------------- | ------------------------------------------------- |
| `NO_PAYMENT_PROFILE` | `422` | No payment method on the account. | Add a payment method (UI or `gddy payments add`). |
| `INVALID_PAYMENT_INFO` | `402` | Payment authorization failed at purchase time — no usable method or card declined. | Verify the card on file or add a new method. |
| `ACCOUNT_NOT_FUNDED` | `403` | Good as Gold balance is $0.00 with no fallback card. | Add funds or add a credit card. |
| `MISSING_CONTACT` | `422` | Registrant phone or address missing from the account profile. | Complete contact info in the account UI. |
Some accounts use a prepaid Good as Gold balance instead of a card. Registrations draw from the balance first. If the balance is $0 and no fallback card is on file, registration fails with a billing-related error. See [What is Good as Gold?](https://www.godaddy.com/help/what-is-good-as-gold-3359).
## Next steps
After billing is configured, continue with [Purchase a domain](https://developer.godaddy.com/docs/api-users/purchase-domains/register).
# Make your first call (https://developer.godaddy.com/en/docs/api-users/quickstart)
***
title: Make your first call
description: Make your first API call to the Domains API using a Personal Access Token (PAT).
agentNotes:
permissions: \["Any account"]
scopes: \["domains.domain:read"]
idempotent: true
destructive: false
failureRecovery: "Read-only. Safe to retry any failure. On 401, verify token has not expired or been revoked. On 429, wait for Retry-After."
related:
guides:
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Manage existing domains"
href: "/docs/api-users/manage-domains"
concepts:
* title: "Authentication"
href: "/docs/api-users/auth"
* title: "Error handling"
href: "/docs/api-users/errors"
apis:
* title: "Domains v3 reference"
href: "/docs/references/rest/domains/v3"
***
For full API coverage, provide the [Domains v3 OpenAPI spec](https://developer.godaddy.com/openapi/domains-v3.json) as additional context to your LLM or API client.
## Overview
This guide walks through making `GET /v3/domains/check-availability` against the production API. The call is read-only and doesn't require domains to already be registered to your account.
## Prerequisites
Before calling the Domains API, you need:
* a GoDaddy account
* a Personal Access Token (PAT) with the appropriate scopes
Go to [Authenticate](https://developer.godaddy.com/docs/api-users/auth) to generate a PAT.
* a terminal with `curl` (macOS, Linux, or WSL)
* Optional: the beta `gddy` CLI, if you prefer CLI workflows. Go to [Set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup).
## Set the credential as an environment variable
The PAT is passed as a Bearer token in the `Authorization` header on every request. Exporting it as an environment variable keeps it out of your shell history and lets you reference it directly in commands without retyping.
* Export the credential:
```bash
export GODADDY_PAT=""
```
## Make the call
`GET /v3/domains/check-availability` takes a single `domain` query parameter and returns whether that domain can be registered, along with current pricing for each registration term. The request is read-only, so no charges apply.
* Run the request:
```bash tab="curl"
curl -s "https://api.godaddy.com/v3/domains/check-availability?domain=your-idea.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch(
"https://api.godaddy.com/v3/domains/check-availability?domain=your-idea.com",
{
headers: {
Authorization: "Bearer " + pat,
},
}
);
const result = await res.json();
console.log(result);
```
```python tab="Python"
import os, requests
pat = os.environ["GODADDY_PAT"]
res = requests.get(
"https://api.godaddy.com/v3/domains/check-availability",
params={"domain": "your-idea.com"},
headers={
"Authorization": "Bearer " + pat,
},
)
print(res.json())
```
## Read the response
The API returns a JSON object describing availability and current pricing. `available` tells you whether the domain can be registered right now. `prices[]` contains one entry per registration term. `price.value` and `renewalPrice.value` are expressed in the smallest currency unit, such as cents for USD. Divide by 100 when displaying USD prices.
* Check that your output matches this shape:
```json
{
"available": true,
"definitive": false,
"domain": "your-idea.com",
"inventory": "REGISTRY",
"prices": [
{
"period": 1,
"price": {
"currencyCode": "USD",
"value": 1199
},
"renewalPrice": {
"currencyCode": "USD",
"value": 2299
},
"term": "YEAR"
},
{
"period": 2,
"price": {
"currencyCode": "USD",
"value": 3098
},
"renewalPrice": {
"currencyCode": "USD",
"value": 4598
},
"term": "YEAR"
}
]
}
```
The API may return more `prices[]` entries for additional periods. Availability and pricing are indicative; the final price is locked when you create a registration quote.
## Common errors
| Error | Likely cause | Fix |
| --------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized` | Token is missing, expired, or wasn't exported | Run `echo $GODADDY_PAT` — if blank, re-run the export. If the token was deleted or expired, generate a new one in the [developer dashboard](https://developer.godaddy.com/personal-access-token). |
| `403 Forbidden` | Token lacks `domains.domain:read` scope, or the account isn't eligible | Check the `code` field in the response body. Scope issues return `UNABLE_TO_AUTHENTICATE`; account issues return a different code. Regenerate the PAT with the correct scope selected. |
| `429 Too Many Requests` | Rate limit exceeded | Wait for the number of seconds in the `Retry-After` header before retrying. Go to [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for current values and retry guidance. |
| Response is `null` or `undefined` | The JSON response wasn't awaited or parsed | Ensure you `await res.json()` in Node, or `res.json()` in Python. |
| `Could not resolve host` | Wrong base URL | The API base is `https://api.godaddy.com`. There is no local dev server — all requests go to production. |
Go to [Handle errors](https://developer.godaddy.com/docs/api-users/errors) for the full error envelope reference, status code semantics, and retry guidance.
## Next steps
Where you go from here depends on what you're trying to do. If you already own domains at GoDaddy, the most common next call is `GET /v1/domains` which lists the domains on your account (covered in [Manage existing domains](https://developer.godaddy.com/docs/api-users/manage-domains/list)). If you want to acquire new domains, start with search and registration (covered in [Search for domains](https://developer.godaddy.com/docs/api-users/search-domains)).
# Handle rate limits (https://developer.godaddy.com/en/docs/api-users/rate-limits)
***
title: Handle rate limits
description: API requests are rate-limited per credential. Limits return HTTP 429 with RateLimit-\* response headers.
agentNotes:
permissions: \["Any account"]
scopes: \["Applies to all authenticated API calls regardless of scope"]
rateLimit: "Rate-limited per credential, per window. RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers are present on every response. Current limit: 600 per \~23-minute window. Values subject to change."
idempotent: true
destructive: false
failureRecovery: "On 429, read the Retry-After header value (seconds). Implement exponential backoff with jitter. Do not retry immediately. Use bulk endpoints where available to reduce call frequency."
related:
guides:
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Pagination"
href: "/docs/api-users/pagination"
* title: "Authentication"
href: "/docs/api-users/auth"
apis:
* title: "Domains v3 reference"
href: "/docs/references/rest/domains/v3"
* title: "Domains v1 reference"
href: "/docs/references/rest/domains/v1"
***
## Overview
The Domains API enforces a per-credential, windowed rate limit. The `RateLimit-Remaining` header on every response shows how many requests remain in the current window. When it reaches 0, the next request returns `HTTP 429` with no response body. The limit applies per [credential](https://developer.godaddy.com/docs/api-users/auth) regardless of which endpoint you call.
Specific limit values are subject to change without notice. Your integration should read `RateLimit-Remaining` from response headers rather than assume a fixed number.
## Rate limit response headers
The following headers are included on **every** response to a rate-limited route — not just 429s — so your client can track current usage without waiting for a rejection.
| Header | Description |
| --------------------- | --------------------------------------------- |
| `RateLimit-Limit` | The limit that applies to the current request |
| `RateLimit-Remaining` | Requests remaining in the current window |
| `RateLimit-Reset` | Seconds until the current window resets |
Example 429 response:
```
HTTP/2 429
ratelimit-limit: 600
ratelimit-remaining: 0
ratelimit-reset: 1399
```
## Handling 429 in code
Read `RateLimit-Reset` to know how long to wait before retrying. For long-running clients, add exponential backoff with jitter on top of the server-suggested wait. The following is an example of how to do this in JavaScript:
```js
async function callWithRetry(url, headers, attempts = 5) {
for (let attempt = 0; attempt < attempts; attempt++) {
const res = await fetch(url, { headers });
if (res.status !== 429) return res;
const resetSec = parseInt(res.headers.get("ratelimit-reset") ?? "30", 10);
const jitter = Math.floor(Math.random() * 1000);
await new Promise((r) => setTimeout(r, resetSec * 1000 + jitter));
}
throw new Error("Rate limit retries exhausted");
}
```
## Strategies to stay under the limit
To avoid hitting the limit, apply one or more of the following strategies:
* **Use bulk operations where they exist.** For single-domain availability checks, use `GET /v3/domains/check-availability` (preferred). For bulk availability, `POST /v1/domains/available` accepts an array of names — one request can replace dozens of single-domain calls.
* **Cache availability results when appropriate (v1 only).** The `definitive` field on `DomainAvailableResponse` indicates whether the answer came from a live registry call or a cached one. Cache `definitive: false` results briefly client-side for repeat lookups.
* **Use cursor pagination, not parallel page-walks.** Go to [Pagination](https://developer.godaddy.com/docs/api-users/pagination) for more information.
* **Spread bursts across credentials only when each credential maps to a distinct logical caller.** Sharing one credential across many hosts and counting on the limit being per-credential is fragile — limits can be tightened to per-account at any time.
## Higher limits
If you have a use case that legitimately needs higher limits than those currently enforced, contact the developer support channel. Document the use case, expected sustained rate, and bursts.
## Additional information
Go to [Retry semantics](https://developer.godaddy.com/docs/api-users/errors#retry-semantics) for full retry guidance.
# Troubleshoot authentication (https://developer.godaddy.com/en/docs/api-users/troubleshoot-authentication)
---
title: Troubleshoot authentication
description: Common authentication errors when calling GoDaddy APIs, with causes and resolutions.
agentNotes:
scopes: ["Any — this page covers cross-cutting auth issues"]
rateLimit: "N/A (diagnostic reference)"
failureRecovery: "Diagnostic page. On 401, check token format and expiration. On 403, distinguish scope vs eligibility via the code field."
faqItems:
- question: "Why do I get 401 Unauthorized from the GoDaddy API?"
answer: "The Authorization header is missing, malformed, or the token has expired or been revoked. Verify the format is 'Authorization: Bearer ', check the token hasn't expired, and confirm it hasn't been revoked on the Personal Access Token page."
- question: "Why do I get 403 Forbidden despite having a valid token?"
answer: "The token doesn't include the scope required for the operation. Generate a new token with the required scopes. The domains.domain:read scope is required even for write operations that need to verify state."
- question: "Why do I get 403 ACCOUNT_NOT_ELIGIBLE?"
answer: "The account doesn't meet eligibility requirements — typically a missing payment profile or domain ownership requirement. Add a payment method or verify you hold at least one domain."
- question: "Why do I get 422 NO_PAYMENT_PROFILE on purchase calls?"
answer: "The operation requires a funded billing method (registration, renewal, transfer) but no payment method is on file. Add a payment method to your account."
- question: "Why did my token stop working after previously working?"
answer: "The token has expired (PATs have configurable expiration) or was revoked. Check the expiration date, generate a new token if needed, and update your secrets manager."
related:
guides:
- title: "Authenticate"
href: "/docs/api-users/auth"
- title: "Set up a payment profile"
href: "/docs/api-users/payment-profile"
- title: "Troubleshoot your first call"
href: "/docs/api-users/troubleshoot-first-call"
concepts:
- title: "Error handling"
href: "/docs/api-users/errors"
---
## Overview
This page covers the most common authentication and authorization errors you'll encounter when calling GoDaddy APIs. Each section describes the symptom, cause, and resolution.
## 401 Unauthorized
**Symptom:** API returns `401` with `code: "UNAUTHORIZED"`.
**Cause:** The `Authorization` header is missing, malformed, or the token has expired or been revoked.
**Resolution:**
- Verify the header format is `Authorization: Bearer ` (no extra whitespace or quotes around the token value).
- Check the token hasn't expired — PATs have a configurable expiration. Generate a new one if needed.
- Confirm the token hasn't been revoked on the [Personal Access Token](https://developer.godaddy.com/personal-access-token) page.
- If using `sso-key`, verify the format is `sso-key :` with no extra spaces.
## 403 Forbidden — missing scope
**Symptom:** API returns `403` with a code indicating insufficient permissions, despite a valid token.
**Cause:** The token is valid but doesn't include the scope required for the operation.
**Resolution:**
- Check the `code` field in the error response — it distinguishes between scope and eligibility issues.
- Generate a new token with the required scopes. Go to [Authentication — PAT scopes](https://developer.godaddy.com/docs/api-users/auth#pat-scopes) for the full list.
- The `domains.domain:read` scope is required even for write operations that need to verify state.
## 403 Forbidden — account eligibility
**Symptom:** API returns `403` with a code like `ACCOUNT_NOT_ELIGIBLE` despite having the correct scope.
**Cause:** The account doesn't meet the eligibility requirements for the operation — typically a missing payment profile or domain ownership requirement.
**Resolution:**
- For billing-related eligibility: add a payment method. Go to [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile).
- For domain management eligibility: the account must hold at least one domain or be on a plan that grants management access.
- Check the `code` field — don't rely on HTTP status alone to distinguish scope from eligibility issues.
## 422 with `NO_PAYMENT_PROFILE`
**Symptom:** API returns `422` with `code: "NO_PAYMENT_PROFILE"` on quote or purchase calls.
**Cause:** The operation requires a funded billing method (registration, renewal, transfer) but the account has no payment method on file.
**Resolution:** Add a payment method. Go to [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile).
## Token stops working after working previously
**Symptom:** A token that was working returns `401` without any code changes.
**Cause:** The token expired (PATs have a configurable expiration) or was revoked.
**Resolution:**
- Check the token's expiration date on the [Personal Access Token](https://developer.godaddy.com/personal-access-token) page.
- If expired or revoked, generate a new token.
- Update your secrets manager or environment variable with the new value.
# Troubleshoot the CLI (https://developer.godaddy.com/en/docs/api-users/troubleshoot-cli)
***
title: Troubleshoot the CLI
description: Common errors when installing or using the GoDaddy CLI (gddy), with causes and resolutions.
agentNotes:
scopes: \["N/A — CLI handles auth internally"]
rateLimit: "N/A (diagnostic reference)"
failureRecovery: "Diagnostic page. For PATH issues, open a new terminal. For auth issues, run 'gddy auth login'. For permission errors, check OS security settings. CLI targets one environment at a time — verify with 'gddy auth status'."
faqItems:
* question: "Why does 'command not found: gddy' appear after installation?"
answer: "Your PATH doesn't include the directory where the CLI was installed. In a terminal window, verify the binary exists at \~/.local/bin/gddy (or %LOCALAPPDATA%\Programs\gddy on Windows), and add the bin directory to PATH if needed."
* question: "Why does 'gddy auth login' open a browser but nothing happens?"
answer: "The browser can't complete the OAuth redirect back to the CLI's local listener. Ensure you're not in a headless environment, try copying the URL manually, check for proxy interference with localhost, or try a different browser."
* question: "Why does 'gddy domain suggest' return an authentication error?"
answer: "Authentication hasn't been configured or the saved token has expired. Run 'gddy auth status' to check, then 'gddy auth login' to re-authenticate if needed."
* question: "Why does the CLI installer fail with a permission error?"
answer: "The script can't write to the target directory, or macOS Gatekeeper is blocking the binary. The installer defaults to \~/.local/bin (macOS/Linux) or %LOCALAPPDATA%\Programs\gddy (Windows), both user-writable, and falls back to sudo automatically on macOS/Linux only if that directory isn't writable. On macOS, allow in Security & Privacy settings if Gatekeeper blocks the binary. On Windows, no elevation should be needed unless you passed a system-owned --prefix."
* question: "Why do CLI commands return different results than curl?"
answer: "The CLI might be using different credentials than your curl commands. Check with 'gddy auth status' and re-authenticate if needed."
related:
guides:
* title: "Set up the CLI"
href: "/docs/api-users/cli-setup"
* title: "Troubleshoot authentication"
href: "/docs/api-users/troubleshoot-authentication"
* title: "Make your first call"
href: "/docs/api-users/quickstart"
***
## Overview
This page covers errors you may encounter when installing, authenticating, or using the `gddy` CLI. If you're setting up for the first time, go to [Set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup) for the installation guide.
## `command not found: gddy`
**Symptom:** Running `gddy` returns "command not found" or "not recognized" after installation.
**Cause:** Your PATH does not include the directory where the CLI was installed.
**Resolution:**
* **Windows:** `install.ps1` adds the install directory to your user `PATH` automatically, but only new terminal sessions pick up the change — open a new terminal and try again.
* **macOS/Linux:** `install.sh` does not modify your `PATH`. Add the bin directory manually, then add the same line to your shell profile (e.g. `~/.zshrc` or `~/.bashrc`) to persist it:
```bash
export PATH="$HOME/.local/bin:$PATH"
```
* Verify the binary exists: `ls ~/.local/bin/gddy` (macOS/Linux) or check `%LOCALAPPDATA%\Programs\gddy\` (Windows).
* Re-run the installer if the binary doesn't exist.
## `gddy auth login` opens a browser but nothing happens
**Symptom:** The CLI opens a browser tab for OAuth login, but the redirect fails or hangs.
**Cause:** The browser can't complete the OAuth redirect back to the CLI's local listener.
**Resolution:**
* Make sure you're not in a headless/SSH environment without browser access.
* If the browser opened but the page failed to load, copy the URL from the terminal output and paste it manually.
* If behind a corporate proxy, the redirect URL (`localhost`) may be intercepted — check with your network team.
* Try a different browser if the default one has strict security extensions blocking localhost redirects.
## `gddy domain suggest` returns an authentication error
**Symptom:** Running domain commands returns an auth-related error.
**Cause:** Authentication hasn't been configured, or the saved token has expired.
**Resolution:**
* Run `gddy auth status` to check whether you're authenticated and which environment you're targeting.
* If expired or not authenticated, run `gddy auth login` to re-authenticate.
* If targeting the wrong environment, use `gddy auth login --env production` to specify.
## Installer fails with a permission error
**Symptom:** The install script exits with "Permission denied" or similar.
**Cause:** The script can't write to the target directory, or macOS Gatekeeper is blocking the binary.
**Resolution:**
* The installer defaults to `~/.local/bin` (macOS/Linux) or `%LOCALAPPDATA%\Programs\gddy` (Windows) — both are user-writable, so this shouldn't come up on a default install.
* On macOS: if you see "cannot be opened because the developer cannot be verified," go to System Preferences → Security & Privacy → General and click "Allow Anyway."
* On Linux: if you passed a `--prefix` pointing at a directory you don't own (e.g. `/usr/local/bin`), the installer falls back to `sudo` automatically.
* On Windows PowerShell: if the execution policy blocks running the remote script via `iex`, run `Set-ExecutionPolicy -Scope Process Bypass` for the session, or download `install.ps1` and inspect it before running.
## CLI commands work but return different results than curl
**Symptom:** The CLI returns different data or errors compared to the same operation via curl.
**Cause:** The CLI might be using different credentials than your curl commands.
**Resolution:**
* Check your current environment: `gddy auth status`
* If targeting the wrong environment, re-authenticate against the correct one.
* Compare the base URL: CLI uses the environment from its auth config, while curl hits whatever URL you specify directly.
# Troubleshoot DNS (https://developer.godaddy.com/en/docs/api-users/troubleshoot-dns)
***
title: Troubleshoot DNS
description: Common errors when managing DNS records with the GoDaddy Domains API, with causes and resolutions.
agentNotes:
scopes: \["domains.domain:read", "domains.dns:update", "domains.nameserver:update"]
idempotent: false
destructive: true
failureRecovery: "Read operations are safe to retry. DNS deletes are irreversible — re-read the zone after failures to verify state. If nameservers were replaced incorrectly, issue a corrective PUT immediately."
faqItems:
* question: "Why aren't my DNS changes showing up?"
answer: "DNS propagation is not instantaneous. GoDaddy's authoritative nameservers apply changes within minutes, but external resolvers cache records for up to the previous TTL duration. Wait for the TTL to expire before assuming propagation has failed. Use a tool like dig @8.8.8.8 to bypass local cache."
* question: "Why do I get 400 when adding a DNS record?"
answer: "The request body failed validation. Common causes: invalid record type, malformed data value (e.g. an A record with a hostname instead of an IP address), unsupported name format, or a TTL below the minimum (600 seconds). Check the fields array in the error response for the specific field and reason."
* question: "Why do I get 403 Forbidden on a DNS request?"
answer: "The token doesn't include the required scope. Read operations need domains.domain:read, write operations need domains.dns:update, and nameserver replacement needs domains.nameserver:update. Generate a new token with the correct scopes."
* question: "Why do I get 404 on a DNS record operation?"
answer: "Either the recordId doesn't exist, the domain doesn't exist in your account, or the domain name in the zone path parameter is wrong. Save the recordId from the Location header when you create a record — don't construct it manually. Verify the domain is visible via GET /v1/domains."
* question: "Why can't I delete NS or SOA records?"
answer: "GoDaddy manages NS and SOA records as part of its hosted DNS infrastructure. These records cannot be deleted or overwritten through the DNS records API. To change nameservers, use the nameservers endpoint (PUT /v3/domains/zones//nameservers) instead."
* question: "Why does adding a CNAME return 422?"
answer: "You can't add a CNAME at the zone apex (@ or the root domain). Use A/AAAA records at the apex instead. For SRV records, the service and protocol fields must be underscore-prefixed (e.g. \_http and \_tcp)."
* question: "Why am I getting 429 rate limit errors?"
answer: "The API enforces a per-credential, windowed rate limit. Check the Retry-After response header and wait that many seconds before retrying. For bulk operations, add a delay between requests or batch reads and writes. Go to /docs/api-users/rate-limits for current values."
* question: "Why does my DNS record add keep returning a duplicate record error?"
answer: "The POST /v3/domains/zones//dns-records endpoint appends records. If you already have a record with the same type, name, and data, the API may reject the duplicate depending on the record type. Read the current records first, then delete the existing one before adding the updated version."
* question: "How long does DNS propagation take after a record change?"
answer: "GoDaddy's authoritative nameservers apply changes within minutes. External resolvers (Google, Cloudflare, ISPs) cache the old values for up to the previous TTL duration. If the old TTL was 3600 seconds (1 hour), expect up to 1 hour for global propagation. Lowering the TTL before a change speeds up subsequent propagation."
related:
guides:
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
* title: "Troubleshoot your first API call"
href: "/docs/api-users/troubleshoot-first-call"
* title: "Troubleshoot authentication"
href: "/docs/api-users/troubleshoot-authentication"
apis:
* title: "Domains v3 — DNS records"
href: "/docs/references/rest/domains/v3/records"
concepts:
* title: "Error handling"
href: "/docs/api-users/errors"
***
## Overview
This page covers errors you're likely to encounter when managing DNS records through the GoDaddy Domains API. For the full DNS management guide, go to [Manage DNS records](https://developer.godaddy.com/docs/api-users/manage-domains/dns).
## DNS changes not visible after update
**Symptom:** You added or updated a DNS record and the change isn't reflected when you query the domain.
**Cause:** DNS propagation is not instantaneous. There are two distinct timelines:
* **Authoritative nameservers** (GoDaddy): changes apply within minutes.
* **External resolvers** (Google 8.8.8.8, Cloudflare 1.1.1.1, ISPs): resolvers cache the old value for up to the previous TTL duration.
**Resolution:**
* Query the authoritative nameserver directly to confirm the change was applied: `dig @ns1.domaincontrol.com your-domain.com A`
* If the authoritative server shows the new value, the change is live — you're waiting for resolver caches to expire.
* If the authoritative server still shows the old value, verify the API call succeeded by reading the record: `GET /v3/domains/zones/{domain}/dns-records`
* To reduce future propagation time, lower the TTL to 600 seconds before making a planned change, then restore it afterward.
## `400` when adding a DNS record
**Symptom:** `POST /v3/domains/zones/{domain}/dns-records` returns `400` with a `fields` array.
**Cause:** The request body failed field-level validation. Common causes:
* **Invalid `type`**: Only supported record types are accepted (`A`, `AAAA`, `CNAME`, `MX`, `NS`, `TXT`, `SRV`, `CAA`).
* **Malformed `data`**: An `A` record must have an IPv4 address, not a hostname. A `CNAME` must be a fully qualified domain name ending with `.`.
* **`ttl` below minimum**: The minimum TTL is 600 seconds.
* **Invalid `name` format**: Use `@` for the apex record, not the domain name itself.
**Resolution:**
* Inspect each item in the `fields` array — `path` identifies the field, `message` describes the constraint.
* Verify the `data` format against the record type. For example: `"data": "192.0.2.1"` for an `A` record, `"data": "mail.example.com."` for an `MX` record.
* Set `ttl` to at least `600`.
## `NS` or `SOA` records can't be modified
**Symptom:** Attempting to delete or replace `NS` or `SOA` records returns an error or has no effect.
**Cause:** GoDaddy manages `NS` and `SOA` records as part of its hosted DNS infrastructure. These records cannot be deleted or overwritten through the DNS records endpoint.
**Resolution:**
* To change nameservers, use the dedicated nameservers endpoint: `PUT /v3/domains/zones/{domain}/nameservers` with an array of new nameserver hostnames.
* `SOA` records are system-managed and cannot be changed directly. Changes to `NS` records propagate the `SOA` automatically.
* If you need to delegate DNS to an external provider (Route 53, Cloudflare), replace the nameservers entirely using the nameservers endpoint, then manage all records there.
## Duplicate record error on `POST`
**Symptom:** `POST /v3/domains/zones/{domain}/dns-records` returns an error indicating a conflicting or duplicate record already exists.
**Cause:** The `POST` endpoint appends records. If a record with the same type, name, and data already exists, or if adding the record would violate DNS constraints (for example, a `CNAME` at the apex, or conflicting `CNAME` and `A` records), the API rejects the request.
**Resolution:**
1. Read the current zone: `GET /v3/domains/zones/{domain}/dns-records?type={TYPE}&name={NAME}`
2. Delete the conflicting record: `DELETE /v3/domains/zones/{domain}/dns-records/{recordId}`
3. Add the updated record: `POST /v3/domains/zones/{domain}/dns-records`
To replace all records of a given type and name in one operation, use `PUT /v3/domains/zones/{domain}/dns-records/{type}/{name}`.
## `403 Forbidden` — insufficient scope
**Symptom:** API returns `403` despite a valid token.
**Cause:** The token doesn't include the scope required for the operation.
**Resolution:**
* Read operations require `domains.domain:read`.
* Write operations (create, delete records) require `domains.dns:update`.
* Nameserver replacement requires `domains.nameserver:update`.
* Generate a new token with the correct scopes. Go to [Authenticate](https://developer.godaddy.com/docs/api-users/auth#pat-scopes) for the full scope list.
## `404 Not Found` — record or domain not found
**Symptom:** API returns `404` on a read, delete, or nameserver operation.
**Cause:** The `recordId` doesn't exist, the domain doesn't exist, or the domain isn't owned by the authenticated account.
**Resolution:**
* Verify the `zone` path parameter matches the domain name exactly (for example, `example.com`, not `www.example.com`).
* For deletes: save the `recordId` from the `Location` header at create time. Don't construct `recordId` values manually.
* Confirm the domain is visible via `GET /v1/domains` — if not found there, it isn't accessible with the current credential.
## `422 Unprocessable` — business rule violation
**Symptom:** API returns `422` after accepting the request structure.
**Cause:** The request is structurally valid but violates a DNS rule — the most common case is a `CNAME` at the zone apex.
**Resolution:**
* Do not create a `CNAME` record with `name: "@"` (the apex). Use `A`/`AAAA` records at the apex instead.
* For `SRV` records, verify the `service` and `protocol` fields are underscore-prefixed (for example, `_http` and `_tcp`).
## `429 Too Many Requests` — rate limit exceeded
**Symptom:** API returns `429`.
**Cause:** The request rate exceeded the per-credential limit for the current window.
**Resolution:**
* Check the `Retry-After` response header and wait that many seconds before retrying.
* For bulk operations, add a delay between requests or batch reads and writes.
* Go to [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for the full rate limit reference.
# Troubleshoot domain registration (https://developer.godaddy.com/en/docs/api-users/troubleshoot-domain-registration)
***
title: Troubleshoot domain registration
description: Common errors when registering a domain with the GoDaddy Domains API, with causes and resolutions.
agentNotes:
scopes: \["domains.domain:read", "domains.domain:create"]
idempotent: false
failureRecovery: "Registration charges the account. Do not resubmit while status is EXECUTING — use the Idempotency-Key header to prevent duplicate charges. If QUOTE\_EXPIRED, re-quote and re-register."
faqItems:
* question: "Why does domain registration return EXECUTING instead of completing immediately?"
answer: "Registration is asynchronous. EXECUTING means the operation is in progress. Poll GET /v3/domains/registrations/ until status is COMPLETED or FAILED. Do not resubmit — use the Idempotency-Key header to prevent duplicate charges if your client retries."
* question: "Why does my registration return 422 QUOTE\_EXPIRED?"
answer: "The quoteToken from the registration-quotes endpoint has expired. Quote tokens are short-lived. Re-call POST /v3/domains/registration-quotes to get a fresh token, then submit the registration again with the new token."
* question: "Why is my registration returning 422 with a fields array?"
answer: "The request body failed field-level validation. Common causes: missing or invalid registrant contact (email, phone, address), domain name format error, or TLD-specific requirements not met. Check each object in the fields array — the path and message identify which field failed and why."
* question: "Why does my registration return 422 NO\_PAYMENT\_PROFILE?"
answer: "The account has no payment method on file. Registration charges the billing method — it cannot proceed without one. Add a payment method at account.godaddy.com/payment-methods or go to Set up a payment profile in the docs."
* question: "How do I prevent duplicate charges if my registration client retries?"
answer: "Include an Idempotency-Key header with a stable, unique value (a UUID per registration attempt). If the server already processed a request with that key, it returns the original response without charging again."
* question: "Why is my registration returning 403 ACCOUNT\_NOT\_ELIGIBLE?"
answer: "Write operations that cost money require a billing method on the account. Go to account.godaddy.com/payment-methods to add a payment method. The account may also be ineligible for specific TLD registrations."
* question: "Why did my domain registration return 422 saying the domain is not available?"
answer: "The domain was registered by someone else between your availability check and the registration attempt, or it's in a status that prevents registration (e.g. redemption period). Call GET /v3/domains/check-availability immediately before registering — don't cache availability results. Use the suggestions endpoint to find alternatives if the domain is taken."
related:
guides:
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Set up a payment profile"
href: "/docs/api-users/payment-profile"
* title: "Troubleshoot authentication"
href: "/docs/api-users/troubleshoot-authentication"
apis:
* title: "v3 Registrations"
href: "/docs/references/rest/domains/v3/registrations"
* title: "v3 Registration Quotes"
href: "/docs/references/rest/domains/v3/registration-quotes"
concepts:
* title: "Error handling"
href: "/docs/api-users/errors"
***
## Overview
This page covers errors you're likely to encounter when registering a domain through the GoDaddy Domains API. Registration is asynchronous and charges the account — read the [full registration guide](https://developer.godaddy.com/docs/api-users/purchase-domains/register) before troubleshooting.
## Registration stays in `EXECUTING` status
**Symptom:** `POST /v3/domains/registrations` returns `202 Accepted` and the status field shows `EXECUTING`. The status never changes to `COMPLETED`.
**Cause:** Registration is asynchronous. `EXECUTING` is the normal initial state — the operation is in progress on GoDaddy's side. It is not an error.
**Resolution:**
* Poll `GET /v3/domains/registrations/{registrationId}` every few seconds until `status` reaches `COMPLETED` or `FAILED`.
* Do not resubmit the registration while `status` is `EXECUTING`. Resubmitting can result in duplicate charges.
* If `status` is `FAILED`, inspect the `error` field for the specific failure reason.
* Use the `Idempotency-Key` header on the original request — if your client retries due to a network error, the server returns the original response without charging again.
## `422` with `QUOTE_EXPIRED`
**Symptom:** `POST /v3/domains/registrations` returns `422` with `code: "QUOTE_EXPIRED"`.
**Cause:** The `quoteToken` from `POST /v3/domains/registration-quotes` has expired. Quote tokens are short-lived and must be used promptly.
**Resolution:**
1. Call `POST /v3/domains/registration-quotes` again with the same domain and contact details to get a fresh `quoteToken`.
2. Resubmit `POST /v3/domains/registrations` with the new `quoteToken`.
3. If you're seeing this frequently, reduce the time between quoting and registering — keep it under a minute in production flows.
## `422` with a `fields` validation error
**Symptom:** `POST /v3/domains/registrations` returns `422` with a `fields` array listing specific field errors.
**Cause:** The request body failed field-level validation. Common causes:
* Missing or invalid registrant contact: `email`, `phone`, `addressMailing`, or `nameFirst`/`nameLast` not provided or malformed.
* Domain name format error: unsupported characters, missing TLD, or invalid punycode.
* TLD-specific requirements not met: some TLDs require additional contact fields or eligibility verification.
**Resolution:**
* Inspect each object in the `fields` array — the `path` field identifies which request property failed and `message` explains why.
* Verify all required registrant contact fields are present. Go to [Register a domain — contacts](https://developer.godaddy.com/docs/api-users/purchase-domains/register#registrant-contact) for the required schema.
* For IDN (internationalized) domains, the domain name must be in punycode A-label form.
## `403` with `ACCOUNT_NOT_ELIGIBLE`
**Symptom:** `POST /v3/domains/registrations` or `POST /v3/domains/registration-quotes` returns `403` with `code: "ACCOUNT_NOT_ELIGIBLE"`.
**Cause:** The account lacks a funded billing method, or is not eligible to register the specific TLD.
**Resolution:**
* Add a payment method at [account.godaddy.com/payment-methods](https://account.godaddy.com/payment-methods). Go to [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile).
* Some TLDs (country-code TLDs, restricted TLDs) require additional account eligibility. Check the TLD-specific agreements returned by `GET /v3/domains/agreements?tlds={tld}`.
## Duplicate charge on retry
**Symptom:** A network failure caused the client to retry the registration, and the account was charged twice.
**Cause:** The first request succeeded server-side but the response was lost in transit. The retry created a second registration.
**Resolution:**
* Always include an `Idempotency-Key` header with a UUID that's stable for the lifetime of a single registration intent.
* If a request returns a network error (not a `4xx` or `5xx`), retry with the same `Idempotency-Key`. The server returns the original response without charging again.
* If a duplicate charge already occurred, contact GoDaddy support with the `registrationId` values.
## Domain not available
**Symptom:** `POST /v3/domains/registrations` returns `422` with a code indicating the domain isn't available.
**Cause:** The domain was registered or reserved by someone else between your availability check and the registration attempt, or the domain is in a status that prevents registration (for example, redemption period).
**Resolution:**
* Call `GET /v3/domains/check-availability` immediately before registering — don't cache availability results.
* If the exact domain is unavailable, use the suggestions endpoint to find alternatives.
* Go to [Search domain availability](https://developer.godaddy.com/docs/api-users/search-domains) for the availability check workflow.
## `422` with `NO_PAYMENT_PROFILE`
**Symptom:** API returns `422` with `code: "NO_PAYMENT_PROFILE"`.
**Cause:** The account has no payment method on file. Registration charges the billing method and cannot proceed without one.
**Resolution:**
* Add a payment method. Go to [Set up a payment profile](https://developer.godaddy.com/docs/api-users/payment-profile).
* Once a payment method is on file, retry the registration with a fresh `quoteToken`.
# Troubleshoot your first API call (https://developer.godaddy.com/en/docs/api-users/troubleshoot-first-call)
---
title: Troubleshoot your first API call
description: Common errors when making your first call to the GoDaddy Domains API, with causes and resolutions.
agentNotes:
scopes: ["domains.domain:read"]
failureRecovery: "Diagnostic page. All operations mentioned are read-only and safe to retry. On 401, verify token. On 403, check scopes. On timeout, check network."
faqItems:
- question: "Why does curl say 'Could not resolve host' for api.godaddy.com?"
answer: "DNS can't resolve the API hostname. Verify internet connectivity, check corporate proxy settings (--proxy flag or HTTPS_PROXY), or disconnect VPN to rule out DNS filtering."
- question: "Why do I get 401 Unauthorized on my first API call?"
answer: "The Authorization header is missing or the token value is wrong. Confirm your env var is set (echo $GODADDY_PAT), verify the format is 'Bearer ' with no extra quotes, and ensure you exported it in the same shell session."
- question: "Why does the availability check return 403 Forbidden?"
answer: "Your token doesn't have the domains.domain:read scope. Generate a new PAT with at least the domains.domain:read scope."
- question: "Why is the JSON response empty or unexpected?"
answer: "The domain parameter is likely malformed — missing the TLD, containing invalid characters, or using unsupported encoding. Use a fully-qualified domain name like 'your-idea.com' and ensure no invisible characters are present."
- question: "Why does the availability check say a domain is unavailable when it appears unregistered?"
answer: "The domain may be reserved, premium, or in a registry hold state. Check the 'definitive' field — if false, retry with optimizeFor=ACCURACY for a live registry check. Some TLDs reserve common words."
- question: "Why is the API connection timing out?"
answer: "Network issues, firewall blocking HTTPS to external hosts, or API degraded performance. Test connectivity with 'curl -I https://api.godaddy.com', ensure port 443 is open, and add --max-time 30 to your curl commands."
related:
guides:
- title: "Make your first call"
href: "/docs/api-users/quickstart"
- title: "Troubleshoot authentication"
href: "/docs/api-users/troubleshoot-authentication"
- title: "Search domain availability"
href: "/docs/api-users/search-domains"
concepts:
- title: "Error handling"
href: "/docs/api-users/errors"
- title: "Rate limits"
href: "/docs/api-users/rate-limits"
---
## Overview
This page covers errors you're likely to encounter during your first API calls. If you're getting started, go to the [quickstart](https://developer.godaddy.com/docs/api-users/quickstart) for the happy path first.
## `curl: (6) Could not resolve host`
**Symptom:** curl reports it can't resolve `api.godaddy.com`.
**Cause:** DNS can't resolve the API hostname. Typically a network or proxy issue.
**Resolution:**
- Verify internet connectivity (`curl https://google.com`).
- If behind a corporate proxy, configure curl to use it with the `--proxy` flag or `HTTPS_PROXY` environment variable.
- If on a VPN, try disconnecting temporarily to rule out DNS filtering.
## 401 Unauthorized on first call
**Symptom:** Your first API call returns `401`.
**Cause:** The `Authorization` header is missing or the token value is wrong.
**Resolution:**
- Confirm the environment variable is set: `echo $GODADDY_PAT` should print the token value.
- Verify the header format is `Bearer ` — no extra quotes, no `"Bearer "` with a trailing space.
- Make sure you exported the variable in the same shell session where you're running curl.
- Go to [Troubleshoot authentication](https://developer.godaddy.com/docs/api-users/troubleshoot-authentication) for deeper auth issues.
## 403 Forbidden on availability check
**Symptom:** `GET /v3/domains/check-availability` returns `403`.
**Cause:** The token doesn't have the `domains.domain:read` scope.
**Resolution:** Generate a new PAT with at least the `domains.domain:read` scope. Go to [Authentication — PAT scopes](https://developer.godaddy.com/docs/api-users/auth#pat-scopes).
## Empty or unexpected JSON response
**Symptom:** The response is empty, missing fields, or returns an unexpected structure.
**Cause:** The domain parameter is malformed — missing the TLD, contains invalid characters, or uses an unsupported encoding.
**Resolution:**
- Use a fully-qualified domain name including the TLD: `your-idea.com`, not `your-idea`.
- IDN (internationalized) domains must use punycode A-label form.
- Check for invisible characters copied from other sources (zero-width spaces, smart quotes).
## `available: false` for a domain you expected to be available
**Symptom:** The availability check returns `false` for a domain that appears unregistered.
**Cause:** The domain may be reserved, premium, or in a registry hold state that makes it unavailable through standard registration.
**Resolution:**
- The `definitive` field indicates whether the result came from a live registry check. If `false`, try again with `optimizeFor=ACCURACY` for a live check.
- Some TLDs reserve common words or short names. Try alternative TLDs.
- Premium domains may be available but at higher pricing — check the aftermarket.
## Connection timeout or slow responses
**Symptom:** curl hangs or times out connecting to the API.
**Cause:** Network issues, firewall blocking HTTPS to external hosts, or the API is experiencing degraded performance.
**Resolution:**
- Test basic connectivity: `curl -I https://api.godaddy.com`
- Check your firewall allows outbound HTTPS (port 443) to `api.godaddy.com`.
- Add a timeout to your curl commands: `curl --max-time 30 ...`
# Manage DNS records (https://developer.godaddy.com/en/docs/api-users/manage-domains/dns)
***
title: Manage DNS records
description: 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.
agentNotes:
permissions: \["DNS Management"]
scopes: \["domains.domain:read", "domains.dns:update", "domains.nameserver:update"]
idempotent: false
destructive: true
failureRecovery: "Read operations are safe to retry. Deletes are irreversible — confirm the recordId before calling DELETE. Re-read the zone after failures to verify state."
related:
apis:
* title: "Domains v3 — DNS records"
href: "/docs/references/rest/domains/v3/records"
guides:
* title: "Registered domains"
href: "/docs/api-users/manage-domains/list"
* title: "Forward a domain"
href: "/docs/api-users/manage-domains/forwarding"
* title: "Troubleshoot DNS"
href: "/docs/api-users/troubleshoot-dns"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
## 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:
| Operation | Description |
| --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| **DNS records** | Create and retrieve A, AAAA, CNAME, MX, TXT, SRV, NS, and CAA records on a domain hosted by GoDaddy's authoritative DNS. |
| **Nameservers** | Change 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](https://developer.godaddy.com/docs/api-users/auth) 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:
```bash tab="curl"
# 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"
```
```js tab="Node"
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);
```
```python tab="Python"
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"])
```
```go tab="Go"
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](#dnsrecord-schema) for the full field reference.
### DNSRecord schema
Every entry in `items[]` is a `DNSRecord` object.
| Field | Required | Description | Note |
| ---------- | --------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `recordId` | Read-only | Server-assigned stable identifier for the record. | |
| `name` | Yes | Record name relative to the zone apex. | Use `@` for the apex. Wildcards (`*`) supported for A, AAAA, and CNAME. |
| `type` | Yes | Record type: `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `SRV`, `NS`, `CAA`, `ALIAS`, or `SOA` (SOA is read-only). | |
| `data` | Yes | Record value. | Format depends on type: IP for A/AAAA, hostname for CNAME, text for TXT, etc. |
| `ttl` | Yes | Time-to-live in seconds. | Minimum 600 (10 min), maximum 86400 (24 hrs). |
| `priority` | MX, SRV | Priority value. | Lower value equals higher preference. |
| `weight` | SRV | Relative weight among equal-priority targets. | |
| `port` | SRV | Target port number. | |
| `service` | SRV | Service name. | Prefixed with an underscore (for example, `_http`). |
| `protocol` | SRV | Transport protocol. | Prefixed with underscore (for example, `_tcp`). |
| `flag` | CAA | Restriction flags byte. | Use `0` for non-critical, `128` for critical. |
| `tag` | CAA | Property 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:
```bash
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:
```bash tab="curl"
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 }'
```
```js tab="Node"
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);
```
```python tab="Python"
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"])
```
```go tab="Go"
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.
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](https://developer.godaddy.com/docs/api-users/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:
```bash tab="curl"
curl -s -X DELETE "https://api.godaddy.com/v3/domains/zones/example.com/dns-records/$RECORD_ID" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
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
```
```python tab="Python"
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
```
```go tab="Go"
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.
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:
```bash tab="curl"
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"]'
```
```js tab="Node"
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
```
```python tab="Python"
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
```
```go tab="Go"
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.
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](https://developer.godaddy.com/docs/api-users/cli-setup), 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:
```bash
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
| Status | Most likely cause |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | Malformed request — missing required field, invalid field type, or unknown record type. Inspect `fields[]`. |
| `401` | Authentication credentials are missing or invalid. |
| `403` | Caller is not authorized. Check that your token includes the required scope (`domains.dns:update` or `domains.nameserver:update`). |
| `404` | Record or domain not found, or not owned by the authenticated account. |
| `409` | Conflict — request cannot be completed in the current state. For DNS: attempting to delete a GoDaddy-managed SOA or NS record (`dns_record_not_mutable`). |
| `422` | Valid structure but violates a business rule (e.g. CNAME at apex). |
| `429` | Rate limit exceeded. |
Full error envelope: [Errors](https://developer.godaddy.com/docs/api-users/errors).
## DNSRecord schema
| Field | Required | Description | Note |
| ---------- | --------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `recordId` | Read-only | Server-assigned stable identifier for the record. | |
| `name` | Yes | Record name relative to the zone apex. | Use `@` for the apex. Wildcards (`*`) supported for A, AAAA, and CNAME. |
| `type` | Yes | Record type: `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `SRV`, `NS`, `CAA`, `ALIAS`, or `SOA` (SOA is read-only). | |
| `data` | Yes | Record value. | Format depends on type (like IP for A/AAAA, hostname for CNAME, and text for TXT). |
| `ttl` | Yes | Time-to-live in seconds. | Minimum 600 (10 min), maximum 86400 (24 hrs). |
| `priority` | MX, SRV | Priority value. | Lower value equals higher preference. |
| `weight` | SRV | Relative weight among equal-priority targets. | |
| `port` | SRV | Target port number. | |
| `service` | SRV | Service name. | Prefixed with an underscore (for example, `_http`). |
| `protocol` | SRV | Transport protocol. | Prefixed with underscore (for example, `_tcp`). |
| `flag` | CAA | Restriction flags byte. | Use `0` for non-critical, `128` for critical. |
| `tag` | CAA | Property tag: `issue`, `issuewild`, or `iodef`. | |
## Reference
* [v3 API reference](https://developer.godaddy.com/docs/references/rest/domains/v3)
## Next
# Forward a domain (https://developer.godaddy.com/en/docs/api-users/manage-domains/forwarding)
***
title: Forward a domain
description: Create, read, update, and delete HTTP redirect rules on a domain or subdomain via the v2 forwarding API.
agentNotes:
permissions: \["Domain Owner"]
scopes: \["domains.domain:read", "domains.domain:update"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "PUT is idempotent — replaying yields the same rule. DELETE is safe; a subsequent GET returns 404. Verify current state via GET before retrying ambiguous errors."
related:
apis:
* title: "Domains v2 — Forwarding"
href: "/docs/references/rest/domains/v2/manage-domain-settings"
guides:
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
* title: "Registered domains"
href: "/docs/api-users/manage-domains/list"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
***
## Overview
Domain forwarding creates an HTTP redirect rule for a fully-qualified domain name (FQDN) — the root domain or a subdomain. When a browser requests the FQDN, the registrar returns a redirect to the target URL. Use forwarding to redirect a root domain to `www`, point a subdomain to an external URL, or set up temporary redirects during a site migration.
Forwarding operations use the v2 API at `/v2/customers/{customerId}/domains/forwards/{fqdn}`. The `customerId` path parameter is your GoDaddy shopper ID.
Domain forwarding is v2-only. There is no equivalent in the v1 namespace.
## Prerequisites
The following prerequisites are required before you manage forwarding rules:
* A GoDaddy account with at least one registered domain
* A [Personal Access Token](https://developer.godaddy.com/docs/api-users/auth) with `domains.domain:read` and `domains.domain:update` scopes
* Your GoDaddy shopper ID (`CUSTOMER_ID`) (located in your [GoDaddy account settings](https://sso.godaddy.com))
## Read a forwarding rule
Returns the `DomainForwarding` object for the FQDN. Returns `404` if no forwarding rule is configured for that FQDN.
The following procedure reads a forwarding rule for an FQDN.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s "https://api.godaddy.com/v2/customers/$CUSTOMER_ID/domains/forwards/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const customer = process.env.CUSTOMER_ID;
const res = await fetch(
`https://api.godaddy.com/v2/customers/${customer}/domains/forwards/example.com`,
{
headers: {
Authorization: `Bearer ${pat}`,
Accept: "application/json",
},
},
);
if (res.status === 404) throw new Error("No forwarding rule set");
console.log(await res.json());
```
```python tab="Python"
import os, requests
customer = os.environ["CUSTOMER_ID"]
res = requests.get(
f"https://api.godaddy.com/v2/customers/{customer}/domains/forwards/example.com",
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Accept": "application/json",
},
)
if res.status_code == 404:
print("No forwarding rule set")
else:
print(res.json())
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
customer := os.Getenv("CUSTOMER_ID")
url := fmt.Sprintf(
"https://api.godaddy.com/v2/customers/%s/domains/forwards/example.com",
customer)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("GODADDY_PAT"))
req.Header.Set("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
if res.StatusCode == 404 {
fmt.Println("No forwarding rule set")
return
}
var rule map[string]any
json.NewDecoder(res.Body).Decode(&rule)
fmt.Println(rule)
}
```
Response (`DomainForwarding` object):
```json
{
"fqdn": "example.com",
"type": "REDIRECT_PERMANENT",
"url": "https://www.example.com/"
}
```
Returns `404` if no forwarding rule is configured for the FQDN.
## Create or replace a forwarding rule
`PUT /v2/customers/{customerId}/domains/forwards/{fqdn}` creates the rule if it doesn't exist, or replaces it if it does. The call is idempotent — replaying the same request produces the same rule.
The following procedure creates or replaces a forwarding rule.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X PUT "https://api.godaddy.com/v2/customers/$CUSTOMER_ID/domains/forwards/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{
"fqdn": "example.com",
"type": "REDIRECT_PERMANENT",
"url": "https://www.example.com/"
}'
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const customer = process.env.CUSTOMER_ID;
const res = await fetch(
`https://api.godaddy.com/v2/customers/${customer}/domains/forwards/example.com`,
{
method: "PUT",
headers: {
Authorization: `Bearer ${pat}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
fqdn: "example.com",
type: "REDIRECT_PERMANENT",
url: "https://www.example.com/",
}),
},
);
console.log(res.status); // expect 204
```
```python tab="Python"
import os, requests
customer = os.environ["CUSTOMER_ID"]
res = requests.put(
f"https://api.godaddy.com/v2/customers/{customer}/domains/forwards/example.com",
json={"fqdn": "example.com", "type": "REDIRECT_PERMANENT", "url": "https://www.example.com/"},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
print(res.status_code) # expect 204
```
```go tab="Go"
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
customer := os.Getenv("CUSTOMER_ID")
body := bytes.NewReader([]byte(
`{"fqdn":"example.com","type":"REDIRECT_PERMANENT","url":"https://www.example.com/"}`))
req, _ := http.NewRequest("PUT",
fmt.Sprintf("https://api.godaddy.com/v2/customers/%s/domains/forwards/example.com", customer),
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 204
}
```
Returns `204 No Content` on success.
### Forward a subdomain
The `fqdn` path parameter accepts any FQDN on a domain you own. The same PUT pattern applies — just change the `fqdn` path parameter and body field to the subdomain:
```bash
curl -s -X PUT "https://api.godaddy.com/v2/customers/$CUSTOMER_ID/domains/forwards/shop.example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{
"fqdn": "shop.example.com",
"type": "REDIRECT_PERMANENT",
"url": "https://store.example.com/"
}'
```
## Delete a forwarding rule
Removes the forwarding rule for the FQDN. Returns `204 No Content`. After deletion, browsers visiting the FQDN no longer receive a redirect.
The following procedure deletes a forwarding rule.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X DELETE "https://api.godaddy.com/v2/customers/$CUSTOMER_ID/domains/forwards/example.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const customer = process.env.CUSTOMER_ID;
const res = await fetch(
`https://api.godaddy.com/v2/customers/${customer}/domains/forwards/example.com`,
{
method: "DELETE",
headers: { Authorization: `Bearer ${pat}` },
},
);
console.log(res.status); // expect 204
```
```python tab="Python"
import os, requests
customer = os.environ["CUSTOMER_ID"]
res = requests.delete(
f"https://api.godaddy.com/v2/customers/{customer}/domains/forwards/example.com",
headers={"Authorization": f"Bearer {os.environ['GODADDY_PAT']}"},
)
print(res.status_code) # expect 204
```
```go tab="Go"
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
customer := os.Getenv("CUSTOMER_ID")
req, _ := http.NewRequest("DELETE",
fmt.Sprintf("https://api.godaddy.com/v2/customers/%s/domains/forwards/example.com", customer),
nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("GODADDY_PAT"))
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
fmt.Println(res.StatusCode) // expect 204
}
```
## Forwarding rule fields
| Field | Required | Description |
| ------ | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `fqdn` | Yes | The domain or subdomain to forward (e.g. `example.com` or `shop.example.com`). Must match the `{fqdn}` path parameter. |
| `type` | Yes | Redirect type — see table below. |
| `url` | Yes | Destination URL (must be a valid `http://` or `https://` URL). |
| `mask` | No | Masking options when `type` is `MASKED`. |
### Redirect types
| Type | HTTP code | Description |
| -------------------- | --------- | -------------------------------------------------------------------------------------------------------------- |
| `REDIRECT_PERMANENT` | 301 | Permanent redirect. Search engines transfer link equity to the target. Use for long-term or permanent moves. |
| `REDIRECT_TEMPORARY` | 302 | Temporary redirect. Search engines retain the source URL's link equity. Use for short-term redirects. |
| `MASKED` | — | The browser loads the target URL but the original FQDN stays visible in the address bar. Uses an inline frame. |
Masked forwarding prevents the destination URL from appearing in the browser address bar by loading it in a frame. It isn't appropriate for most use cases and can harm SEO. Prefer `REDIRECT_PERMANENT` or `REDIRECT_TEMPORARY` unless masking is specifically required.
## Common errors
| Status | Most likely cause |
| ------ | -------------------------------------------------------------------------------------------------------------- |
| `403` | Credential lacks write access to this domain. |
| `404` | Domain doesn't exist, isn't owned by the authenticated account, or no forwarding rule exists (for GET/DELETE). |
| `409` | Domain status prevents the operation (e.g. domain is in a pending transfer). |
| `422` | Invalid `fqdn`, invalid destination URL, or unrecognized `type` value. |
Full error envelope: [Errors](https://developer.godaddy.com/docs/api-users/errors).
## Reference
* [v2 forwarding operations](https://developer.godaddy.com/docs/references/rest/domains/v2/manage-domain-settings)
## Next
# Browse the Domains API (https://developer.godaddy.com/en/docs/api-users/manage-domains)
***
title: Browse the Domains API
description: The Domain object, related resources, and task-grouped operations.
related:
apis:
* title: "Domains v3 reference"
href: "/docs/references/rest/domains/v3"
* title: "Domains v1 reference"
href: "/docs/references/rest/domains/v1"
* title: "Domains v2 reference"
href: "/docs/references/rest/domains/v2"
guides:
* title: "Quickstart"
href: "/docs/api-users/quickstart"
* title: "Authenticate"
href: "/docs/api-users/auth"
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
***
## Overview
The Domains API supports availability search, registration, DNS and contact management, registry lock, forwarding, and inbound transfers. Operations span three version namespaces. v3 is the preferred API for domain registration, v1 and v2 provide everything else (DNS, renewals, transfers, and customer actions).
## Version namespaces
The following table lists the version namespaces and what they contain.
| Version | Base path | What's here |
| ------- | ---------------------------------------- | ----------------------------------------------------------------------------------- |
| v3 | `/v3/domains/...` | Availability checks and registration (the preferred namespace for new integrations) |
| v2 | `/v2/customers/{customerId}/domains/...` | v1 capabilities with async processing and operations tracking |
| v1 | `/v1/domains/...` | List, DNS, contacts, lock, and renewals |
## The Domain object
A domain registered or managed through this API is the central resource of the Domains namespace. It carries registry metadata, expiration and renewal state, the four WHOIS contact roles, registry lock and privacy flags, and the authoritative nameservers returned at the TLD. Almost every operation in this namespace either returns a `DomainDetail` or modifies a field on one.
The schema is named `DomainDetail` in v1 and `DomainDetailV2` in v2. The two are largely overlapping; v2 extends v1 with async operation tracking — the `DomainDetailV2` schema adds status values and action references used by long-running writes like transfers and redemptions. For single-domain detail, prefer v2: it returns more consistent status values and exposes async operation tracking if you need it.
The following table lists the key fields on a `DomainDetail` object.
| Field | Description |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `domain` | Fully-qualified domain name (for example `example.com`). |
| `status` | Current registry or registrar state, like `ACTIVE`, `PENDING_TRANSFER`, or `EXPIRED`. |
| `expires` | Expiration timestamp in ISO-8601 format. |
| `renewAuto` | Whether auto-renew is enabled on the domain. |
| `locked` | Whether the registry transfer-lock is engaged. |
| `privacy` | Whether WHOIS privacy is purchased and active. |
| `nameServers` | Authoritative nameservers the registry returns for the domain. |
| `contactRegistrant` / `contactAdmin` / `contactBilling` / `contactTech` | The four WHOIS contact roles, each a `Contact` object. |
The full schema is in the OpenAPI specs, available as machine-readable JSON at [/openapi/domains-v1.json](https://developer.godaddy.com/openapi/domains-v1.json) and [/openapi/domains-v2.json](https://developer.godaddy.com/openapi/domains-v2.json). Go to the [Domains REST reference](https://developer.godaddy.com/docs/references/rest/domains) for the complete API reference.
### Related objects
Every operation in the Domains namespace returns or accepts one of the following objects in addition to `DomainDetail`. Each links to the rendered reference where its full schema and the operations it appears on are documented.
| Object | Description | Reference |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `DNSRecord` | A single DNS record on a domain managed by GoDaddy's authoritative nameservers, supporting `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `SRV`, `NS`, `SOA`, and `CAA` types. | [v1 DNS operations](https://developer.godaddy.com/docs/references/rest/domains/v1/manage-dns) |
| `Contact` | A WHOIS contact record covering name, organization, address, email, and phone. The same shape is used for the registrant, admin, billing, and tech roles on a domain. | [v2 management operations](https://developer.godaddy.com/docs/references/rest/domains/v2/manage-domain-settings) |
| `Action` | An asynchronous-operation tracker returned with `202 Accepted` when the API queues a long-running write (transfers, redemption). Callers poll the action endpoint until the action's `status` reaches a terminal state. | [v2 action operations](https://developer.godaddy.com/docs/references/rest/domains/v2/domain-actions) |
| `DomainAvailableResponse` | The result of a single-domain availability check, including the available flag, current price in `currency-micro-unit` format, the registration period in years, and whether the answer came from a live registry call or cache. | [v1 availability operations](https://developer.godaddy.com/docs/references/rest/domains/v1/find-domains) |
| `DomainForwarding` | An HTTP forwarding rule that redirects requests for a domain to a target URL, configurable as masked or unmasked and as a permanent (`301`) or temporary (`302`) redirect. | [v2 management operations](https://developer.godaddy.com/docs/references/rest/domains/v2/manage-domain-settings) |
| `DomainTransferIn` | The request shape for an inbound transfer, carrying the domain name, authcode, and required contacts. | [v2 transfer operations](https://developer.godaddy.com/docs/references/rest/domains/v2/transfer-domains) |
| `Error` / `ErrorLimit` | The standard error envelope returned on `4xx` and `5xx` responses across the namespace. `ErrorLimit` extends `Error` with `retryAfterSec` for `429` rate-limited responses. | [Errors](https://developer.godaddy.com/docs/api-users/errors) |
Most Domains API writes complete synchronously and return `204 No Content`. A few long-running operations — transfers, redemption — return `202 Accepted` with an `Action` body instead. Poll `GET /v2/customers/{customerId}/domains/actions/{actionId}` until `status` reaches a terminal state (`COMPLETED`, `FAILED`, or `CANCELLED`).
## Tasks
### Manage existing domains
### Acquire new domains
* [Generate a Personal Access Token (PAT)](https://developer.godaddy.com/docs/api-users/auth).
* [Fund your account](https://www.godaddy.com/help/add-a-payment-method-to-my-godaddy-account-20037) for write operations.
* [Set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup).
* [Make your first call](https://developer.godaddy.com/docs/api-users/quickstart).
# Registered domains (https://developer.godaddy.com/en/docs/api-users/manage-domains/list)
***
title: Registered domains
description: Retrieve the domains owned by the authenticated account, with cursor pagination, and fetch full detail for any one domain.
agentNotes:
permissions: \["DNS Management", "Domain Owner"]
scopes: \["domains.domain:read"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "Read-only. Safe to retry any failure. For paginated cursors, resume from the last successful marker."
related:
apis:
* title: "Domains v1 — List domains"
href: "/docs/references/rest/domains/v1/manage-domain-settings"
* title: "Domains v2 — Get domain detail"
href: "/docs/references/rest/domains/v2/manage-domain-settings"
guides:
* title: "Update contacts"
href: "/docs/api-users/manage-domains/update-contacts"
* title: "Manage renewals"
href: "/docs/api-users/manage-domains/renewals"
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
concepts:
* title: "Pagination"
href: "/docs/api-users/pagination"
* title: "Authentication"
href: "/docs/api-users/auth"
***
## Overview
Retrieve the domains registered to an account using `GET /v1/domains`, then fetch full detail for any single domain using `GET /v2/customers/{customerId}/domains/{domain}`. List results are paginated using `limit` and `marker` cursor parameters.
Domain listing isn't available in v3 yet. This page uses the v1 endpoint (`GET /v1/domains`) for account-scoped listing and the v2 endpoint (`GET /v2/customers/{customerId}/domains/{domain}`) for single-domain detail. Prefer v2 for single-domain detail — v2 domain statuses are more consistent, and v2 gives you access to async operation tracking if you need it.
`GET /v1/domains` returns the domains owned by the authenticated account, paginated with `limit` and `marker`. `GET /v1/domains/{domain}` returns full detail for a single domain.
This page assumes you have a PAT credential. See [Authentication](https://developer.godaddy.com/docs/api-users/auth) and [Quickstart](https://developer.godaddy.com/docs/api-users/quickstart) if you don't.
## Retrieve registered domains
The response is an array of domain summaries. For pagination semantics and a looping example, see [Pagination](https://developer.godaddy.com/docs/api-users/pagination).
The following procedure retrieves the domains registered to the authenticated account.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s "https://api.godaddy.com/v1/domains?limit=100" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch("https://api.godaddy.com/v1/domains?limit=100", {
headers: {
Authorization: `Bearer ${pat}`,
Accept: "application/json",
},
});
const domains = await res.json();
console.log(domains.map((d) => d.domain));
```
```python tab="Python"
import os, requests
pat = os.environ["GODADDY_PAT"]
res = requests.get(
"https://api.godaddy.com/v1/domains",
params={"limit": 100},
headers={
"Authorization": f"Bearer {pat}",
"Accept": "application/json",
},
)
res.raise_for_status()
for d in res.json():
print(d["domain"], d.get("status"))
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
type Domain struct {
Domain string `json:"domain"`
Status string `json:"status"`
}
func main() {
pat := os.Getenv("GODADDY_PAT")
req, _ := http.NewRequest("GET",
"https://api.godaddy.com/v1/domains?limit=100", nil)
req.Header.Set("Authorization", "Bearer "+pat)
req.Header.Set("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()
var domains []Domain
json.NewDecoder(res.Body).Decode(&domains)
for _, d := range domains {
fmt.Println(d.Domain, d.Status)
}
}
```
### Filtering
`GET /v1/domains` accepts these query parameters in addition to `limit` and `marker`:
| Parameter | Notes |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `statuses` | Comma-separated list of domain statuses (e.g. `ACTIVE`, `EXPIRED`, `PENDING_TRANSFER`). Returns only domains in one of the listed statuses. |
| `statusGroups` | Coarser filter — by status group (e.g. `VISIBLE`, `EXPIRED`). |
| `includes` | Comma-separated list of expansions to include (e.g. `contacts`). Adds related objects to each item without a follow-up call. |
| `modifiedDate` | ISO-8601 timestamp. Returns only domains modified at or after this time. |
Reference: [`GET /v1/domains`](https://developer.godaddy.com/docs/references/rest/domains/v1/manage-domain-settings).
## Get details for a single domain
The response is a `DomainDetail` object covering registration metadata, expiration, contacts, nameservers, lock state, privacy state, and auto-renew configuration. For the full schema, see the reference.
The following procedure retrieves details for a single domain.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch("https://api.godaddy.com/v1/domains/example.com", {
headers: {
Authorization: `Bearer ${pat}`,
Accept: "application/json",
},
});
const detail = await res.json();
console.log(detail.domain, detail.status, detail.expires);
```
```python tab="Python"
import os, requests
pat = os.environ["GODADDY_PAT"]
res = requests.get(
"https://api.godaddy.com/v1/domains/example.com",
headers={"Authorization": f"Bearer {pat}", "Accept": "application/json"},
)
res.raise_for_status()
d = res.json()
print(d["domain"], d["status"], d["expires"])
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
pat := os.Getenv("GODADDY_PAT")
req, _ := http.NewRequest("GET",
"https://api.godaddy.com/v1/domains/example.com", nil)
req.Header.Set("Authorization", "Bearer "+pat)
req.Header.Set("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
var detail struct {
Domain string `json:"domain"`
Status string `json:"status"`
Expires string `json:"expires"`
}
json.NewDecoder(res.Body).Decode(&detail)
fmt.Println(detail.Domain, detail.Status, detail.Expires)
}
```
Reference: [`GET /v1/domains/{domain}`](https://developer.godaddy.com/docs/references/rest/domains/v1/manage-domain-settings).
## v2 — single domain detail
Use the v2 endpoint for single-domain detail. It returns consistent status values and gives you access to async operation tracking if you need it.
The following procedure retrieves domain details for a specific customer.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s "https://api.godaddy.com/v2/customers/$CUSTOMER_ID/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const customer = process.env.CUSTOMER_ID;
const res = await fetch(
`https://api.godaddy.com/v2/customers/${customer}/domains/example.com`,
{
headers: {
Authorization: `Bearer ${pat}`,
Accept: "application/json",
},
},
);
const detail = await res.json();
console.log(detail.domain, detail.status);
```
```python tab="Python"
import os, requests
customer = os.environ["CUSTOMER_ID"]
res = requests.get(
f"https://api.godaddy.com/v2/customers/{customer}/domains/example.com",
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Accept": "application/json",
},
)
res.raise_for_status()
d = res.json()
print(d["domain"], d["status"])
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
customer := os.Getenv("CUSTOMER_ID")
pat := os.Getenv("GODADDY_PAT")
req, _ := http.NewRequest("GET",
fmt.Sprintf("https://api.godaddy.com/v2/customers/%s/domains/example.com", customer), nil)
req.Header.Set("Authorization", "Bearer "+pat)
req.Header.Set("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
var detail struct {
Domain string `json:"domain"`
Status string `json:"status"`
}
json.NewDecoder(res.Body).Decode(&detail)
fmt.Println(detail.Domain, detail.Status)
}
```
Reference: [`GET /v2/customers/{customerId}/domains/{domain}`](https://developer.godaddy.com/docs/references/rest/domains/v2/manage-domain-settings).
v2 paths (`/v2/customers/{customerId}/domains/...`) are preferred for single-domain detail; v1 paths are appropriate for list operations and account-scoped writes.
## Use the CLI
After you [set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup), you can use it to list domains in your account and fetch full details for one domain.
The following procedure lists domains and fetches domain details using the CLI.
* Run the command for your operation:
```bash
gddy domain list
gddy domain list --status ACTIVE
gddy domain get example.com
```
Use the REST API for v2 single-domain detail; the preceding CLI commands use v1 account-scoped endpoints.
## Common errors
| Status | Most likely cause |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `401` | Token missing, expired, or revoked. |
| `403` | Account doesn't meet requirements for this operation. See [Account requirements](https://developer.godaddy.com/docs/api-users/auth#account-requirements). |
| `404` (single-domain GET) | Domain doesn't exist, or isn't owned by the authenticated account. |
| `429` | Rate limit. Wait `retryAfterSec` and retry. |
Full error envelope and retry guidance: [Errors](https://developer.godaddy.com/docs/api-users/errors).
## Next
# Lock a domain (https://developer.godaddy.com/en/docs/api-users/manage-domains/lock)
***
title: Lock a domain
description: Read and toggle the registry transfer-lock state on a domain you own. Unlock only when a transfer or registrant change requires it.
agentNotes:
permissions: \["Domain Owner"]
scopes: \["domains.domain:read", "domains.domain:update"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "Idempotent — locking an already-locked domain is a no-op. Prefer GET-before-PATCH to confirm current state on error retries."
related:
apis:
* title: "Domains v1 — Update domain"
href: "/docs/references/rest/domains/v1/manage-domain-settings"
guides:
* title: "Update contacts"
href: "/docs/api-users/manage-domains/update-contacts"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
***
## Overview
Registry lock sets the `clientTransferProhibited` flag at the domain registry, preventing any registrar from initiating an outbound transfer without your explicit consent. Lock is enabled by default at registration and has no effect on DNS resolution, email delivery, or any service hosted on the domain. Disable it only for the duration of a transfer or registrant change, then re-enable it immediately.
Lock state is a field on the `DomainDetail` object, read with `GET /v1/domains/{domain}` and toggled with `PATCH /v1/domains/{domain}`.
Registry lock management isn't available in v3 yet. This page uses the v1 endpoint (`PATCH /v1/domains/{domain}`).
## Prerequisites
The following prerequisites are required before you manage registry lock:
* A GoDaddy account that owns the domain
* A [Personal Access Token](https://developer.godaddy.com/docs/api-users/auth) with `domains.domain:read` and `domains.domain:update` scopes
## Read lock state
Returns the full `DomainDetail` object. The `locked` boolean is `true` when `clientTransferProhibited` is set at the registry.
The following procedure reads the lock state for a domain.
* Run the following command:
```bash
curl -s "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
```json
{
"domain": "example.com",
"status": "ACTIVE",
"locked": true,
"renewAuto": true,
"expires": "2026-03-15T00:00:00.000Z"
}
```
## Enable lock
Send `{"locked": true}` to the domain update endpoint. Returns `204 No Content`. Idempotent — locking an already-locked domain is a no-op.
The following procedure enables the registry transfer-lock on a domain.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X PATCH "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"locked": true}'
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch("https://api.godaddy.com/v1/domains/example.com", {
method: "PATCH",
headers: {
Authorization: `Bearer ${pat}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ locked: true }),
});
console.log(res.status); // expect 204
```
```python tab="Python"
import os, requests
res = requests.patch(
"https://api.godaddy.com/v1/domains/example.com",
json={"locked": True},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
print(res.status_code) # expect 204
```
```go tab="Go"
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := bytes.NewReader([]byte(`{"locked": true}`))
req, _ := http.NewRequest("PATCH",
"https://api.godaddy.com/v1/domains/example.com", 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 204
}
```
## Disable lock
Send `{"locked": false}` to release the transfer-lock. Returns `204 No Content`.
The following procedure disables the registry transfer-lock on a domain.
Unlock only for as long as the transfer or registrant change requires. Once the operation completes, re-enable lock with `{"locked": true}`. High-value and production-serving domains should be locked at all other times.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X PATCH "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"locked": false}'
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch("https://api.godaddy.com/v1/domains/example.com", {
method: "PATCH",
headers: {
Authorization: `Bearer ${pat}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ locked: false }),
});
console.log(res.status); // expect 204
```
```python tab="Python"
import os, requests
res = requests.patch(
"https://api.godaddy.com/v1/domains/example.com",
json={"locked": False},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
print(res.status_code) # expect 204
```
```go tab="Go"
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := bytes.NewReader([]byte(`{"locked": false}`))
req, _ := http.NewRequest("PATCH",
"https://api.godaddy.com/v1/domains/example.com", 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 204
}
```
## When to unlock
Two operations require the lock to be off before they can proceed:
| Scenario | Detail |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Outbound transfer** | The receiving registrar cannot initiate the transfer until lock is disabled. |
| **Registrant change on some TLDs** | A subset of ccTLDs require unlock before the registry accepts a registrant update. Check the TLD's registry policy before attempting the change. |
Lock is enabled by default at registration. Leave it on at all other times — it has no effect on DNS resolution, email delivery, or any service hosted on the domain.
## Request body
`PATCH /v1/domains/{domain}` accepts a `DomainUpdate` object. Only the fields you include are updated.
| Field | Type | Description |
| ------------- | --------- | --------------------------------------------------------------------------------------------------------------------------- |
| `locked` | boolean | Whether to engage the registry transfer-lock. |
| `renewAuto` | boolean | Whether auto-renew is enabled. See [Renewals](https://developer.godaddy.com/docs/api-users/manage-domains/renewals). |
| `nameServers` | string\[] | Authoritative nameservers (apex). See [DNS → Manage nameservers](https://developer.godaddy.com/docs/api-users/manage-domains/dns#manage-nameservers-v2). |
| `exposeWhois` | boolean | Whether contact details appear in WHOIS. Overridden by `privacy`. |
## Common errors
| Status | Most likely cause |
| ------ | ----------------------------------------------------------------- |
| `400` | Malformed request body. |
| `403` | Credential lacks write access to this domain. |
| `404` | Domain doesn't exist or isn't owned by the authenticated account. |
| `409` | Conflicting operation in progress (e.g. mid-transfer). |
| `422` | Invalid field value. |
Full error envelope: [Errors](https://developer.godaddy.com/docs/api-users/errors).
## Reference
* [v1 domain settings — domain update (`PATCH /v1/domains/{domain}`)](https://developer.godaddy.com/docs/references/rest/domains/v1/manage-domain-settings)
## Next
# Manage renewals (https://developer.godaddy.com/en/docs/api-users/manage-domains/renewals)
***
title: Manage renewals
description: Toggle auto-renew and manually renew a domain before expiration.
agentNotes:
permissions: \["Domain Owner", "Billing"]
scopes: \["domains.domain:read", "domains.domain:update"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: false
destructive: false
failureRecovery: "renewAuto toggle is idempotent. Manual renew is NOT — charging the account is a real-money side effect. On timeout/network error, GET the domain to verify the new expires timestamp before retrying."
related:
apis:
* title: "Domains v1 — Renew"
href: "/docs/references/rest/domains/v1/manage-domain-settings"
guides:
* title: "Registered domains"
href: "/docs/api-users/manage-domains/list"
* title: "Update contacts"
href: "/docs/api-users/manage-domains/update-contacts"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
***
## Overview
Control when and how a domain renews using two mechanisms: auto-renew (a flag that fires before expiration) and manual renewal (a POST call that extends registration immediately and charges the account). Use auto-renew for domains you want to keep without manual intervention; use manual renewal to extend a domain ahead of an upcoming expiration.
Renewal management isn't available in v3 yet. This page uses the v1 endpoints (`POST /v1/domains/{domain}/renew` and `PATCH /v1/domains/{domain}`).
A domain's renewal state is controlled through two mechanisms:
* **Auto-renew** — a flag on the domain that tells the registrar to renew automatically before expiration. Free to toggle. No registry interaction until the renewal actually fires.
* **Manual renew** — a `POST /v1/domains/{domain}/renew` call that adds a registration period immediately. Charges the account in production.
Both the `renewAuto` flag and the `expires` timestamp live on the `DomainDetail` object.
## Read renewal state
Returns the full `DomainDetail` object. The `renewAuto` flag and `expires` timestamp are the two renewal-relevant fields.
The following procedure reads the renewal state for a domain.
* Run the following command:
```bash
curl -s "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Accept: application/json"
```
```json
{
"domain": "example.com",
"status": "ACTIVE",
"renewAuto": true,
"expires": "2026-03-15T00:00:00.000Z"
}
```
## Toggle auto-renew
Auto-renew is toggled through `PATCH /v1/domains/{domain}`.
The following procedure toggles auto-renew on a domain.
**Enable auto-renew:**
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X PATCH "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"renewAuto": true}'
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch("https://api.godaddy.com/v1/domains/example.com", {
method: "PATCH",
headers: {
Authorization: `Bearer ${pat}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ renewAuto: true }),
});
console.log(res.status); // expect 204
```
```python tab="Python"
import os, requests
res = requests.patch(
"https://api.godaddy.com/v1/domains/example.com",
json={"renewAuto": True},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
print(res.status_code) # expect 204
```
```go tab="Go"
package main
import (
"bytes"
"fmt"
"net/http"
"os"
)
func main() {
body := bytes.NewReader([]byte(`{"renewAuto": true}`))
req, _ := http.NewRequest("PATCH",
"https://api.godaddy.com/v1/domains/example.com", 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 204
}
```
**Disable auto-renew:**
* Run the following command:
```bash
curl -s -X PATCH "https://api.godaddy.com/v1/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"renewAuto": false}'
```
Both return `204 No Content`. The operation is free and idempotent — setting the flag to its current value is a no-op.
Auto-renew is enabled by default at registration time. If you are managing domains on behalf of customers, consider whether you want the domain to auto-renew without explicit confirmation.
## Manually renew a domain
`POST /v1/domains/{domain}/renew` appends a registration period to the current expiration date.
The following procedure manually renews a domain.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X POST "https://api.godaddy.com/v1/domains/example.com/renew" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"period": 1}'
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const res = await fetch("https://api.godaddy.com/v1/domains/example.com/renew", {
method: "POST",
headers: {
Authorization: `Bearer ${pat}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ period: 1 }),
});
if (!res.ok) throw new Error(`Renewal failed: ${res.status}`);
const order = await res.json();
console.log("Order:", order.orderId, "Total:", order.total / 1_000_000, order.currency);
```
```python tab="Python"
import os, requests
res = requests.post(
"https://api.godaddy.com/v1/domains/example.com/renew",
json={"period": 1},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
res.raise_for_status()
order = res.json()
print("Order:", order["orderId"], "Total:", order["total"] / 1_000_000, order["currency"])
```
```go tab="Go"
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body := bytes.NewReader([]byte(`{"period": 1}`))
req, _ := http.NewRequest("POST",
"https://api.godaddy.com/v1/domains/example.com/renew", 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 order struct {
OrderID int `json:"orderId"`
Total int `json:"total"`
Currency string `json:"currency"`
}
json.NewDecoder(res.Body).Decode(&order)
fmt.Printf("Order: %d Total: %.2f %s\n",
order.OrderID, float64(order.Total)/1_000_000, order.Currency)
}
```
Response:
```json
{
"orderId": 8675309,
"itemCount": 1,
"total": 1199000,
"currency": "USD"
}
```
`total` is in `currency-micro-unit` format — divide by 1,000,000 to get the value in `currency`.
### Request body
| Field | Required | Description |
| -------- | -------- | ------------------------------------------------------------------------------- |
| `period` | No | Years to add (1–10). Defaults to the period specified at original registration. |
`POST /v1/domains/{domain}/renew` charges the account's billing method. Verify the domain name, period, and price before sending. To check the renewal price first, call the v2 domain detail endpoint:
```bash
curl -s "https://api.godaddy.com/v2/customers/{customerId}/domains/example.com" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json"
```
The response includes a `renewal` object with the current price:
```json
{
"renewal": {
"currency": "USD",
"price": 11990000,
"renewable": true
}
}
```
`price` is in `currency-micro-unit` format — divide by 1,000,000 for the currency value (for example, `11990000` = `$11.99`).
### Response: DomainPurchaseResponse
| Field | Description |
| ----------- | --------------------------------------------------------------------------------------- |
| `orderId` | Unique identifier of the order. |
| `itemCount` | Number of items in the order (typically 1). |
| `total` | Total cost in `currency-micro-unit` format. Divide by 1,000,000 for the currency value. |
| `currency` | ISO 4217 currency code (e.g. `USD`). |
## Expiration and grace periods
After a domain expires, GoDaddy provides a recovery window before the domain is permanently released. Standard renewal pricing applies for approximately 12 days post-expiration. After that, the domain leaves your account and additional fees apply to recover it.
ccTLDs and some other TLDs follow different expiration timelines. Check the full timeline before relying on these windows in your logic.
Go to [Standard domain expiration timeline](https://www.godaddy.com/help/standard-domain-expiration-timeline-609) for the complete day-by-day expiration timeline.
## Common errors
| Status | Most likely cause |
| ------ | ---------------------------------------------------------------------------------------- |
| `400` | Malformed request body or invalid `period` value. |
| `403` | Credential lacks write access to this domain. |
| `404` | Domain doesn't exist or isn't owned by the authenticated account. |
| `409` | Domain status prevents renewal (e.g. domain is in a transfer in progress). |
| `422` | Period exceeds the TLD maximum or would push total registration past the registry limit. |
Full error envelope: [Errors](https://developer.godaddy.com/docs/api-users/errors).
## Reference
* [v1 domain settings — `PATCH /v1/domains/{domain}` (auto-renew toggle)](https://developer.godaddy.com/docs/references/rest/domains/v1/manage-domain-settings)
* [v1 registration and renewals — `POST /v1/domains/{domain}/renew`](https://developer.godaddy.com/docs/references/rest/domains/v1/register-and-renew-domains)
## Next
# Update contacts (https://developer.godaddy.com/en/docs/api-users/manage-domains/update-contacts)
***
title: Update contacts
description: Change the registrant, admin, billing, or tech contact on a domain you own via PATCH /v1/domains//contacts.
agentNotes:
permissions: \["Domain Owner"]
scopes: \["domains.domain:update"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "Idempotent on identical bodies. On 409 (registrant change on locked ccTLD), unlock, retry, and relock. Verify state via GET before retrying an unclear failure."
related:
apis:
* title: "Domains v1 — Update contacts"
href: "/docs/references/rest/domains/v1/manage-domain-settings"
guides:
* title: "Lock a domain"
href: "/docs/api-users/manage-domains/lock"
* title: "Registered domains"
href: "/docs/api-users/manage-domains/list"
concepts:
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Authentication"
href: "/docs/api-users/auth"
***
## Overview
Update the registrant, admin, billing, or tech contact on a domain you own using `PATCH /v1/domains/{domain}/contacts`. Each contact role can be updated independently — include only the roles you want to change in the request body. The registrant contact is the legal owner of the domain and is required; the other three roles default to the registrant if omitted.
## Prerequisites
The following prerequisites are required before you update domain contacts:
* A GoDaddy account that owns the domain
* A [Personal Access Token](https://developer.godaddy.com/docs/api-users/auth) with `domains.domain:update` scope
* Registrant name, email, phone (E.164 format), and mailing address
## Update the registrant contact
Send a `PATCH` with only `contactRegistrant` in the body. Admin, billing, and tech contacts are untouched when omitted. Returns `204 No Content`.
The following procedure updates the registrant contact for a domain.
A subset of ccTLDs require registry lock to be disabled before the registry accepts a registrant update. If you receive a `409`, check whether the domain is locked and disable it before retrying. Re-enable lock after the update completes. See [Registry lock](https://developer.godaddy.com/docs/api-users/manage-domains/lock).
* Run the following command for your preferred language:
```bash tab="curl"
curl -s -X PATCH "https://api.godaddy.com/v1/domains/example.com/contacts" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{
"contactRegistrant": {
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": {
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US"
}
}
}'
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const body = {
contactRegistrant: {
nameFirst: "Jane",
nameLast: "Smith",
email: "jane@example.com",
phone: "+1.5555550100",
addressMailing: {
address1: "123 Main St",
city: "Tempe",
state: "AZ",
postalCode: "85281",
country: "US",
},
},
};
const res = await fetch("https://api.godaddy.com/v1/domains/example.com/contacts", {
method: "PATCH",
headers: {
Authorization: `Bearer ${pat}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
console.log(res.status); // expect 204
```
```python tab="Python"
import os, requests
pat = os.environ["GODADDY_PAT"]
body = {
"contactRegistrant": {
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": {
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US",
},
}
}
res = requests.patch(
"https://api.godaddy.com/v1/domains/example.com/contacts",
json=body,
headers={
"Authorization": f"Bearer {pat}",
"Content-Type": "application/json",
},
)
print(res.status_code) # expect 204
```
```go tab="Go"
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
pat := os.Getenv("GODADDY_PAT")
body := map[string]any{
"contactRegistrant": map[string]any{
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": map[string]any{
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US",
},
},
}
b, _ := json.Marshal(body)
req, _ := http.NewRequest("PATCH",
"https://api.godaddy.com/v1/domains/example.com/contacts",
bytes.NewReader(b))
req.Header.Set("Authorization", "Bearer "+pat)
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()
fmt.Println(res.StatusCode) // expect 204
}
```
Returns `204 No Content` on success.
## Update all four roles at once
Include all four roles in one call. Each uses the same `Contact` shape.
The following procedure updates all four contact roles in a single request.
* Run the following command:
```bash
curl -s -X PATCH "https://api.godaddy.com/v1/domains/example.com/contacts" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{
"contactRegistrant": {
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": {
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US"
}
},
"contactAdmin": {
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": {
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US"
}
},
"contactBilling": {
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": {
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US"
}
},
"contactTech": {
"nameFirst": "Jane",
"nameLast": "Smith",
"email": "jane@example.com",
"phone": "+1.5555550100",
"addressMailing": {
"address1": "123 Main St",
"city": "Tempe",
"state": "AZ",
"postalCode": "85281",
"country": "US"
}
}
}'
```
## Contact object
| Field | Required | Description |
| ---------------- | -------- | --------------------------------------- |
| `nameFirst` | Yes | First name. |
| `nameLast` | Yes | Last name. |
| `email` | Yes | Email address. |
| `phone` | Yes | Phone in E.164 format: `+1.5555550100`. |
| `addressMailing` | Yes | Mailing address object — see below. |
| `nameMiddle` | No | Middle name. |
| `organization` | No | Organization name. |
| `jobTitle` | No | Job title. |
| `fax` | No | Fax number in E.164 format. |
### Mailing address
| Field | Required | Description |
| ------------ | -------- | ------------------------------------------------------------------- |
| `address1` | Yes | Street address line 1. |
| `address2` | No | Street address line 2. |
| `city` | Yes | City. |
| `state` | Yes | State or province code (for countries that use it). |
| `postalCode` | Yes | Postal code. |
| `country` | Yes | Two-letter ISO 3166-1 alpha-2 country code (e.g. `US`, `GB`, `DE`). |
## Request body summary
`PATCH /v1/domains/{domain}/contacts` accepts a `DomainContacts` object.
| Role | Required | Description |
| ------------------- | -------- | ------------------------------------------------ |
| `contactRegistrant` | Yes | The legal owner of the domain. |
| `contactAdmin` | No | Administrative contact. Not modified if omitted. |
| `contactBilling` | No | Billing contact. Not modified if omitted. |
| `contactTech` | No | Technical contact. Not modified if omitted. |
## Common errors
| Status | Most likely cause |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `400` | Malformed request body or invalid contact field (bad email format, invalid country code). Inspect `fields[]` in the error response. |
| `403` | Credential lacks write access to this domain. |
| `404` | Domain doesn't exist or isn't owned by the authenticated account. |
| `409` | Domain is locked and the TLD requires unlock for registrant changes. |
| `422` | TLD-specific validation failure (e.g. missing organization for certain country-code TLDs). |
Full error envelope: [Errors](https://developer.godaddy.com/docs/api-users/errors).
## Reference
* [v1 domain settings — `PATCH /v1/domains/{domain}/contacts`](https://developer.godaddy.com/docs/references/rest/domains/v1/manage-domain-settings)
## Next
# Register a domain (https://developer.godaddy.com/en/docs/api-users/purchase-domains/register)
***
title: Register a domain
description: Register a domain using the GoDaddy Domains API.
agentNotes:
permissions: \["Domain Registration"]
scopes: \["domains.domain:read", "domains.domain:create"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: false
destructive: false
failureRecovery: "Registration charges the account and is not reversible. Use the Idempotency-Key header to prevent duplicate purchases. If the operation status is EXECUTING, poll — do not resubmit."
related:
apis:
* title: "v3 Registrations"
href: "/docs/references/rest/domains/v3/registrations"
* title: "v3 Registration Quotes"
href: "/docs/references/rest/domains/v3/registration-quotes"
guides:
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
* title: "Set up a payment profile"
href: "/docs/api-users/payment-profile"
concepts:
* title: "Authentication"
href: "/docs/api-users/auth"
* title: "Error handling"
href: "/docs/api-users/errors"
***
## Overview
This guide covers registering a domain programmatically using the GoDaddy Domains API.
Registration charges the account's billing method and isn't reversible. Make sure you have a [payment method on file](https://developer.godaddy.com/docs/api-users/payment-profile) before registering.
ICANN requires that registrant contact information be accurate. Providing false contact information can result in domain suspension. Use WHOIS privacy after registration if you want to protect your contact details. Don't enter fake data.
## Prerequisites
* a GoDaddy account with a payment method on file
Go to [Create account](https://sso.godaddy.com/account/create/) to create a GoDaddy account and add or update payment methods.
* a [PAT](https://developer.godaddy.com/docs/api-users/auth) with `domains.domain:create` scope
* a registrant contact with name, email, phone, and mailing address
* a confirmed available domain
* *(optional)* the [GoDaddy CLI](https://developer.godaddy.com/docs/api-users/cli-setup) installed and configured
## Register a domain
v3 separates pricing from execution. You get a price quote first, locking a `quoteToken`, then execute the registration with that token. This ensures the price you agreed to is the price charged. Always poll at least once even if the initial response appears synchronous.
v3 does not accept inline payment or registrant contact overrides. The billing method and registrant contact are resolved from the account profile. If the account is missing a payment method or required contact fields, the quote returns `422` with field-level details.
### Check availability
Confirm the domain is available before quoting.
* Run the availability check:
```bash tab="curl"
curl -s "https://api.godaddy.com/v3/domains/check-availability?domain=example.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
const res = await fetch(
"https://api.godaddy.com/v3/domains/check-availability?domain=example.com",
{ headers: { Authorization: `Bearer ${process.env.GODADDY_PAT}` } }
);
const { available } = await res.json();
if (!available) throw new Error("Domain not available");
```
```python tab="Python"
import os, requests
res = requests.get(
"https://api.godaddy.com/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"
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
req, _ := http.NewRequest("GET",
"https://api.godaddy.com/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"` }
json.NewDecoder(res.Body).Decode(&data)
if !data.Available { panic("not available") }
fmt.Println("available")
}
```
Go to [Search availability](https://developer.godaddy.com/docs/api-users/search-domains) for bulk checks and suggestions.
### Get a registration quote
`POST /v3/domains/registration-quotes` locks the price and returns the `requiredAgreements` list you need for the next step. The `quoteToken` guarantees the price you see is the price charged at registration.
* Get a quote:
```bash tab="curl"
curl -s -X POST "https://api.godaddy.com/v3/domains/registration-quotes" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{"domain": "example.com", "period": 1}'
```
```js tab="Node"
const res = await fetch("https://api.godaddy.com/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, requiredAgreements } = await res.json();
console.log("Quote locked until", expiresAt);
```
```python tab="Python"
import os, requests
res = requests.post(
"https://api.godaddy.com/v3/domains/registration-quotes",
json={"domain": "example.com", "period": 1},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
},
)
res.raise_for_status()
quote = res.json()
required_agreements = quote["requiredAgreements"]
print("Quote locked until", quote["expiresAt"])
```
```go tab="Go"
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
body := bytes.NewReader([]byte(`{"domain": "example.com", "period": 1}`))
req, _ := http.NewRequest("POST",
"https://api.godaddy.com/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"`
RequiredAgreements []struct {
AgreementType string `json:"agreementType"`
Title string `json:"title"`
URL string `json:"url"`
} `json:"requiredAgreements"`
}
json.NewDecoder(res.Body).Decode("e)
fmt.Println("Quote locked until", quote.ExpiresAt)
}
```
```json
{
"quoteToken": "qt_abc123...",
"expiresAt": "2026-01-15T10:45:00.000Z",
"requiredAgreements": [
{
"agreementType": "API_DPA",
"title": "API Domain Purchase Agreement",
"url": "https://www.godaddy.com/agreements/showdoc?pageid=reg_sa"
}
],
"items": [
{
"domain": "example.com",
"period": 1,
"price": 1199990,
"currency": "USD"
}
]
}
```
The `quoteToken` expires after a short window. If it expires before you execute, fetch a new quote.
### Review the required agreements
The quote response includes a `requiredAgreements` list (the legal agreements you need to review before you submit the registration). Each item has a `title` for display and a `url` linking to the full legal text.
1. Display each agreement to the user:
```js tab="Node"
for (const agreement of requiredAgreements) {
console.log(`Review: ${agreement.title}`);
console.log(`Full text: ${agreement.url}`);
}
```
```python tab="Python"
for agreement in required_agreements:
print(f"Review: {agreement['title']}")
print(f"Full text: {agreement['url']}")
```
```go tab="Go"
for _, agreement := range quote.RequiredAgreements {
fmt.Println("Review:", agreement.Title)
fmt.Println("Full text:", agreement.URL)
}
```
2. After the user confirms, capture the agreement types and consent timestamp:
```js tab="Node"
const agreedAt = new Date().toISOString();
const agreedTypes = requiredAgreements.map((a) => a.agreementType);
```
```python tab="Python"
from datetime import datetime, timezone
agreed_at = datetime.now(timezone.utc).isoformat()
agreed_types = [a["agreementType"] for a in required_agreements]
```
```go tab="Go"
agreedAt := time.Now().UTC().Format(time.RFC3339)
agreedTypes := make([]string, len(quote.RequiredAgreements))
for i, a := range quote.RequiredAgreements {
agreedTypes[i] = a.AgreementType
}
```
Use the actual timestamp of when the user clicked accept for `agreedAt` — not the time of the API call. Synthetic timestamps violate ICANN policy.
Required agreements depend on the TLD. `.ca` domains require a CIRA agreement, `.au` domains require an AURA agreement. Always use the `agreementType` values from `requiredAgreements` — don't hardcode them.
### Submit the registration
Send the `quoteToken` and consent to execute the registration. Always include an `Idempotency-Key` header — if the request times out or returns `5xx`, replay with the same key and the server deduplicates.
`POST /v3/domains/registrations` charges the account's billing method. Verify the domain name and the quoted price before executing.
* Submit the registration request:
```bash tab="curl"
curl -s -X POST "https://api.godaddy.com/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-01-15T10:30:00.000Z",
"agreementTypes": ["API_DPA"]
}
}'
```
```js tab="Node"
import { randomUUID } from "node:crypto";
const res = await fetch("https://api.godaddy.com/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, // timestamp captured in step 3
agreementTypes: agreedTypes, // types from requiredAgreements in step 3
},
}),
});
if (!res.ok) throw new Error(`Registration failed: ${res.status}`);
const { registrationId, domain } = await res.json();
console.log("Registered:", domain, "registrationId:", registrationId);
```
```python tab="Python"
import os, uuid, requests
res = requests.post(
"https://api.godaddy.com/v3/domains/registrations",
json={
"quoteToken": "qt_abc123...",
"domain": "example.com",
"period": 1,
"consent": {
"agreedAt": agreed_at, # timestamp captured in step 3
"agreementTypes": agreed_types, # types from requiredAgreements in step 3
},
},
headers={
"Authorization": f"Bearer {os.environ['GODADDY_PAT']}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
)
res.raise_for_status()
data = res.json()
print("Registered:", data["domain"], "registrationId:", data["registrationId"])
```
```go tab="Go"
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
"time"
"github.com/google/uuid"
)
func main() {
body := map[string]any{
"quoteToken": "qt_abc123...",
"domain": "example.com",
"period": 1,
"consent": map[string]any{
"agreedAt": agreedAt, // timestamp captured in step 3
"agreementTypes": agreedTypes, // types from requiredAgreements in step 3
},
}
b, _ := json.Marshal(body)
req, _ := http.NewRequest("POST",
"https://api.godaddy.com/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 != 202 { panic(fmt.Sprint("registration failed: ", res.StatusCode)) }
var reg struct {
RegistrationID string `json:"registrationId"`
Domain string `json:"domain"`
}
json.NewDecoder(res.Body).Decode(®)
fmt.Println("Registered:", reg.Domain, "registrationId:", reg.RegistrationID)
}
```
Use the actual consent timestamp for `agreedAt`; synthetic values violate ICANN policy. Use the `agreementTypes` keys from `requiredAgreements` in the quote response; the registration returns `INVALID_AGREEMENT_KEYS` if they don't match. The `period` must match the quoted period, or you get `QUOTE_MISMATCH`. The `Idempotency-Key` must be a unique UUID per attempt; retrying with the same key is safe after a timeout.
### Poll the operation
The registration is asynchronous. Poll the returned `registrationId` URL every few seconds until the status reaches a terminal state.
* Poll for the registration status:
```bash tab="curl"
curl -s "https://api.godaddy.com/v3/domains/registrations/{registrationId}" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
async function pollRegistration(registrationId, intervalMs = 3000) {
while (true) {
const res = await fetch(
`https://api.godaddy.com/v3/domains/registrations/${registrationId}`,
{ headers: { Authorization: `Bearer ${process.env.GODADDY_PAT}` } }
);
const { status, domain } = await res.json();
if (status === "COMPLETED") return domain;
if (status === "FAILED") throw new Error("Registration failed");
await new Promise((r) => setTimeout(r, intervalMs));
}
}
```
```python tab="Python"
import os, time, requests
def poll_registration(registration_id, interval=3):
while True:
res = requests.get(
f"https://api.godaddy.com/v3/domains/registrations/{registration_id}",
headers={"Authorization": f"Bearer {os.environ['GODADDY_PAT']}"},
)
data = res.json()
if data["status"] == "COMPLETED":
return data["domain"]
if data["status"] == "FAILED":
raise RuntimeError("Registration failed")
time.sleep(interval)
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"time"
)
func pollRegistration(registrationID string) {
for {
req, _ := http.NewRequest("GET",
"https://api.godaddy.com/v3/domains/registrations/"+registrationID, nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("GODADDY_PAT"))
res, _ := http.DefaultClient.Do(req)
var data struct {
Status string `json:"status"`
}
json.NewDecoder(res.Body).Decode(&data)
res.Body.Close()
switch data.Status {
case "COMPLETED":
fmt.Println("Registration complete")
return
case "FAILED":
panic("Registration failed")
}
time.Sleep(3 * time.Second)
}
}
```
| Status | Meaning |
| ----------- | ------------------------------------------------------------- |
| `CONFIRMED` | Accepted, processing in progress. Keep polling. |
| `EXECUTING` | Actively executing. Keep polling. |
| `COMPLETED` | Terminal — succeeded. `domain` and `expiresAt` are populated. |
| `FAILED` | Terminal — failed. |
You can also poll through `GET /v3/domains/operations/{operationId}`. Both endpoints resolve the same resource.
## Use the CLI
After you [set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup):
1. Check availability:
```bash
gddy domain available example.com
```
2. Review the required agreements for the TLD:
```bash
gddy domain agreements --tld com
```
3. Inspect TLD-specific schema requirements:
```bash
gddy domain schema com
```
4. Register the domain:
```bash
gddy domain purchase example.com --agree --confirm
```
Registration is paid and not reversible. Run without `--agree` first to review the required agreements, and use `--dry-run` to preview before confirming.
Use `gddy domain contacts init` to save default contacts for repeated purchases — the command writes a local `contacts.toml` template that the purchase command can use.
## Registration body fields
The following table lists the fields required for the registration body.
| Field | Required | Description |
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quoteToken` | Yes | Token from `POST /v3/domains/registration-quotes`. |
| `domain` | Yes | Fully-qualified domain name to register. |
| `period` | Yes | Registration period in years (must match the quoted period). |
| `consent` | Yes | ICANN consent object capturing the agreement type, consenting party, and timestamp listed in the [Consent object fields](#consent-object-fields) table. |
| `Idempotency-Key` header | Yes | UUID generated per request. |
## Consent object fields
The following table lists the fields required for the consent object.
| Field | Required | Description | Note |
| ---------------- | -------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `agreementTypes` | Yes | Agreement type keys from the TLD's required agreements (for example, `API_DPA`). | Get these from the `requiredAgreements` field in the quote response. |
| `agreedAt` | Yes | Actual ISO 8601 timestamp of when the user consented. | |
## Common errors
The following table lists common errors and recommended actions. Go to [Errors](https://developer.godaddy.com/docs/api-users/errors) for the full error envelope.
| Status | Most likely cause | Recommended action |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `400` | Malformed request body or missing required field. | Inspect `fields[]` in the error response. |
| `403` | Credential lacks write access, no [payment method on file](https://developer.godaddy.com/docs/api-users/payment-profile), or account billing issue. | Check `code` to distinguish. |
| `404` | TLD not supported. | |
| `409` | Domain is already registered (by anyone). | |
| `422 QUOTE_MISMATCH` | The `period` or payment profile in the execute body doesn't match the quote. | Re-use the same `period` from the quote, or fetch a new quote. |
| `422 INVALID_AGREEMENT_KEYS` | Wrong `agreementTypes` value. | Use the keys returned in `requiredAgreements` from the quote response. |
| `422 MISSING_CONTACT` | No registrant contact on the account profile. | Add a registrant contact to the account profile. |
| `422 MISSING_BILLING_PHONE` | Contact phone is missing or malformed. | Verify `phone.countryCode` and `phone.nationalNumber` are both set. |
| `422` | Domain isn't available, missing or invalid consent, or other contact validation failure. | Inspect `fields[]` for specifics. |
## Additional information
* [v3 Registrations — `POST /v3/domains/registrations`](https://developer.godaddy.com/docs/references/rest/domains/v3/registrations)
* [v3 Registration Quotes — `POST /v3/domains/registration-quotes`](https://developer.godaddy.com/docs/references/rest/domains/v3/registration-quotes)
* [v3 Operations — `GET /v3/domains/operations/{operationId}`](https://developer.godaddy.com/docs/references/rest/domains/v3/operations)
* [v1 registration and renewals — `POST /v1/domains/purchase`](https://developer.godaddy.com/docs/references/rest/domains/v1/register-and-renew-domains)
# Search domain availability (https://developer.godaddy.com/en/docs/api-users/search-domains)
***
title: Search domain availability
description: Check whether a domain is available to register, or get natural-language suggestions for alternatives. Both operations are available through the v3 API.
agentNotes:
permissions: \["Domain Search"]
scopes: \["domains.domain:read"]
idempotent: true
destructive: false
failureRecovery: "Safe to retry on any error. Results are cached; use optimizeFor=ACCURACY for live registry checks."
related:
apis:
* title: "Domains v3 — Discovery"
href: "/docs/references/rest/domains/v3/discovery"
guides:
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
concepts:
* title: "Authentication"
href: "/docs/api-users/auth"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
## Overview
Search operations let you check whether a specific domain is available for registration, and discover alternative names based on keywords or natural-language queries. Both operations are read-only, require no payment method, and return indicative pricing alongside results.
## v3 (recommended)
v3 offers two discovery operations: a single-domain availability check and a suggestions endpoint that returns available alternatives for a natural-language query.
### Check availability
`GET /v3/domains/check-availability?domain={domain}` returns availability and per-term pricing for a single domain.
The following procedure checks whether a domain is available to register.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s "https://api.godaddy.com/v3/domains/check-availability?domain=your-idea.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const url = new URL("https://api.godaddy.com/v3/domains/check-availability");
url.searchParams.set("domain", "your-idea.com");
const res = await fetch(url, {
headers: { Authorization: `Bearer ${pat}` },
});
const result = await res.json();
console.log(result.available, result.prices?.[0]?.price);
```
```python tab="Python"
import os, requests
pat = os.environ["GODADDY_PAT"]
res = requests.get(
"https://api.godaddy.com/v3/domains/check-availability",
params={"domain": "your-idea.com"},
headers={"Authorization": f"Bearer {pat}"},
)
data = res.json()
print(data["available"], data["prices"][0]["price"])
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
)
func main() {
pat := os.Getenv("GODADDY_PAT")
req, _ := http.NewRequest("GET",
"https://api.godaddy.com/v3/domains/check-availability?domain=your-idea.com", nil)
req.Header.Set("Authorization", "Bearer "+pat)
res, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()
var result struct {
Available bool `json:"available"`
Prices []map[string]any `json:"prices"`
}
json.NewDecoder(res.Body).Decode(&result)
fmt.Println(result.Available, result.Prices)
}
```
| Parameter | Required | Description | Note |
| ------------- | -------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------- |
| `domain` | Yes | Fully-qualified domain name to check. | IDN values must be in punycode A-label form. |
| `optimizeFor` | No | `SPEED` (default, cached) or `ACCURACY` (live registry check, higher latency). | Availability is always re-verified at quote time regardless of this setting. |
| `iscCode` | No | ISC discount code for pricing context. | When provided, prices reflect the applicable rates for this ISC. |
Response includes availability and indicative per-term pricing:
```json
{
"domain": "your-idea.com",
"available": true,
"definitive": false,
"inventory": "REGISTRY",
"prices": [
{ "term": "YEAR", "period": 1, "price": { "currencyCode": "USD", "value": 1199 }, "renewalPrice": { "currencyCode": "USD", "value": 2299 } },
{ "term": "YEAR", "period": 2, "price": { "currencyCode": "USD", "value": 3098 }, "renewalPrice": { "currencyCode": "USD", "value": 4598 } }
]
}
```
`prices[]` contains one entry per available registration term. All price values are in cents.
Prices from availability checks are indicative. The authoritative price is locked when you call `POST /v3/domains/registration-quotes`. Go to [Register a domain](https://developer.godaddy.com/docs/api-users/purchase-domains/register) for the full quote-execute flow.
Reference: [`GET /v3/domains/check-availability`](https://developer.godaddy.com/docs/references/rest/domains/v3/discovery)
### Get suggestions
`GET /v3/domains/suggestions` returns available domain name suggestions for a natural-language query or keyword set. All results are available without filtering required.
The following procedure gets domain name suggestions for a query.
* Run the following command for your preferred language:
```bash tab="curl"
curl -s "https://api.godaddy.com/v3/domains/suggestions?query=sunrise+bakery&tlds=com,net,shop&pageSize=10" \
-H "Authorization: Bearer $GODADDY_PAT"
```
```js tab="Node"
const pat = process.env.GODADDY_PAT;
const url = new URL("https://api.godaddy.com/v3/domains/suggestions");
url.searchParams.set("query", "sunrise bakery");
url.searchParams.set("tlds", "com,net,shop");
url.searchParams.set("pageSize", "10");
const res = await fetch(url, {
headers: { Authorization: `Bearer ${pat}` },
});
const { items } = await res.json();
items.forEach((item) => console.log(item.domain, item.prices?.[0]?.price));
```
```python tab="Python"
import os, requests
pat = os.environ["GODADDY_PAT"]
res = requests.get(
"https://api.godaddy.com/v3/domains/suggestions",
params={"query": "sunrise bakery", "tlds": "com,net,shop", "pageSize": 10},
headers={"Authorization": f"Bearer {pat}"},
)
for item in res.json()["items"]:
print(item["domain"], item["prices"][0]["price"])
```
```go tab="Go"
package main
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
)
func main() {
pat := os.Getenv("GODADDY_PAT")
u, _ := url.Parse("https://api.godaddy.com/v3/domains/suggestions")
q := u.Query()
q.Set("query", "sunrise bakery")
q.Set("tlds", "com,net,shop")
q.Set("pageSize", "10")
u.RawQuery = q.Encode()
req, _ := http.NewRequest("GET", u.String(), nil)
req.Header.Set("Authorization", "Bearer "+pat)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
var body struct {
Items []struct{ Domain string `json:"domain"` } `json:"items"`
}
json.NewDecoder(res.Body).Decode(&body)
for _, item := range body.Items {
fmt.Println(item.Domain)
}
}
```
| Parameter | Required | Description | Note |
| ----------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ |
| `query` | No | Natural-language query or keywords. | For example, `sunrise bakery`. |
| `tlds` | No | Comma-separated TLDs to include. | For example, `com,net,shop`. |
| `pageSize` | No | Number of suggestions to return. | 1–50, default `10`. |
| `lengthMin` | No | Minimum second-level domain length. | |
| `lengthMax` | No | Maximum second-level domain length. | |
| `sources` | No | Comma-separated suggestion strategies: `EXTENSION` (vary TLD), `KEYWORD_SPIN` (rotate keywords), `CC_TLD` (country-code TLDs), `PREMIUM` (include premium-priced names). | |
Response is an object with an `items` array. Each entry includes the domain name and indicative per-term pricing:
```json
{
"items": [
{
"domain": "sunrisebakery.com",
"inventory": "REGISTRY",
"prices": [
{ "term": "YEAR", "period": 1, "price": { "currencyCode": "USD", "value": 1199 }, "renewalPrice": { "currencyCode": "USD", "value": 2299 } }
]
}
]
}
```
`price.value` and `renewalPrice.value` are in cents — divide by 100 for the display price.
Reference: [`GET /v3/domains/suggestions`](https://developer.godaddy.com/docs/references/rest/domains/v3/discovery)
## Use the CLI
After you [set up the CLI](https://developer.godaddy.com/docs/api-users/cli-setup), you can use it to check single-domain availability and get domain suggestions.
The following procedure checks availability and gets suggestions using the CLI.
* Run the command for your operation:
```bash
gddy domain available your-idea.com
gddy domain available your-idea.com --check-type full
gddy domain suggest "your idea" --tlds com --tlds app --limit 10
```
## Read the response
Price fields return a `{currencyCode, value}` object. `value` is an integer in cents — divide by 100 for the display price. For example, `{"currencyCode": "USD", "value": 1199}` displays as `$11.99`.
## Common errors
| Status | Most likely cause |
| ------ | ----------------------------------------------------------------------------------------- |
| `400` | Malformed request — domain missing, not a valid FQDN, or invalid query parameter. |
| `401` | Authentication credentials are missing or invalid. |
| `403` | Caller is not authorized. Check that your token includes the `domains.domain:read` scope. |
| `429` | Rate limit exceeded. Honor the `Retry-After` header before retrying. |
| `5xx` | Upstream registry timeout. Safe to retry — availability checks are idempotent. |
## Additional information
# Build an API integration (https://developer.godaddy.com/en/docs/api-users/workflows/api-integration)
***
title: Build an API integration
description: End-to-end workflow — set up credentials, make authenticated calls, handle errors, and prepare for production.
agentNotes:
permissions: \["Any account"]
scopes: \["domains.domain:read (minimum for example calls in this guide)"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: true
destructive: false
failureRecovery: "All calls in this guide are read-only. Safe to retry any failure. On 401, verify the token is exported correctly. On 429, implement exponential backoff with the Retry-After header."
related:
apis:
* title: "Domains v3 reference"
href: "/docs/references/rest/domains/v3"
guides:
* title: "Quickstart"
href: "/docs/api-users/quickstart"
* title: "Authenticate"
href: "/docs/api-users/auth"
* title: "Handle errors"
href: "/docs/api-users/errors"
* title: "Rate limits"
href: "/docs/api-users/rate-limits"
***
## Overview
This workflow takes you from zero to a production-ready API integration. It covers credential setup, your first call, error handling patterns, and the operational considerations for running in production.
## Prerequisites
The following prerequisites are required before you build an API integration:
* A GoDaddy account (create one at [sso.godaddy.com](https://sso.godaddy.com/account/create/))
* A terminal with `curl`, or Node.js / Python installed
## Generate a Personal Access Token
The following procedure generates a Personal Access Token (PAT) for authenticating API calls.
1. Sign in to the [Personal Access Token](https://developer.godaddy.com/personal-access-token) page.
2. Click **+ Generate Token**.
3. Select the scopes your integration needs (at minimum, `domains.domain:read` for read operations).
4. Copy the token immediately (it only displays once).
5. Export the credential:
```bash
export GODADDY_PAT=""
```
Go to [Authentication](https://developer.godaddy.com/docs/api-users/auth) for the full scope reference and environment guidance.
## Make your first authenticated call
The following procedure verifies your token works with a simple availability check. A successful response returns JSON with `available`, `prices`, and other fields. If you get a `401`, check that the token is correctly set in the environment variable.
* Run the request:
```bash
curl -s "https://api.godaddy.com/v3/domains/check-availability?domain=example-test.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
Go to the [quickstart](https://developer.godaddy.com/docs/api-users/quickstart) for a detailed walkthrough of this call.
## Handle errors gracefully
The following procedure implements error handling for API responses. Every error response follows the same envelope. Match on `code`, not `message`. Build a switch/match statement for the codes you expect.
1. Examine the error shape:
```json
{
"code": "STABLE_ERROR_CODE",
"message": "Human-readable description",
"fields": []
}
```
2. Implement error handling:
```js
const res = await fetch(url, { headers });
if (!res.ok) {
const err = await res.json();
switch (err.code) {
case "QUOTA_EXCEEDED":
await sleep(err.retryAfterSec * 1000);
return retry(url, headers);
case "UNAUTHORIZED":
throw new Error("Token expired or invalid");
default:
throw new Error(`API error: ${err.code}`);
}
}
```
Go to [Handle errors](https://developer.godaddy.com/docs/api-users/errors) for the full status code reference and retry semantics.
## Add rate limit handling
When you apply rate limiting use the following strategies to stay under the limit:
* Use bulk endpoints where available (e.g., `POST /v1/domains/available` for batch checks)
* Cache availability results briefly when `definitive: false`
* Use cursor pagination instead of parallel page-walks
The following procedure adds rate limit handling to your integration. The API enforces a per-credential, windowed rate limit — go to [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for current values.
* Implement retry logic that respects the `retryAfterSec` field:
```js
async function callWithRetry(url, headers, attempts = 3) {
for (let i = 0; i < attempts; i++) {
const res = await fetch(url, { headers });
if (res.status !== 429) return res;
const { retryAfterSec } = await res.json();
const jitter = Math.random() * 1000;
await new Promise(r => setTimeout(r, retryAfterSec * 1000 + jitter));
}
throw new Error("Rate limit retries exhausted");
}
```
Go to [Handle rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) for the full strategy guide.
## Production readiness checklist
Before deploying to production, verify:
| Concern | Action |
| ----------------------- | ------------------------------------------------------------------ |
| **Credential security** | PAT stored in a secrets manager, never committed to source control |
| **Error handling** | All expected error codes handled with appropriate user feedback |
| **Rate limiting** | Exponential backoff with jitter implemented |
| **Idempotency** | Write operations use `Idempotency-Key` header where supported |
| **Monitoring** | Log `code` field from error responses for alerting |
| **Pagination** | List operations use cursor pagination, not parallel fetches |
| **Environment** | Production PAT targeting `api.godaddy.com` |
# Register and configure a domain (https://developer.godaddy.com/en/docs/api-users/workflows/domain-lifecycle)
***
title: Register and configure a domain
description: End-to-end workflow — search for a domain, register it, configure DNS, and verify the setup.
agentNotes:
permissions: \["Domain Registration", "DNS Management"]
scopes: \["domains.domain:read", "domains.domain:create", "domains.dns:update"]
rateLimit: "Rate-limited per credential per window. Go to /docs/api-users/rate-limits for current values."
idempotent: false
destructive: false
failureRecovery: "Registration charges the account and is not reversible. Use the Idempotency-Key header on POST /v3/domains/registrations to prevent duplicate charges. If a step fails mid-workflow, poll the operation URL before retrying the registration step. DNS writes are safe to retry."
related:
apis:
* title: "v3 Registrations"
href: "/docs/references/rest/domains/v3/registrations"
* title: "v3 Registration Quotes"
href: "/docs/references/rest/domains/v3/registration-quotes"
guides:
* title: "Search domain availability"
href: "/docs/api-users/search-domains"
* title: "Register a domain"
href: "/docs/api-users/purchase-domains/register"
* title: "Manage DNS records"
href: "/docs/api-users/manage-domains/dns"
* title: "Set up a payment profile"
href: "/docs/api-users/payment-profile"
***
## Overview
This workflow walks through the complete domain lifecycle from search to live configuration. By the end, you'll have a registered domain with DNS records serving traffic.
## Prerequisites
The following prerequisites are required before you register and configure a domain:
* A GoDaddy account with a [payment profile](https://developer.godaddy.com/docs/api-users/payment-profile) configured
* A [Personal Access Token](https://developer.godaddy.com/docs/api-users/auth) with `domains.domain:read`, `domains.domain:create`, and `domains.dns:update` scopes, exported as `GODADDY_PAT` in your environment
* A terminal with `curl`
## Search for an available domain
The following procedure checks whether your desired domain is available for registration.
1. Check availability:
```bash
curl -s "https://api.godaddy.com/v3/domains/check-availability?domain=your-idea.com" \
-H "Authorization: Bearer $GODADDY_PAT"
```
If `available` is `true`, proceed to quoting. If `false`, use the suggestions endpoint to find alternatives.
2. Get suggestions:
```bash
curl -s "https://api.godaddy.com/v3/domains/suggestions?query=your+idea&tlds=com,net,io&pageSize=10" \
-H "Authorization: Bearer $GODADDY_PAT"
```
Go to [Search domain availability](https://developer.godaddy.com/docs/api-users/search-domains) for the full parameter reference.
## Get a registration quote
The following procedure locks in a price by requesting a quote. The `quoteToken` in the response is valid for 10 minutes.
1. Request a quote:
```bash
curl -s -X POST "https://api.godaddy.com/v3/domains/registration-quotes" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{
"domain": "your-idea.com",
"period": 1
}'
```
2. Note the `quoteToken` and `requiredAgreements` from the response (you'll need both for registration).
## Execute the registration
The following procedure submits the registration using the quote token and ICANN consent.
Registration applies charges to your payment profile and not reversible. Verify the domain name and quoted price before executing.
* Submit the registration:
```bash
curl -s -X POST "https://api.godaddy.com/v3/domains/registrations" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"quoteToken": "",
"domain": "your-idea.com",
"period": 1,
"consent": {
"agreedAt": "2026-01-15T10:30:00.000Z",
"agreementTypes": ["API_DPA"]
}
}'
```
Go to [Register a domain](https://developer.godaddy.com/docs/api-users/purchase-domains/register) for the full field reference and error handling.
## Poll until complete
The following procedure polls the registration status. Registration is asynchronous. Poll the returned operation URL until the status reaches a terminal state. The following table lists the possible statuses:
| Status | Meaning |
| ----------- | ----------------------------------------------- |
| `CONFIRMED` | Accepted, processing. Keep polling. |
| `EXECUTING` | In progress. Keep polling. |
| `COMPLETED` | Registration succeeded. |
| `FAILED` | Registration failed. Check `error` for details. |
* Poll the registration:
```bash
curl -s "https://api.godaddy.com/v3/domains/registrations/" \
-H "Authorization: Bearer $GODADDY_PAT"
```
## Add DNS records
The following procedure adds DNS records to point the domain at your infrastructure. Run these after registration completes.
1. Add an A record for the apex:
```bash
curl -s -X POST "https://api.godaddy.com/v3/domains/zones/your-idea.com/dns-records" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{ "type": "A", "name": "@", "data": "192.0.2.1", "ttl": 600 }'
```
2. Add additional records as needed (CNAME for `www`, MX for email, TXT for verification):
```bash
curl -s -X POST "https://api.godaddy.com/v3/domains/zones/your-idea.com/dns-records" \
-H "Authorization: Bearer $GODADDY_PAT" \
-H "Content-Type: application/json" \
-d '{ "type": "CNAME", "name": "www", "data": "your-idea.com", "ttl": 600 }'
```
Go to [Manage DNS records](https://developer.godaddy.com/docs/api-users/manage-domains/dns) for the full record type reference.
## Verify DNS propagation
The following procedure verifies that your DNS records were created and are propagating.
* List your records to confirm they were created:
```bash
curl -s "https://api.godaddy.com/v3/domains/zones/your-idea.com/dns-records" \
-H "Authorization: Bearer $GODADDY_PAT"
```
DNS changes propagate within minutes for GoDaddy-hosted nameservers. External resolvers may cache the old state for up to the previous TTL value.
# REST API Reference (https://developer.godaddy.com/en/docs/references/rest)
***
title: REST API Reference
description: Complete REST API documentation with interactive examples
full: true
----------
## Domain Lifecycle
### Domains & DNS
Manage domain registrations, DNS records, privacy settings, and transfers. Operations span version namespaces: **v1** is the original REST API; **v2** added async processing (action queues, notifications, and status polling) in 2019; **v3** is the newest API with a quote-execute registration model. Machine-readable OpenAPI specs: [domains-v1.json](https://developer.godaddy.com/openapi/domains-v1.json) and [domains-v2.json](https://developer.godaddy.com/openapi/domains-v2.json).
***
## Domain Marketplace & Aftermarket
### Aftermarket API
Auction-related actions exclusive to allowlisted reseller partners (list, bid on, and manage aftermarket domain listings. Auth: sso-key).
### Auctions API
Domain auction operations — retrieve active auctions, place bids, and manage auction state. Auth: sso-key.
### Transactions API
List and read store transactions, signatures, and reference data from the Transactions API v2.
***
## Domain Monetization
### Parking API
Domain parking configuration — enable, disable, and manage monetized parked-page settings for domains. Auth: sso-key.
***
## Customer & Identity
### Agreements API
Retrieve the legal agreements required for domain registration, transfers, and privacy changes. The `agreementKeys` returned here must be passed in the `consent` object when purchasing a domain. Auth: sso-key.
### Shoppers API
Manage shopper accounts, subaccounts, and authentication used by resellers acting on behalf of customers.
***
## Security & Risk
### Abuse API
Report and manage domain abuse cases. Auth: sso-key.
### Certificates API
Manage SSL/TLS certificate orders, validation, reissuance, and domain verification. Auth: sso-key.
***
## Platform & Integration
### ANS API
Agent Name Service (ANS) is a decentralized naming layer for registering, resolving, and managing ANS handles and identities. Auth: OAuth.
### Node.js Hosting API
Deploy and operate Node.js apps on GoDaddy's hosting platform. Manage apps, source uploads, deployments, secrets, and logs.
***
## Reference Data
### Countries API
Country reference data — states and provinces, dialing codes, and country codes for use in contact and address fields. Auth: sso-key.
# Aftermarket (https://developer.godaddy.com/en/docs/references/rest/aftermarket/aftermarket)
***
title: Aftermarket
description: API for auction-related actions exclusive to whitelisted partners.
full: true
\_openapi:
toc:
* depth: 2
title: List GoDaddy Auction listings
url: '#list-godaddy-auction-listings'
* depth: 2
title: Remove listings from GoDaddy Auction
url: '#remove-listings-from-godaddy-auction'
* depth: 2
title: Add expiry listings to GoDaddy Auction
url: '#add-expiry-listings-to-godaddy-auction'
structuredData:
headings:
* content: List GoDaddy Auction listings
id: list-godaddy-auction-listings
* content: Remove listings from GoDaddy Auction
id: remove-listings-from-godaddy-auction
* content: Add expiry listings to GoDaddy Auction
id: add-expiry-listings-to-godaddy-auction
contents: \[]
***
# Agreements (https://developer.godaddy.com/en/docs/references/rest/agreements/agreements)
***
title: Agreements
description: Endpoints for retrieving legal agreements and terms of service.
full: true
\_openapi:
method: GET
toc:
* depth: 2
title: Retrieve legal agreements
url: '#retrieve-legal-agreements'
structuredData:
headings:
* content: Retrieve legal agreements
id: retrieve-legal-agreements
contents: \[]
***
# Agents (https://developer.godaddy.com/en/docs/references/rest/ans/agents)
***
title: Agents
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Search registered agents
url: '#search-registered-agents'
* depth: 2
title: List registered agents
url: '#list-registered-agents'
* depth: 2
title: Retrieve agent details
url: '#retrieve-agent-details'
structuredData:
headings:
* content: Search registered agents
id: search-registered-agents
* content: List registered agents
id: list-registered-agents
* content: Retrieve agent details
id: retrieve-agent-details
contents:
* content: >-
Searches registered agents using request-body criteria and returns
ranked results.
heading: search-registered-agents
* content: >-
Lists registered agents using query parameters and returns a ranked
collection response. This operation is the canonical follow-up target
for pagination `links[].href` values.
heading: list-registered-agents
* content: >-
Returns a single registered agent with trust explainability details.
Search-only ranking scores are not included.
heading: retrieve-agent-details
***
# Certificate Management (https://developer.godaddy.com/en/docs/references/rest/ans/certificate-management)
***
title: Certificate Management
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Retrieve agent identity certificates
url: '#retrieve-agent-identity-certificates'
* depth: 2
title: Submit identity certificate CSR
url: '#submit-identity-certificate-csr'
* depth: 2
title: Retrieve agent server certificates
url: '#retrieve-agent-server-certificates'
* depth: 2
title: Retrieve pending renewal status
url: '#retrieve-pending-renewal-status'
* depth: 2
title: Submit server certificate renewal request
url: '#submit-server-certificate-renewal-request'
* depth: 2
title: Cancel pending renewal
url: '#cancel-pending-renewal'
* depth: 2
title: Verify ACME challenges for pending server cert renewal
url: '#verify-acme-challenges-for-pending-server-cert-renewal'
* depth: 2
title: Get CSR status
url: '#get-csr-status'
structuredData:
headings:
* content: Retrieve agent identity certificates
id: retrieve-agent-identity-certificates
* content: Submit identity certificate CSR
id: submit-identity-certificate-csr
* content: Retrieve agent server certificates
id: retrieve-agent-server-certificates
* content: Retrieve pending renewal status
id: retrieve-pending-renewal-status
* content: Submit server certificate renewal request
id: submit-server-certificate-renewal-request
* content: Cancel pending renewal
id: cancel-pending-renewal
* content: Verify ACME challenges for pending server cert renewal
id: verify-acme-challenges-for-pending-server-cert-renewal
* content: Get CSR status
id: get-csr-status
contents:
* content: Retrieves all identity certificates for the specified agent
heading: retrieve-agent-identity-certificates
* content: >
Submits a Certificate Signing Request (CSR) for the agent's identity
certificate.
The response contains a "csrId", that is going to match the same field
from CertificateResponse.
heading: submit-identity-certificate-csr
* content: Retrieves all TLS server certificates for the specified agent
heading: retrieve-agent-server-certificates
* content: |
Returns current renewal status if one exists.
Used for:
* Checking if ACME verification is complete
* Polling for certificate issuance (CSR path)
* Retrieving challenges if client lost the POST response
* Getting TLSA record after completion
heading: retrieve-pending-renewal-status
* content: >
Initiates server certificate renewal. Returns ACME challenges; the
caller must verify domain control via POST verify-acme.
Supports two paths:
* CSR path: RA issues a new certificate.
* BYOC path: Client provides a certificate; RA validates and stores
it.
Only one pending renewal is allowed per agent (409 if one already
exists).
heading: submit-server-certificate-renewal-request
* content: |
Cancels the pending server certificate renewal for this agent.
Use cases:
* Client submitted incorrect CSR and wants to retry
* Client wants to switch from CSR path to BYOC path (or vice versa)
* Client no longer wishes to complete the renewal
Side effects:
* If renewal type is SERVER\_CSR, marks the associated CSR as REJECTED
* Removes pending renewal from database
* Client can immediately submit a new renewal request
heading: cancel-pending-renewal
* content: >
Triggers ACME validation for a pending server certificate renewal.
Verifies:
* DNS-01 challenge (TXT record at \_acme-challenge.)
* HTTP-01 challenge (file at /.well-known/acme-challenge/)
Response depends on renewal type:
* SERVER\_CSR: Returns 202 (asynchronous certificate issuance).
* SERVER\_BYOC: Returns 200 (certificate stored; TLSA record ready for
DNS update).
heading: verify-acme-challenges-for-pending-server-cert-renewal
* content: >
Retrieves the current status of a Certificate Signing Request (CSR).
This endpoint allows clients to check if a CSR has been signed, is
still pending,
or has been rejected. The failureReason field provides additional
context when
a CSR is rejected.
heading: get-csr-status
***
# Events (https://developer.godaddy.com/en/docs/references/rest/ans/events)
***
title: Events
description: ''
full: true
\_openapi:
method: GET
toc:
* depth: 2
title: Retrieve ANS agent events
url: '#retrieve-ans-agent-events'
structuredData:
headings:
* content: Retrieve ANS agent events
id: retrieve-ans-agent-events
contents:
* content: >-
Returns a paginated, strictly ordered list of ANS events. When
providerId is omitted, the API returns events for all providers; when
providerId is provided, only events associated with that provider are
returned. Pagination is driven by an opaque cursor token returned in
each response.
heading: retrieve-ans-agent-events
***
# Registration (https://developer.godaddy.com/en/docs/references/rest/ans/registration)
***
title: Registration
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Register a new agent with the ANS
url: '#register-a-new-agent-with-the-ans'
* depth: 2
title: Retrieve agent details
url: '#retrieve-agent-details'
structuredData:
headings:
* content: Register a new agent with the ANS
id: register-a-new-agent-with-the-ans
* content: Retrieve agent details
id: retrieve-agent-details
contents:
* content: >
Registers a new agent with the Agent Name Service. Supports three
registration flows:
1. GoDaddy domains with CSRs (synchronous) - Returns 202 immediately
with wait instruction
2. External domains with CSRs (async ACME) or BYOC - Returns 202 with
validation requirements. BYOC is permitted for server certificates
only; identity certificates are always issued by the RA.
The Registration Authority (RA) validates the agent's identity and
submitted
information, then interacts with the CA to issue certificates or
validates
provided server certificates.
heading: register-a-new-agent-with-the-ans
* content: Retrieves detailed information about a registered agent
heading: retrieve-agent-details
***
# Resolution (https://developer.godaddy.com/en/docs/references/rest/ans/resolution)
***
title: Resolution
description: ''
full: true
\_openapi:
method: POST
toc:
* depth: 2
title: Resolve an ANSName to an endpoint
url: '#resolve-an-ansname-to-an-endpoint'
structuredData:
headings:
* content: Resolve an ANSName to an endpoint
id: resolve-an-ansname-to-an-endpoint
contents:
* content: >
Resolves an ANSName to an actionable endpoint reference. The query
includes
the ANSName of the target agent and can optionally incorporate
capability
filters to refine the search. The ANS service queries the Agent
Registry,
which returns a digitally signed endpoint record if found.
heading: resolve-an-ansname-to-an-endpoint
***
# Revocation (https://developer.godaddy.com/en/docs/references/rest/ans/revocation)
***
title: Revocation
description: ''
full: true
\_openapi:
method: POST
toc:
* depth: 2
title: Revoke an active agent or cancel a pending registration
url: '#revoke-an-active-agent-or-cancel-a-pending-registration'
structuredData:
headings:
* content: Revoke an active agent or cancel a pending registration
id: revoke-an-active-agent-or-cancel-a-pending-registration
contents:
* content: >
Revokes an active agent or cancels a pending registration.
For ACTIVE agents: Revokes the agent due to key compromise,
decommissioning,
or other security reasons. The certificate is added to the Certificate
Revocation List (CRL) and the agent's entry in the registry is
flagged.
For PENDING registrations (PENDING\_CERTS or PENDING\_DNS status):
Cancels
the registration attempt after domain validation has been completed.
This
will cancel any pending certificate issuance jobs and revoke any
already-issued
certificates.
Registrations in PENDING\_VALIDATION status (pre-ACME verification)
are not cancellable via this API and will automatically expire if the
ACME verification is not completed within the specified timeframe.
heading: revoke-an-active-agent-or-cancel-a-pending-registration
***
# Search (https://developer.godaddy.com/en/docs/references/rest/ans/search)
***
title: Search
description: ''
full: true
\_openapi:
method: GET
toc:
* depth: 2
title: Search the ANSName Registry with flexible criteria
url: '#search-the-ansname-registry-with-flexible-criteria'
structuredData:
headings:
* content: Search the ANSName Registry with flexible criteria
id: search-the-ansname-registry-with-flexible-criteria
contents:
* content: >
Searches the Agent Name Service registry using flexible criteria such
as
partial agent names, agent host domains, and version ranges. The
search
can return multiple matching agents along with their metadata and
endpoints.
Results are paginated to handle large datasets efficiently.
heading: search-the-ansname-registry-with-flexible-criteria
***
# Validation (https://developer.godaddy.com/en/docs/references/rest/ans/validation)
***
title: Validation
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Trigger ACME validation
url: '#trigger-acme-validation'
* depth: 2
title: Verify DNS record configuration
url: '#verify-dns-record-configuration'
structuredData:
headings:
* content: Trigger ACME validation
id: trigger-acme-validation
* content: Verify DNS record configuration
id: verify-dns-record-configuration
contents:
* content: >
Initiates validation of domain control. The AHP calls this after
placing
the ACME challenge token at the specified location (DNS or HTTP).
The RA validates domain control, which is required before issuing both
server and identity certificates. A single domain validation is used
for both certificates.
The RA will automatically determine which validation method to use
based
on the registration configuration and what is discoverable.
heading: trigger-acme-validation
* content: >
Verifies that all required DNS records have been configured correctly.
The RA knows which records are required based on the registration
and will check for all four required records (HTTPS, TLSA, \_ans,
\_ra-badge).
This is the final step for external domain registration.
heading: verify-dns-record-configuration
***
# Auctions (https://developer.godaddy.com/en/docs/references/rest/auctions/auctions)
***
title: Auctions
description: Endpoints for placing bids on GoDaddy Auction listings.
full: true
\_openapi:
method: POST
toc:
* depth: 2
title: Place multiple bids
url: '#place-multiple-bids'
structuredData:
headings:
* content: Place multiple bids
id: place-multiple-bids
contents: \[]
***
# v1 (https://developer.godaddy.com/en/docs/references/rest/certificates/v1)
---
title: v1
description: ''
full: true
_openapi:
toc:
- depth: 2
title: Create a pending order for certificate
url: '#create-a-pending-order-for-certificate'
- depth: 2
title: Validate a pending order for certificate
url: '#validate-a-pending-order-for-certificate'
- depth: 2
title: Retrieve certificate details
url: '#retrieve-certificate-details'
- depth: 2
title: Retrieve all certificate actions
url: '#retrieve-all-certificate-actions'
- depth: 2
title: Resend an email
url: '#resend-an-email'
- depth: 2
title: Add alternate email address
url: '#add-alternate-email-address'
- depth: 2
title: Resend email to email address
url: '#resend-email-to-email-address'
- depth: 2
title: Retrieve email history
url: '#retrieve-email-history'
- depth: 2
title: Retrieve system stateful action callback url
url: '#retrieve-system-stateful-action-callback-url'
- depth: 2
title: Unregister system callback
url: '#unregister-system-callback'
- depth: 2
title: Register of certificate action callback
url: '#register-of-certificate-action-callback'
- depth: 2
title: Cancel a pending certificate
url: '#cancel-a-pending-certificate'
- depth: 2
title: Download certificate
url: '#download-certificate'
- depth: 2
title: Reissue active certificate
url: '#reissue-active-certificate'
- depth: 2
title: Renew active certificate
url: '#renew-active-certificate'
- depth: 2
title: Revoke active certificate
url: '#revoke-active-certificate'
- depth: 2
title: Get Site seal
url: '#get-site-seal'
- depth: 2
title: Check Domain Control
url: '#check-domain-control'
structuredData:
headings:
- content: Create a pending order for certificate
id: create-a-pending-order-for-certificate
- content: Validate a pending order for certificate
id: validate-a-pending-order-for-certificate
- content: Retrieve certificate details
id: retrieve-certificate-details
- content: Retrieve all certificate actions
id: retrieve-all-certificate-actions
- content: Resend an email
id: resend-an-email
- content: Add alternate email address
id: add-alternate-email-address
- content: Resend email to email address
id: resend-email-to-email-address
- content: Retrieve email history
id: retrieve-email-history
- content: Retrieve system stateful action callback url
id: retrieve-system-stateful-action-callback-url
- content: Unregister system callback
id: unregister-system-callback
- content: Register of certificate action callback
id: register-of-certificate-action-callback
- content: Cancel a pending certificate
id: cancel-a-pending-certificate
- content: Download certificate
id: download-certificate
- content: Reissue active certificate
id: reissue-active-certificate
- content: Renew active certificate
id: renew-active-certificate
- content: Revoke active certificate
id: revoke-active-certificate
- content: Get Site seal
id: get-site-seal
- content: Check Domain Control
id: check-domain-control
contents:
- content: >-
Creating a certificate order can be a long running asynchronous
operation in the PKI workflow. The PKI API supports 2 options for
getting the completion stateful actions for this asynchronous
operations: 1) by polling operations -- see
/v1/certificates//actions 2) via WebHook style callback
-- see '/v1/certificates//callback'.
heading: create-a-pending-order-for-certificate
- content: >-
Once the certificate order has been created, this method can be used
to check the status of the certificate. This method can also be used
to retrieve details of the certificate.
heading: retrieve-certificate-details
- content: >-
This method is used to retrieve all stateful actions relating to a
certificate lifecycle.
heading: retrieve-all-certificate-actions
- content: >-
This method can be used to resend emails by providing the certificate
id and the email id
heading: resend-an-email
- content: >-
This method adds an alternate email address to a certificate order and
re-sends all existing request emails to that address.
heading: add-alternate-email-address
- content: >-
This method can be used to resend emails by providing the certificate
id, the email id, and the recipient email address
heading: resend-email-to-email-address
- content: This method can be used to retrieve all emails sent for a certificate.
heading: retrieve-email-history
- content: >-
This method is used to retrieve the registered callback url for a
certificate.
heading: retrieve-system-stateful-action-callback-url
- content: Unregister the callback for a particular certificate.
heading: unregister-system-callback
- content: >-
This method is used to register/replace url for callbacks for stateful
actions relating to a certificate lifecycle. The callback url is a
Webhook style pattern and will receive POST http requests with json
body defined in the CertificateAction model definition for each
certificate action. Only one callback URL is allowed to be registered
for each certificateId, so it will replace a previous registration.
heading: register-of-certificate-action-callback
- content: Use the cancel call to cancel a pending certificate order.
heading: cancel-a-pending-certificate
- content: >-
Rekeying is the process by which the private and public key is
changed for a certificate. It is a simplified reissue,where only the
CSR is changed. Reissuing is the process by which domain names are
added or removed from a certificate.Once a request is validated and
approved, the certificate will be reissued with the new common name
and sans specified. Unlimited reissues are available during the
lifetime of the certificate.New names added to a certificate that do
not share the base domain of the common name may take additional time
to validate. If this API call is made before a previous pending
reissue has been validated and issued, the previous reissue request is
automatically rejected and replaced with the current request.
heading: reissue-active-certificate
- content: >-
Renewal is the process by which the validity of a certificate is
extended. Renewal is only available 60 days prior to expiration of the
previous certificate and 30 days after the expiration of the previous
certificate. The renewal supports modifying a set of the original
certificate order information. Once a request is validated and
approved, the certificate will be issued with extended validity. Since
subject alternative names can be removed during a renewal, we require
that you provide the subject alternative names you expect in the
renewed certificate. New names added to a certificate that do not
share the base domain of the common name may take additional time to
validate.
heading: renew-active-certificate
- content: >-
Use revoke call to revoke an active certificate, if the certificate
has not been issued a 404 response will be returned.
heading: revoke-active-certificate
- content: >-
This method is used to obtain the site seal information for an
issued certificate. A site seal is a graphic that the certificate
purchaser can embed on their web site to show their visitors
information about their SSL certificate. If a web site visitor clicks
on the site seal image, a pop-up page is displayed that contains
detailed information about the SSL certificate. The site seal token is
used to link the site seal graphic image to the appropriate
certificate details pop-up page display when a user clicks on the site
seal. The site seal images are expected to be static images and hosted
on the reseller's website, to minimize delays for customer page load
times.
heading: get-site-seal
- content: >-
Domain control is a means for verifying the domain included in the
certificate order. This resource is useful for resellers that control
the domains for their customers, and can expedite the verification
process. See
https://www.godaddy.com/help/verifying-your-domain-ownership-for-ssl-certificate-requests-html-or-dns-7452
heading: check-domain-control
---
# v2 (https://developer.godaddy.com/en/docs/references/rest/certificates/v2)
***
title: v2
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Search for certificate details by entitlement
url: '#search-for-certificate-details-by-entitlement'
* depth: 2
title: Create a pending order for certificate
url: '#create-a-pending-order-for-certificate'
* depth: 2
title: Reissue active certificate
url: '#reissue-active-certificate'
* depth: 2
title: Download certificate by entitlement
url: '#download-certificate-by-entitlement'
* depth: 2
title: Retrieve customer's certificates
url: '#retrieve-customers-certificates'
* depth: 2
title: Retrieve individual certificate details
url: '#retrieve-individual-certificate-details'
* depth: 2
title: Retrieve domain verification status
url: '#retrieve-domain-verification-status'
* depth: 2
title: Retrieve detailed information for supplied domain
url: '#retrieve-detailed-information-for-supplied-domain'
* depth: 2
title: Retrieves the external account binding for the specified customer
url: '#retrieves-the-external-account-binding-for-the-specified-customer'
* depth: 2
title: Get a page of subscriptions by domain
url: '#get-a-page-of-subscriptions-by-domain'
* depth: 2
title: GET a page of certificates for a specific domain product
url: '#get-a-page-of-certificates-for-a-specific-domain-product'
structuredData:
headings:
* content: Search for certificate details by entitlement
id: search-for-certificate-details-by-entitlement
* content: Create a pending order for certificate
id: create-a-pending-order-for-certificate
* content: Reissue active certificate
id: reissue-active-certificate
* content: Download certificate by entitlement
id: download-certificate-by-entitlement
* content: Retrieve customer's certificates
id: retrieve-customers-certificates
* content: Retrieve individual certificate details
id: retrieve-individual-certificate-details
* content: Retrieve domain verification status
id: retrieve-domain-verification-status
* content: Retrieve detailed information for supplied domain
id: retrieve-detailed-information-for-supplied-domain
* content: Retrieves the external account binding for the specified customer
id: retrieves-the-external-account-binding-for-the-specified-customer
* content: Get a page of subscriptions by domain
id: get-a-page-of-subscriptions-by-domain
* content: GET a page of certificates for a specific domain product
id: get-a-page-of-certificates-for-a-specific-domain-product
contents:
* content: >-
Once the certificate order has been created, this method can be used
to check the status of the certificate. This method can also be used
to retrieve details of the certificates associated to an entitlement.
heading: search-for-certificate-details-by-entitlement
* content: >-
Creating a certificate order for a subscription can be a long
running asynchronous operation in the PKI workflow. The PKI API
supports 2 options for getting the completion stateful actions for
this asynchronous operations: 1) by polling operations -- see
/v1/certificates//actions 2) via WebHook style callback
\-- see '/v1/certificates//callback'.
heading: create-a-pending-order-for-certificate
* content: >-
Rekeying is the process by which the private and public key is
changed for a certificate. It is a simplified reissue,where only the
CSR is changed. Reissue extends validity of the existing certificate
by requesting a new certificate with all the same values as existing
issued certificate. Once a request is validated and approved, the
certificate will be reissued with the same common name and sans
specified from existing certificate. Unlimited reissues are available
during the lifetime of the certificate.If this API call is made before
a previous pending reissue has been validated and issued, the previous
reissue request is automatically rejected and replaced with the
current request.
heading: reissue-active-certificate
* content: >-
This method can be used to retrieve a list of certificates for a
specified customer. **shopperId** is **not the same** as
**customerId**. **shopperId** is a number of max length 10 digits
(*ex:* 1234567890) whereas **customerId** is a UUIDv4 (*ex:*
295e3bc3-b3b9-4d95-aae5-ede41a994d13)
heading: retrieve-customers-certificates
* content: >-
Once the certificate order has been created, this method can be used
to check the status of the certificate. This method can also be used
to retrieve details of the certificate. **shopperId** is **not
the same** as **customerId**. **shopperId** is a number of max length
10 digits (*ex:* 1234567890) whereas **customerId** is a UUIDv4 (*ex:*
295e3bc3-b3b9-4d95-aae5-ede41a994d13)
heading: retrieve-individual-certificate-details
* content: >-
This method can be used to retrieve the domain verification status for
a certificate request.**shopperId** is **not the same** as
**customerId**. **shopperId** is a number of max length 10 digits
(*ex:* 1234567890) whereas **customerId** is a UUIDv4 (*ex:*
295e3bc3-b3b9-4d95-aae5-ede41a994d13)"
heading: retrieve-domain-verification-status
* content: >-
Retrieve detailed information for supplied domain, including domain
verification details and Certificate Authority Authorization (CAA)
verification details. **shopperId** is **not the same** as
**customerId**. **shopperId** is a number of max length 10 digits
(*ex:* 1234567890) whereas **customerId** is a UUIDv4 (*ex:*
295e3bc3-b3b9-4d95-aae5-ede41a994d13)
heading: retrieve-detailed-information-for-supplied-domain
* content: >-
Use this endpoint to retrieve a key identifier and Hash-based Message
Authentication Code (HMAC) key for Automated Certificate Management
Environment (ACME) External Account Binding (EAB). These credentials
can be used with an ACME client that supports EAB (ex. CertBot) to
automate the issuance request and deployment of DV SSL certificates
heading: retrieves-the-external-account-binding-for-the-specified-customer
* content: >-
The pagination starts at page 1. Each page contains a page of
*subscriptions*, not certificates. This endpoint is meant for paging
the subscriptions under the authorized user's account. Each
subscription contains a snapshot of certificates contained within the
subscription. To fetch further certificates under a subscription, use
the /v2/certificates/subscription/ endpoint with the
subscription GUID obtained from this call. If any filtering is
applied, subscriptions without any certificates will be omitted.
heading: get-a-page-of-subscriptions-by-domain
***
# Countries (https://developer.godaddy.com/en/docs/references/rest/countries/countries)
***
title: Countries
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Retrieve country information
url: '#retrieve-country-information'
* depth: 2
title: Retrieve country and state information
url: '#retrieve-country-and-state-information'
structuredData:
headings:
* content: Retrieve country information
id: retrieve-country-information
* content: Retrieve country and state information
id: retrieve-country-and-state-information
contents:
* content: Authorization is not required
heading: retrieve-country-information
* content: Authorization is not required
heading: retrieve-country-and-state-information
***
# Domains REST reference (https://developer.godaddy.com/en/docs/references/rest/domains)
***
title: Domains REST reference
description: REST reference for the Domains API. v3 quote-execute registration, plus v1/v2 for DNS, contacts, transfers, and forwarding.
----------------------------------------------------------------------------------------------------------------------------------------
The complete OpenAPI specs for this namespace are available as JSON — useful for code generation, SDK tooling, and LLM context: [domains-v3.json](https://developer.godaddy.com/openapi/domains-v3.json) (discovery + registration), [domains-v1.json](https://developer.godaddy.com/openapi/domains-v1.json) (account-scoped), and [domains-v2.json](https://developer.godaddy.com/openapi/domains-v2.json) (async operations).
The Domains REST API exposes domain availability search, registration, DNS and contact management, registry lock, WHOIS privacy, forwarding, and inbound and outbound transfers. Operations span three version namespaces: `v3` (quote-execute registration model), `v1` (account-scoped), and `v2` (async operation tracking).
For a task-shaped guide written for DIY API users, see [Use the API → Domains](https://developer.godaddy.com/docs/api-users/manage-domains).
## The core objects
The Domains namespace is built around a small set of resources. Each operation in the reference reads or writes one of these objects.
| Object | Description |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DomainDetail` (v1) / `DomainDetailV2` (v2) | A registered domain and its registry metadata: name, status, expiration, contacts, nameservers, lock state, and privacy state. |
| `DNSRecord` | A single DNS record (`A`, `AAAA`, `CNAME`, `MX`, `TXT`, `SRV`, `NS`, `SOA`, or `CAA`) on a domain that uses GoDaddy's authoritative nameservers. |
| `Contact` | A WHOIS contact record covering name, organization, address, email, and phone. The same shape is used for the registrant, admin, billing, and tech roles on a domain. |
| `Action` | An asynchronous-operation tracker returned with `202 Accepted` when the API queues a long-running write. Callers poll the action endpoint until the action's `status` reaches a terminal state. |
| `DomainAvailableResponse` | The result of an availability check, including the available flag, current price in `currency-micro-unit` format, the registration period in years, and whether the answer is from a live registry call or cache. |
| `DomainForwarding` | An HTTP forwarding rule on a domain, configurable as masked or unmasked and as a permanent (`301`) or temporary (`302`) redirect. |
| `DomainTransferIn` | The request shape for an inbound transfer, carrying the domain name, authcode, and required contacts. |
| `Error` / `ErrorLimit` | The standard error envelope returned on `4xx` and `5xx` responses across the namespace. `ErrorLimit` extends `Error` with `retryAfterSec` for `429` rate-limited responses. |
## Version namespaces
## Conventions used across the namespace
| Concern | Where it's documented |
| -------------------------------------------------------------- | ------------------------------------------ |
| Authentication (PAT for v3; PAT or legacy `sso-key` for v1/v2) | [Authentication](https://developer.godaddy.com/docs/api-users/auth) |
| Error envelope and retry semantics | [Errors](https://developer.godaddy.com/docs/api-users/errors) |
| Rate limits (60 requests/minute per credential) | [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) |
| Cursor-based pagination on v1 list endpoints | [Pagination](https://developer.godaddy.com/docs/api-users/pagination) |
## Related references
# Apps (https://developer.godaddy.com/en/docs/references/rest/nodejs-hosting/apps)
***
title: Apps
description: Create, read, update, and delete apps.
full: true
\_openapi:
toc:
* depth: 2
title: List apps
url: '#list-apps'
* depth: 2
title: Create app
url: '#create-app'
* depth: 2
title: Get app creation status
url: '#get-app-creation-status'
* depth: 2
title: Get app
url: '#get-app'
* depth: 2
title: Update app metadata
url: '#update-app-metadata'
* depth: 2
title: Delete app
url: '#delete-app'
structuredData:
headings:
* content: List apps
id: list-apps
* content: Create app
id: create-app
* content: Get app creation status
id: get-app-creation-status
* content: Get app
id: get-app
* content: Update app metadata
id: update-app-metadata
* content: Delete app
id: delete-app
contents: \[]
***
# Deployments (https://developer.godaddy.com/en/docs/references/rest/nodejs-hosting/deployments)
***
title: Deployments
description: >-
Publish the latest code, list past deployments, roll back to a previous one,
and probe runtime status.
full: true
\_openapi:
toc:
* depth: 2
title: List deployments
url: '#list-deployments'
* depth: 2
title: Publish app (deploy latest code)
url: '#publish-app-deploy-latest-code'
* depth: 2
title: Get app status
url: '#get-app-status'
* depth: 2
title: Rollback to a previous deployment
url: '#rollback-to-a-previous-deployment'
structuredData:
headings:
* content: List deployments
id: list-deployments
* content: Publish app (deploy latest code)
id: publish-app-deploy-latest-code
* content: Get app status
id: get-app-status
* content: Rollback to a previous deployment
id: rollback-to-a-previous-deployment
contents: \[]
***
# Overview (https://developer.godaddy.com/en/docs/references/rest/nodejs-hosting)
***
title: Overview
description: >
Reference for the Node.js Hosting Public API, a REST API for deploying and
operating GoDaddy Node.js Hosting applications.
Async-first: long-running writes return immediately with a job or deployment record you poll to completion.
-----------------------------------------------------------------------------------------------------------
## Overview
The Node.js Hosting API lets you build, deploy, and operate Node.js apps on GoDaddy's hosting platform without touching a dashboard. Each app has two variants — `preview` and `publish` — so you can iterate safely and promote when you're ready.
Long-running operations (create app, upload source, publish, rollback) return immediately with a job or deployment record. Create app responds with `202 Accepted`. Upload, publish, and rollback respond with `200 OK`. Poll until each operation reaches a terminal state. See [Concepts](https://developer.godaddy.com/docs/hosting/concepts) for the full pattern.
Every endpoint is authenticated with an **OAuth 2.0 client-credentials** access token. Get a token, send it as `Authorization: Bearer `, and request only the scopes each operation requires. See [Authentication](https://developer.godaddy.com/docs/hosting/authentication).
## Endpoint groups
## Typical flow
```
POST /apps → 202, job id
GET /apps/jobs/{jobId} → poll until app is ready
POST /apps/{appId}/source → 200, upload jobId (multipart/form-data)
GET /apps/{appId}/source/status?jobId → poll until upload is processed
POST /apps/{appId}/deployments → 200, deployment record
GET /apps/{appId}/deployments → list past deployments
GET /apps/{appId}/status → runtime status per variant
POST /apps/{appId}/rollback → 200, rollback started
```
## Conventions
| Convention | Detail |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Base URL | Gateway-relative: `/v1/hosting/nodejs` (host determined by the GoDaddy API gateway) |
| Async writes | Create app returns `202 Accepted` with a job id. Upload, publish, and rollback return `200 OK` with a job or deployment record. Poll the relevant endpoint until the operation reaches a terminal state. |
| Variants | Every app has `preview` and `publish` variants. Filter per endpoint: `/secrets?variant=…`, `/logs?target=…`. `/status` returns both. |
| Auth | OAuth 2.0 client credentials — token URL `https://oauth.api.godaddy.com/v2/oauth2/token` |
| Secret values | Never returned by any endpoint. Only names and metadata are readable. |
| Rate limits | Enforced by the API gateway. Not currently surfaced in schemas. |
# Logs (https://developer.godaddy.com/en/docs/references/rest/nodejs-hosting/logs)
***
title: Logs
description: Read application and build logs.
full: true
\_openapi:
method: GET
toc:
* depth: 2
title: Get application logs
url: '#get-application-logs'
structuredData:
headings:
* content: Get application logs
id: get-application-logs
contents: \[]
***
# Secrets (https://developer.godaddy.com/en/docs/references/rest/nodejs-hosting/secrets)
***
title: Secrets
description: Manage environment secrets per variant. Values are never returned.
full: true
\_openapi:
toc:
* depth: 2
title: List app secrets (metadata only)
url: '#list-app-secrets-metadata-only'
* depth: 2
title: Add, update, or delete app secrets
url: '#add-update-or-delete-app-secrets'
structuredData:
headings:
* content: List app secrets (metadata only)
id: list-app-secrets-metadata-only
* content: Add, update, or delete app secrets
id: add-update-or-delete-app-secrets
contents: \[]
***
# Source (https://developer.godaddy.com/en/docs/references/rest/nodejs-hosting/source)
***
title: Source
description: Upload app source as a zip and poll the upload job.
full: true
\_openapi:
toc:
* depth: 2
title: Upload app source (zip)
url: '#upload-app-source-zip'
* depth: 2
title: Poll zip upload status
url: '#poll-zip-upload-status'
structuredData:
headings:
* content: Upload app source (zip)
id: upload-app-source-zip
* content: Poll zip upload status
id: poll-zip-upload-status
contents: \[]
***
# Parking (https://developer.godaddy.com/en/docs/references/rest/parking/parking)
***
title: Parking
description: Endpoints for retrieving parking metrics and domain performance data.
full: true
\_openapi:
toc:
* depth: 2
title: List parking metrics
url: '#list-parking-metrics'
* depth: 2
title: List domain metrics
url: '#list-domain-metrics'
structuredData:
headings:
* content: List parking metrics
id: list-parking-metrics
* content: List domain metrics
id: list-domain-metrics
contents: \[]
***
# Shoppers (https://developer.godaddy.com/en/docs/references/rest/shoppers/shoppers)
***
title: Shoppers
description: ''
full: true
\_openapi:
toc:
* depth: 2
title: Create a Subaccount owned by the authenticated Reseller
url: '#create-a-subaccount-owned-by-the-authenticated-reseller'
* depth: 2
title: Get details for the specified Shopper
url: '#get-details-for-the-specified-shopper'
* depth: 2
title: Update details for the specified Shopper
url: '#update-details-for-the-specified-shopper'
* depth: 2
title: Request the deletion of a shopper profile
url: '#request-the-deletion-of-a-shopper-profile'
* depth: 2
title: Get details for the specified Shopper
url: '#get-details-for-the-specified-shopper-1'
* depth: 2
title: Set subaccount's password
url: '#set-subaccounts-password'
structuredData:
headings:
* content: Create a Subaccount owned by the authenticated Reseller
id: create-a-subaccount-owned-by-the-authenticated-reseller
* content: Get details for the specified Shopper
id: get-details-for-the-specified-shopper
* content: Update details for the specified Shopper
id: update-details-for-the-specified-shopper
* content: Request the deletion of a shopper profile
id: request-the-deletion-of-a-shopper-profile
* content: Get details for the specified Shopper
id: get-details-for-the-specified-shopper-1
* content: Set subaccount's password
id: set-subaccounts-password
contents:
* content: >-
Notes:Shopper deletion is not supported in
production — contact GoDaddy support for account removal.
heading: request-the-deletion-of-a-shopper-profile
* content: >-
Notes:Password set is only supported by API
Resellers setting subaccount passwords.
heading: set-subaccounts-password
***
# General Endpoints (https://developer.godaddy.com/en/docs/references/rest/transactions/general-endpoints)
***
title: General Endpoints
description: Store transactions, signatures, and references.
full: true
\_openapi:
toc:
* depth: 2
title: Get all transactions
url: '#get-all-transactions'
* depth: 2
title: Get transaction by ID
url: '#get-transaction-by-id'
structuredData:
headings:
* content: Get all transactions
id: get-all-transactions
* content: Get transaction by ID
id: get-transaction-by-id
contents:
* content: Retrieve all the transactions for a specific store using the store ID.
heading: get-all-transactions
* content: >-
Retrieve all the information for a single transaction using the store
and transaction IDs.
heading: get-transaction-by-id
***
# v1 (Legacy) (https://developer.godaddy.com/en/docs/references/rest/abuse/v1-legacy)
***
title: v1 (Legacy)
description: Legacy v1 endpoints, maintained for backward compatibility.
full: true
\_openapi:
toc:
* depth: 2
title: List abuse tickets
url: '#list-abuse-tickets'
* depth: 2
title: Create a new abuse ticket
url: '#create-a-new-abuse-ticket'
* depth: 2
title: Retrieve abuse ticket details
url: '#retrieve-abuse-ticket-details'
structuredData:
headings:
* content: List abuse tickets
id: list-abuse-tickets
* content: Create a new abuse ticket
id: create-a-new-abuse-ticket
* content: Retrieve abuse ticket details
id: retrieve-abuse-ticket-details
contents: \[]
***
# v2 (https://developer.godaddy.com/en/docs/references/rest/abuse/v2)
***
title: v2
description: >-
An incremental update that keeps the endpoints largely the same, but
deprecates some commonly misused parameters and add some features to ensure
reports can be worked quicker.
full: true
\_openapi:
toc:
* depth: 2
title: List abuse tickets
url: '#list-abuse-tickets'
* depth: 2
title: Create a new abuse ticket
url: '#create-a-new-abuse-ticket'
* depth: 2
title: Retrieve abuse ticket details
url: '#retrieve-abuse-ticket-details'
structuredData:
headings:
* content: List abuse tickets
id: list-abuse-tickets
* content: Create a new abuse ticket
id: create-a-new-abuse-ticket
* content: Retrieve abuse ticket details
id: retrieve-abuse-ticket-details
contents: \[]
***
# Find Domains (https://developer.godaddy.com/en/docs/references/rest/domains/v1/find-domains)
***
title: Find Domains
full: true
\_openapi:
toc:
* depth: 2
title: Determine whether or not the specified domain is available for purchase
url: '#determine-whether-or-not-the-specified-domain-is-available-for-purchase'
* depth: 2
title: >-
Determine whether or not the specified domains are available for
purchase
url: >-
\#determine-whether-or-not-the-specified-domains-are-available-for-purchase
* depth: 2
title: >-
Suggest alternate Domain names based on a seed Domain, a set of
keywords, or the shopper's purchase history
url: >-
\#suggest-alternate-domain-names-based-on-a-seed-domain-a-set-of-keywords-or-the-shoppers-purchase-history
structuredData:
headings:
* content: >-
Determine whether or not the specified domain is available for
purchase
id: >-
determine-whether-or-not-the-specified-domain-is-available-for-purchase
* content: >-
Determine whether or not the specified domains are available for
purchase
id: >-
determine-whether-or-not-the-specified-domains-are-available-for-purchase
* content: >-
Suggest alternate Domain names based on a seed Domain, a set of
keywords, or the shopper's purchase history
id: >-
suggest-alternate-domain-names-based-on-a-seed-domain-a-set-of-keywords-or-the-shoppers-purchase-history
contents:
* content: >-
Checks whether a single domain is available to register and returns
the current price in currency-micro-unit format. The definitive flag
indicates whether the result came from a live registry query.
heading: >-
determine-whether-or-not-the-specified-domain-is-available-for-purchase
* content: >-
Checks availability for multiple domains in a single request. Returns
an array of availability and pricing results, one per domain queried.
heading: >-
determine-whether-or-not-the-specified-domains-are-available-for-purchase
* content: >-
Returns domain name suggestions based on a seed domain, keywords, or
purchase history. Useful for presenting alternatives when a desired
domain is unavailable.
heading: >-
suggest-alternate-domain-names-based-on-a-seed-domain-a-set-of-keywords-or-the-shoppers-purchase-history
***
# Domains v1 (https://developer.godaddy.com/en/docs/references/rest/domains/v1)
***
title: Domains v1
description: Account-scoped Domains operations under /v1/domains. Search, register, list, DNS, privacy, renewals, and transfer.
-------------------------------------------------------------------------------------------------------------------------------
## Overview
The `v1` namespace exposes Domains operations that act on the domains owned by the authenticated account. Caller identity is established by the `Authorization` header alone; some operations also accept an `X-Shopper-Id` header to act on behalf of a specific shopper.
The `v1` namespace is account-scoped; use `v2` when you need async operation tracking (action queues, status polling, and notifications). For a task-shaped guide layered on top of these endpoints, see [Use the API → Domains](https://developer.godaddy.com/docs/api-users/manage-domains).
The complete OpenAPI spec for the v1 namespace is available at [/openapi/domains-v1.json](https://developer.godaddy.com/openapi/domains-v1.json) — useful for code generation, SDK tooling, and LLM context.
## Operation groups
The v1 namespace is organized into five operation groups, each rendered on its own reference page below.
## Authentication and scopes
Every v1 operation requires an `Authorization` header carrying a Personal Access Token (Bearer) or a legacy `sso-key` credential. PATs use the granular Domains & DNS scopes listed in [Authentication](https://developer.godaddy.com/docs/api-users/auth), like `domains.domain:read`, `domains.domain:update`, `domains.dns:update`, and `domains.transfer:execute`.
## Conventions
| Concern | Where it's documented |
| ----------------------------------------------- | ------------------------------------------ |
| Error envelope and retry semantics | [Errors](https://developer.godaddy.com/docs/api-users/errors) |
| Rate limits (60 requests/minute per credential) | [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) |
| Cursor-based pagination on `GET /v1/domains` | [Pagination](https://developer.godaddy.com/docs/api-users/pagination) |
# Manage DNS (https://developer.godaddy.com/en/docs/references/rest/domains/v1/manage-dns)
***
title: Manage DNS
full: true
\_openapi:
toc:
* depth: 2
title: Add the specified DNS Records to the specified Domain
url: '#add-the-specified-dns-records-to-the-specified-domain'
* depth: 2
title: Replace all DNS Records for the specified Domain
url: '#replace-all-dns-records-for-the-specified-domain'
* depth: 2
title: >-
Retrieve DNS Records for the specified Domain, optionally with the
specified Type and/or Name
url: >-
\#retrieve-dns-records-for-the-specified-domain-optionally-with-the-specified-type-andor-name
* depth: 2
title: >-
Delete all DNS Records for the specified Domain with the specified Type
and Name
url: >-
\#delete-all-dns-records-for-the-specified-domain-with-the-specified-type-and-name
* depth: 2
title: >-
Replace all DNS Records for the specified Domain with the specified Type
and Name
url: >-
\#replace-all-dns-records-for-the-specified-domain-with-the-specified-type-and-name
* depth: 2
title: Replace all DNS Records for the specified Domain with the specified Type
url: >-
\#replace-all-dns-records-for-the-specified-domain-with-the-specified-type
structuredData:
headings:
* content: Add the specified DNS Records to the specified Domain
id: add-the-specified-dns-records-to-the-specified-domain
* content: Replace all DNS Records for the specified Domain
id: replace-all-dns-records-for-the-specified-domain
* content: >-
Retrieve DNS Records for the specified Domain, optionally with the
specified Type and/or Name
id: >-
retrieve-dns-records-for-the-specified-domain-optionally-with-the-specified-type-andor-name
* content: >-
Delete all DNS Records for the specified Domain with the specified
Type and Name
id: >-
delete-all-dns-records-for-the-specified-domain-with-the-specified-type-and-name
* content: >-
Replace all DNS Records for the specified Domain with the specified
Type and Name
id: >-
replace-all-dns-records-for-the-specified-domain-with-the-specified-type-and-name
* content: >-
Replace all DNS Records for the specified Domain with the specified
Type
id: >-
replace-all-dns-records-for-the-specified-domain-with-the-specified-type
contents:
* content: >-
Appends DNS records to the domain's zone without removing existing
records. Existing records with the same type and name are preserved.
Returns 204 No Content.
heading: add-the-specified-dns-records-to-the-specified-domain
* content: >-
Replaces the entire DNS record set for the domain. All existing
records are removed and replaced with the submitted set. Returns 204
No Content.
heading: replace-all-dns-records-for-the-specified-domain
* content: >-
Returns DNS records for the domain. Optionally filter by record type
and name. Returns an array of DNSRecord objects.
heading: >-
retrieve-dns-records-for-the-specified-domain-optionally-with-the-specified-type-andor-name
* content: >-
Deletes all DNS records matching the specified type and name. All
other records are preserved. Returns 204 No Content.
heading: >-
delete-all-dns-records-for-the-specified-domain-with-the-specified-type-and-name
* content: >-
Replaces all DNS records of the specified type and name. All other
records are preserved. Returns 204 No Content.
heading: >-
replace-all-dns-records-for-the-specified-domain-with-the-specified-type-and-name
* content: >-
Replaces all DNS records of the specified type across all names.
Records of other types are preserved. Returns 204 No Content.
heading: >-
replace-all-dns-records-for-the-specified-domain-with-the-specified-type
***
# Manage Domain Settings (https://developer.godaddy.com/en/docs/references/rest/domains/v1/manage-domain-settings)
***
title: Manage Domain Settings
full: true
\_openapi:
toc:
* depth: 2
title: Retrieve a list of Domains for the specified Shopper
url: '#retrieve-a-list-of-domains-for-the-specified-shopper'
* depth: 2
title: >-
Validate the request body using the Domain Contact Validation Schema for
specified domains.
url: >-
\#validate-the-request-body-using-the-domain-contact-validation-schema-for-specified-domains
* depth: 2
title: Retrieve details for the specified Domain
url: '#retrieve-details-for-the-specified-domain'
* depth: 2
title: Update details for the specified Domain
url: '#update-details-for-the-specified-domain'
* depth: 2
title: Cancel a purchased domain
url: '#cancel-a-purchased-domain'
* depth: 2
title: Update domain
url: '#update-domain'
* depth: 2
title: Re-send Contact E-mail Verification for specified Domain
url: '#re-send-contact-e-mail-verification-for-specified-domain'
structuredData:
headings:
* content: Retrieve a list of Domains for the specified Shopper
id: retrieve-a-list-of-domains-for-the-specified-shopper
* content: >-
Validate the request body using the Domain Contact Validation Schema
for specified domains.
id: >-
validate-the-request-body-using-the-domain-contact-validation-schema-for-specified-domains
* content: Retrieve details for the specified Domain
id: retrieve-details-for-the-specified-domain
* content: Update details for the specified Domain
id: update-details-for-the-specified-domain
* content: Cancel a purchased domain
id: cancel-a-purchased-domain
* content: Update domain
id: update-domain
* content: Re-send Contact E-mail Verification for specified Domain
id: re-send-contact-e-mail-verification-for-specified-domain
contents:
* content: >-
Returns a paginated list of domains owned by the authenticated
account. Supports filtering by status and optional inclusion of
contacts, nameservers, and authCode in each record.
heading: retrieve-a-list-of-domains-for-the-specified-shopper
* content: >-
All contacts specified in request will be validated against all
domains specified in "domains". As an alternative, you can also pass
in tlds, with the exception of `uk`, which requires full domain names
heading: >-
validate-the-request-body-using-the-domain-contact-validation-schema-for-specified-domains
* content: >-
Returns the full DomainDetail object including status, contacts,
nameservers, lock state, privacy flag, and expiration timestamp.
heading: retrieve-details-for-the-specified-domain
* content: >-
Updates one or more fields on the domain. Accepts a partial
DomainUpdate body - only fields included are modified. Returns 204 No
Content.
heading: update-details-for-the-specified-domain
* content: >-
Cancels a purchased domain and initiates a refund if within the
cancellation window. This action is irreversible.
heading: cancel-a-purchased-domain
* content: >-
Updates domain settings. Only fields included in the request body are
modified. Returns 204 No Content.
heading: update-domain
* content: >-
Re-sends the ICANN registrant email verification to the domain's
registrant contact. Use when the original verification email was not
received or has expired.
heading: re-send-contact-e-mail-verification-for-specified-domain
***
# Register and Renew Domains (https://developer.godaddy.com/en/docs/references/rest/domains/v1/register-and-renew-domains)
***
title: Register and Renew Domains
full: true
\_openapi:
toc:
* depth: 2
title: >-
Retrieve the legal agreement(s) required to purchase the specified TLD
and add-ons
url: >-
\#retrieve-the-legal-agreements-required-to-purchase-the-specified-tld-and-add-ons
* depth: 2
title: Purchase and register the specified Domain
url: '#purchase-and-register-the-specified-domain'
* depth: 2
title: >-
Retrieve the schema to be submitted when registering a Domain for the
specified TLD
url: >-
\#retrieve-the-schema-to-be-submitted-when-registering-a-domain-for-the-specified-tld
* depth: 2
title: >-
Validate the request body using the Domain Purchase Schema for the
specified TLD
url: >-
\#validate-the-request-body-using-the-domain-purchase-schema-for-the-specified-tld
* depth: 2
title: Retrieves a list of TLDs supported and enabled for sale
url: '#retrieves-a-list-of-tlds-supported-and-enabled-for-sale'
* depth: 2
title: Renew the specified Domain
url: '#renew-the-specified-domain'
structuredData:
headings:
* content: >-
Retrieve the legal agreement(s) required to purchase the specified TLD
and add-ons
id: >-
retrieve-the-legal-agreements-required-to-purchase-the-specified-tld-and-add-ons
* content: Purchase and register the specified Domain
id: purchase-and-register-the-specified-domain
* content: >-
Retrieve the schema to be submitted when registering a Domain for the
specified TLD
id: >-
retrieve-the-schema-to-be-submitted-when-registering-a-domain-for-the-specified-tld
* content: >-
Validate the request body using the Domain Purchase Schema for the
specified TLD
id: >-
validate-the-request-body-using-the-domain-purchase-schema-for-the-specified-tld
* content: Retrieves a list of TLDs supported and enabled for sale
id: retrieves-a-list-of-tlds-supported-and-enabled-for-sale
* content: Renew the specified Domain
id: renew-the-specified-domain
contents:
* content: >-
Returns the TLD-specific legal agreements that must be accepted before
purchase or transfer. The agreementKeys from this response are
required in the consent object.
heading: >-
retrieve-the-legal-agreements-required-to-purchase-the-specified-tld-and-add-ons
* content: >-
Registers the specified domain. Requires a consent object with
agreement keys from GET /v1/domains/agreements. Charges the account's
billing method.
heading: purchase-and-register-the-specified-domain
* content: >-
Returns the JSON schema for the domain purchase request body for the
specified TLD. Fetch before purchasing to identify required fields and
TLD-specific constraints.
heading: >-
retrieve-the-schema-to-be-submitted-when-registering-a-domain-for-the-specified-tld
* content: >-
Validates a purchase request body against the TLD schema with no side
effects and no charge. Returns 200 on success.
heading: >-
validate-the-request-body-using-the-domain-purchase-schema-for-the-specified-tld
* content: >-
Returns all TLDs currently available for registration, including
pricing and any eligibility requirements.
heading: retrieves-a-list-of-tlds-supported-and-enabled-for-sale
* content: >-
Renews the domain for the specified period, extending the expiration
date. Charges the account's billing method.
heading: renew-the-specified-domain
***
# Transfer Domains (https://developer.godaddy.com/en/docs/references/rest/domains/v1/transfer-domains)
***
title: Transfer Domains
full: true
\_openapi:
method: POST
toc:
* depth: 2
title: Purchase and start or restart transfer process
url: '#purchase-and-start-or-restart-transfer-process'
structuredData:
headings:
* content: Purchase and start or restart transfer process
id: purchase-and-start-or-restart-transfer-process
contents:
* content: >-
Initiates an inbound domain transfer from another registrar. Requires
an authcode and a consent object with agreement keys. Charges a
transfer fee.
heading: purchase-and-start-or-restart-transfer-process
***
# Domain Actions (https://developer.godaddy.com/en/docs/references/rest/domains/v2/domain-actions)
***
title: Domain Actions
description: >-
Poll the status and cancel asynchronous operations queued by domain write
requests.
full: true
\_openapi:
toc: \[]
structuredData:
headings: \[]
contents:
* content: >-
Returns a paginated list of recent actions for the domain. Use to
track long-running operations or audit domain history.
* content: >-
Returns the most recent action of the specified type including status,
timestamps, and any error details.
* content: >-
Cancels the most recent user-initiated action if it is still in a
cancellable state. Returns 202 Accepted.
***
# Domain Notifications (https://developer.godaddy.com/en/docs/references/rest/domains/v2/domain-notifications)
***
title: Domain Notifications
description: >-
Manage notification opt-in preferences, retrieve notification schemas, and
acknowledge domain lifecycle notifications.
full: true
\_openapi:
toc: \[]
structuredData:
headings: \[]
contents:
* content: >-
Returns the next unacknowledged domain notification. Returns 200 with
a Notification body, or 204 if no notifications are pending.
* content: >-
Returns the notification types the account is currently opted in to
receive.
* content: >-
Opts the account in to receiving the specified notification types.
Returns 204 No Content.
* content: >-
Returns the JSON schema for a specific notification type's data
payload. Use to validate or parse notification data before processing.
* content: >-
Acknowledges a domain notification, removing it from the notification
queue. Returns 204 No Content.
***
# Domains API Usage (https://developer.godaddy.com/en/docs/references/rest/domains/v2/domains-api-usage)
***
title: Domains API Usage
description: >-
Retrieve monthly API request usage counts for your account. Data is retained
for three months.
full: true
\_openapi:
method: GET
toc: \[]
structuredData:
headings: \[]
contents:
* content: >-
Returns monthly API request counts for the account. Data is retained
for three months.
***
# Domains v2 (https://developer.godaddy.com/en/docs/references/rest/domains/v2)
***
title: Domains v2
description: Domains v2 — v1 capabilities plus async operation tracking. Action queues, status polling, notifications, forwarding, and registration under /v2/customers//domains.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
## Overview
The `v2` namespace extends the Domains API with async operation tracking — action queues, status polling, and lifecycle notifications. Operation paths follow `/v2/customers/{customerId}/domains/...`.
Use `v2` when you need to track long-running writes (transfers, redemptions) that return `202 Accepted` instead of completing synchronously. For a task-shaped guide layered on top of these endpoints, see [Use the API → Domains](https://developer.godaddy.com/docs/api-users/manage-domains).
The complete OpenAPI spec for the v2 namespace is available at [/openapi/domains-v2.json](https://developer.godaddy.com/openapi/domains-v2.json) — useful for code generation, SDK tooling, and LLM context.
## Operation groups
The v2 namespace is organized into seven operation groups, each rendered on its own reference page below.
## Authentication and scopes
Every v2 operation requires an `Authorization` header carrying a Personal Access Token (Bearer) or a legacy `sso-key` credential. The principal must additionally be authorized for the customer named in the URL. PATs use the granular Domains & DNS scopes listed in [Authentication](https://developer.godaddy.com/docs/api-users/auth), such as `domains.domain:read`, `domains.domain:update`, and `domains.transfer:execute`.
## v2-only capabilities
Some operations have no v1 equivalent and must be reached through `v2`:
* **Domain forwarding** (HTTP redirects on a domain).
* **Notification subscriptions** (lifecycle events delivered to a callback or pulled on demand).
* **Customer-scoped change-of-registrant** (managed across customer boundaries).
## Conventions
| Concern | Where it's documented |
| ---------------------------------------------------- | -------------------------------------------------------------------- |
| Error envelope and retry semantics | [Errors](https://developer.godaddy.com/docs/api-users/errors) |
| Rate limits (60 requests/minute per credential) | [Rate limits](https://developer.godaddy.com/docs/api-users/rate-limits) |
| Asynchronous-write polling via the `Action` resource | [Actions reference](https://developer.godaddy.com/docs/references/rest/domains/v2/domain-actions) |
# Manage Domain Settings (https://developer.godaddy.com/en/docs/references/rest/domains/v2/manage-domain-settings)
***
title: Manage Domain Settings
description: >-
Retrieve domain details and manage nameservers, forwarding rules, and privacy
forwarding.
full: true
\_openapi:
toc:
* depth: 2
title: Retrieve the forwarding information for the given fqdn
url: '#retrieve-the-forwarding-information-for-the-given-fqdn'
* depth: 2
title: Create a new forwarding configuration for the given FQDN
url: '#create-a-new-forwarding-configuration-for-the-given-fqdn'
* depth: 2
title: Submit a forwarding cancellation request for the given fqdn
url: '#submit-a-forwarding-cancellation-request-for-the-given-fqdn'
* depth: 2
title: Modify the forwarding information for the given fqdn
url: '#modify-the-forwarding-information-for-the-given-fqdn'
structuredData:
headings:
* content: Retrieve the forwarding information for the given fqdn
id: retrieve-the-forwarding-information-for-the-given-fqdn
* content: Create a new forwarding configuration for the given FQDN
id: create-a-new-forwarding-configuration-for-the-given-fqdn
* content: Submit a forwarding cancellation request for the given fqdn
id: submit-a-forwarding-cancellation-request-for-the-given-fqdn
* content: Modify the forwarding information for the given fqdn
id: modify-the-forwarding-information-for-the-given-fqdn
contents:
* content: >-
Returns the full DomainDetailV2 object including status, contacts,
nameservers, lock state, privacy flag, and expiration timestamp.
* content: >-
Replaces the domain's authoritative nameservers. Returns 202 - poll
GET .../actions/DOMAIN\_UPDATE\_NAME\_SERVERS until the action reaches a
terminal state.
* content: >-
Returns current change of registrant details including status,
requested contacts, and any pending approvals.
* content: >-
Cancels a pending change of registrant. Returns 202 - poll GET
.../actions/CHANGE\_OF\_REGISTRANT\_DELETE until COMPLETED, FAILED, or
CANCELLED.
* content: >-
Returns the current privacy email forwarding configuration including
target address and forwarding mode.
* content: >-
Updates privacy email forwarding settings. Only fields included in the
request are modified. Returns 202 - poll the actions endpoint for
completion.
* content: >-
Returns the forwarding configuration for the FQDN including
destination URL and redirect type. Returns 404 if no forwarding rule
exists.
heading: retrieve-the-forwarding-information-for-the-given-fqdn
* content: >-
Creates or replaces the forwarding configuration for the FQDN.
Idempotent - replaying the same request produces the same rule.
Returns 204 No Content.
heading: create-a-new-forwarding-configuration-for-the-given-fqdn
* content: >-
Removes the forwarding configuration for the FQDN. Returns 204 No
Content.
heading: submit-a-forwarding-cancellation-request-for-the-given-fqdn
* content: >-
Updates the forwarding configuration for the FQDN. Only fields
included in the request are modified. Returns 204 No Content.
heading: modify-the-forwarding-information-for-the-given-fqdn
***
# Register Domains (https://developer.godaddy.com/en/docs/references/rest/domains/v2/register-domains)
***
title: Register Domains
description: >-
Register new domains, retrieve registration schemas by TLD, and validate
registration requests.
full: true
\_openapi:
toc: \[]
structuredData:
headings: \[]
contents:
* content: >-
Registers the specified domain. Requires a consent object with TLD
agreement keys from the schema endpoint. Charges the account's billing
method. Returns 202 - poll GET .../actions/REGISTER until the action
reaches a terminal state.
* content: >-
Returns the JSON schema for the registration request body for the
specified TLD. Fetch before registering to identify required fields
and TLD-specific constraints.
* content: >-
Validates the registration request body against the TLD schema with no
side effects and no charge. Returns 204 on success.
***
# Transfer Domains (https://developer.godaddy.com/en/docs/references/rest/domains/v2/transfer-domains)
***
title: Transfer Domains
description: >-
Initiate and manage inbound and outbound domain transfers and transfer
lifecycle actions.
full: true
\_openapi:
toc: \[]
structuredData:
headings: \[]
contents:
* content: >-
Initiates an inbound domain transfer from another registrar. Requires
an authcode and consent object. Returns 202 - poll GET
.../actions/TRANSFER until COMPLETED, FAILED, or CANCELLED.
* content: >-
Explicitly accepts an in-progress inbound transfer to expedite the
process. Returns 202 - poll GET .../actions/TRANSFER\_IN\_ACCEPT until
the action reaches a terminal state.
* content: >-
Cancels an in-progress inbound transfer. Returns 202 - poll GET
.../actions/TRANSFER\_IN\_CANCEL until the action reaches a terminal
state.
* content: >-
Restarts a stalled inbound transfer from the beginning. Returns 202 -
poll GET .../actions/TRANSFER\_IN\_RESTART until the action reaches a
terminal state.
* content: >-
Retries a failed inbound transfer with a new authorization code.
Returns 202 - poll GET .../actions/TRANSFER\_IN\_RETRY until the action
reaches a terminal state.
* content: >-
Initiates an outbound transfer for .uk domains. Returns 202 - poll the
actions endpoint for completion.
* content: >-
Accepts a pending outbound transfer request. Returns 202 - poll GET
.../actions/TRANSFER\_OUT\_ACCEPT until the action reaches a terminal
state.
* content: >-
Rejects a pending outbound transfer request, keeping the domain at
GoDaddy. Returns 202 - poll GET .../actions/TRANSFER\_OUT\_REJECT until
the action reaches a terminal state.
***
# Discovery (https://developer.godaddy.com/en/docs/references/rest/domains/v3/discovery)
***
title: Discovery
description: >
Indicative, non-committing operations for finding and checking domains. Use
suggestDomains for natural-language queries and getDomainAvailability for
specific domain verification. Both return indicative pricing; locked pricing
is established only at quote time. The check-availability controller carries
no persistent identity.
full: true
\_openapi:
toc:
* depth: 2
title: Suggest available domains for a query
url: '#suggest-available-domains-for-a-query'
* depth: 2
title: Check availability of a single domain
url: '#check-availability-of-a-single-domain'
structuredData:
headings:
* content: Suggest available domains for a query
id: suggest-available-domains-for-a-query
* content: Check availability of a single domain
id: check-availability-of-a-single-domain
contents:
* content: |
Returns available domain name suggestions for a natural-language query
or keyword set. All results are available (available-only contract).
Prices are indicative; the authoritative price and availability check
is at quote time.
heading: suggest-available-domains-for-a-query
* content: >
Returns an indicative availability result for one domain, including
per-term pricing when available. Availability is best-effort; the
authoritative check is performed at quote time. This operation does
not persist the check — there is no check identity or poll URL.
A domain that cannot be checked is still returned as a `200` with an
`error` object on the body; request-level failures use the `4xx`
responses.
heading: check-availability-of-a-single-domain
***
# Domain Management (https://developer.godaddy.com/en/docs/references/rest/domains/v3/domain-management)
***
title: Domain Management
description: >
Non-commercial async mutations on owned domain instances: contacts,
nameservers, privacy, auto-renew, and transfer-lock. All sub-resources of
/domain-names/. All mutations return a DomainOperation for
polling.
full: true
\_openapi:
method: PUT
toc:
* depth: 2
title: Replace the nameservers for a domain
url: '#replace-the-nameservers-for-a-domain'
structuredData:
headings:
* content: Replace the nameservers for a domain
id: replace-the-nameservers-for-a-domain
contents:
* content: >
Replaces the authoritative nameservers for the domain with the
provided list. Minimum 2, maximum 13. Returns a DomainOperation;
propagation to the registry is asynchronous.
heading: replace-the-nameservers-for-a-domain
***
# Domains (https://developer.godaddy.com/en/docs/references/rest/domains/v3/domains)
***
title: Domains
description: >
The core domain entity collection. Supports listing and reading owned domain
records, and cancelling registrations.
full: true
\_openapi:
method: GET
toc:
* depth: 2
title: Get a registered domain
url: '#get-a-registered-domain'
structuredData:
headings:
* content: Get a registered domain
id: get-a-registered-domain
contents:
* content: >
Returns the management view of a single registered domain owned by the
authenticated account, including status, nameservers, privacy and
auto-renew preferences, and expiry date.
heading: get-a-registered-domain
***
# Overview (https://developer.godaddy.com/en/docs/references/rest/domains/v3)
***
title: Overview
description: >
Reference for the Domains v3 API — a quote-execute model for domain discovery,
registration, and management.
-----------------------------
## Overview
Domains v3 introduces a **quote-execute** model built for clarity and pricing predictability:
1. **Discover** — check availability and get suggestions
2. **Quote** — lock in a price with a `quoteToken`
3. **Register** — execute the registration using that token
4. **Poll** — follow the async operation to completion
All write operations return `202 Accepted` with an operation or registration ID. Poll the returned URL until status reaches `COMPLETED` or `FAILED`.
v3.1 covers domain discovery, registration, domain reads, nameserver management, and DNS records. Renewals, transfers, contact updates, forwarding, and privacy settings remain on the [v1 API](https://developer.godaddy.com/docs/references/rest/domains/v1) and [v2 API](https://developer.godaddy.com/docs/references/rest/domains/v2).
## Endpoint groups
## Quote-execute flow
```
GET /v3/domains/check-availability?domain={domain}
→ availability result (indicative price)
POST /v3/domains/registration-quotes
→ quoteToken (locked price, short TTL)
POST /v3/domains/registrations
(body: quoteToken + domain + period + consent)
→ 202 Accepted, Registration entity with poll URL
GET /v3/domains/registrations/{registrationId}
or
GET /v3/domains/operations/{operationId}
→ poll until status = COMPLETED | FAILED
```
## Conventions
| Convention | Detail |
| -------------------- | ---------------------------------------------------------------------------- |
| Base URL | `https://api.godaddy.com` |
| Version prefix | `/v3/` |
| Async writes | `202 Accepted` with `links[rel=self]` poll URL |
| Idempotency | `Idempotency-Key` header required on registration |
| Indicative vs locked | Availability and suggestions return indicative prices; quotes lock the price |
| Auth | `Authorization: Bearer ${GODADDY_PAT}` |
## What v3 does not cover
The following operations are not yet in v3. Use v1 or v2 instead:
| Operation | Use instead |
| ------------------------- | ---------------------------------------------- |
| Domain renewals | [Domains v1](https://developer.godaddy.com/docs/references/rest/domains/v1) |
| Domain transfers | [Domains v1](https://developer.godaddy.com/docs/references/rest/domains/v1) |
| Contact updates | [Domains v1](https://developer.godaddy.com/docs/references/rest/domains/v1) |
| Domain forwarding | [Domains v1](https://developer.godaddy.com/docs/references/rest/domains/v1) |
| Privacy settings | [Domains v1](https://developer.godaddy.com/docs/references/rest/domains/v1) |
| List owned domains | [Domains v1](https://developer.godaddy.com/docs/references/rest/domains/v1) |
| Shopper-scoped operations | [Domains v2](https://developer.godaddy.com/docs/references/rest/domains/v2) |
# Operations (https://developer.godaddy.com/en/docs/references/rest/domains/v3/operations)
***
title: Operations
description: >
Abstract operation polling. Poll GET /operations/ for any domain
mutation until it reaches COMPLETED or FAILED. Operation IDs are unique across
Registration, Renewal, and Transfer — clients that prefer typed polling can
use the concrete resource endpoints instead.
full: true
\_openapi:
method: GET
toc:
* depth: 2
title: Poll an async domain operation
url: '#poll-an-async-domain-operation'
structuredData:
headings:
* content: Poll an async domain operation
id: poll-an-async-domain-operation
contents:
* content: >
Universal poll endpoint for all asynchronous domain mutations. Returns
the current state of the operation. Non-terminal responses include a
`Retry-After` header.
Terminal statuses:
* `COMPLETED` — operation succeeded; `result` contains the final
outcome.
* `FAILED` — operation terminated with an error; `error` contains
detail.
While status is non-terminal (`CONFIRMED`, `EXECUTING`), neither
`result` nor `error` is present. Poll until a terminal status is
reached.
The poll URL is provided in the `Location` header of the initiating
202
response and in `links[rel=self]`. Clients must not construct this URL
independently.
heading: poll-an-async-domain-operation
***
# Records (https://developer.godaddy.com/en/docs/references/rest/domains/v3/records)
***
title: Records
description: >
CRUD operations on DNS records within the GoDaddy-managed zone. Sub-collection
of /zones/. Changes are applied synchronously.
full: true
\_openapi:
toc:
* depth: 2
title: List DNS records in a zone
url: '#list-dns-records-in-a-zone'
* depth: 2
title: Create a DNS record for a zone
url: '#create-a-dns-record-for-a-zone'
* depth: 2
title: Delete a DNS record
url: '#delete-a-dns-record'
structuredData:
headings:
* content: List DNS records in a zone
id: list-dns-records-in-a-zone
* content: Create a DNS record for a zone
id: create-a-dns-record-for-a-zone
* content: Delete a DNS record
id: delete-a-dns-record
contents:
* content: |
Returns a paginated collection of DNS resource records for the
specified zone. Supports filtering by record type and host name,
field projection, and page-based pagination.
Pagination uses page (1-based) and pageSize query parameters.
Pass totalRequired=true to include totalItems and totalPages when
at least one record matches; both are omitted for empty result
sets. Defaults to false to avoid count-query overhead.
Filter parameters are combined with logical AND. Pagination links
in the response preserve active filter, pagination, and
field-projection parameters.
sortBy and sortOrder are not supported. Results are always
returned in canonical zone-file order: resource record type (IANA
RR type number ascending — e.g. A before NS before CNAME), then
name, then data. This matches authoritative DNS ordering and is
not client-configurable.
heading: list-dns-records-in-a-zone
* content: >
Creates a new DNS record in the GoDaddy-managed zone. Changes are
applied synchronously; no operation polling required.
heading: create-a-dns-record-for-a-zone
* content: |
Permanently removes a DNS resource record from the zone. The
recordId must refer to an existing record within the specified
zone. Changes are applied synchronously.
GoDaddy-managed system records (SOA and NS) are read-only. When
recordId refers to such a record, the request fails with
`409 Conflict` — the record exists but cannot be deleted.
heading: delete-a-dns-record
***
# Registration Quotes (https://developer.godaddy.com/en/docs/references/rest/domains/v3/registration-quotes)
***
title: Registration Quotes
description: >
Quote a domain registration. Returns a locked price, resolved settings,
required agreements, and a single-use quoteToken. Free and read-only.
full: true
\_openapi:
method: POST
toc:
* depth: 2
title: Quote a single-domain registration (no commitment)
url: '#quote-a-single-domain-registration-no-commitment'
structuredData:
headings:
* content: Quote a single-domain registration (no commitment)
id: quote-a-single-domain-registration-no-commitment
contents:
* content: >
Prices the registration, resolves contact and preference settings,
returns required legal agreements, and mints a single-use quoteToken
with a 10-minute TTL. Free and read-only; safe to call speculatively.
When the domain is unavailable, `available: false` is returned with
no quoteToken — this is a valid non-error response.
When required contact fields are missing, a `422` is returned with
field-level details so the agent can collect the missing data and
re-quote.
May pass `iscCode` to lock pricing at applicable rates;
the same value must be supplied on /registrations if provided here.
heading: quote-a-single-domain-registration-no-commitment
***
# Registrations (https://developer.godaddy.com/en/docs/references/rest/domains/v3/registrations)
***
title: Registrations
description: >
Top-level registration entity collection. Execute a domain registration by
POSTing with a quoteToken, domain, period, and consent. Returns a Registration
entity with links to the concrete poll URL (GET
/registrations/) and the abstract operation (GET
/operations/).
full: true
\_openapi:
toc:
* depth: 2
title: Register a domain (requires quoteToken)
url: '#register-a-domain-requires-quotetoken'
* depth: 2
title: Get a registration record
url: '#get-a-registration-record'
structuredData:
headings:
* content: Register a domain (requires quoteToken)
id: register-a-domain-requires-quotetoken
* content: Get a registration record
id: get-a-registration-record
contents:
* content: >
Executes a previously quoted domain registration. \*\*Irreversible once
accepted; creates a charge.\*\* Requires a valid unexpired quoteToken
from
`quoteDomainRegistration`, an `Idempotency-Key` header, and a consent
record. The target domain and period are in the request body alongside
the quoteToken.
Before calling this endpoint, retrieve `requiredAgreements` from the
quote response and review each agreement before submitting the
registration. Each agreement
includes a `title` (display label) and optional `url` (full legal
text).
The `consent.agreementTypes` array must contain the `agreementType`
value
from every item in `requiredAgreements`; a mismatch returns
`INVALID_AGREEMENT_KEYS`.
Idempotency takes precedence over the single-use check: retrying with
the same `Idempotency-Key` replays the original operation even after
the token is consumed.
Returns a `Registration` entity. Poll `links[rel=self]`
(`GET /registrations/{registrationId}`) until status is `COMPLETED` or
`FAILED`. The `operationId` field is also provided for clients that
prefer `GET /operations/{operationId}`; both resolve the same
resource.
Poll either until status is `COMPLETED` or `FAILED`. The operation is
fire-and-forget; always poll at least once even if the server
completed
it synchronously.
When `iscCode` was supplied at quote time, the same value must be
provided here or the request fails with `quote_mismatch`.
heading: register-a-domain-requires-quotetoken
* content: >
Returns a single registration record by its server-assigned
registrationId, including the current execution status and the domain
expiry date once the registration completes. This is the concrete poll
endpoint for registration operations; the abstract equivalent is GET
/operations/.
heading: get-a-registration-record
***