Skill: solarx56/godaddy-api (version 1.1.0)

--- name: godaddy description: Complete GoDaddy API skill with shell scripts + MCP server for domains, DNS, certificates, shoppers, subscriptions, agreements, countries, and aftermarket listings. homepage: https://developer.godaddy.com/doc metadata: {"openclaw": {"emoji": "🌐", "requires": {"bins": ["bash", "curl", "jq", "node", "npm"]}}} --- # GoDaddy API ## Setup ```bash export GODADDY_API_BASE_URL="https://api.godaddy.com" # or https://api.ote-godaddy.com export GODADDY_API_KEY="your-key" export GODADDY_API_SECRET="your-secret" ``` Keys: <https://developer.godaddy.com/keys> ## Shell scripts - `scripts/gd-domains.sh` — list/get/availability, validate purchase, purchase, renew, transfer, update, update contacts, delete, privacy on/off, domain agreements get/accept - `scripts/gd-dns.sh` — get all/type/name, patch add, replace all/type/type+name, delete type+name - `scripts/gd-certs.sh` — create/validate/get/actions/download/renew/reissue/revoke/verify domain control - `scripts/gd-shoppers.sh` — get/update/delete shopper - `scripts/gd-subscriptions.sh` — list/get/cancel subscription - `scripts/gd-agreements.sh` — list legal agreements - `scripts/gd-countries.sh` — list countries - `scripts/gd-aftermarket.sh` — list/get aftermarket listings Destructive/financial actions prompt for confirmation. ## MCP server Path: `scripts/mcp-server/` ```bash cd scripts/mcp-server npm install npm run build node dist/index.js ``` Exposes MCP tools for all skill operations (domains, DNS, certs, shoppers, subscriptions, agreements, countries, aftermarket). Example MCP config: ```json { "mcpServers": { "godaddy": { "command": "node", "args": ["path/to/mcp-server/dist/index.js"], "env": { "GODADDY_API_BASE_URL": "https://api.godaddy.com", "GODADDY_API_KEY": "", "GODADDY_API_SECRET": "" } } } } ``` ## References - `references/endpoints.md` — complete endpoint map - `references/auth-and-env.md` — auth/env setup - `references/request-bodies.md` — payload examples - `references/error-handling.md` — troubleshooting - `references/safety-playbook.md` — safe operation patterns

path: assets/payload-templates/certificate-create.json
content: {
  "type": "DV_SSL",
  "commonName": "example.com",
  "period": 1,
  "productId": "ssl123",
  "slotSize": "5",
  "contact": {
    "nameFirst": "John",
    "nameLast": "Doe",
    "email": "[REDACTED_SECRET]",
    "phone": "+1.5555551234",
    "addressMailing": {
      "address1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "postalCode": "12345",
      "country": "US"
    }
  }
}


path: assets/payload-templates/dns-records-replace.json
content: type: A
name: @
data: 192.0.2.1
ttl: 3600

type: A
name: www
data: 192.0.2.1
ttl: 3600

type: CNAME
name: blog
data: example.com
ttl: 3600

type: MX
name: @
data: mail.example.com
priority: 10
ttl: 3600

type: TXT
name: @
data: v=spf1 include:_spf.example.com ~all
ttl: 3600

type: TXT
name: _dmarc
data: v=DMARC1; p=quarantine; rua=mailto:[REDACTED_SECRET]
ttl: 3600

path: assets/payload-templates/purchase-domain.json
content: {
  "domain": "example.com",
  "privacy": true,
  "nameServers": [
    "ns01.domaincontrol.com",
    "ns02.domaincontrol.com"
  ],
  "consent": {
    "agreedBy": "192.0.2.1",
    "agreedAt": "2024-01-01T00:00:00Z",
    "agreementKeys": ["DNRA"]
  },
  "period": 1,
  "contactAdmin": {
    "nameFirst": "John",
    "nameLast": "Doe",
    "email": "[REDACTED_SECRET]",
    "phone": "+1.5555551234",
    "addressMailing": {
      "address1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "postalCode": "12345",
      "country": "US"
    }
  },
  "contactRegistrant": {
    "nameFirst": "John",
    "nameLast": "Doe",
    "email": "[REDACTED_SECRET]",
    "phone": "+1.5555551234",
    "addressMailing": {
      "address1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "postalCode": "12345",
      "country": "US"
    }
  },
  "contactBilling": {
    "nameFirst": "John",
    "nameLast": "Doe",
    "email": "[REDACTED_SECRET]",
    "phone": "+1.5555551234",
    "addressMailing": {
      "address1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "postalCode": "12345",
      "country": "US"
    }
  },
  "contactTech": {
    "nameFirst": "John",
    "nameLast": "Doe",
    "email": "[REDACTED_SECRET]",
    "phone": "+1.5555551234",
    "addressMailing": {
      "address1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "postalCode": "12345",
      "country": "US"
    }
  }
}


path: references/auth-and-env.md
content: # Authentication & Environment Setup

## Getting API Credentials

1. Go to <https://developer.godaddy.com/keys>
2. Create a new API key (choose "Production" or "OTE" for testing)
3. Save your **API Key** and **API Secret** securely

## Environment Variables

Set these in your shell:

```bash
# For production
export GODADDY_API_BASE_URL="https://api.godaddy.com"
export GODADDY_API_KEY="your-key-here"
export GODADDY_API_SECRET="your-secret-here"

# For OTE (test environment)
export GODADDY_API_BASE_URL="https://api.ote-godaddy.com"
export GODADDY_API_KEY="your-ote-key"
export GODADDY_API_SECRET="your-ote-secret"
```

Add to `~/.zshrc` or `~/.bashrc` for persistence:

```bash
echo 'export GODADDY_API_KEY="..."' >> ~/.zshrc
echo 'export GODADDY_API_SECRET="..."' >> ~/.zshrc
echo 'export GODADDY_API_BASE_URL="https://api.godaddy.com"' >> ~/.zshrc
source ~/.zshrc
```

## Authorization Header Format

All API calls use this header:

```
Authorization: sso-key <API_KEY>:<API_SECRET>
```

Example:
```
Authorization: sso-key dGVzdGtleToxMjM0:dGVzdHNlY3JldDo1Njc4
```

## Testing Authentication

Run a simple list domains call:

```bash
./scripts/gd-domains.sh list
```

If auth works, you'll see JSON output. If not, check:
- Environment variables are set correctly
- API key/secret are valid and not expired
- You're using the correct base URL (production vs OTE)


path: references/endpoints.md
content: # GoDaddy API Endpoints Reference

Base URLs:
- Production: `https://api.godaddy.com`
- OTE (test): `https://api.ote-godaddy.com`

## Domains

| Method | Endpoint | Description |
|---|---|---|
| GET | `/v1/domains` | List domains |
| GET | `/v1/domains/{domain}` | Get domain details |
| GET | `/v1/domains/available?domain={domain}&checkType={FAST\|FULL}&forTransfer={bool}` | Check single availability/transfer |
| POST | `/v1/domains/available?checkType={FAST\|FULL}` | Bulk availability (body: `string[]`) |
| POST | `/v1/domains/purchase/validate` | Validate purchase payload |
| POST | `/v1/domains/purchase` | Purchase domain |
| POST | `/v1/domains/{domain}/renew` | Renew domain |
| POST | `/v1/domains/{domain}/transfer` | Transfer domain in |
| PATCH | `/v1/domains/{domain}` | Update domain settings |
| PATCH | `/v1/domains/{domain}/contacts` | Update domain contacts |
| DELETE | `/v1/domains/{domain}` | Cancel/delete domain |
| PUT | `/v1/domains/{domain}/privacy` | Enable privacy |
| DELETE | `/v1/domains/{domain}/privacy` | Disable privacy |
| GET | `/v1/domains/agreements` | Get domain purchase/transfer agreements |
| POST | `/v1/domains/agreements` | Accept domain agreements |

## DNS

| Method | Endpoint | Description |
|---|---|---|
| GET | `/v1/domains/{domain}/records` | Get all DNS records |
| GET | `/v1/domains/{domain}/records/{type}` | Get records by type |
| GET | `/v1/domains/{domain}/records/{type}/{name}` | Get records by type+name |
| PATCH | `/v1/domains/{domain}/records` | Add/update DNS records |
| PUT | `/v1/domains/{domain}/records` | Replace all DNS records |
| PUT | `/v1/domains/{domain}/records/{type}` | Replace records for type |
| PUT | `/v1/domains/{domain}/records/{type}/{name}` | Replace records for type+name |
| DELETE | `/v1/domains/{domain}/records/{type}/{name}` | Delete records for type+name |

## Certificates

| Method | Endpoint | Description |
|---|---|---|
| POST | `/v1/certificates` | Create certificate order |
| POST | `/v1/certificates/validate` | Validate certificate order payload |
| GET | `/v1/certificates/{certificateId}` | Get certificate details |
| GET | `/v1/certificates/{certificateId}/actions` | Get certificate actions |
| GET | `/v1/certificates/{certificateId}/download` | Download certificate |
| POST | `/v1/certificates/{certificateId}/renew` | Renew certificate |
| POST | `/v1/certificates/{certificateId}/reissue` | Reissue certificate |
| POST | `/v1/certificates/{certificateId}/revoke` | Revoke certificate |
| POST | `/v1/certificates/{certificateId}/verifyDomainControl` | Verify domain control |

## Shoppers

| Method | Endpoint | Description |
|---|---|---|
| GET | `/v1/shoppers/{shopperId}` | Get shopper details |
| PATCH | `/v1/shoppers/{shopperId}` | Update shopper |
| DELETE | `/v1/shoppers/{shopperId}` | Delete shopper |

## Subscriptions

| Method | Endpoint | Description |
|---|---|---|
| GET | `/v1/subscriptions` | List subscriptions |
| GET | `/v1/subscriptions/{subscriptionId}` | Get subscription details |
| POST | `/v1/subscriptions/{subscriptionId}/cancel` | Cancel subscription |

## Agreements / metadata

| Method | Endpoint | Description |
|---|---|---|
| GET | `/v1/agreements` | List legal agreements |
| GET | `/v1/countries` | List countries |

## Aftermarket

| Method | Endpoint | Description |
|---|---|---|
| GET | `/v1/aftermarket/listings` | List aftermarket listings |
| GET | `/v1/aftermarket/listings/{listingId}` | Get listing details |

## Notes

- DNS types include `A`, `AAAA`, `CNAME`, `TXT`, `MX`, `SRV`, `NS`, `CAA`, etc.
- GoDaddy typically enforces ~60 requests/minute per endpoint.
- OTE is recommended for testing and is less restricted than production.


path: references/error-handling.md
content: # Error Handling

## Common HTTP Status Codes

### 401 Unauthorized
**Cause**: Invalid or missing API credentials

**Solutions**:
- Check `GODADDY_API_KEY` is set correctly
- Check `GODADDY_API_SECRET` is set correctly
- Verify credentials at <https://developer.godaddy.com/keys>
- Ensure no extra whitespace in env vars

### 403 Forbidden / ACCESS_DENIED
**Cause**: Valid auth but account doesn't meet production API requirements

GoDaddy locks production endpoints based on account size:
- **Availability API**: Requires **50+ domains** in account
- **Management & DNS APIs**: Requires **10+ domains** OR **Discount Domain Club – Domain Pro Plan**

**Solutions**:
- **Quick fix**: Use OTE environment for testing (`export GODADDY_API_BASE_URL="https://api.ote-godaddy.com"`)
- **Unlock production**: Subscribe to Discount Domain Club – Domain Pro Plan (also gives lower domain pricing)
- **Accumulate domains**: Once you have 10+ domains, management/DNS APIs unlock automatically
- For purchases: verify Good as Gold funding is enabled

**Common scenario**: You create a production API key, call `/v1/domains`, get `ACCESS_DENIED` or empty results — your account just doesn't meet the domain count threshold.

### 404 Not Found
**Cause**: Resource doesn't exist

**Solutions**:
- Verify domain name spelling
- Check domain is in your account
- Confirm endpoint URL is correct

### 422 Unprocessable Entity
**Cause**: Request payload is malformed or invalid

**Solutions**:
- Validate JSON syntax with `jq`
- Check required fields are present
- Verify data types (strings, numbers, booleans)
- Review payload examples in [request-bodies.md](request-bodies.md)
- Use `/v1/domains/purchase/validate` before actual purchase

### 429 Too Many Requests
**Cause**: Rate limit exceeded (60 requests/min per endpoint)

**Solutions**:
- Wait 60 seconds before retrying
- Implement exponential backoff
- Batch operations when possible
- Consider caching responses

### 500 Internal Server Error
**Cause**: GoDaddy API issue

**Solutions**:
- Retry after a few seconds
- Check GoDaddy status page
- If persistent, contact GoDaddy support

## Error Response Format

Typical error response:
```json
{
  "code": "INVALID_BODY",
  "message": "Request body doesn't fulfill schema",
  "fields": [
    {
      "path": "contactAdmin.email",
      "message": "Invalid email format"
    }
  ]
}
```

## Debugging Tips

1. **Test in OTE first**: Use `https://api.ote-godaddy.com` to test without affecting production
2. **Validate JSON**: Run `cat payload.json | jq .` before sending
3. **Inspect curl output**: Add `-v` flag to curl for verbose debugging
4. **Check response**: Pipe output to `jq` for readable formatting
5. **Redact secrets**: Never log `GODADDY_API_KEY` or `GODADDY_API_SECRET`

## Example Debug Session

```bash
# Test auth
./scripts/gd-domains.sh list

# If 401, check env
echo "Key: ${GODADDY_API_KEY}"
echo "[REDACTED_SECRET]" # partial for security
echo "URL: ${GODADDY_API_BASE_URL}"

# Validate JSON payload
cat payload.json | jq .

# Test with verbose curl
curl -v -X GET "${GODADDY_API_BASE_URL}/v1/domains" \
  -H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}" \
  -H "Accept: application/json"
```


path: references/request-bodies.md
content: # Request Body Schemas

## Domain Purchase

```json
{
  "domain": "example.com",
  "privacy": true,
  "nameServers": ["ns01.domaincontrol.com", "ns02.domaincontrol.com"],
  "consent": {
    "agreedBy": "192.0.2.1",
    "agreedAt": "2024-01-01T00:00:00Z",
    "agreementKeys": ["DNRA"]
  },
  "period": 1,
  "contactAdmin": {
    "nameFirst": "John",
    "nameLast": "Doe",
    "email": "[REDACTED_SECRET]",
    "phone": "+1.5555551234",
    "addressMailing": {
      "address1": "123 Main St",
      "city": "Anytown",
      "state": "CA",
      "postalCode": "12345",
      "country": "US"
    }
  },
  "contactRegistrant": { /* same as contactAdmin */ },
  "contactBilling": { /* same as contactAdmin */ },
  "contactTech": { /* same as contactAdmin */ }
}
```

## Domain Renewal

```json
{
  "period": 1
}
```

## DNS Record (single)

```json
{
  "type": "A",
  "name": "@",
  "data": "192.0.2.1",
  "ttl": 3600
}
```

## DNS Records (array for add/replace)

```json
[
  {
    "type": "A",
    "name": "@",
    "data": "192.0.2.1",
    "ttl": 3600
  },
  {
    "type": "CNAME",
    "name": "www",
    "data": "example.com",
    "ttl": 3600
  },
  {
    "type": "TXT",
    "name": "_acme-challenge",
    "data": "verification-token-here",
    "ttl": 600
  },
  {
    "type": "MX",
    "name": "@",
    "data": "mail.example.com",
    "priority": 10,
    "ttl": 3600
  }
]
```

## Bulk Availability Check

```json
["example.com", "example.net", "example.org"]
```

## Certificate Order

```json
{
  "type": "DV_SSL",
  "commonName": "example.com",
  "period": 1,
  "productId": "ssl123",
  "slotSize": "5"
}
```

## Notes

- Use templates in `assets/payload-templates/` as starting points
- Always validate JSON before sending
- Check required fields per endpoint in official docs
- TTL is in seconds (common values: 600, 1800, 3600, 86400)
- Priority field only for MX/SRV records


path: references/safety-playbook.md
content: # Safety Playbook

## High-Risk Operations

These operations require explicit confirmation:

### 💰 Financial (costs money)
- Domain purchase
- Domain renewal
- Certificate purchase/renewal

### 🔥 Destructive (irreversible or high-impact)
- DNS replace-all (wipes all records)
- DNS delete
- Domain cancellation
- Certificate revocation

## Confirmation Pattern

All high-risk scripts implement this pattern:

```bash
echo "⚠️  WARNING: [description of action and consequences]" >&2
echo "Details: [show payload or parameters]" >&2
read -p "Continue? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
  echo "Aborted." >&2
  exit 1
fi
# ... proceed with operation
```

## Pre-Flight Checklist

Before executing high-risk operations:

### Domain Purchase
- [ ] Verified domain availability
- [ ] Validated purchase payload JSON
- [ ] Confirmed pricing and period
- [ ] Checked Good as Gold funding
- [ ] Reviewed contact information
- [ ] Confirmed consent agreements

### Domain Renewal
- [ ] Verified domain is eligible for renewal
- [ ] Confirmed renewal period
- [ ] Checked account balance

### DNS Replace-All
- [ ] Backed up current DNS records (`./scripts/gd-dns.sh get <domain>`)
- [ ] Reviewed replacement payload
- [ ] Tested in OTE environment first (if possible)
- [ ] Confirmed no critical services will break

### DNS Delete
- [ ] Verified record is not critical
- [ ] Confirmed no services depend on it
- [ ] Documented reason for deletion

### Certificate Revocation
- [ ] Confirmed certificate is no longer needed
- [ ] Reviewed impact on services
- [ ] Have replacement certificate ready (if needed)

## Testing Strategy

**Always test in OTE first:**

1. Set up OTE environment:
   ```bash
   export GODADDY_API_BASE_URL="https://api.ote-godaddy.com"
   export GODADDY_API_KEY="your-ote-key"
   export GODADDY_API_SECRET="your-ote-secret"
   ```

2. Run operation in OTE
3. Verify results
4. Switch to production:
   ```bash
   export GODADDY_API_BASE_URL="https://api.godaddy.com"
   export GODADDY_API_KEY="your-prod-key"
   export GODADDY_API_SECRET="your-prod-secret"
   ```

## Recovery Procedures

### Accidentally deleted DNS records
- Restore from backup (if taken)
- Contact GoDaddy support for historical data
- Reconfigure from documentation

### Purchased wrong domain
- Domain purchases are generally non-refundable
- Contact GoDaddy support immediately
- May be eligible for Good as Gold credit

### Broke DNS for live service
- Use GoDaddy web UI for emergency fix
- Update records via API once stabilized
- Document incident for post-mortem

## Best Practices

1. **Backup before changes**: Always export current state before modifications
2. **Test in OTE**: Use test environment for workflow validation
3. **One change at a time**: Don't batch unrelated operations
4. **Document changes**: Keep audit trail of what was changed and why
5. **Verify after change**: Confirm operation succeeded as expected
6. **Monitor impact**: Watch for downstream effects (email, web, etc.)


path: scripts/gd-aftermarket.sh
content: #!/usr/bin/env bash
#
# gd-aftermarket.sh - GoDaddy aftermarket listings operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

usage() {
  cat <<EOF
Usage:
  $0 list [queryString]
  $0 get <listingId>

Example queryString:
  status=ACTIVE&pageSize=50&pageNumber=1
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  list)
    query="${1:-}"
    if [[ -n "$query" ]]; then
      gd_api GET "/v1/aftermarket/listings?${query}" | jq .
    else
      gd_api GET "/v1/aftermarket/listings" | jq .
    fi
    ;;

  get)
    listing_id="${1:?listingId required}"
    gd_api GET "/v1/aftermarket/listings/${listing_id}" | jq .
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-agreements.sh
content: #!/usr/bin/env bash
#
# gd-agreements.sh - GoDaddy legal agreements operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

usage() {
  cat <<EOF
Usage:
  $0 list [queryString]

Example queryString:
  product=domain&marketId=en-US
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  list)
    query="${1:-}"
    if [[ -n "$query" ]]; then
      gd_api GET "/v1/agreements?${query}" | jq .
    else
      gd_api GET "/v1/agreements" | jq .
    fi
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-api.sh
content: #!/usr/bin/env bash
#
# gd-api.sh - Base helper for GoDaddy API calls
#
set -euo pipefail

: "${GODADDY_API_BASE_URL:?Set GODADDY_API_BASE_URL}"
: "${GODADDY_API_KEY:?Set GODADDY_API_KEY}"
: "${GODADDY_API_SECRET:?Set GODADDY_API_SECRET}"

gd_api() {
  local method="$1" path="$2" body="${3:-}"
  
  if [[ -n "$body" ]]; then
    curl -sS -X "$method" "${GODADDY_API_BASE_URL}${path}" \
      -H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}" \
      -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      --data "$body"
  else
    curl -sS -X "$method" "${GODADDY_API_BASE_URL}${path}" \
      -H "Authorization: sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}" \
      -H "Accept: application/json"
  fi
}

# Export for use by other scripts
export -f gd_api


path: scripts/gd-certs.sh
content: #!/usr/bin/env bash
#
# gd-certs.sh - GoDaddy certificate operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

confirm() {
  local msg="$1"
  read -r -p "${msg} [y/N] " reply
  [[ "$reply" =~ ^[Yy]$ ]]
}

require_file() {
  local file="$1"
  [[ -f "$file" ]] || { echo "Error: File not found: $file" >&2; exit 1; }
}

usage() {
  cat <<EOF
Usage:
  $0 create <payload.json>
  $0 validate <payload.json>
  $0 get <certificateId>
  $0 actions <certificateId>
  $0 download <certificateId>
  $0 renew <certificateId> <payload.json>
  $0 reissue <certificateId> <payload.json>
  $0 revoke <certificateId> <payload.json>
  $0 verify-domain-control <certificateId> <payload.json>
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  create)
    file="${1:?JSON payload file required}"
    require_file "$file"
    echo "⚠️  WARNING: This creates a certificate order and may charge your account." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/certificates" "$(cat "$file")" | jq .
    ;;

  validate)
    file="${1:?JSON payload file required}"
    require_file "$file"
    gd_api POST "/v1/certificates/validate" "$(cat "$file")" | jq .
    ;;

  get)
    certificate_id="${1:?certificateId required}"
    gd_api GET "/v1/certificates/${certificate_id}" | jq .
    ;;

  actions)
    certificate_id="${1:?certificateId required}"
    gd_api GET "/v1/certificates/${certificate_id}/actions" | jq .
    ;;

  download)
    certificate_id="${1:?certificateId required}"
    gd_api GET "/v1/certificates/${certificate_id}/download" | jq .
    ;;

  renew)
    certificate_id="${1:?certificateId required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    echo "⚠️  WARNING: This may renew certificate ${certificate_id} and charge your account." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/certificates/${certificate_id}/renew" "$(cat "$file")" | jq .
    ;;

  reissue)
    certificate_id="${1:?certificateId required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    gd_api POST "/v1/certificates/${certificate_id}/reissue" "$(cat "$file")" | jq .
    ;;

  revoke)
    certificate_id="${1:?certificateId required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    echo "⚠️  WARNING: This will revoke certificate ${certificate_id}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/certificates/${certificate_id}/revoke" "$(cat "$file")" | jq .
    ;;

  verify-domain-control)
    certificate_id="${1:?certificateId required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    gd_api POST "/v1/certificates/${certificate_id}/verifyDomainControl" "$(cat "$file")" | jq .
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-countries.sh
content: #!/usr/bin/env bash
#
# gd-countries.sh - GoDaddy country metadata operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

usage() {
  cat <<EOF
Usage:
  $0 list
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  list)
    gd_api GET "/v1/countries" | jq .
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-dns.sh
content: #!/usr/bin/env bash
#
# gd-dns.sh - GoDaddy DNS record operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

confirm() {
  local msg="$1"
  read -r -p "${msg} [y/N] " reply
  [[ "$reply" =~ ^[Yy]$ ]]
}

require_file() {
  local file="$1"
  [[ -f "$file" ]] || { echo "Error: File not found: $file" >&2; exit 1; }
}

usage() {
  cat <<EOF
Usage:
  $0 get-all <domain>
  $0 get-type <domain> <type>
  $0 get <domain> <type> <name>
  $0 add <domain> <records.json>
  $0 replace-all <domain> <records.json>
  $0 replace-type <domain> <type> <records.json>
  $0 replace-type-name <domain> <type> <name> <records.json>
  $0 delete-type-name <domain> <type> <name>

Types: A, AAAA, CNAME, TXT, MX, SRV, NS, etc.
Name: Use @ for apex, or subdomain name
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  get-all)
    domain="${1:?Domain required}"
    gd_api GET "/v1/domains/${domain}/records" | jq .
    ;;

  get-type)
    domain="${1:?Domain required}"
    type="${2:?Type required}"
    gd_api GET "/v1/domains/${domain}/records/${type}" | jq .
    ;;

  get)
    domain="${1:?Domain required}"
    type="${2:?Type required}"
    name="${3:?Name required}"
    gd_api GET "/v1/domains/${domain}/records/${type}/${name}" | jq .
    ;;

  add)
    domain="${1:?Domain required}"
    file="${2:?JSON file required}"
    require_file "$file"
    gd_api PATCH "/v1/domains/${domain}/records" "$(cat "$file")" | jq .
    ;;

  replace-all)
    domain="${1:?Domain required}"
    file="${2:?JSON file required}"
    require_file "$file"
    echo "⚠️  WARNING: This will REPLACE ALL DNS RECORDS for ${domain}." >&2
    echo "Payload: $(jq -c . "$file")" >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api PUT "/v1/domains/${domain}/records" "$(cat "$file")" | jq .
    ;;

  replace-type)
    domain="${1:?Domain required}"
    type="${2:?Type required}"
    file="${3:?JSON file required}"
    require_file "$file"
    echo "⚠️  WARNING: This will replace all ${type} records for ${domain}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api PUT "/v1/domains/${domain}/records/${type}" "$(cat "$file")" | jq .
    ;;

  replace-type-name)
    domain="${1:?Domain required}"
    type="${2:?Type required}"
    name="${3:?Name required}"
    file="${4:?JSON file required}"
    require_file "$file"
    gd_api PUT "/v1/domains/${domain}/records/${type}/${name}" "$(cat "$file")" | jq .
    ;;

  delete-type-name)
    domain="${1:?Domain required}"
    type="${2:?Type required}"
    name="${3:?Name required}"
    echo "⚠️  WARNING: This will delete ${type} record '${name}' for ${domain}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api DELETE "/v1/domains/${domain}/records/${type}/${name}" | jq .
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-domains.sh
content: #!/usr/bin/env bash
#
# gd-domains.sh - GoDaddy domain operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

confirm() {
  local msg="$1"
  read -r -p "${msg} [y/N] " reply
  [[ "$reply" =~ ^[Yy]$ ]]
}

require_file() {
  local file="$1"
  [[ -f "$file" ]] || { echo "Error: File not found: $file" >&2; exit 1; }
}

usage() {
  cat <<EOF
Usage:
  $0 list
  $0 get <domain>
  $0 available <domain> [FAST|FULL] [forTransfer=true|false]
  $0 available-bulk <file.json> [FAST|FULL]
  $0 validate-purchase <payload.json>
  $0 purchase <payload.json>
  $0 renew <domain> <periodYears>
  $0 transfer <domain> <payload.json>
  $0 update <domain> <payload.json>
  $0 update-contacts <domain> <contacts.json>
  $0 delete <domain>
  $0 privacy-enable <domain>
  $0 privacy-disable <domain>
  $0 agreements-get [queryString]
  $0 agreements-accept <payload.json>

Notes:
  - agreements-get queryString example: tlds=com,net&privacy=true&forTransfer=false
  - update / update-contacts payloads are sent as-is (see references/request-bodies.md)
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  list)
    gd_api GET "/v1/domains" | jq .
    ;;

  get)
    domain="${1:?Domain required}"
    gd_api GET "/v1/domains/${domain}" | jq .
    ;;

  available)
    domain="${1:?Domain required}"
    check_type="${2:-FAST}"
    for_transfer="${3:-false}"
    gd_api GET "/v1/domains/available?domain=${domain}&checkType=${check_type}&forTransfer=${for_transfer}" | jq .
    ;;

  available-bulk)
    file="${1:?JSON file required}"
    check_type="${2:-FAST}"
    require_file "$file"
    gd_api POST "/v1/domains/available?checkType=${check_type}" "$(cat "$file")" | jq .
    ;;

  validate-purchase)
    file="${1:?JSON payload file required}"
    require_file "$file"
    gd_api POST "/v1/domains/purchase/validate" "$(cat "$file")" | jq .
    ;;

  purchase)
    file="${1:?JSON payload file required}"
    require_file "$file"
    echo "⚠️  WARNING: This will purchase a domain and charge your account." >&2
    echo "Payload: $(jq -c . "$file")" >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/domains/purchase" "$(cat "$file")" | jq .
    ;;

  renew)
    domain="${1:?Domain required}"
    period="${2:?Period (years) required}"
    echo "⚠️  WARNING: This will renew ${domain} for ${period} year(s) and charge your account." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/domains/${domain}/renew" "{\"period\": ${period}}" | jq .
    ;;

  transfer)
    domain="${1:?Domain required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    echo "⚠️  WARNING: This may initiate a paid transfer for ${domain}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/domains/${domain}/transfer" "$(cat "$file")" | jq .
    ;;

  update)
    domain="${1:?Domain required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    gd_api PATCH "/v1/domains/${domain}" "$(cat "$file")" | jq .
    ;;

  update-contacts)
    domain="${1:?Domain required}"
    file="${2:?JSON contacts payload file required}"
    require_file "$file"
    gd_api PATCH "/v1/domains/${domain}/contacts" "$(cat "$file")" | jq .
    ;;

  delete)
    domain="${1:?Domain required}"
    echo "⚠️  WARNING: This will cancel/delete ${domain}. This may be irreversible." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api DELETE "/v1/domains/${domain}" | jq .
    ;;

  privacy-enable)
    domain="${1:?Domain required}"
    echo "⚠️  WARNING: This may incur privacy-protection charges for ${domain}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api PUT "/v1/domains/${domain}/privacy" "{}" | jq .
    ;;

  privacy-disable)
    domain="${1:?Domain required}"
    echo "⚠️  WARNING: This will disable privacy protection for ${domain}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api DELETE "/v1/domains/${domain}/privacy" | jq .
    ;;

  agreements-get)
    query="${1:-}"
    if [[ -n "$query" ]]; then
      gd_api GET "/v1/domains/agreements?${query}" | jq .
    else
      gd_api GET "/v1/domains/agreements" | jq .
    fi
    ;;

  agreements-accept)
    file="${1:?JSON payload file required}"
    require_file "$file"
    echo "⚠️  WARNING: This records legal agreement acceptance." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api POST "/v1/domains/agreements" "$(cat "$file")" | jq .
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-shoppers.sh
content: #!/usr/bin/env bash
#
# gd-shoppers.sh - GoDaddy shopper operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

confirm() {
  local msg="$1"
  read -r -p "${msg} [y/N] " reply
  [[ "$reply" =~ ^[Yy]$ ]]
}

require_file() {
  local file="$1"
  [[ -f "$file" ]] || { echo "Error: File not found: $file" >&2; exit 1; }
}

usage() {
  cat <<EOF
Usage:
  $0 get <shopperId>
  $0 update <shopperId> <payload.json>
  $0 delete <shopperId>
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  get)
    shopper_id="${1:?shopperId required}"
    gd_api GET "/v1/shoppers/${shopper_id}" | jq .
    ;;

  update)
    shopper_id="${1:?shopperId required}"
    file="${2:?JSON payload file required}"
    require_file "$file"
    gd_api PATCH "/v1/shoppers/${shopper_id}" "$(cat "$file")" | jq .
    ;;

  delete)
    shopper_id="${1:?shopperId required}"
    echo "⚠️  WARNING: This will delete shopper ${shopper_id}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    gd_api DELETE "/v1/shoppers/${shopper_id}" | jq .
    ;;

  *)
    usage
    ;;
esac


path: scripts/gd-subscriptions.sh
content: #!/usr/bin/env bash
#
# gd-subscriptions.sh - GoDaddy subscription operations
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/gd-api.sh"

confirm() {
  local msg="$1"
  read -r -p "${msg} [y/N] " reply
  [[ "$reply" =~ ^[Yy]$ ]]
}

usage() {
  cat <<EOF
Usage:
  $0 list
  $0 get <subscriptionId>
  $0 cancel <subscriptionId> [payload.json]
EOF
  exit 1
}

cmd="${1:-}"
shift || true

case "$cmd" in
  list)
    gd_api GET "/v1/subscriptions" | jq .
    ;;

  get)
    subscription_id="${1:?subscriptionId required}"
    gd_api GET "/v1/subscriptions/${subscription_id}" | jq .
    ;;

  cancel)
    subscription_id="${1:?subscriptionId required}"
    file="${2:-}"
    echo "⚠️  WARNING: This will cancel subscription ${subscription_id}." >&2
    confirm "Continue?" || { echo "Aborted." >&2; exit 1; }
    if [[ -n "$file" ]]; then
      [[ -f "$file" ]] || { echo "Error: File not found: $file" >&2; exit 1; }
      gd_api POST "/v1/subscriptions/${subscription_id}/cancel" "$(cat "$file")" | jq .
    else
      gd_api POST "/v1/subscriptions/${subscription_id}/cancel" "{}" | jq .
    fi
    ;;

  *)
    usage
    ;;
esac


path: scripts/mcp-server/package.json
content: {
  "name": "godaddy-mcp-server",
  "version": "1.0.0",
  "description": "MCP server exposing GoDaddy API operations",
  "type": "module",
  "main": "dist/index.js",
  "bin": {
    "godaddy-mcp-server": "dist/index.js"
  },
  "scripts": {
    "build": "tsc -p tsconfig.json",
    "start": "node dist/index.js"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.17.4",
    "zod": "^3.24.1",
    "zod-to-json-schema": "^3.23.5"
  },
  "devDependencies": {
    "typescript": "^5.7.3",
    "@types/node": "^22.10.2"
  }
}

path: scripts/mcp-server/tsconfig.json
content: {
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*.ts"]
}

Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: suspicious | SkillSpector: suspicious (HIGH)