Skip to main content
POST /domains/availability accepts up to 25 domains per call and returns one row per domain - available, taken, premium, or unusable for a specific provider. The cache is fresh for 5 minutes per domain; stale rows return reason: "stale" and Peeker refreshes them in the background.

Full workflow

cURL · full workflow
BASE="https://api.peeker.ai/api/partner/v1"
AUTH="Authorization: Bearer pk_test_<your-key>"

# Step 1: Bulk-check the candidates the customer typed.
#         Up to 25 per request; debounce 250-400ms client-side.
curl -X POST "$BASE/domains/availability" \
  -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{ "domains": ["acme-mail.com", "team-acme.com", "premium-domain.com"] }'

# Step 2: Filter the response - show only orderable rows in your UI.
#         (Same call; pipe through jq to demonstrate the filter shape.)
curl -sS -X POST "$BASE/domains/availability" \
  -H "$AUTH" -H 'Content-Type: application/json' \
  -d '{ "domains": ["acme-mail.com", "team-acme.com", "premium-domain.com"] }' \
  | jq '.data.domains[] | select(.available and (.usable_for // [] | index("google")))'

Steps in detail

1. Send the batch

Per-row fields:
FieldMeaning
availabletrue if you can register and order it now.
usable_forWhich mail providers the domain can run - ["google", "microsoft"], ["google"] only, or absent if unavailable.
premiumtrue if the registry classifies it as premium (high cost, manual procurement only).
reasonPresent only when available: false. Possible values: taken, premium, invalid, errored, stale.
200 OK
{
  "data": {
    "domains": [
      { "domain": "acme-mail.com",      "available": true,  "usable_for": ["google", "microsoft"], "premium": false },
      { "domain": "team-acme.com",      "available": false, "premium": false, "reason": "taken"   },
      { "domain": "premium-domain.com", "available": false, "premium": true,  "reason": "premium" }
    ]
  }
}
In your UI, present any available: true row that includes the customer’s chosen provider in usable_for. Hide premium and stale rows or surface them as “needs manual help.”
The availability cache is fresh for 5 minutes per domain. Stale rows return reason: "stale" and Peeker refreshes them in the background.In a search box, debounce keystrokes by 250–400 ms and batch the latest typed candidates into one call. Don’t fire one request per character - a single call with 25 domains is far cheaper (and burns one rate-limit token instead of 25).
If a row comes back with premium: true, you can’t place an order against it - POST /orders rejects it with premium_domain_not_supported. Surface premiums as “contact us” in your UI; partners on a manual procurement plan can email support to acquire them.
400 premium_domain_not_supported
{
  "error": {
    "code":    "premium_domain_not_supported",
    "message": "A premium domain was submitted on the standard order flow",
    "field":   "domains",
    "details": { "domains": ["premium-domain.com"] }
  }
}

What’s next

Buying domains & ordering

Take the available domains and place an order - Peeker buys from a partner registrar.

Importing domains & ordering

The customer already owns domains? Import them and order on top.
Last modified on June 29, 2026