---
name: fairverra-domains
description: Register, transfer, renew, restore, cancel, uncancel and trade internet domains via the Fairverra Agent API. Use when a task involves checking domain availability or USD/EUR prices, registering or transferring a domain, managing DNS records, DNSSEC or nameservers (including glue), handles, or renewing/restoring/canceling domains. Self-service sandbox; no human signup needed. Pass currency USD on check_domain for dollar labels; the wallet stays EUR.
---

# Fairverra domain registration for agents

Fairverra is an API-first domain registrar. Everything below works without
human intervention: you can sign up, get a key, and register sandbox domains
in one session.

Base URL (sandbox): https://sandbox.api.fairverra.com/v1
OpenAPI 3.1 spec: https://sandbox.api.fairverra.com/v1/openapi
Errors are always `{"error": "...", "code": "STABLE_CODE"}` — branch on `code`.

## Step 0 — try it without a key

`POST /domains/check` works keyless (strict IP rate limit; prices shown are
list prices — your own account pricing is never higher):

```bash
curl -X POST https://sandbox.api.fairverra.com/v1/domains/check \
  -H 'Content-Type: application/json' -d '{"domain": "example-name.nl"}'
```

Dollar labels (wallet stays EUR):

```bash
curl -X POST https://sandbox.api.fairverra.com/v1/domains/check \
  -H 'Content-Type: application/json' -d '{"domain": "example-name.nl", "currency": "USD"}'
```

## Step 1 — sign up (key-first)

```bash
curl -X POST https://sandbox.api.fairverra.com/v1/signup \
  -H 'Content-Type: application/json' -d '{"email": "you@example.com"}'
```

A new email returns `status: restricted_key_issued` with a `key` you can use
immediately for checks, pricing and WHOIS (scopes: domains:check, domains:read,
whois:read, pricing:read). A verification code is emailed at the same time.

## Step 2 — verify to unlock everything

Ask the user for the 6-digit code from their inbox (valid 10 minutes), then:

```bash
curl -X POST https://sandbox.api.fairverra.com/v1/signup/verify \
  -H 'Content-Type: application/json' -d '{"email": "you@example.com", "code": "123456"}'
```

This returns a full-access `fv_test_` key (all scopes). The restricted key
from step 1 is revoked — switch to the new key. Send it on every call:
`Authorization: Bearer fv_test_...`

## Step 3 — fund the sandbox wallet

Money only moves on an explicit confirm of a priced quote, paid from a prepaid
wallet. In the sandbox, create a deposit link and pay with Mollie test mode:

```bash
curl -X POST https://sandbox.api.fairverra.com/v1/wallet/deposit-links \
  -H 'Authorization: Bearer $KEY' -H 'Content-Type: application/json' \
  -d '{"amount": "100.00", "currency": "EUR"}'
```

Check balance with `GET /wallet`.

## Step 4 — register a domain (quote → confirm)

1. `POST /handles` — create a contact (required for .nl: pass it as tech handle).
   NL phone: `{"country_code":"+31","area_code":"6","subscriber_number":"12345678"}`
   — area_code is required; do not put the 6 inside subscriber_number.
2. `POST /quotes` with `{"action": "register", "domains": [...], "handles": {...}}`
   — returns a priced quote with an `approval_id`. Mixing TLDs in one quote is fine.
3. `POST /approvals/{approval_id}/confirm` — debits the wallet and registers.
   Per-domain results; failed registrations are auto-credited back.

After register, `PUT /handles/{id}` updates address/email (Individual name and
Organization company stay locked). `PATCH /domains/{id}/handles` switches
admin, billing and/or tech. Registrant change is a trade, not that call.

Same pattern for transfer, renew and restore (`action` field). `cancel` and
`uncancel` are €0 quotes: they only set Fairverra status (canceled/active),
not a registry delete and not `auto_renew`. `trade` is the registrant
change (`handles.registrant` required); the TLD must have
`trade_supported` or you get 422 `UNSUPPORTED_ACTION` — there is no
silent fallback. Quotes expire
after 24h (`410 QUOTE_EXPIRED`); insufficient balance gives
`402 INSUFFICIENT_BALANCE` with a `deposit_hint`.

DNS records: `GET/POST/PATCH/DELETE /dns/{domain}/records` (not
`/domains/{id}/dns/records`). DNSSEC: `GET/PUT/DELETE /domains/{id}/dnssec`
with DNSKEYs, not DS digests. URL-forward: `GET/PUT/DELETE /domains/{id}/url-forward`
(301 of apex and www; not a quote; confirm before `replace_web_records`).
Fairverra DNS is nameserver_group `dns-fairverra1` (use that name in quotes
and `set_domain_nameservers`; `dns-openprovider` is the same set).
Nameserver groups accept hostname strings or
`{hostname, ip, ip6}` for in-bailiwick glue.

Account mail: `PATCH /me` with `language` (nl/en) and/or `status_email`
(on/off). off suppresses renewal and transfer mail.

## Sandbox magic names (deterministic registrar simulation)

- `sandbox-premium*` — premium pricing path
- `sandbox-taken*` — check says free, register fails (code 346)
- `sandbox-requirements*` — extra TLD requirements
- `sandbox-pending*` — slow transfer (completes after ~2 min)
- `sandbox-locked*` — transfer-locked
- `sandbox-expiring-<days>*` — registers with expiry that many days out
- `sandbox-redemption*` — registers already expired (30 days past): test restore
- auth code `SANDBOX-WRONG` — invalid transfer code
- contact last name `sandbox-rejected` — handle rejected by registry

## MCP server (alternative to REST)

Remote MCP (streamable HTTP): https://sandbox.api.fairverra.com/mcp
Auth: `Authorization: Bearer fv_test_...`, or OAuth 2.0 with email + one-time
code (discovered automatically via RFC 9728 — works as a claude.ai custom
connector without a key).

Humans can install from https://fairverra.com/ai (Add to Cursor / Claude).
In Claude Code, prefer the Fairverra plugin over a bare connector. It wraps
this MCP server with skills (register-and-connect-domain, transfer-domain,
manage-dns):

```
claude plugin marketplace add gerbenlive/fairverra-claude-plugin
claude plugin install fairverra@fairverra
```

From a checkout: `claude --plugin-dir ./plugins/fairverra`. The plugin
connector is production (https://api.fairverra.com/mcp).

On production, after billing, call `accept_legal_documents` with the current
id+version pairs from whoami. Show the texts (/legal indexes /terms, /privacy
and /domain-registration-agreement). Humans can accept on
https://login.fairverra.com/account. Only send the tool after an explicit yes.
Do not use POST /me/accept-terms (terms only). Then deposit, then `upgrade_key`.

## Production

Humans without an agent can use https://fairverra.com/get-started (email + code)
or https://fairverra.com/ai.

Production (`fv_live_` keys) is self-service on https://api.fairverra.com/v1:

1. `POST /signup` {"email"} — restricted live key (check/pricing/whois)
2. `POST /signup/verify` {"email","code"} — provisional key (adds wallet)
3. `PUT /me/billing` — name, street, street_number, postal_code, city, country
   (company + vat_number optional); required for invoicing
4. `POST /me/acceptances` {"documents":[{"id","version"}, ...]} — versions are
   in `GET /me` under `acceptances.documents`. Texts at /legal. Humans accept
   on https://login.fairverra.com/account. An API key accepts for the account
   holder, including when an agent sends the call.
5. `POST /wallet/deposit-links` — pay the first deposit (prepaid wallet)
6. `POST /keys/upgrade` — exchanges the provisional key for a full-access key
   (shown once; the old key is revoked; a daily spend cap applies)

## Rules for agents

- Never confirm an approval without explicit approval from your human when real
  money is involved.
- One domain per check call (no bulk); respect 429 Retry-After.
- Keys are secrets: never print or log them.
