# Domain Expiry & Purchase via Cloudflare Registrar

## API setup

Requires a Cloudflare API token with TWO permission groups:

| Permission | Level | What it gives |
|---|---|---|
| Zone → DNS → Edit | Edit | DNS record management |
| Account → Domain Registration → Read | Read | View domains, expiry dates, auto-renew status |
| Account → Domain Registration → Admin | Write (+ Admin) | Purchase domains, transfer domains, renew |

The Admin level adds `domain_create`, `domain_register` capabilities not visible in `Read`. The `check_availability` endpoint requires Route: `GET /accounts/{id}/registrar/domains/{name}/check` — NOT the POST variant.

## Endpoints

### List registered domains
```
GET /accounts/{id}/registrar/domains
```
Returns:
- `name`: domain name
- `expires_at`: ISO date (e.g. "2027-02-06T00:43:04.000Z")
- `auto_renew`: boolean
- `cloudflare_registration`: boolean (true = registered through Cloudflare)
- `permissions`: array of strings (e.g. `["contact_read", "contact_write", "domain_renew", "nameserver_write", "domain_delete"]`)

### Check domain availability
```
GET /accounts/{id}/registrar/domains/{name}/check
```
Returns:
- `available`: boolean
- `can_register`: boolean
- `supported_tld`: boolean
- `premium`: boolean
- `fees.registration_fee`: number (USD)
- `fees.renewal_fee`: number (USD)
- `fees.transfer_fee`: number (USD)

### Renew a domain
```
PUT /accounts/{id}/registrar/domains/{name}/renewal
Body: {"period": 1}  # years
```

## Real data pulled from Germaine's account (Jul 6, 2026)

12 domains, all registered through Cloudflare, all auto-renew ON:

| Domain | Expires | Days Left | Price/yr |
|---|---|---|---|
| forefrontisp.com | Oct 7, 2026 | 92 | $10.46 |
| vigilanttac.com | Oct 14, 2026 | 99 | $10.46 |
| voipsimplicity.com | Nov 17, 2026 | 133 | $10.46 |
| katiewattsdesign.com | Dec 29, 2026 | 175 | $10.46 |
| boxpilotlogistics.com | Feb 6, 2027 | 214 | $10.46 |
| germainebrown.com | Aug 3, 2027 | 392 | $10.46 |

All standard .com pricing at $10.46/yr (Cloudflare at cost — no markup).

## Portal integration

The DNS & Domains portal page (`dns.html`) has two tabs:

1. **DNS Zones** — Lists all zones with record count, plan, customer link. Opens DNS record editor.
2. **Registered Domains** — Lists all domains with expiry, auto-renew, days left (color-coded). Renew button per domain. Search + Register panel with availability check and pricing.

Key fields for the domain table:
- `name` → domain name
- `expires_at` → formatted as "Mon DD, YYYY"
- `auto_renew` → boolean badge (green if ON, red if OFF)
- Days left = `(expires_at - now).days`
- Color coding: green (>180 days), amber (90-180 days), red (<90 days)

The search panel shows availability results with registration fee, renewal fee, and transfer fee. "Add to Cart" button would trigger registration flow.

## Pitfalls

- The availability check endpoint uses GET with the domain in the path, NOT POST with body. POST returns "Page not found".
- `can_register` is `False` on domains already owned by the account — that's expected, not an error.
- Expiry dates are stored in UTC. Convert to local timezone when displaying.
- Cloudflare does NOT disclose registration fees in the availability check response JSON field directly — the fee is nested under `fees.registration_fee`.
- Premium domains return `premium: true` and have different pricing. The portal should flag these.
