Skip to content

API Reference

1. Create User

Anyone can register. Accounts are created pending admin approval — you will not be able to log in or generate API keys until an administrator approves your account. You'll receive a confirmation email once the account is active.

curl -L -i -k \
  -X POST "https://zonefeeds.com/api/auth/register" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "username":"<YOUR_USERNAME>",
    "email":"<YOUR_EMAIL>",
    "password":"<YOUR_PASSWORD>"
  }'

2. Generate API Key

Authenticate with your username and password in the body (no Bearer header on this endpoint). expires_in_days is optional — omit it to use the default for your plan (Trial: 7 days, Basic / Enterprise: 365 days).

curl -L -i -k \
  -X POST "https://zonefeeds.com/api/auth/api-keys/generate" \
  -H "Content-Type: application/json" \
  --data-raw '{
    "username":"<YOUR_USERNAME>",
    "password":"<YOUR_PASSWORD>",
    "name":"<KEY_NAME>",
    "expires_in_days":<DAYS_UNTIL_EXPIRY>
  }'

3. List User API Keys

Returns all active API keys for your account.

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/auth/api-keys" \
  -H "Authorization: Bearer ${API_KEY}"

4. Delete an API Key

Remove a key by its name. Key names that contain spaces or other reserved URL characters must be URL-encoded in the path (e.g. a key called prod key becomes prod%20key).

curl -L -i -k \
  -X DELETE "https://zonefeeds.com/api/auth/api-keys/<KEY_NAME>" \
  -H "Authorization: Bearer ${API_KEY}"

5. Get User Info

Fetch details about the user tied to your API key.

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/auth/me" \
  -H "Authorization: Bearer ${API_KEY}"

6. Search Domains

Search the “dev.zone” dataset for matching domains. Tip: You can replace dev.zone with any zone name returned by List All Zones. Use *.zone (i.e. set the path segment to *) to search across all zones in one query (subject to your plan's limits). Limits: Maximum date range is 10 days. Maximum limit is 10,000 per request. Your plan also applies a ceiling to the effective limit — see Query Parameters below.

Response status codes

Code Meaning
200 Results returned. An empty results array on a cursor request means you've reached the last page.
400 Invalid search pattern, invalid date, start / end in the future, or after / pit sent without the other.
404 First-page query returned zero matching domains. Clients should stop; cursor pages never return 404.
410 The pit session has expired (2 minutes of inactivity). Restart from page 1 to obtain a fresh pit.

First page

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/download/dev.zone?search=<TERM>&limit=<N>" \
  -H "Authorization: Bearer ${API_KEY}"

Next page (cursor-based)

Use the pit and after values returned by the previous response.

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/download/dev.zone?limit=<N>&pit=<PIT_ID>&after=<CURSOR_B64>" \
  -H "Authorization: Bearer ${API_KEY}"

7. Get Delta (google.zone)

Fetch the change-set (“delta”) between two timestamps in the “google.zone” dataset. Tip: You can replace google.zone with any zone name returned by List All Zones.

First page

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/download/google.zone?search=<TERM>&start=<ISO_START>&end=<ISO_END>&limit=<N>" \
  -H "Authorization: Bearer ${API_KEY}"

Next page (cursor-based)

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/download/google.zone?start=<ISO_START>&end=<ISO_END>&limit=<N>&pit=<PIT_ID>&after=<CURSOR_B64>" \
  -H "Authorization: Bearer ${API_KEY}"

8. List All Zones

Retrieve a list of all available zones.

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/zones/" \
  -H "Authorization: Bearer ${API_KEY}"

9. RDAP Domain Lookup

Fetch a live RDAP Dossier for a single domain — registrar of record, lifecycle dates, EPP status codes, abuse contacts, nameservers, and the raw RDAP JSON returned by the authoritative registry. The {domain} path segment must be a single label.tld (e.g. example.com). Repeat lookups of the same domain are served from cache and are free (not counted, not rate-limited). Lookups are metered per plan — see RDAP Rate Limits and Quotas. This endpoint is for interactive, on-demand lookups only. Automated, bulk, or high-volume programmatic use is prohibited — see Acceptable use.

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/rdap/example.com" \
  -H "Authorization: Bearer ${API_KEY}"

Response status codes

Code Meaning
200 RDAP record returned.
400 Invalid domain shape (invalid_domain) or a TLD with no RDAP server wired (unsupported_tld).
403 RDAP is disabled on your tier (rdap_not_available), or your subscription has expired.
404 The registry has no RDAP record for the domain (domain_not_found).
429 Per-minute rate limit (rdap_rate_limited, with a Retry-After header) or daily allowance exhausted (rdap_quota_exceeded, with resets_at).
502 / 504 The upstream registry RDAP server errored or timed out. These do not count against your allowance.

10. List RDAP Zones

List the TLDs for which RDAP Dossier lookups are available.

curl -L -i -k \
  -X GET "https://zonefeeds.com/api/api/v1/rdap/zones" \
  -H "Authorization: Bearer ${API_KEY}"

Query Parameters

Parameter Type Description
search string Domain match applied against the domain field (case-insensitive). If the value contains *, a wildcard match is used (e.g. app*, *-bank*); otherwise a prefix match is used. Allowed characters: a-z, 0-9, ., *, and - (not at the start of a segment).
limit integer Maximum number of records to return. Range: 110000. Default: 1000. Your plan applies its own ceiling on top of this — if you request more than your plan allows, the effective limit is capped server-side without error.
start string ISO 8601 timestamp indicating the inclusive lower bound (e.g. 2025-07-19T10:30:00Z). Must not be in the future.
end string ISO 8601 timestamp indicating the exclusive upper bound (e.g. 2025-07-23T10:30:00Z). Must not be in the future. The window end − start cannot exceed 10 days.
after string Base64-encoded sort cursor to fetch the next page of results. Must be sent together with pit.
pit string Elasticsearch Point-In-Time id used to keep pagination consistent across pages. Returned by the first-page response; valid for 2 minutes after the last request.

Important note on pagination (migration change)

We’ve migrated to a new backend for faster searches. As part of this change, offset-based pagination with skip has been removed.
Use cursor-based pagination with pit and after (plus limit) instead:

  • The first page response includes a pit id. If more results exist, it also includes a next_cursor string.
  • To fetch the next page, send the original query parameters plus pit=<PIT_ID> and after=<next_cursor> (i.e. take the next_cursor value from the previous response and put it in the after= query parameter).
  • A response whose results array is empty or that has no next_cursor is the last page — stop paginating.
  • The pit is valid for 2 minutes after the last request. If it expires, the next cursor call returns 410 and you must restart from the first page to get a fresh pit.
  • Cursor (pagination) requests do not consume your monthly query quota — only the first-page request for a given search does.

Example

Initial request:

GET https://zonefeeds.com/api/api/v1/download/com.zone?start=2025-12-20T10:30:00Z&end=2025-12-25T10:30:00Z&limit=1000&search=technology

Response body:

{
  "pit": "w8abBAYNZGN6ZHMucmVjb3JkcxZ...",
  "results": [
    { "domain": "technology-hub.com", "status": "active", "timestamp": 1734691200000 }
  ],
  "next_cursor": "WzEyODg2XQ=="
}

Next-page request — reuse the original filters and pass pit as-is, after=<next_cursor>:

GET https://zonefeeds.com/api/api/v1/download/com.zone?
  start=2025-12-20T10:30:00Z&
  end=2025-12-25T10:30:00Z&
  limit=1000&
  search=technology&
  pit=w8abBAYNZGN6ZHMucmVjb3JkcxZ...&
  after=WzEyODg2XQ==

Signature reference (server side):

after: Optional[str] = Query(None, description="Base64-encoded sort values")
pit:   Optional[str] = Query(None, description="Elasticsearch PIT id")