Skip to content

Reseller API Implementation Guide

The Reseller API provides domain search, registration, DNS management, and lifecycle operations through a single RESTful API. It is designed for resellers who want to offer traditional DNS domain registration and management to their end users.

To get started, visit the Reseller Dashboard to create an account and obtain your API key.

The API is available in two environments:

EnvironmentBase URL
Productionhttps://api.unstoppabledomains.com/partner/v3
Sandboxhttps://api.ud-sandbox.com/partner/v3

Use the sandbox environment for development and testing. There is no charge for sandbox usage. For complete endpoint details, see the API Reference.

Your Responsibilities as a Reseller

The Reseller API handles domain operations, but several responsibilities fall on you as the integrating platform:

  • Domain-to-user mapping. The API does not track which end user owns which domain. You must maintain this mapping in your own system so that you can associate domains with the correct user accounts.

  • Contact management. You are responsible for creating ICANN contacts and associating them with domains during registration. Unstoppable Domains handles contact verification by sending a verification email to the contact's email address. You decide how to map contacts to your users -- whether each user gets their own contact, or multiple users share a contact, or some other arrangement.

  • Payment processing. Unstoppable Domains keeps a running balance against your reseller account and invoices you periodically. You are responsible for building your own checkout and billing experience for end users and collecting payment from them.

  • Renewal tracking. The API provides renewal eligibility and pricing information, but you are responsible for monitoring domain expiration dates and initiating renewals on time. Build reminders and automation into your platform to avoid letting domains expire.

  • DNS configuration. You can set up DNS records on behalf of your users or expose DNS management directly in your UI. Either way, it is your responsibility to ensure domains are configured correctly for your users.

Core Concepts

Operations

Every mutating API call (registration, DNS changes, renewals, etc.) returns an Operation object. Operations are the primary mechanism for tracking the progress of asynchronous work.

An Operation progresses through the following statuses:

QUEUED → PROCESSING → COMPLETED | FAILED | CANCELLED

Two additional statuses exist:

  • PREVIEW -- Returned when using preview mode ($preview=true). The operation was not executed.
  • AWAITING_UPDATES -- The operation requires additional input or action before it can proceed.

Each Operation contains dependencies, which are smaller units of work that make up the overall operation. Each dependency has its own status, so you can track granular progress.

To check the status of an operation, poll the operation endpoint:

curl "https://api.ud-sandbox.com/partner/v3/operations/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response:

{
  "id": "op-a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "status": "PROCESSING",
  "type": "DOMAIN_REGISTRATION",
  "dependencies": [
    {
      "type": "DNS_REGISTRATION",
      "status": "COMPLETED"
    },
    {
      "type": "CONTACT_ASSOCIATION",
      "status": "PROCESSING"
    }
  ]
}

Preview Mode

Add the $preview=true query parameter to any mutating request to validate it without executing. This is useful for:

  • Getting a price quote before committing to a registration or renewal
  • Validating request parameters before submitting
  • Showing users what will happen before they confirm

A preview request returns what the Operation would look like, with the status set to PREVIEW. No changes are made, and no charges are incurred.

curl -X POST "https://api.ud-sandbox.com/partner/v3/domains?\$preview=true" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "example.com"}'

Domain Flags

Domain flags control what actions are permitted on a domain. There are six flags:

FlagEPP StatusDescription
DNS_RESOLUTIONclientHoldControls whether the domain resolves via DNS
DNS_TRANSFER_OUTclientTransferProhibitedControls whether the domain can be transferred to another registrar
DNS_DELETEclientDeleteProhibitedControls whether the domain can be deleted
DNS_UPDATEclientUpdateProhibitedControls whether DNS records can be modified
DNS_RENEWclientRenewProhibitedControls whether the domain can be renewed
DNS_WHOIS_PROXY--Controls whether WHOIS privacy protection is enabled

Some flags may be read-only, meaning you cannot change them. When a flag is read-only, the API returns a reason code explaining why:

  • ADMIN -- The flag is locked by an administrator.
  • HOSTING -- The flag is controlled by the hosting configuration.
  • DNS_PROVIDER -- The flag is controlled by the DNS provider.

Getting Started

Prerequisites

  1. Create an account and apply on the Reseller Dashboard.
  2. Wait for our team to approve your application.
  3. Obtain your API key from the dashboard.
  4. All requests require a Bearer token in the Authorization header.

Your First Request

Search for domain availability using the sandbox environment:

curl "https://api.ud-sandbox.com/partner/v3/domains?query=example.com&ending=com&\$expand=registration" \
  -H "Authorization: Bearer YOUR_API_KEY"

The $expand=registration parameter includes registration availability and pricing information in the response. If the request succeeds, you are authenticated and ready to integrate.

Search and Registration Flow

This section walks through the full flow from searching for a domain to completing registration.

Step 1: Search for Available Domains

Search for domains matching a query:

curl "https://api.ud-sandbox.com/partner/v3/domains?query=example.com&ending=com&\$expand=registration" \
  -H "Authorization: Bearer YOUR_API_KEY"

The response includes availability status and registration information for each matching domain.

Step 2: Check Pricing

Get detailed pricing for a specific domain:

curl "https://api.ud-sandbox.com/partner/v3/pricing/dns/domains/example.com" \
  -H "Authorization: Bearer YOUR_API_KEY"

This returns the registration price, renewal price, and any applicable fees.

Step 3: Create a Contact

Before registering a domain, you need an ICANN contact. Create one with the required fields:

curl -X POST "https://api.ud-sandbox.com/partner/v3/contacts" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Jane",
    "lastName": "Doe",
    "email": "jane.doe@example.com",
    "phone": {
      "dialingPrefix": "+1",
      "number": "5551234567"
    },
    "countryCode": "US",
    "street": "123 Main St",
    "city": "San Francisco",
    "postalCode": "94105",
    "stateProvince": "CA"
  }'

A verification email will be sent to the contact's email address. The contact can be used in domain registrations immediately, but domains associated with unverified contacts may become unmanageable after a certain period. See the Contact Management section for details on verification statuses.

Step 4: Register the Domain

With a contact created, register the domain. Use $preview=true first to validate and get a price quote, then switch to $preview=false to execute:

curl -X POST "https://api.ud-sandbox.com/partner/v3/domains?\$preview=false" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "example.com",
    "owner": {
      "type": "SELF",
      "contact": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab"
    },
    "dns": {
      "period": 1,
      "contacts": {
        "admin": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab",
        "tech": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab",
        "billing": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab"
      }
    }
  }'

The response includes an Operation ID that you use to track the registration progress.

Step 5: Track the Operation

Poll the operation endpoint until the status reaches COMPLETED or FAILED:

curl "https://api.ud-sandbox.com/partner/v3/operations/{id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "id": "op-a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "status": "COMPLETED",
  "type": "DOMAIN_REGISTRATION"
}

Poll at a reasonable interval (every 2-5 seconds) and implement a timeout. For production systems, consider using webhooks instead of polling.

Using Preview Mode for Price Quotes

Before committing to a registration, run the same request with $preview=true instead of $preview=false. The response includes the pricing breakdown and validates all fields without actually registering the domain. See Preview Mode for details.

Contact Management

Contacts represent the ICANN registrant, admin, tech, and billing entities associated with a domain. Proper contact management is essential for domain registration and compliance.

Required Fields

Every contact requires the following fields:

FieldDescription
firstNameContact's first name
lastNameContact's last name
emailContact's email address (used for verification)
phoneObject with dialingPrefix (e.g., "+1") and number
countryCodeTwo-letter ISO country code (e.g., "US")
streetStreet address
cityCity
postalCodePostal or ZIP code
stateProvinceState or province

The organization field is optional and should be included when registering domains on behalf of a business.

Email Verification

Contacts can be used in domain registrations immediately without waiting for verification. However, if a contact remains unverified past a deadline, their status becomes SUSPENDED, which can lead to domain suspension.

The verification flow works as follows:

  1. During registration -- New contacts are created with UNVERIFIED status. Existing registrant contacts are marked as PENDING for verification. Registration proceeds immediately.
  2. After registration -- A background job picks up PENDING contacts, sends a verification email with a deadline link, and marks them as REQUESTED.
  3. Enforcement -- If the contact does not verify by the deadline, they are marked SUSPENDED, which can lead to domain suspension.
UNVERIFIED → PENDING → REQUESTED → VERIFIED

A contact can also reach FAILED or SUSPENDED status if verification fails or the deadline passes.

Contact Roles

Domains have four contact roles:

  • Owner (Registrant) -- The legal owner of the domain. Set during registration via the owner field.
  • Admin -- The administrative contact for the domain.
  • Tech -- The technical contact responsible for DNS configuration.
  • Billing -- The billing contact for renewal and payment matters.

Contacts are assigned during registration. You can update contacts after registration using:

curl -X PATCH "https://api.ud-sandbox.com/partner/v3/domains/{name}/dns/contacts?\$preview=false" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "admin": "ct-new-contact-id",
    "tech": "ct-new-contact-id",
    "billing": "ct-new-contact-id"
  }'

Inline vs. Referenced Contacts

You can create contacts in two ways:

  • Referenced -- Create a contact first via POST /contacts, then reference its ID during registration. This is useful when reusing the same contact across multiple domains.
  • Inline -- Provide the full contact details directly in the registration request body. The API creates the contact automatically. This is convenient for one-off registrations.

DNS Management

The Reseller API provides full DNS record management for domains registered through your account.

Listing Records

Retrieve all DNS records for a domain:

curl "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/records" \
  -H "Authorization: Bearer YOUR_API_KEY"

You can filter by record type and subdomain:

curl "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/records?type=A&subName=www" \
  -H "Authorization: Bearer YOUR_API_KEY"

Creating Records

Create a new DNS record:

curl -X POST "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/records" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "A",
    "subName": "www",
    "value": "192.0.2.1",
    "ttl": 3600
  }'

Supported record types include A, AAAA, CNAME, MX, TXT, SRV, and others.

The $upsert query parameter controls behavior when a conflicting record already exists:

ValueBehavior
REPLACEReplace the existing record with the new one
APPENDAdd the new record alongside the existing one
DISALLOWEDFail if a conflicting record exists (default)

Updating and Deleting Records

Each DNS record has a unique ID in the format rr-<uuid>. Use this ID to update or delete individual records:

# Update a record
curl -X PUT "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/records/rr-a1b2c3d4" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "value": "192.0.2.2",
    "ttl": 7200
  }'

# Delete a record
curl -X DELETE "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/records/rr-a1b2c3d4" \
  -H "Authorization: Bearer YOUR_API_KEY"

Nameservers

By default, domains use Unstoppable Domains-managed nameservers.

You can set custom nameservers if needed. You must provide between 2 and 12 nameservers:

curl -X PUT "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/nameservers" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nameservers": [
      "ns1.example.net",
      "ns2.example.net"
    ]
  }'

To revert to UD-managed nameservers:

curl -X DELETE "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/nameservers" \
  -H "Authorization: Bearer YOUR_API_KEY"

Domain Lifecycle

Renewal

Check if a domain is eligible for renewal and get pricing:

curl "https://api.ud-sandbox.com/partner/v3/domains/example.com/renewals" \
  -H "Authorization: Bearer YOUR_API_KEY"

Renew the domain by specifying the renewal period in years:

curl -X POST "https://api.ud-sandbox.com/partner/v3/domains/example.com/renewals?\$preview=false" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "period": 1
  }'

This returns an Operation that you can track to confirm the renewal completed.

Transfers Out

To transfer a domain to another registrar:

  1. Ensure the DNS_TRANSFER_OUT flag is enabled on the domain.
  2. Retrieve the EPP authorization code:
curl "https://api.ud-sandbox.com/partner/v3/domains/example.com/dns/authorization-code" \
  -H "Authorization: Bearer YOUR_API_KEY"
  1. Provide the authorization code to the gaining registrar to initiate the transfer on their end.

Transfers In

To transfer a domain from another registrar into your account, use the same POST /domains endpoint used for registration. Include the dns.authorizationCode field in the request body -- the presence of an authorization code tells the API this is a transfer rather than a new registration:

curl -X POST "https://api.ud-sandbox.com/partner/v3/domains?\$preview=false" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "example.com",
    "owner": {
      "type": "SELF",
      "contact": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab"
    },
    "dns": {
      "authorizationCode": "EPP_AUTH_CODE_HERE",
      "contacts": {
        "admin": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab",
        "tech": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab",
        "billing": "ct-a1b2c3d4-5678-90ab-cdef-1234567890ab"
      }
    }
  }'

Managing Flags

View the current flags for a domain:

curl "https://api.ud-sandbox.com/partner/v3/domains/example.com/flags" \
  -H "Authorization: Bearer YOUR_API_KEY"

Update flags:

curl -X PATCH "https://api.ud-sandbox.com/partner/v3/domains/example.com/flags?\$preview=false" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "DNS_TRANSFER_OUT": false,
    "DNS_WHOIS_PROXY": true
  }'

Common patterns include:

  • Enabling transfer lock (DNS_TRANSFER_OUT: false) on newly registered domains to prevent accidental transfers.
  • Enabling WHOIS privacy (DNS_WHOIS_PROXY: true) to protect registrant information.

Webhooks

Webhooks provide real-time notifications when operations complete, fail, or require action. For production systems, webhooks are more efficient than polling and ensure you respond to events promptly.

Event Types

TypeDescription
OPERATION_FINISHEDAn operation has completed (successfully or with failure)
OPERATION_ACTION_REQUIREDAn operation needs manual intervention to proceed
OPERATION_CREATEDA new operation has been started

Registering a Webhook

Register a webhook endpoint to receive notifications:

curl -X POST "https://api.ud-sandbox.com/partner/v3/account/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-platform.com/webhooks/ud",
    "type": "OPERATION_FINISHED"
  }'

Register multiple webhooks if you want to listen for different event types.

Webhook Payload

When an event occurs, the API sends a POST request to your registered URL with a JSON body containing:

FieldDescription
@typeThe webhook payload type identifier
typeThe event type (e.g., OPERATION_FINISHED)
dataThe full Operation object with current status and dependencies

The request includes two headers for verification:

  • x-ud-timestamp -- The Unix timestamp when the webhook was sent.
  • x-ud-signature -- A Base64-encoded HMAC-SHA256 signature of the raw request body, using your API key as the secret.

Verifying Webhook Signatures

Always verify the x-ud-signature header to confirm the webhook came from Unstoppable Domains. Compute the HMAC-SHA256 of the raw request body bytes using your API key as the secret, then Base64-encode the result. Compare it to the value in the x-ud-signature header.

Example in Node.js:

const crypto = require("crypto");

function verifyWebhook(rawBody, signature, apiKey) {
  const expected = crypto
    .createHmac("sha256", apiKey)
    .update(rawBody)
    .digest("base64");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Retry Behavior

If your endpoint does not respond with a 200 status code, the API retries with exponential backoff for up to 8 attempts:

RetryDelay
11 minute
22 minutes
34 minutes
48 minutes
516 minutes
632 minutes
764 minutes
8120 minutes

Your endpoint must respond with HTTP 200 to acknowledge receipt. Any other status code triggers a retry.

Webhooks vs. Polling

Use webhooks in production for efficient, real-time notifications. Polling (repeatedly calling GET /operations/{id}) is acceptable during development and debugging, but is not recommended for production due to unnecessary API load and delayed responses.

Error Handling

Error Response Format

When a request fails, the API returns a JSON error response with a status code and descriptive message:

{
  "code": "VALIDATION_ERROR",
  "message": "The 'name' field is required.",
  "status": 400
}

Common Status Codes

CodeMeaning
400Validation error -- the request body or parameters are invalid
401Authentication error -- the API key is missing or invalid
403Permission error -- the API key does not have access to this resource
404Not found -- the requested domain, contact, or operation does not exist
409Conflict -- the action conflicts with the current state (e.g., the domain is already registered)
500Internal server error -- retry the request after a short delay

Partial Failures

An Operation can have some dependencies that COMPLETED and others that FAILED. When an operation finishes, always check the status of each individual dependency rather than relying solely on the top-level operation status. This allows you to identify exactly which part of a multi-step operation failed and take appropriate corrective action.

For complete endpoint details, request schemas, and response examples, see the API Reference.