# 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 ***