API
API and access keys
Everything a client does in the account is available through the API — except six actions that always need a human.
A key is a set of policies
Rights and resources are different axes: “edit DNS” and “in which domains” don’t merge into one. Conditions (IP, expiry, spend limit) apply to the whole key.
Key
├─ environment: live · test
├─ policy: right [dns.edit] on resources [domains tagged “client A”]
├─ policy: right [domain.renew] on resources [example.com.ua]
└─ limits: IP 203.0.113.0/24 · until 2026-12-26 · spend ≤ 2 000 ₴/moFour danger classes
The class sets the key’s lifetime, whether an IP restriction is mandatory, and who confirms the operation.
| Class | Name | Example | Confirmation |
|---|---|---|---|
| 0 | Read | domain list, DNS records, certificate status | ordinary sign-in |
| 1 | Reversible change | a DNS record, a monitoring check, a webhook | ordinary sign-in |
| 2 | Money | renewal, registration, top-up | sign-in + notice to owners |
| 3 | Ownership and irreversible | lift the transfer lock, change nameservers | a second owner or a 24-hour activation delay |
Rights catalogue (excerpt)
The full catalogue is in the docs; here are the most common rights with their danger class on the right.
- domain.read
- domain list, expiry dates, statuses 0
- domain.renew
- renew a domain — this is a spend 2
- domain.nameservers
- change nameservers; on a live domain this breaks the site and mail for the TTL window 3
- dns.edit
- create, change, delete DNS records through a checked plan 1
- dns.acme_challenge
- only a TXT record under
_acme-challenge.<name>— for certbot and similar 1 - cert.issue
- a free Let’s Encrypt certificate 1
- monitor.read
- checks, history, monitoring reports 0
- billing.topup
- top up the balance from a saved card 2
The dns.acme_challenge right is deliberately narrow: a compromised web server with this key can only reissue a certificate for its own domain, not rewrite MX and steal the mail.
What a key never gets
- A domain transfer code — only to a human in the account, after re-authentication.
- Changing the domain owner (registrant).
- Managing an organisation’s people and keys.
- The payment method, turning off two-factor checks, deleting the account.
Sample request
Every write call requires an Idempotency-Key: a repeat returns the same result, not a new operation.
GET /v1/domains/kava.com.ua HTTP/1.1
Authorization: Bearer zr_live_…
Idempotency-Key: 8f14e45f-…
200 OK
{ "domain": "kava.com.ua", "status": ["ok"],
"expires_at": "2027-09-12", "auto_renew": true }An error is a machine code plus a human-readable message and suggested actions:
{ "error": {
"code": "domain_taken",
"message": { "uk": "kava.com.ua зайнятий до 2027-09-12.",
"en": "kava.com.ua is registered until 2027-09-12." },
"actions": [ { "type": "check_alternatives", "href": "/v1/search?q=kava" } ] } }Where to issue a key
Keys are issued in the account: a rights template → domains → conditions → a plain-language summary. The public read-only MCP is available without a key.
FAQ
What is the public MCP?
A read-only tool for assistants (models), no key required: domain check, certificate status. It never writes to an account.
Can we test an integration without spending money?
Yes, a test key zr_test_… runs against the sandbox: registrations and charges look real but aren’t.
Can we get a domain transfer code through the API?
No. It’s one of six actions available only to a human in the account after re-authentication — even with domain.lock in the key.