---
title: "Bulk Registration"
method: POST
path: "/bulk-registration"
tags: ["tools"]
---

# Bulk Registration

`POST /bulk-registration`

## Request

- Base URL: `https://dnsdoctor.dev/api/v1`
- URL: `https://dnsdoctor.dev/api/v1/bulk-registration`
- Auth: none declared

RDAP registration for 2-50 domains in one paid call. **402 on every call.**

Priced per domain from the batch. Settled only when at least one row is a
registry answer (`registered` / `not_registered`); an all-`unknown` batch is
returned unsettled.

## Request body

- BulkRegistrationIn: 2-50 domains, canonicalized and deduped server-side. Bounded at the model as bulk-scan's body is, so pydantic refuses an oversized array during parse; `_normalize` re-checks the floor on the DEDUPED count, which is what runs and what is priced.
  - `domains` string[], required

## Response `200`

Successful Response

- BulkRegistrationOut: The batch. `domains_resolved` is what the settle gate reads. Every requested name gets a row, in request order — `unknown` with a reason when it could not be read, so "missing" is never mistaken for an answer.
  - `domains_requested` integer, required
  - `domains_resolved` integer, required
  - `results` RegistrationResponse[], required
    - `domain` string, required
    - `status` 'registered' | 'not_registered' | 'unknown', required: What the registry told us. `UNKNOWN` is the honest third answer. Deliberately three-valued: a registry that did not answer has said nothing about the domain, and collapsing that into `NOT_REGISTERED` would tell a caller a name is free on the strength of a 429.
    - `reason` string, nullable
    - `registration` Registration: What a registry publishes about one domain. Observation only. Every field is optional because every field is redactable: a registry that publishes only status codes and nameservers is the normal post-GDPR case, not a failure. `status` carries the registry's own strings verbatim (RFC 9083 spells them `client transfer prohibited`; some registries still emit EPP camelCase) — normalizing them would invent a vocabulary neither side uses.
      - `registrar` string, nullable
      - `registrar_iana_id` string, nullable
      - `registered_at` string, date-time, nullable
      - `updated_at` string, date-time, nullable
      - `expires_at` string, date-time, nullable
      - `status` string[]
      - `nameservers` string[]
      - `dnssec` boolean, nullable
      - `abuse_email` string, nullable
      - `redacted` boolean
    - `queried_at` string, date-time, required

## Other responses

- `402`: Payment required — retry with an x402 payment header.
- `422`: Validation Error

---

[API](https://skmtc.dev/dnsdoctor/apis/dns-doctor-api.md) · [All operations](https://skmtc.dev/dnsdoctor/apis/dns-doctor-api/llms.txt) · [OpenAPI document](https://skmtc.dev/dnsdoctor/apis/dns-doctor-api/revisions/1d0114806e76?raw)
