Skip to main content

godaddy

Domain registration, domain lifecycle management and DNS from GoDaddy, through the GoDaddy Domains APIs (v1, v2 and v3) on the GoDaddy Developer Platform.

Provider Summary

total services: 4
total resources: 32

See also: [SHOW] [DESCRIBE] [REGISTRY]


Installation

To pull the latest version of the godaddy provider, run the following command:

REGISTRY PULL godaddy;

To view previous provider versions or to pull a specific provider version, see here.

Authentication

The provider authenticates with a GoDaddy Personal Access Token (PAT), sent as a bearer token. Create one on the GoDaddy Developer Platform with the scopes the queries need (domains.domain:read for inventory queries, domains.dns:update for DNS changes, domains.domain:update and domains.nameserver:update for domain settings, domains.domain:create for registration), then export it:

  • GODADDY_API_KEY - the Personal Access Token
export GODADDY_API_KEY='gd_...'

or using PowerShell:

$env:GODADDY_API_KEY = 'gd_...'

This variable is sourced at runtime (from the local machine or as a CI variable/secret).

Classic Developer Key (sso-key)

GoDaddy is retiring the classic key/secret credential (it is deprecated for the Domains APIs and does not work with the Domains v3 API). Where a classic key is still in use, put the pair in a single variable as key:secret and pass an api_key auth context with the sso-key prefix using the --auth flag of the stackql program:

export GODADDY_SSO_KEY='<key>:<secret>'
AUTH='{ "godaddy": { "type": "api_key", "valuePrefix": "sso-key ", "credentialsenvvar": "GODADDY_SSO_KEY" }}'
stackql shell --auth="${AUTH}"

or using PowerShell:

$env:GODADDY_SSO_KEY = '<key>:<secret>'
$Auth = "{ 'godaddy': { 'type': 'api_key', 'valuePrefix': 'sso-key ', 'credentialsenvvar': 'GODADDY_SSO_KEY' }}"
stackql.exe shell --auth=$Auth

Resources with the _v3 suffix reject the classic key.

API versions and resource naming

GoDaddy publishes three Domains APIs, and this provider exposes all of them side by side. The resource name tells you which one you are using:

Resource nameAPINotes
bare (domains, records, agreements, ...)Domains v1The original API: full domain detail with contacts, DNS records by type and name, purchase and renewal. Collections are complete (the domain list is paged with a marker cursor automatically).
_v2 suffix (domains_v2, actions_v2, forwards_v2, ...)Domains v2Customer-scoped and asynchronous: registrant changes, privacy forwarding, pending actions, notifications, forwarding rules, the transfer workflow. Every method takes a customer_id (see below).
_v3 suffix (domains_v3, records_v3, registrations_v3, ...)Domains v3The newest API (PAT only): record-id based DNS management, the quote-then-register model, HATEOAS pagination followed automatically, asynchronous operations polled through godaddy.domains.operations_v3.

Customer scope (Domains v2)

The Domains v2 resources address a customer by its UUID (not the numeric shopper number). The customer identifier is a server variable resolved from the GODADDY_CUSTOMER_ID environment variable when it is set, so queries need no WHERE customer_id clause:

export GODADDY_CUSTOMER_ID='<customer-uuid>'
SELECT type, origination, status, created_at
FROM godaddy.domains.actions_v2
WHERE domain = 'example.com';

A WHERE customer_id = '...' value always takes precedence over the environment, which is how a reseller acts on a subaccount. With the variable unset, customer_id is a required parameter on every _v2 method and SHOW METHODS lists it.

Parameter and column casing

Columns and parameters are snake_case at the SQL surface over GoDaddy's camelCase wire names: name_servers, renew_auto, record_id, page_size. Request body fields follow the same rule, so INSERT columns and UPDATE assignments use snake_case too. Nested JSON values (contacts, prices, links) keep the wire casing inside the blob and are addressed with json_extract.

Two v1 query parameters are SQL keywords. Quote them in a WHERE clause, or use LIMIT, which is pushed down to the API's page-size parameter on the list reads:

SELECT domain, status FROM godaddy.domains.domains LIMIT 10;
SELECT domain FROM godaddy.registration.suggestions WHERE query = 'stackql' LIMIT 5;

Rate limit

The Domains API allows 60 requests per minute per credential and answers 429 Too Many Requests with a Retry-After header beyond that. Wide queries that fan out across many domains (DNS records for every domain, for example) should be sequenced rather than issued in parallel sessions.

Domain inventory

Every domain in the account with its lifecycle status and expiry, across all statuses:

SELECT domain, status, expires, renew_auto, locked, privacy
FROM godaddy.domains.domains
ORDER BY expires;

Only active domains, filtered server-side (statuses and status_groups are pushed down as query parameters):

SELECT domain, expires, name_servers
FROM godaddy.domains.domains
WHERE statuses = 'ACTIVE';

Domains expiring within 90 days:

SELECT domain, expires, renew_auto
FROM godaddy.domains.domains
WHERE statuses = 'ACTIVE'
AND expires < datetime('now', '+90 days')
ORDER BY expires;

The same inventory through the v3 API, with lifecycle group filtering and cursor pagination handled for you:

SELECT domain, status, expires_at, renew_by, auto_renew, transfer_lock
FROM godaddy.domains.domains_v3
WHERE statuses = 'ACTIVE,EXPIRED';

Domain detail and registrant contacts

SELECT domain, status, created_at, expires,
json_extract(contact_registrant, '$.nameFirst') AS registrant_first_name,
json_extract(contact_registrant, '$.nameLast') AS registrant_last_name,
json_extract(contact_registrant, '$.email') AS registrant_email,
json_extract(contact_registrant, '$.organization') AS registrant_org
FROM godaddy.domains.domains
WHERE domain = 'example.com';

Nameserver audit

Domains whose nameservers are not GoDaddy's, with the delegation:

SELECT domain, name_servers
FROM godaddy.domains.domains
WHERE statuses = 'ACTIVE'
AND name_servers NOT LIKE '%domaincontrol.com%';

DNS records

All records in a zone (v3, record ids included, paged automatically):

SELECT record_id, name, type, data, ttl, priority
FROM godaddy.dns.records_v3
WHERE zone = 'example.com';

Records of one type, filtered server-side:

SELECT name, data, ttl
FROM godaddy.dns.records_v3
WHERE zone = 'example.com' AND type = 'TXT';

The v1 read by type and name:

SELECT name, type, data, ttl
FROM godaddy.dns.records
WHERE domain = 'example.com' AND type = 'A' AND name = '@';

Availability and pricing

SELECT domain, available, definitive, price, currency, period
FROM godaddy.registration.availability
WHERE domain = 'my-next-domain.com';

Price terms through the v3 API (prices is a JSON array of term prices):

SELECT domain, available, inventory,
json_extract(prices, '$[0].price.value') AS first_year_cents,
json_extract(prices, '$[0].renewalPrice.value') AS renewal_cents
FROM godaddy.registration.availability_v3
WHERE domain = 'my-next-domain.com';

Name suggestions:

SELECT domain FROM godaddy.registration.suggestions
WHERE query = 'stackql' AND tlds = 'com,io' LIMIT 10;

Provision, mutate and tear down

Mutations use the same SQL grammar: INSERT creates a resource, UPDATE patches it, EXEC invokes lifecycle methods and DELETE removes it. A DNS record end to end (v3):

-- create
INSERT INTO godaddy.dns.records_v3 (zone, name, type, data, ttl)
SELECT 'example.com', 'app', 'A', '203.0.113.10', 3600;

-- find the record id
SELECT record_id FROM godaddy.dns.records_v3
WHERE zone = 'example.com' AND type = 'A' AND name = 'app';

-- replace it (PUT: the full record is required)
UPDATE godaddy.dns.records_v3
SET name = 'app', type = 'A', data = '203.0.113.11', ttl = 600
WHERE zone = 'example.com' AND record_id = '<record-id>';

-- remove it
DELETE FROM godaddy.dns.records_v3
WHERE zone = 'example.com' AND record_id = '<record-id>';

Bulk record writes through the v1 API take the record array as the records attribute:

EXEC godaddy.dns.records.add
@domain = 'example.com',
@records = '[{"type": "TXT", "name": "_verify", "data": "token", "ttl": 600}]';

EXEC godaddy.dns.records.replace_by_type_name
@domain = 'example.com', @type = 'A', @name = 'app',
@records = '[{"data": "203.0.113.12", "ttl": 600}]';

Domain settings:

-- auto-renew and transfer lock
UPDATE godaddy.domains.domains
SET renew_auto = 'true', locked = 'true'
WHERE domain = 'example.com';

-- nameservers through the v3 API (asynchronous - poll the returned operation)
EXEC godaddy.domains.domains_v3.update_nameservers
@domain_name = 'example.com',
@idempotency_key = '2f1e0c4e-0d5b-4c6a-9d1e-1c2b3a4d5e6f',
@name_servers = '["ns1.example.net", "ns2.example.net"]';

SELECT operation_id, type, status, result
FROM godaddy.domains.operations_v3
WHERE operation_id = '<operation-id>';

Registration through the v3 quote-then-register model (INSERT returns the quote and registration objects; both are billable operations):

INSERT INTO godaddy.registration.registration_quotes_v3 (domain, period)
SELECT 'my-next-domain.com', 1;

INSERT INTO godaddy.registration.registrations_v3 (quote_token, consent, idempotency_key)
SELECT '<quote-token>', '{"agreementKeys": ["DNRA"], "agreedAt": "2026-09-16T00:00:00Z", "agreedBy": "203.0.113.5"}', '<uuid>';

Renewal (v1, billable) and the registrant email verification are lifecycle methods on the domain:

EXEC godaddy.domains.domains.renew @domain = 'example.com', @period = 1;
EXEC godaddy.domains.domains.verify_registrant_email @domain = 'example.com';

Services