Download OpenAPI specification:
Register and manage domains through Golzak, from your own systems or AI agents.
Reseller API to register and manage domains through Golzak. A partner
company (the reseller) registers, renews, transfers and manages names for
its own clients, paid from the prepaid credit of its Golzak account.
Version 1 covers .ma domains only: .ma, .co.ma, .net.ma and
.org.ma. Later versions may add extensions; GET /prices lists the
extensions you can order.
GET /check and
GET /prices return them. No price is written in this document.GET /balance). Not enough credit means
error insufficient_credit and nothing is ordered.POST /domains returns an operation.
Its status moves pending → active, or refused when the registry
(ANRT) refuses the name. Results arrive by signed webhook and by
GET /operations/{id}.Holder schema.Human guides, the AI integration guide and llms.txt are published next
to this reference.
Your prepaid credit (read live from Golzak's billing system) and, for the key making the call, its daily spending cap and what it has spent since 00:00 UTC.
{- "credit": {
- "amount": "<your balance>",
- "currency": "<your account currency>"
}, - "daily_spend_cap": {
- "amount": "<cap set for this key>",
- "currency": "<your account currency>"
}, - "spent_today": {
- "amount": "<spent since 00:00 UTC>",
- "currency": "<your account currency>"
}, - "cap_resets_at": "2026-10-09T00:00:00Z"
}Is a name free, and what does it cost you. Prices are read live from your client group.
Answers whether name can be registered and returns your price for
one year. The availability answer comes from a WHOIS lookup and is a
strong hint, not a reservation: the registry gives the final answer
when the registration is submitted.
Only .ma, .co.ma, .net.ma and .org.ma are accepted.
.ac.ma, .gov.ma and .press.ma answer tld_manual_only.
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: name=atlas-tours.ma name=atlas-export.co.ma Full domain name, lower case, e.g. |
{- "name": "atlas-tours.ma",
- "extension": ".ma",
- "available": true,
- "price": {
- "operation": "register",
- "years": 1,
- "amount": "<your price, read live>",
- "currency": "<your account currency>"
}
}Your register, renew and transfer prices for .ma, .co.ma,
.net.ma and .org.ma, per number of years. The figures come from
your client group at Golzak and are read live on every call: never
cache them for longer than a quote you show to a client.
The year counts listed are the only ones you can order.
{- "currency": "<your account currency>",
- "source": "client_group",
- "read_at": "2026-10-08T09:00:00Z",
- "extensions": [
- {
- "extension": ".ma",
- "grace_period_days": 27,
- "redemption_period_days": 2,
- "register": {
- "1": "<your price, read live>",
- "2": "<your price, read live>"
}, - "renew": {
- "1": "<your price, read live>"
}, - "transfer": {
- "1": "<your price, read live>"
}
}
]
}Every domain of your account, newest first, paginated with an opaque cursor.
| limit | integer <int32> [ 1 .. 100 ] Default: 50 Page size. |
| cursor | string <= 512 characters ^[^\u0000-\u001F\u007F]*$ The |
{- "data": [
- {
- "name": "atlas-tours.ma",
- "status": "active",
- "registered_at": "2026-10-08",
- "expires_at": "2027-10-08",
- "auto_renew": false,
- "pending_operation_id": null
}
], - "next_cursor": null
}Orders the registration of name for years, for the holder given,
paid from your credit. Every check runs before anything is
ordered: name and extension, holder rules, availability, your price,
your credit balance and your daily spending cap. If one fails you get
the error and nothing is ordered or charged.
On success the answer is 202 with an operation in status pending.
Follow it with webhooks or GET /operations/{id}. It ends in:
active: the domain is registered;refused: the registry (ANRT) refused the name; the charge is
returned to your credit (see refund);failed: a technical failure; the charge is returned to your credit.While ANRT examines a name (pending_reason: registry_review),
documents_required is true (and documents_deadline when known): send
the documents asked for in Golzak's e-mail before that date, or the
request lapses.
Send ?dry_run=true to run every check without ordering: the answer
is 200 with the charge that would be made.
| dry_run | boolean Default: false
|
| Idempotency-Key required | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Example: 0b8c7f0e-6a39-4b8f-9a0e-2f5d7c1e9a41 Required on every POST. A unique value per intended action (a UUID v4
is ideal). Retrying with the same key and the same body returns the
first answer with |
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... A lower-case ASCII host name (letters, digits, hyphens, dots). The API
then checks the extension and answers | |||||||||||||||
| years required | integer <int32> [ 1 .. 5 ] Must be one of the year counts in your | |||||||||||||||
required | object (Holder) The domain holder (registrant): your client, never your own company
and never a registrar's staff. The API refuses a holder whose e-mail or
organization is your own account's (
| |||||||||||||||
| nameservers required | Array of strings (Nameservers) [ 2 .. 5 ] items unique [ items [ 3 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]... ] 2 to 5 distinct nameserver host names (Golzak API rule). |
{- "name": "atlas-tours.ma",
- "years": 1,
- "holder": {
- "type": "individual",
- "moroccan": true,
- "legal_id": "<CIN number>",
- "first_name": "Salma",
- "last_name": "Bennani",
- "email": "salma.bennani@example.com",
- "phone": "+212.612345678",
- "address": {
- "line1": "12 Rue Example",
- "city": "Casablanca",
- "postal_code": "20000",
- "country": "MA"
}
}, - "nameservers": [
- "ns1.example-dns.com",
- "ns2.example-dns.com"
]
}{- "dry_run": true,
- "would_charge": {
- "amount": "<your price, read live>",
- "currency": "<your account currency>"
}, - "credit_after": {
- "amount": "<your balance minus the charge>",
- "currency": "<your account currency>"
}
}Status, dates, nameservers, auto-renew and transfer-lock state of one of
your domains. A name that is not in your account answers
domain_not_found, whether or not it exists elsewhere.
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: atlas-tours.ma atlas-export.co.ma Full domain name of one of your domains. |
{- "name": "atlas-tours.ma",
- "status": "active",
- "registered_at": "2026-10-08",
- "expires_at": "2027-10-08",
- "auto_renew": false,
- "transfer_locked": true,
- "pending_operation_id": null,
- "nameservers": [
- "ns1.example-dns.com",
- "ns2.example-dns.com"
]
}Renews name for years, paid from your credit at your renew price.
Credit and daily cap are checked before anything is ordered. Returns
an operation that ends active (renewed, new expires_at on the
domain) or failed (charge returned to your credit).
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: atlas-tours.ma atlas-export.co.ma Full domain name of one of your domains. |
| dry_run | boolean Default: false
|
| Idempotency-Key required | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Example: 0b8c7f0e-6a39-4b8f-9a0e-2f5d7c1e9a41 Required on every POST. A unique value per intended action (a UUID v4
is ideal). Retrying with the same key and the same body returns the
first answer with |
| years required | integer <int32> [ 1 .. 5 ] Must be one of the year counts in your |
{- "years": 1
}{- "dry_run": true,
- "would_charge": {
- "amount": "string",
- "currency": "string"
}, - "credit_after": {
- "amount": "string",
- "currency": "string"
}
}Replaces the full nameserver list. Synchronous: the answer comes after
the registry accepted the change. A name still under ANRT examination
cannot be changed (domain_status_prohibits). Idempotency-Key is
accepted and recommended here.
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: atlas-tours.ma atlas-export.co.ma Full domain name of one of your domains. |
| Idempotency-Key | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Optional on PUT; same rules as on POST. Recommended. |
| nameservers required | Array of strings (Nameservers) [ 2 .. 5 ] items unique [ items [ 3 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]... ] 2 to 5 distinct nameserver host names (Golzak API rule). |
{- "nameservers": [
- "ns1.example-dns.com",
- "ns2.example-dns.com"
]
}{- "name": "atlas-tours.ma",
- "status": "pending_registration",
- "registered_at": "2019-08-24",
- "expires_at": "2019-08-24",
- "auto_renew": true,
- "pending_operation_id": "string",
- "transfer_locked": true,
- "nameservers": [
- "string"
]
}Returns the transfer code (EPP auth code) the holder needs to move the name to another registrar. Each call sets a new code at the registry; the previous code stops working. Give the code only to the domain holder.
The code alone is not enough: Golzak locks every name against
transfer. Remove the lock first with
PUT /domains/{name}/transfer-lock ({"locked": false}), or the
new registrar's transfer request is refused.
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: atlas-tours.ma atlas-export.co.ma Full domain name of one of your domains. |
{- "name": "atlas-tours.ma",
- "epp_code": "<new code>"
}Turns the registry transfer lock (clientTransferProhibited) on or
off. Golzak locks every name after registration and after a transfer
in. Unlock it only when the holder is moving the name to another
registrar, together with GET /domains/{name}/epp-code; lock it
again if the move is abandoned. Synchronous. A name under ANRT
examination or expired cannot be changed (domain_status_prohibits).
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: atlas-tours.ma atlas-export.co.ma Full domain name of one of your domains. |
| Idempotency-Key | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Optional on PUT; same rules as on POST. Recommended. |
| locked required | boolean
|
{- "locked": false
}{- "name": "atlas-tours.ma",
- "status": "pending_registration",
- "registered_at": "2019-08-24",
- "expires_at": "2019-08-24",
- "auto_renew": true,
- "pending_operation_id": "string",
- "transfer_locked": true,
- "nameservers": [
- "string"
]
}Domains registered or transferred through the API start with
auto_renew: false: nothing is ever charged without a call from you.
With auto_renew: true, Golzak renews the name for one year shortly
before expires_at, at your renew price, paid from your credit. That
renewal counts against your account's daily cap for automatic renewals
(not a key's cap), appears as an operation with initiator: auto_renew,
and is reported by webhook. If credit or cap do not allow it, the
operation ends failed and you are told by webhook; renew by hand
before expires_at.
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... Examples: atlas-tours.ma atlas-export.co.ma Full domain name of one of your domains. |
| Idempotency-Key | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Optional on PUT; same rules as on POST. Recommended. |
| enabled required | boolean |
{- "enabled": true
}{- "name": "atlas-tours.ma",
- "status": "pending_registration",
- "registered_at": "2019-08-24",
- "expires_at": "2019-08-24",
- "auto_renew": true,
- "pending_operation_id": "string",
- "transfer_locked": true,
- "nameservers": [
- "string"
]
}Golzak POSTs this to every webhook endpoint of your account (set on developers.golzak.com, each with its own secret) when an operation changes state. Verify the signature before trusting it:
Golzak-Signature: v1=<hex> where <hex> is
HMAC-SHA256(webhook_secret, "<Golzak-Webhook-Timestamp>.<raw body>").
Refuse a timestamp more than 300 seconds from your clock. Compare in
constant time.
Answer any 2xx within 10 seconds. Other answers and timeouts are
retried with backoff for 24 hours. Deliveries can repeat or arrive out
of order: deduplicate on Golzak-Webhook-Id, and trust the
operation's updated_at (or re-read GET /operations/{id}).
| Golzak-Webhook-Id required | string <= 255 characters ^[^\u0000-\u001F\u007F]*$ Unique per event; the same on every retry of that event. |
| Golzak-Webhook-Timestamp required | string <= 255 characters ^[0-9]{10}$ Unix time (seconds) when this delivery was signed. |
| Golzak-Signature required | string <= 255 characters ^v1=[0-9a-f]{64}$
|
| id required | string <= 255 characters ^[^\u0000-\u001F\u007F]*$ Same value as the Golzak-Webhook-Id header. |
| type required | string <= 255 characters ^[^\u0000-\u001F\u007F]*$
v1 may add event types: acknowledge (2xx) and ignore a type you do not know. |
| created_at required | string <date-time> <= 255 characters |
required | object |
{- "id": "evt_01JA7XB2C3D4E5F6G7H8J9K0LM",
- "type": "operation.active",
- "created_at": "2026-10-09T08:00:00Z",
- "data": {
- "operation": {
- "id": "op_01JA7X3M9Q2W8E5R6T7Y8U9I0P",
- "type": "register",
- "initiator": "api",
- "status": "active",
- "pending_reason": null,
- "domain": "atlas-tours.ma",
- "years": 1,
- "charge": {
- "amount": "<your price, read live>",
- "currency": "<your account currency>"
}, - "refund": null,
- "documents_required": false,
- "documents_deadline": null,
- "error": null,
- "created_at": "2026-10-08T09:00:00Z",
- "updated_at": "2026-10-09T08:00:00Z",
- "completed_at": "2026-10-09T08:00:00Z"
}
}
}The current state of an operation returned by a POST, or created by an
automatic renewal. Poll it when you missed a webhook; once a minute at
most, once an hour during registry_review.
| id required | string <= 255 characters ^op_[0-9A-Z]{26}$ Operation ID returned by a POST. |
{- "id": "op_01JA7X3M9Q2W8E5R6T7Y8U9I0P",
- "type": "register",
- "initiator": "api",
- "status": "pending",
- "pending_reason": "registry_review",
- "domain": "atlas-tours.ma",
- "years": 1,
- "charge": {
- "amount": "<your price, read live>",
- "currency": "<your account currency>"
}, - "refund": null,
- "documents_required": true,
- "documents_deadline": null,
- "error": null,
- "created_at": "2026-10-08T09:00:00Z",
- "updated_at": "2026-10-08T09:01:10Z",
- "completed_at": null
}Transfers name from another registrar to Golzak with the EPP code
the holder got from the current registrar. Your transfer price is read
live from your client group, like every other price (GET /prices).
Credit and daily cap are checked first. Returns an operation that
ends active (the name is in your account) or failed (charge
returned to your credit).
Timing (ANRT decision 02/2024 art. 35): the current registrar has two
business days to accept or oppose; without an answer the transfer
completes automatically. If ANRT has to decide an opposition it takes
up to three more business days. Before ordering, make sure the name
is unlocked at the current registrar. If the transfer has not
completed 10 business days after the request, the operation ends
failed with transfer_not_completed and the charge is returned.
| dry_run | boolean Default: false
|
| Idempotency-Key required | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Example: 0b8c7f0e-6a39-4b8f-9a0e-2f5d7c1e9a41 Required on every POST. A unique value per intended action (a UUID v4
is ideal). Retrying with the same key and the same body returns the
first answer with |
| name required | string (DomainNameInput) [ 4 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0... A lower-case ASCII host name (letters, digits, hyphens, dots). The API
then checks the extension and answers |
| epp_code required | string [ 1 .. 255 ] characters ^[^\u0000-\u001F\u007F]*$ Transfer code (EPP auth code) from the current registrar. |
| nameservers | Array of strings (Nameservers) [ 2 .. 5 ] items unique [ items [ 3 .. 253 ] characters ^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]... ] 2 to 5 distinct nameserver host names (Golzak API rule). |
{- "name": "atlas-tours.ma",
- "epp_code": "<code from the current registrar>"
}{- "dry_run": true,
- "would_charge": {
- "amount": "string",
- "currency": "string"
}, - "credit_after": {
- "amount": "string",
- "currency": "string"
}
}