Business Registry Domain Reservation API (1.1.0)

Download OpenAPI specification:Download

Domain Reservation API for the Estonian Business Registry

This API allows the Business Registry (Ariregister) to reserve .ee domain names on behalf of entrepreneurs during the company registration process.

Glossary

Term Description
Registration code (password) A unique secret code returned when a domain is reserved. The entrepreneur must provide this code to an accredited .ee registrar to complete the domain registration via the EPP protocol. Without this code, the domain cannot be registered.
user_unique_id A 10-character identifier generated for each reservation request. It links a user session to their reserved domains. Must be stored by the Business Registry portal to retrieve reservation details later.
invoice_number An invoice identifier generated by the billing system for paid (long-term) reservations. Must be stored together with user_unique_id to check payment status.
linkpay_url A one-time Everypay payment page URL. The Business Registry portal should redirect the user to this URL to complete the payment. No automatic callback redirect — use the status endpoint to poll for payment completion.

End-to-End Flow

Step 1: Generate domain name suggestions

The Business Registry portal sends the organization name to the API. The API generates domain variants (with and without hyphens, across all .ee zones), removes common legal forms (AS, OU, FIE, MTU, etc.), checks availability in the domain registry, and returns only the domains that are both unregistered and not already reserved.

Endpoint: GET /api/v1/business_registry/domain_names/{organization_name}

Step 2: Reserve selected domains

The user picks one or more domain names from the suggestions. The Business Registry portal sends them to one of the reservation endpoints:

Option A: Short-term (free) reservation — 7 days

  • Endpoint: POST /api/v1/business_registry/reserve_domains
  • Domains are reserved immediately, no payment required
  • Response includes the registration code (password) for each domain
  • The user has 7 days to register the domain at an accredited registrar using the code
  • Important: Store the returned user_unique_id to retrieve reservation details later

Option B: Long-term (paid) reservation — 1 year

  • Endpoint: POST /api/v1/business_registry/long_reserve_domains
  • Creates an invoice (10 EUR per domain) and returns a payment link (linkpay_url)
  • Domains are NOT yet reserved — they enter pending status until payment is completed
  • Important: Store both invoice_number and user_unique_id to check payment status later
  • After the user pays, the domains are reserved for 1 year and registration codes become available

Step 3: Check reservation status and retrieve registration codes

For short-term reservations:

  • Endpoint: GET /api/v1/business_registry/reserve_domains/{user_unique_id}
  • Returns the list of domains with their current status and registration codes

For long-term reservations:

  • Endpoint: GET /api/v1/business_registry/long_reserve_domains_status?invoice_number=...&user_unique_id=...
  • Poll this endpoint after redirecting the user to the payment page
  • When status becomes paid, the response includes registration codes for each domain
  • Note: Calling this endpoint when the invoice is paid also triggers the creation of reserved domain records (idempotent)

Step 4: Register the domain

The entrepreneur takes the registration code (password) to any accredited .ee registrar and registers the domain via the EPP protocol. Once registered, the domain is removed from the reserved list.

Domain Status Tracking

Both status endpoints (/reserve_domains/{user_unique_id} and /long_reserve_domains_status) return a status field for each domain, allowing the Business Registry portal to show only the domains that still need action:

Status Meaning Fields present
reserved Domain is reserved and waiting for registration name, status, password, expire_at
registered Domain has been registered through a registrar name, status
expired Reservation has expired (domain is no longer held) name, status

Typical usage: Filter the response to show only domains with status: "reserved" — these are the domains the user still needs to register.

Long-term Reservation: Invoice and Payment Logic

  • Each reservation request generates a unique invoice in the Everypay billing system
  • If a new reservation request includes domains that overlap with an existing unpaid invoice:
    • The system checks if the existing invoice has been paid in the meantime
    • If not paid, a new invoice is created with the same invoice number but a different user_unique_id
    • If the existing invoice was already paid, the request is rejected with an error
  • When any user completes payment for a shared invoice number, all other unpaid invoices with the same number are automatically cancelled (Everypay Linkpay behavior)
  • Users whose invoices were cancelled must submit a new reservation request
  • Price: Currently fixed at 10 EUR per domain

Authentication

All endpoints require two forms of authentication:

  1. IP restriction: The request must originate from an IP address listed in the server configuration
  2. Bearer token: The Authorization header must contain a valid API token
Authorization: Bearer <your-api-token>

Limits and Validation

  • Maximum 20 domains per reservation request
  • Domain names must match the pattern [\p{L}\p{N}\-\.]+ (letters, numbers, hyphens, dots)
  • Domain names are normalized to lowercase Unicode before processing
  • Organization names for domain suggestions: max 100 characters, pattern [\p{L}\p{N}\s\-]+

Domain Suggestions

Get available domain name suggestions for an organization

Generates domain name variants based on the organization name and returns only those that are currently available for registration.

How it works:

  1. Strips common Estonian legal forms from the name (AS, OU, FIE, MTU, etc.)
  2. Generates variants: concatenated (examplecompany) and hyphenated (example-company)
  3. Combines variants with all available .ee zone origins
  4. Checks each variant against the domain registry (EPP) for availability
  5. Filters out domains that are already reserved by other users
  6. Returns only the available domain names

Note: Expired reservations are automatically cleaned up during the availability check, so a previously reserved domain may become available again after its reservation period ends.

Authorizations:
(ipRestrictionBearerAuth)
path Parameters
organization_name
required
string <= 100 characters ^[\p{L}\p{N}\s\-]+$
Example: Example Company OU

Name of the organization to generate domain variants for. Common legal forms (AS, OU, FIE, MTU, etc.) are automatically removed before generating variants.

Responses

Response samples

Content type
application/json
Example
{
  • "variants": [
    ]
}

Short-term Reservation (Free)

Reserve domains for 7 days without payment

Creates free short-term domain reservations (7 days). Reserved domains receive a unique registration code (password) that the entrepreneur must use to register the domain at an accredited .ee registrar.

Important behaviors:

  • Only domains that are currently available (not registered and not reserved) will be reserved
  • If some requested domains are unavailable, they are silently skipped — only available ones are reserved
  • If none of the requested domains are available, a 422 error is returned
  • Each reserved domain gets its own unique registration code
  • The reservation expires after 7 days — after that, the domain becomes available again

What to store: Save the user_unique_id from the response. You will need it to retrieve the registration codes later via GET /reserve_domains/{user_unique_id}.

Authorizations:
(ipRestrictionBearerAuth)
Request Body schema: application/json
domain_names
required
Array of strings [ 1 .. 20 ] items

Array of domain names to reserve. Must include the zone (e.g., .ee).

Responses

Request samples

Content type
application/json
{
  • "domain_names": [
    ]
}

Response samples

Content type
application/json
{
  • "message": "Domains reserved successfully",
  • "reserved_domains": [
    ],
  • "user_unique_id": "f8d51313-b"
}

Get status and registration codes for short-term reserved domains

Retrieves the current state of domains from a short-term (free) reservation.

Each domain in the response includes a status field that reflects its current state:

  • reserved — Domain is still reserved. The response includes the password (registration code) and expire_at date. The entrepreneur can use the registration code to register the domain at a registrar.
  • registered — Domain has already been registered through a registrar using the registration code. No password or expire_at is returned.
  • expired — The 7-day reservation period has ended. The domain is no longer held and may be taken by someone else. No password or expire_at is returned.

Typical usage: Display only domains with status: "reserved" to the user — these are the ones that still need to be registered at a registrar.

Note: For long-term (paid) reservations, use GET /api/v1/business_registry/long_reserve_domains_status instead.

Authorizations:
(ipRestrictionBearerAuth)
path Parameters
user_unique_id
required
string
Example: f8d51313-b

The unique identifier returned in the user_unique_id field when the domains were reserved via POST /reserve_domains.

Responses

Response samples

Content type
application/json
Example
[
  • {
    },
  • {
    }
]

Long-term Reservation (Paid)

Reserve domains for 1 year with payment

Creates a paid long-term domain reservation (1 year). This endpoint does not reserve the domains immediately — it creates an invoice and returns a payment link.

Flow:

  1. Call this endpoint with the desired domain names
  2. Receive linkpay_url, invoice_number, and user_unique_id
  3. Redirect the user to linkpay_url to complete payment in Everypay
  4. Poll GET /long_reserve_domains_status?invoice_number=...&user_unique_id=... to check payment status
  5. Once paid, the domains are reserved and registration codes become available

Important behaviors:

  • Only available domains are included in the invoice (unavailable ones are filtered out)
  • The available_domains field in the response shows which domains were actually included
  • Price: currently 10 EUR per domain
  • If some requested domains overlap with existing unpaid invoices, the system reuses the same invoice number
  • If overlapping domains already have a paid invoice, the request is rejected

What to store: Save both invoice_number and user_unique_id — they are required to check payment status and retrieve registration codes later.

Authorizations:
(ipRestrictionBearerAuth)
Request Body schema: application/json
domain_names
required
Array of strings [ 1 .. 20 ] items

Array of domain names to reserve. Must include the zone (e.g., .ee).

Responses

Request samples

Content type
application/json
{
  • "domain_names": [
    ]
}

Response samples

Content type
application/json
{
  • "message": "Domains are in pending status. Need to pay for domains.",
  • "invoice_number": 1234567,
  • "user_unique_id": "a1b2c3d4e5",
  • "available_domains": [
    ]
}

Check payment status and get registration codes for long-term reservations

Checks the payment status of a long-term domain reservation invoice and returns registration codes once paid.

How to use:

  1. After redirecting the user to the Everypay payment page, poll this endpoint periodically
  2. When the response status changes to paid, the registration codes are available
  3. Display the reserved_domains array to the user, filtering by status: "reserved"

Response variants:

  • paid — Invoice is paid. The response includes reserved_domains with registration codes and domain statuses (reserved, registered, or expired).
  • Any other status (pending, unpaid, failed, error, cancelled) — Invoice is not yet paid. The response includes the names array (plain list of domain names without registration codes).

Side effect: When the invoice status is paid, calling this endpoint also triggers the creation of reserved domain records if they haven't been created yet (idempotent operation).

Note: For short-term (free) reservations, use GET /api/v1/business_registry/reserve_domains/{user_unique_id} instead.

Authorizations:
(ipRestrictionBearerAuth)
query Parameters
invoice_number
required
string
Example: invoice_number=1234567

Invoice number returned by POST /long_reserve_domains.

user_unique_id
required
string
Example: user_unique_id=a1b2c3d4e5

Unique identifier returned by POST /long_reserve_domains. Both invoice_number and user_unique_id must match to retrieve the invoice.

Responses

Response samples

Content type
application/json
Example
{
  • "status": "paid",
  • "message": "Payment received",
  • "reserved_domains": [
    ]
}