# End-to-end workflow (https://developer.godaddy.com/en/docs/api-users/full-workflow)



<Callout type="info" title="What you'll build">
  A complete end-to-end workflow: search for an available domain, lock a price with a quote, register it (with idempotency for retry safety), add a DNS record, and verify. Every step is copy-paste runnable in curl, Node, Python, or Go.
</Callout>

## Overview

<Mermaid
  chart="
sequenceDiagram
participant You
participant API as api.godaddy.com

You->>API: 1. GET /v3/domains/check-availability?domain=example.com
API-->>You: { available: true, prices: [...] }
You->>API: 2. POST /v3/domains/registration-quotes
API-->>You: { quoteToken: 'qt_...', expiresAt: '...' }
You->>API: 3. POST /v3/domains/registrations (Idempotency-Key: uuid)
API-->>You: 201 { orderId, domain }
You->>API: 4. POST /v3/domains/zones/example.com/dns-records
API-->>You: 201 { recordId, ... }
You->>API: 5. GET /v3/domains/zones/example.com/dns-records
API-->>You: { items: [...] } (verify)
"
/>

**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="<YOUR_TOKEN>"
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.

<Tabs items={['curl', 'Node', 'Python', 'Go']}>
  <>
    <Tab value="curl">
      ```bash
      curl -s "$BASE/v3/domains/check-availability?domain=example.com" \
        -H "Authorization: Bearer $GODADDY_PAT"
      ```
    </Tab>

    <Tab value="Node">
      ```js
      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);
      ```
    </Tab>

    <Tab value="Python">
      ```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']}")
      ```
    </Tab>

    <Tab value="Go">
      ```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)
      }
      ```
    </Tab>
  </>
</Tabs>

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.

<Tabs items={['curl', 'Node', 'Python', 'Go']}>
  <>
    <Tab value="curl">
      ```bash
      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}'
      ```
    </Tab>

    <Tab value="Node">
      ```js
      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);
      ```
    </Tab>

    <Tab value="Python">
      ```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"])
      ```
    </Tab>

    <Tab value="Go">
      ```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(&quote)
      fmt.Println("Quote locked until", quote.ExpiresAt)
      ```
    </Tab>
  </>
</Tabs>

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

<Callout type="warning" title="Charges real money">
  This call charges the account's payment profile. Verify the domain name and quoted price before executing.
</Callout>

<Tabs items={['curl', 'Node', 'Python', 'Go']}>
  <>
    <Tab value="curl">
      ```bash
      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"]
          }
        }'
      ```
    </Tab>

    <Tab value="Node">
      ```js
      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);
      ```
    </Tab>

    <Tab value="Python">
      ```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"])
      ```
    </Tab>

    <Tab value="Go">
      ```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)) }
      ```
    </Tab>
  </>
</Tabs>

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.

<Tabs items={['curl', 'Node', 'Python', 'Go']}>
  <>
    <Tab value="curl">
      ```bash
      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}'
      ```
    </Tab>

    <Tab value="Node">
      ```js
      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);
      ```
    </Tab>

    <Tab value="Python">
      ```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"])
      ```
    </Tab>

    <Tab value="Go">
      ```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()
      ```
    </Tab>
  </>
</Tabs>

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