Fairverra Agent API
Check, register, transfer, renew, restore, cancel, uncancel and trade domains. Manage contacts, nameservers (including glue IPs), DNS and DNSSEC, and pay from a prepaid EUR wallet. Optional USD labels on check and catalog. Every paid action is a two-step quote → confirm: you always see the exact price before anything is charged. Cancel, uncancel and trade are €0 quotes.
Sandbox https://sandbox.api.fairverra.com/v1 (fv_test_ keys, simulated registrar, Mollie test mode) Production https://api.fairverra.com/v1 (fv_live_ keys, self-service) Authorization: Bearer fv_test_...
Sandbox keys are free and self-service (see the quickstart). The sandbox runs the full product flow against a simulated registrar: no real registrations, no real money. Production is self-service too: signup → verify → billing details (PUT /me/billing) → accept the legal documents (terms, privacy, registration agreement) → first wallet deposit → POST /keys/upgrade issues the full key. The API contract is identical to the sandbox.
Paths below are relative to the base URL. The OpenAPI spec is the authoritative contract, including all request/response schemas and the stable error-code enum.
| POST /signup | — | Restricted key (check/pricing/WHOIS) plus a verification code by email |
| POST /signup/verify | — | Swap the restricted key for full sandbox access, or a provisional live key |
| PUT /me/billing | any key | Invoice details; production deposit needs ISO-2 country (e.g. NL) |
| POST /keys/upgrade | provisional live key | Exchange a provisional live key for full access after billing, legal accept and a credited deposit |
| GET /openapi | — | Machine-readable OpenAPI 3.1 contract for everything below |
| GET & PATCH /me | any key | Identity, language (nl/en), status_email (on/off), wallet, legal-acceptance |
| GET & POST /me/acceptances | any key | Accept the current terms, privacy and registration agreement (humans: login.fairverra.com/account) |
| POST /domains/check | domains:check | Availability, premium flag and sell prices; pass currency USD for dollar labels |
| POST /whois/check | whois:read | Registry status; with auth_code also transfer eligibility |
| GET /pricing/extensions | pricing:read | TLD catalog with your sell prices; ?currency=USD for dollar labels |
| GET /domains/registration-requirements | pricing:read | Per-TLD requirements: handle roles, restrictions, periods |
| GET & POST /handles, PUT /handles/{id} | handles:read/write | Contacts at the registrar; NL phone needs area_code; PUT cannot change Individual name or Organization company |
| PATCH /domains/{id}/handles | domains:write | Switch admin, billing and/or tech; registrant is a trade, not this call |
| GET & POST /nameserver-groups | domains:read/write | Default and custom nameserver sets; glue IPs optional as {hostname, ip, ip6} |
| PUT /domains/{id}/nameservers | domains:write | Switch a domain to another nameserver set |
| GET /wallet | wallet:read | Balance, credit line and recent transactions |
| POST /wallet/deposit-links | wallet:read | Top-up link (branded deposit page + direct checkout URL) |
| GET /payment-methods | wallet:read | Whether a recurring card mandate is active |
| POST /payment-methods/setup-links | wallet:read | Save a recurring card mandate (EUR 0.01 setup payment) |
| POST /quotes | quotes:create | Priced quote for register, transfer, renew, restore, cancel, uncancel or trade |
| GET /approvals/{id} | quotes:create | Quote status: open, confirmed or expired |
| POST /approvals/{id}/confirm | approvals:confirm | Execute the quote: wallet debit + registrar; cancel/uncancel/trade are €0 |
| GET /domains | domains:read | Your domains with status, expiry, auto-renew and handle ids |
| PATCH /domains/{id} | domains:write | Toggle auto_renew (requires a funded wallet or saved card) |
| GET /domains/{id}/auth-code | domains:read | EPP/transfer code + registrar lock status, live |
| PUT /domains/{id}/transfer-lock | domains:write | Set the registrar transfer lock (not every TLD supports it) |
| GET/POST/PATCH/DELETE /dns/{domain}/records | dns:read/write | DNS records for domains on Fairverra nameservers (A, AAAA, CNAME, MX, TXT, SRV, CAA) |
| GET/PUT/DELETE /domains/{id}/dnssec | dns:read/write | DNSSEC keyset: send DNSKEYs, not DS digests |
| GET/PUT/DELETE /domains/{id}/url-forward | dns:read/write | 301 apex and www to a URL; not a quote |
currency: "USD" on check (works keyless) or ?currency=USD on the catalog. prices stay EUR; presentment is the dollar amount. The wallet stays EUR. Never convert FX yourself.{ "error": "...", "code": "STABLE_CODE" }; texts may change, codes never do.idempotency_key; replays return the original result, conflicting replays get 409 IDEMPOTENCY_CONFLICT.The same API is available as a remote MCP server, so agents in Cursor, Claude and other MCP clients can use it directly — tools for checking, quoting, confirming, wallet, contacts, DNS, DNSSEC, legal accept and key upgrade. One-click install: fairverra.com/ai. check_domain and list_extension_pricing accept optional currency: "USD" for dollar labels. The wallet stays EUR.
The Fairverra plugin wraps the remote MCP server with skills such as "register a domain and connect it to this project". It points at production https://api.fairverra.com/mcp and uses the same OAuth sign-in.
claude plugin marketplace add gerbenlive/fairverra-claude-plugin claude plugin install fairverra@fairverra
From a checkout: claude --plugin-dir ./plugins/fairverra. Skills: /fairverra:register-and-connect-domain, /fairverra:transfer-domain, /fairverra:manage-dns.
Use Add to Claude or paste https://api.fairverra.com/mcp as a custom connector. Claude discovers our OAuth flow automatically: you sign in with your email address and a one-time code — no API key needed. Sandbox (no real registrations): https://sandbox.api.fairverra.com/mcp.
One-click: Add to Cursor. Or the same OAuth URL, or an API key:
{
"mcpServers": {
"fairverra": {
"type": "http",
"url": "https://api.fairverra.com/mcp"
}
}
}Paid actions keep the quote → confirm split as separate tools: create_quote shows the price, confirm_approval is documented to require explicit human approval first. Legal acceptances use accept_legal_documents the same way: show the three document URLs from whoami, then call only after an explicit yes. That records terms, privacy and the registration agreement. POST /me/accept-terms is terms-only and is not enough on production.
The simulated registrar reserves magic names so you can exercise every path deterministically:
sandbox-premium* · sandbox-taken* · sandbox-requirements* · sandbox-pending* (slow transfer) · sandbox-locked* · sandbox-expiring-<days>* (registers with expiry that many days out) · sandbox-redemption* (registers already expired — test restore) · auth code SANDBOX-WRONG · contact last name "sandbox-rejected"