regzone
Sign in

API for developers

An HTTPS API for your programs: DNS records (certbot and other Let’s Encrypt clients, deployment systems, your own scripts), the “Domains” section — terms, nameservers, auto-renewal, availability checks — and purchases from the balance: registering and renewing domains. Responses are JSON.

API key

Keys are created in the account under “API keys”. A key is bound to chosen domains or to every domain of the account, including future ones, and grants permissions in three sections — DNS, “Domains” and purchases. A key’s settings can be changed in the account at any time; the key itself stays the same.

“Full access” in the account means DNS management and domain management at once. Purchases are not part of it: the right to spend money is switched on separately, with optional limits.

Send the key in the Authorization: Bearer <key> header. A key is shown once when created; if you lose it or it leaks, reissue it in the account (“Reissue”: a new value, the same permissions) or delete it.

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/zones

HTTP/1.1 200 OK
{"scope":"acme","zones":[{"name":"example.com","status":"active"}]}

Response: scope is the key’s DNS access (acme, dns_read, dns_write, or null when the key has none); zones lists the domains the key may use, alphabetically: name is the domain (internationalised names in punycode), status is its state (active, pending, expired, etc.). Records can be changed only on a domain with status active; others answer 409. There are no other fields.

Checking a key

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/key

{"key":{"name":"certbot","scope":"acme","domainsAccess":null,"purchases":null,"allDomains":false,"domains":["example.com"],"allowedIps":["203.0.113.7"],"expiresAt":null}}

The request changes nothing and needs no permission — it is how to check that a key is set up correctly and what it may do. scope, domainsAccess and purchases are the key’s permissions (null means none); domains lists the domains it covers; allDomains means it works with every domain of the account, future ones included; allowedIps lists the addresses it works from (empty means any); expiresAt is the end of its term (ISO 8601), or null for a key that never expires.

Endpoints

Base URL: https://regzone.pro/api/v1

GET/keyWhat this key may do: permissions, domains, allowed addresses, term. Changes nothing.
GET/zonesDomains available to the key, and its permission.
GET/zones/{zone}/recordsZone records the key may see.
POST/zones/{zone}/recordsAdd a record. The response carries its id.
DELETE/zones/{zone}/records/{id}Delete one record by id.
GET/domainsThe key’s domains: expiry, auto-renew, nameservers.
GET/domains/{domain}One domain — the same fields.
PUT/domains/{domain}/nameserversChange the domain’s nameservers.
PUT/domains/{domain}/auto-renewSwitch auto-renew on or off.
GET/availability?domain={domain}Whether a domain is free, and the registration and renewal price.
GET/balanceThe account balance and the key’s spending limits.
GET/contactsContacts domains can be registered to.
POST/domainsRegister a domain from the balance.
POST/domains/{domain}/renewRenew a domain from the balance.
GET/orders/{id}An order placed with this key and its state.

Add a record

Body: type, name, value, ttl (optional; 60 by default for _acme-challenge, 3600 otherwise), priority (required for MX and SRV).

curl -X POST https://regzone.pro/api/v1/zones/example.com/records \
  -H "Authorization: Bearer rz_…" \
  -H "Content-Type: application/json" \
  -d '{"type":"TXT","name":"_acme-challenge","value":"<token>","ttl":60}'

HTTP/1.1 201 Created
{"record":{"id":"4Zt2…","type":"TXT","name":"_acme-challenge","value":"<token>","ttl":60,"priority":null},"created":true}

List records

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/zones/example.com/records

{"zone":"example.com","records":[{"id":"4Zt2…","type":"TXT","name":"_acme-challenge","value":"<token>","ttl":60,"priority":null}]}

An “SSL validation only” key sees only _acme-challenge records — handy for finding and cleaning up leftover validation records.

Delete a record

curl -X DELETE -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/zones/example.com/records/4Zt2…

HTTP/1.1 204 No Content

Exactly one record is deleted; other TXT records on the same name stay. An unknown id returns 404.

Domains

Requires “Domains: read” or “Domains: manage”.

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/domains

{"domains":[{"name":"example.com","status":"active","expiresAt":"2027-10-02T00:00:00.000Z","autoRenew":true,"nameservers":["ns1.regzone.pro","ns2.regzone.pro"],"dns":"platform"}]}

expiresAt is the end of the term (ISO 8601), or null while the domain is being registered; dns is platform when the default nameservers serve the zone, otherwise other.

Nameservers

curl -X PUT https://regzone.pro/api/v1/domains/example.com/nameservers \
  -H "Authorization: Bearer rz_…" \
  -H "Content-Type: application/json" \
  -d '{"nameservers":["ns1.example.net","ns2.example.net"]}'

{"domain":{"name":"example.com",…,"nameservers":["ns1.example.net","ns2.example.net"],"dns":"other"}}

Requires “Domains: manage”. From 2 to 13 names. The default nameservers are not set this way (409 platform_nameservers): going back to them is a button in the account, and it carries the zone’s records over. Your own servers for such a domain are fine: the domain leaves the default DNS just as it would from the account. The response is the domain after the change.

Auto-renew

curl -X PUT https://regzone.pro/api/v1/domains/example.com/auto-renew \
  -H "Authorization: Bearer rz_…" \
  -H "Content-Type: application/json" \
  -d '{"enabled":false}'

Requires “Domains: manage”. Auto-renew charges the balance 14 days before the term ends; the API only switches it on and off.

Is a domain free

curl -H "Authorization: Bearer rz_…" "https://regzone.pro/api/v1/availability?domain=example.org"

{"domain":"example.org","available":true,"premium":false,"sold":true,"price":{"minor":113480,"currency":"RUB"},"renewPrice":{"minor":113480,"currency":"RUB"}}

Requires “Domains: read”. One full name per request. Prices are in minor units (minor) and in the balance currency; premium is a premium domain with its own price; sold: false means we do not sell this zone. Up to 40 checks a minute.

Purchases

Needs “Purchases: renewal” or “Purchases: registration and renewal”. Money is taken from the account balance — top it up in the account beforehand. The account e-mail address must be confirmed.

Balance and limits

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/balance

{"balance":{"minor":500000,"currency":"RUB"},"key":{"purchases":"register","dailyLimit":{"minor":300000,"currency":"RUB"},"purchaseLimit":null,"spentLast24h":{"minor":113480,"currency":"RUB"},"remainingLast24h":{"minor":186520,"currency":"RUB"}}}

dailyLimit and purchaseLimit are the key’s limits (null — no limit); spentLast24h is what the key spent in the last 24 hours; remainingLast24h is what it may still spend (null — no limit).

Contacts

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/contacts

{"contacts":[{"id":"8f0c…","label":"Основной","name":"Иван Петров","country":"RU","default":true}]}

Needs “Purchases: registration and renewal”. Contacts are created in the account; the API returns only their id, label, name and country.

Register a domain

curl -X POST https://regzone.pro/api/v1/domains \
  -H "Authorization: Bearer rz_…" \
  -H "Idempotency-Key: 3b1f6c2e-7a4d-4f0e-9c1a-5d2b8e6f0a11" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example.org","years":1,"contact":"8f0c…","autoRenew":true}'

HTTP/1.1 202 Accepted
{"order":{"id":"c41e…","status":"processing"},"domain":"example.org","years":1,"charged":{"minor":113480,"currency":"RUB"},"replayed":false}

Body: domain — one full name; years — the term in years (1 by default; .ru and .рф take 1 only); contact — the owner contact’s id (the default contact if omitted); autoRenew — renew the domain automatically from the balance (false by default). 202 means the order is paid and the registration is under way — usually a minute. Follow it with GET /orders/{id}; the domain then appears in GET /domains if the key works with all of the account’s domains. Zones that need extra data (.ru, .рф, .us, .it) take it from the contact, filled in in the account.

Renew a domain

curl -X POST https://regzone.pro/api/v1/domains/example.com/renew \
  -H "Authorization: Bearer rz_…" \
  -H "Idempotency-Key: renew-example.com-2027" \
  -H "Content-Type: application/json" \
  -d '{"years":1}'

{"domain":{"name":"example.com","status":"active","expiresAt":"2028-10-02T00:00:00.000Z",…},"years":1,"charged":{"minor":113480,"currency":"RUB"},"replayed":false}

Body: years — the term in years (1 by default; the body may be omitted). Only the key’s domains can be renewed. The response carries the domain with its new term. If the zone’s registry does not accept a renewal yet (.ru and .рф — two months before expiry), the answer is 409 renewal_not_open with the date.

Order

curl -H "Authorization: Bearer rz_…" https://regzone.pro/api/v1/orders/c41e…

{"order":{"id":"c41e…","status":"completed","total":{"minor":113480,"currency":"RUB"},"placedAt":"2026-10-03T09:15:00.000Z","items":[{"domain":"example.org","years":1}]}}

A key sees only its own orders. status: processing — paid, registration under way; completed — the domain is registered; failed or refunded — it did not work out and the money went back to the balance.

Limits

Errors

An error is an HTTP status and a body with a machine code (code), an explanation (message) and the request number (request_id):

HTTP/1.1 409 Conflict
X-Request-Id: req_5b1c0e7a9d2f4c68b3a1e0d97f246c15

{"error":{"code":"zone_not_active","message":"The domain is not active: its status is \"pending\". Records can be managed once it is \"active\".","details":{"status":"pending"},"request_id":"req_5b1c0e7a9d2f4c68b3a1e0d97f246c15"}}

Every response carries an X-Request-Id header, and an error repeats it in request_id. Send it to support: it is how we find the request in the log.

Some errors carry a details field saying what exactly is wrong: zone_not_active has status (the domain’s current status); zone_not_served has nameservers (the nameservers recorded for the domain) and expected_nameservers (the ones the API manages records for); ip_not_allowed has ip (the address the request came from).

400idempotency_key_requiredNo Idempotency-Key header — without it a purchase could be repeated by accident.
400invalid_jsonThe request body is not JSON.
401invalid_tokenNo key, or the key is invalid, revoked or expired.
402insufficient_balanceNot enough money on the balance — top it up in the account.
403insufficient_scopeThe key has no permission for this section or action.
403ip_not_allowedThe key may not be used from this address: it is not in the key’s allowed list.
403email_not_verifiedConfirm the account e-mail address first.
403purchase_limit_exceededThe purchase costs more than this key’s per-purchase limit.
403daily_limit_exceededThe purchase does not fit this key’s 24-hour limit.
403forbidden_recordThe key’s permission does not allow this record.
403zone_suspendedThe domain is suspended — its zone cannot be changed.
403domain_suspendedThe domain is suspended — it cannot be changed.
404zone_not_foundThe key has no such zone.
404record_not_foundNo such record.
404domain_not_foundThe key has no such domain.
404order_not_foundNo such order for this key.
409zone_not_activeThe domain is not active; its status is in details.status. Records can be managed once the status is active.
409zone_not_servedThe domain is delegated to other nameservers — manage records there. details says which nameservers are recorded for the domain and which are needed.
409zone_fullThe zone already holds the maximum number of records.
409platform_nameserversThe default nameservers are set with a button in the account.
409not_supportedThis change is not available for this domain.
409domain_not_availableThe domain is taken and cannot be registered.
409price_unavailableThe price cannot be determined right now — retry later.
409renewal_not_openThe zone’s registry does not accept the renewal yet — the response names the date.
409renewal_in_progressThis domain is being renewed right now.
409late_fee_requiredRenewing now costs an extra fee — nothing was charged; contact support.
409request_in_progressA request with this Idempotency-Key is still running — retry in a minute.
409previous_order_failedThe purchase with this Idempotency-Key already failed and the money went back. Use a new value to try again.
413body_too_largeThe request is too large.
422invalid_bodyThe body is not JSON of the expected shape.
422invalid_valueInvalid value, name, TTL or record type.
422invalid_typeUnknown record type, or one this domain does not support.
422invalid_nameInvalid record name, or a name from another zone.
422invalid_ttlTTL out of range.
422priority_requiredThis record type needs a priority.
422invalid_nameserversGive 2 to 13 names like ns1.example.net.
422invalid_domainGive one full domain name.
422invalid_yearsThe term is outside what the zone allows.
422contact_requiredThe account has no contacts — add one in the account.
422contact_not_foundNo such contact — see GET /contacts.
422contact_incompleteThe contact is incomplete — complete it in the account.
422contact_missing_zone_dataThe contact lacks data this zone needs — fill in its “Documents” section.
422contact_not_eligibleThe zone’s registry does not accept an owner from the contact’s country.
429rate_limitedToo many requests — try again later.
500internal_errorUnexpected error — try again shortly; if it keeps happening, send the request_id to support.
502dns_unavailableThe zone could not be read — try again shortly.
502dns_write_failedThe record could not be saved — try again in a minute.
502registry_unavailableThe change did not go through — try again shortly.
502check_failedThe check did not complete — try again shortly.
502purchase_failedThe purchase did not go through and nothing was charged — retry shortly.
502renewal_failedThe renewal did not go through; the money went back to the balance — retry shortly.
502charge_failedThe balance could not be charged — retry shortly.
503check_unavailableThe registry did not answer — try again shortly.
503temporarily_unavailableChanges are temporarily unavailable.
503api_disabledThe API is temporarily disabled.

Wildcard certificate with certbot

Two certbot scripts: the first adds the validation record, the second removes it after validation. Replace example.com with your domain.

#!/bin/sh
# /etc/letsencrypt/regzone-auth.sh — certbot --manual-auth-hook
set -eu
KEY=$(cat /etc/letsencrypt/regzone.key)
ZONE="example.com"
ID_FILE="/var/tmp/regzone-$CERTBOT_DOMAIN-$CERTBOT_VALIDATION.id"

curl -fsS -X POST "https://regzone.pro/api/v1/zones/$ZONE/records" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d "{\"type\":\"TXT\",\"name\":\"_acme-challenge.$CERTBOT_DOMAIN\",\"value\":\"$CERTBOT_VALIDATION\",\"ttl\":60}" \
  | sed -n 's/.*"id":"\([^"]*\)".*/\1/p' > "$ID_FILE"

# The record reaches the public nameservers within 1–2 minutes.
sleep 90
#!/bin/sh
# /etc/letsencrypt/regzone-cleanup.sh — certbot --manual-cleanup-hook
set -eu
KEY=$(cat /etc/letsencrypt/regzone.key)
ZONE="example.com"
ID_FILE="/var/tmp/regzone-$CERTBOT_DOMAIN-$CERTBOT_VALIDATION.id"

if [ -s "$ID_FILE" ]; then
  curl -fsS -X DELETE "https://regzone.pro/api/v1/zones/$ZONE/records/$(cat "$ID_FILE")" \
    -H "Authorization: Bearer $KEY"
  rm -f "$ID_FILE"
fi

Save the key to a file and issue the certificate — renewal uses the same scripts:

printf '%s' 'rz_…' > /etc/letsencrypt/regzone.key
chmod 600 /etc/letsencrypt/regzone.key
chmod 700 /etc/letsencrypt/regzone-auth.sh /etc/letsencrypt/regzone-cleanup.sh

certbot certonly --manual --preferred-challenges dns \
  --manual-auth-hook /etc/letsencrypt/regzone-auth.sh \
  --manual-cleanup-hook /etc/letsencrypt/regzone-cleanup.sh \
  -d example.com -d '*.example.com'

# Renewal re-uses the same hooks:
certbot renew

The “SSL validation only” permission is enough. A certificate for example.com and *.example.com needs two TXT records on one name — the API supports that.

Security

API for developers · regzone