openapi: 3.0.3

info:
  title: DomainKits - Domain Search & Intelligence API
  version: "0.1.0-beta"
  description: |
    The DomainKits REST API provides programmatic access to domain intelligence data.
    Search newly registered, active, aged, expired, and deleted domains. Look up WHOIS
    records, DNS and reverse nameserver data, inspect Certificate Transparency logs,
    generate registered typo variants, and download NRDs data files.

    Responses contain no personal data. WHOIS results are limited to registrar, dates,
    status codes and nameservers; registrant names, emails, addresses and phone numbers
    are not returned.

    API access requires a Premium or higher plan. Interactive documentation:
    https://domainkits.com/dev/api-docs
  contact:
    url: https://domainkits.com/dev/api-docs
  termsOfService: https://domainkits.com/terms

servers:
  - url: https://premium-api.domainkits.com/api/v1

security:
  - BearerAuth: []
  - ApiKeyAuth: []

tags:
  - name: Search
    description: Domain lifecycle search (nrds, aged, active, expired, deleted, market). Most types support two modes; keyword search and TLD browse.
  - name: Tools
    description: Per-domain lookups (WHOIS, DNS, reverse NS, safety, IP, registrar, status codes)
  - name: Certificate Transparency
    description: Certificate Transparency subdomain, certificate, and free-text search
  - name: Typosquat
    description: Registered typo, combosquatting, IDN homograph, and TLD variants for a domain
  - name: Monitor
    description: Domain change tracking
  - name: Trends
    description: Registration volume and keyword trends
  - name: Download
    description: Bulk data file downloads
  - name: Account
    description: API key usage

paths:

  # ==================== Search ====================

  /search/nrds:
    get:
      tags: [Search]
      operationId: searchNrds
      summary: Search newly registered domains (last 60 days)
      description: |
        Two modes. Keyword search: provide `keyword` to search across all TLDs.
        TLD browse: provide `tld` without `keyword` to browse all new registrations
        under a gTLD (gTLDs only, ccTLDs not supported). At least one of `keyword`
        or `tld` is required. Add `export=csv|txt` to download up to 50,000 results.
      parameters:
        - $ref: '#/components/parameters/keyword'
        - $ref: '#/components/parameters/tldBrowse'
        - $ref: '#/components/parameters/position'
        - $ref: '#/components/parameters/lengthRange'
        - $ref: '#/components/parameters/typeFilter'
        - name: days_range
          in: query
          description: Registration recency in days.
          schema: { type: string, enum: ["0-10", "10-20", "20+"] }
        - name: reg_date
          in: query
          description: >-
            Filter by registration date. Accepts a full date (`2026-07-10`),
            a month (`2026-07`), or a year (`2026`); a `from:to` range is also
            accepted (`2026-07-01:2026-07-25`, inclusive of both ends), and
            either side may be omitted for an open-ended range (`2026-07-20:`
            or `:2026-07-20`).
          schema:
            type: string
            pattern: '^(\d{4}(-\d{2}(-\d{2})?)?|[^:]*:[^:]*)$'
          examples:
            day: { value: "2026-07-10", summary: One day }
            month: { value: "2026-07", summary: One month }
            range: { value: "2026-07-01:2026-07-25", summary: Date range }
        - name: period
          in: query
          description: Registration term in years.
          schema: { type: string, enum: ["1", "2-5", "6+"] }
        - name: has_sale
          in: query
          description: Only show domains with a marketplace listing.
          schema: { type: string, enum: ["true", "false"] }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - $ref: '#/components/parameters/exclude'
        - name: sort
          in: query
          schema:
            type: string
            enum: [reg_date_desc, reg_date_asc, length_asc, length_desc, period_asc, period_desc, tld_counter_asc, tld_counter_desc, alpha]
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/export'
      responses:
        "200":
          description: Search results (JSON), or a CSV/TXT file when `export` is set.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SearchEnvelope'
                  - type: object
                    properties:
                      data:
                        type: array
                        items: { $ref: '#/components/schemas/NrdsItem' }
            text/csv:
              schema: { type: string, description: "Columns: domain, registered_date, expiry_date, tld_count" }
            text/plain:
              schema: { type: string, description: One domain per line }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /search/aged:
    get:
      tags: [Search]
      operationId: searchAged
      summary: Search aged domains (5 to 20+ years of registration history)
      description: |
        Two modes. Keyword search: provide `keyword`. TLD browse: provide `tld` without
        `keyword` (gTLDs only). At least one of `keyword` or `tld` is required.
        Add `export=csv|txt` to download up to 50,000 results.
      parameters:
        - $ref: '#/components/parameters/keyword'
        - $ref: '#/components/parameters/tldBrowse'
        - $ref: '#/components/parameters/position'
        - $ref: '#/components/parameters/lengthRange'
        - $ref: '#/components/parameters/typeFilter'
        - name: age_range
          in: query
          description: >-
            Domain age in years. Accepts a preset band (`5-10`, `10-15`,
            `15-20`, `20+`; each excludes its lower bound and includes its
            upper), an exact age (`25`), or a range (`20-25`, inclusive of
            both ends). Supports multi-select with a comma, e.g. `5-10,20+`.
          schema:
            type: string
            example: "20+"
          examples:
            band: { value: "20+", summary: Preset band }
            exact: { value: "25", summary: Exactly 25 years old }
            range: { value: "20-25", summary: 20 to 25 years old }
            multi: { value: "5-10,20+", summary: Multi-select }
        - name: has_sale
          in: query
          schema: { type: string, enum: ["true", "false"] }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - $ref: '#/components/parameters/exclude'
        - name: sort
          in: query
          schema:
            type: string
            enum: [age_desc, age_asc, length_asc, length_desc, reg_date_asc, reg_date_desc, alpha, tld_counter_asc, tld_counter_desc]
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/export'
      responses:
        "200":
          description: Search results (JSON), or a CSV/TXT file when `export` is set.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SearchEnvelope'
                  - type: object
                    properties:
                      data:
                        type: array
                        items: { $ref: '#/components/schemas/AgedItem' }
            text/csv:
              schema: { type: string }
            text/plain:
              schema: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /search/active:
    get:
      tags: [Search]
      operationId: searchActive
      summary: Search active (currently registered) domains, 240M+ inventory
      description: |
        Two modes. Keyword search: provide `keyword`. TLD browse: provide `tld` without
        `keyword` to browse the full registered inventory of a gTLD, shortest names
        first (gTLDs only). At least one of `keyword` or `tld` is required.
        Add `export=csv|txt` to download up to 50,000 results; the active CSV contains
        a single domain column.
      parameters:
        - $ref: '#/components/parameters/keyword'
        - $ref: '#/components/parameters/tldBrowse'
        - name: position
          in: query
          description: Keyword position. Keyword mode only.
          schema: { type: string, enum: [start, end, contain] }
        - $ref: '#/components/parameters/lengthRange'
        - $ref: '#/components/parameters/typeFilter'
        - name: status
          in: query
          description: Registration status filter.
          schema: { type: string, enum: [forsale] }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - name: sort
          in: query
          schema: { type: string, enum: [length_asc, length_desc, alpha] }
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/export'
      responses:
        "200":
          description: Search results (JSON), or a CSV/TXT file when `export` is set.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SearchEnvelope'
                  - type: object
                    properties:
                      data:
                        type: array
                        items: { $ref: '#/components/schemas/ActiveItem' }
            text/csv:
              schema: { type: string, description: Single domain column }
            text/plain:
              schema: { type: string, description: One domain per line }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /search/expired:
    get:
      tags: [Search]
      operationId: searchExpired
      summary: Search expired domains (grace, redemption, pending delete)
      description: |
        Two modes. Keyword search: provide `keyword`. TLD browse: provide `tld` without
        `keyword` (gTLDs only). At least one of `keyword` or `tld` is required.
        Add `export=csv|txt` to download up to 50,000 results.
      parameters:
        - $ref: '#/components/parameters/keyword'
        - $ref: '#/components/parameters/tldBrowse'
        - $ref: '#/components/parameters/position'
        - $ref: '#/components/parameters/lengthRange'
        - $ref: '#/components/parameters/typeFilter'
        - name: age_range
          in: query
          description: >-
            Domain age in years. Accepts a preset band (`0-5`, `5-10`,
            `10-20`, `20+`; `0-5` includes both ends, the rest exclude
            their lower bound and include their upper), an exact age
            (`25`), or a range (`20-25`, inclusive of both ends).
            Supports multi-select with a comma, e.g. `0-5,20+`.
          schema:
            type: string
          examples:
            band: { value: "20+", summary: Preset band }
            exact: { value: "25", summary: Exactly 25 years old }
            range: { value: "20-25", summary: 20 to 25 years old }
            multi: { value: "0-5,20+", summary: Multi-select }
        - name: status
          in: query
          description: Expiry stage filter.
          schema: { type: string, enum: [expired, redemption, pending_delete] }
        - name: hold
          in: query
          schema: { type: string, enum: [no_hold, has_hold] }
        - name: new
          in: query
          description: >-
            Only domains that entered the expired pool recently: `1` within
            the last observed day, `2` within the last 2 days, `3` within the
            last 3 days. `true` is equivalent to `3`. Applies to the
            `expired` stage only; domains already in redemption or pending
            delete are never matched.
          schema: { type: string, enum: ["1", "2", "3", "true"] }
        - name: auction_date
          in: query
          description: "Filter by drop/auction date: today, tomorrow, or YYYY-MM-DD."
          schema: { type: string }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - $ref: '#/components/parameters/exclude'
        - name: sort
          in: query
          schema: { type: string, enum: [age_desc, age_asc, length_asc, length_desc] }
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/export'
      responses:
        "200":
          description: Search results (JSON), or a CSV/TXT file when `export` is set.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SearchEnvelope'
                  - type: object
                    properties:
                      data:
                        type: array
                        items: { $ref: '#/components/schemas/ExpiredItem' }
            text/csv:
              schema: { type: string }
            text/plain:
              schema: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /search/deleted:
    get:
      tags: [Search]
      operationId: searchDeleted
      summary: Search deleted (dropped) domains
      description: |
        Keyword search only; `keyword` is required (no TLD browse mode for this type).
        Add `export=csv|txt` to download up to 50,000 results.
      parameters:
        - name: keyword
          in: query
          required: true
          description: Search keyword (min 3 characters, letters/digits/hyphens).
          schema: { type: string, minLength: 3, maxLength: 64 }
        - name: tld
          in: query
          description: Filter by TLD.
          schema: { type: string }
        - $ref: '#/components/parameters/position'
        - $ref: '#/components/parameters/lengthRange'
        - $ref: '#/components/parameters/typeFilter'
        - name: age_range
          in: query
          description: >-
            Domain age in years. Accepts a preset band (`0-5`, `5-10`,
            `10-20`, `20+`; `0-5` includes both ends, the rest exclude
            their lower bound and include their upper), an exact age
            (`25`), or a range (`20-25`, inclusive of both ends).
            Supports multi-select with a comma, e.g. `0-5,20+`.
          schema: { type: string }
        - name: hold
          in: query
          schema: { type: string, enum: [no_hold, has_hold] }
        - name: new
          in: query
          description: >-
            Only domains that dropped recently: `1` within the last observed
            day, `2` within the last 2 days, `3` within the last 3 days.
            `true` is equivalent to `3`.
          schema: { type: string, enum: ["1", "2", "3", "true"] }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - $ref: '#/components/parameters/exclude'
        - name: sort
          in: query
          schema: { type: string, enum: [age_desc, age_asc, length_asc, length_desc, tld_counter_asc, tld_counter_desc] }
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/export'
      responses:
        "200":
          description: Search results (JSON), or a CSV/TXT file when `export` is set.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SearchEnvelope'
                  - type: object
                    properties:
                      data:
                        type: array
                        items: { $ref: '#/components/schemas/DeletedItem' }
            text/csv:
              schema: { type: string }
            text/plain:
              schema: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /search/market:
    get:
      tags: [Search]
      operationId: searchMarket
      summary: Search marketplace domains listed for sale
      description: |
        Two modes. Keyword search: provide `keyword` (no minimum length). TLD browse:
        provide `tld` without `keyword` to browse all listings under a gTLD, shortest
        names first. At least one of `keyword` or `tld` is required.
        Add `export=csv|txt` to download up to 50,000 results.
      parameters:
        - name: keyword
          in: query
          description: Search keyword (letters/digits/hyphens). No minimum length.
          schema: { type: string, maxLength: 64 }
        - $ref: '#/components/parameters/tldBrowse'
        - name: position
          in: query
          description: >-
            Keyword position within the domain name. Defaults to `start` on
            this endpoint; pass `contain` to match anywhere.
          schema: { type: string, enum: [start, end, contain], default: start }
        - $ref: '#/components/parameters/lengthRange'
        - $ref: '#/components/parameters/typeFilter'
        - name: platform
          in: query
          description: >-
            Marketplace the domain is listed on. Values: `Afternic`, `Atom`,
            `BuyDomains`, `Dan`, `DDD`, `DN.com`, `Godaddy`, `Hugedomains`,
            `SawSells`, `Sedo`, `Venture`, `4.cn`. Case-insensitive.
            Supports multi-select with a comma, e.g. `Sedo,Godaddy`.
          schema:
            type: string
          examples:
            single: { value: "Sedo", summary: One marketplace }
            multi: { value: "Sedo,Godaddy", summary: Multi-select }
        - name: new
          in: query
          description: >-
            Only listings that first appeared on a marketplace recently:
            `1` within the last day, `2` within the last 2 days, `3` within
            the last 3 days. `true` is equivalent to `3`.
          schema: { type: string, enum: ["1", "2", "3", "true"] }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - $ref: '#/components/parameters/exclude'
        - name: sort
          in: query
          description: In TLD browse mode results default to shortest first; only tld_counter_desc changes the order.
          schema: { type: string, enum: [length_asc, length_desc, alpha, tld_counter_asc, tld_counter_desc] }
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
        - $ref: '#/components/parameters/export'
      responses:
        "200":
          description: Search results (JSON), or a CSV/TXT file when `export` is set.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/SearchEnvelope'
                  - type: object
                    properties:
                      data:
                        type: array
                        items: { $ref: '#/components/schemas/MarketItem' }
            text/csv:
              schema: { type: string }
            text/plain:
              schema: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /search/status:
    get:
      tags: [Search]
      operationId: searchStatus
      summary: Search data freshness by source
      description: Returns the last filesystem update time for each lifecycle search dataset.
      responses:
        "200":
          description: Last update time and relative age for each search source.
          content:
            application/json:
              schema:
                type: object
                required: [success, data]
                properties:
                  success: { type: boolean, example: true }
                  data:
                    type: object
                    additionalProperties:
                      $ref: '#/components/schemas/SearchSourceStatus'
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  # ==================== Tools ====================

  /whois:
    get:
      tags: [Tools]
      operationId: whois
      summary: WHOIS registration data for a domain
      parameters:
        - name: domain
          in: query
          required: true
          description: Full domain name including TLD (e.g. abtdomain.com).
          schema: { type: string }
      responses:
        "200":
          description: WHOIS record.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  registered: { type: boolean }
                  data:
                    type: object
                    properties:
                      domain: { type: string }
                      registrar_name: { type: string }
                      created: { type: string, format: date-time }
                      expires: { type: string, format: date-time }
                      updated: { type: string, format: date-time }
                      nameservers:
                        type: array
                        items: { type: string }
                      status:
                        type: array
                        items: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /dns:
    get:
      tags: [Tools]
      operationId: dns
      summary: DNS records for a domain (A, AAAA, MX, NS, SOA)
      parameters:
        - name: domain
          in: query
          required: true
          schema: { type: string }
      responses:
        "200":
          description: DNS records grouped by type.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  data:
                    type: object
                    properties:
                      domain: { type: string }
                      records:
                        type: object
                        description: Keys are record types (A, AAAA, MX, NS, SOA); values are arrays of record objects.
                        additionalProperties: true
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /bulk/dns:
    post:
      tags: [Tools]
      operationId: bulkDns
      summary: Nameservers for up to 20 domains in one request
      description: >
        Resolves nameservers for a list of domains and labels those whose
        nameservers identify a marketplace or a parking service. Each domain in
        the batch draws one unit from the same daily quota as `/dns`, so a batch
        of 20 costs the same as 20 single lookups. Batch calls are additionally
        capped at 5 per minute.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [domains]
              properties:
                domains:
                  type: array
                  maxItems: 20
                  items: { type: string }
                  example: ["example.com", "example.net"]
      responses:
        "200":
          description: One entry per domain, in the order supplied.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  total: { type: integer }
                  registered:
                    type: integer
                    description: How many domains in the batch resolved to nameservers.
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        domain: { type: string }
                        status:
                          type: string
                          description: '`registered` when nameservers were found, `unknown` otherwise.'
                        nameservers:
                          type: array
                          items: { type: string }
                        domain_status:
                          type: string
                          enum: [for_sale, parking]
                          description: >
                            Present only when the nameservers identify a
                            marketplace listing or a parking service. Absent for
                            domains in normal use.
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /bulk/whois:
    post:
      tags: [Tools]
      operationId: bulkWhois
      summary: WHOIS records for up to 30 domains in one request
      description: >
        Registrar, dates, EPP status codes and nameservers for a list of domains.
        No registrant personal data is returned. Each domain in the batch draws
        one unit from the same daily quota as `/whois`, so a batch of 30 costs the
        same as 30 single lookups. Batch calls are additionally capped at 5 per
        minute.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [domains]
              properties:
                domains:
                  type: array
                  maxItems: 30
                  items: { type: string }
                  example: ["example.com", "example.net"]
      responses:
        "200":
          description: One entry per domain, in the order supplied.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  total: { type: integer }
                  registered:
                    type: integer
                    description: How many domains in the batch are registered.
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        domain: { type: string }
                        registered: { type: boolean }
                        registrar_name: { type: string }
                        created: { type: string }
                        updated: { type: string }
                        expires: { type: string }
                        status:
                          type: array
                          items: { type: string }
                          description: EPP status codes as returned by the registry.
                        nameservers:
                          type: array
                          items: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /ns-reverse:
    get:
      tags: [Tools]
      operationId: nsReverse
      summary: Reverse nameserver lookup, all gTLD domains hosted on a nameserver
      parameters:
        - name: ns
          in: query
          required: true
          description: Nameserver hostname (e.g. ns1.example.com).
          schema: { type: string }
        - name: tld
          in: query
          description: Filter results by TLD.
          schema: { type: string }
        - name: keyword
          in: query
          description: Filter by substring within domain names.
          schema: { type: string }
        - name: sort
          in: query
          schema: { type: string, enum: [length_asc, length_desc, alpha_asc, alpha_desc] }
        - $ref: '#/components/parameters/noNumber'
        - $ref: '#/components/parameters/noHyphen'
        - $ref: '#/components/parameters/typeFilter'
        - name: min_len
          in: query
          schema: { type: integer }
        - name: max_len
          in: query
          schema: { type: integer }
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        "200":
          description: Domains using the nameserver.
          content:
            application/json:
              schema:
                type: object
                required: [success, data, total]
                properties:
                  success: { type: boolean }
                  data:
                    type: array
                    items: { type: string }
                    description: Domain names hosted on the nameserver.
                  total:
                    type: integer
                    description: Total matches across all pages.
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /safety:
    get:
      tags: [Tools]
      operationId: safety
      summary: Google Safe Browsing flags and Google index status for a domain
      parameters:
        - name: domain
          in: query
          required: true
          schema: { type: string }
      responses:
        "200":
          description: Safety and index data.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  data:
                    type: object
                    properties:
                      domain: { type: string }
                      safe:
                        type: object
                        properties:
                          is_safe: { type: boolean }
                          threat_types:
                            type: array
                            items: { type: string }
                          matches_count: { type: integer }
                      index:
                        type: object
                        properties:
                          indexed: { type: boolean }
                          index_count: { type: integer }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /ip-lookup:
    get:
      tags: [Tools]
      operationId: ipLookup
      summary: Geolocation and network info for an IP address or domain
      description: Uses MaxMind GeoLite2 data.
      parameters:
        - name: query
          in: query
          required: true
          description: IPv4/IPv6 address or domain name.
          schema: { type: string }
      responses:
        "200":
          description: Geolocation and network details.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  data:
                    type: object
                    properties:
                      ip: { type: string }
                      type: { type: string, example: IPv4 }
                      connection:
                        type: object
                        properties:
                          asn: { type: integer }
                          org: { type: string }
                          isp: { type: string }
                      location:
                        type: object
                        additionalProperties: true
                      timezone: { type: string }
                      attribution: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /registrar:
    get:
      tags: [Tools]
      operationId: registrarCheck
      summary: Search ICANN-accredited registrars by name or IANA ID
      description: Fuzzy name search with common aliases, or exact match by IANA ID. Returns up to 20 registrars.
      parameters:
        - name: query
          in: query
          required: true
          description: Registrar name or IANA ID (e.g. godaddy or 146).
          schema: { type: string }
      responses:
        "200":
          description: Matching registrars.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  data:
                    type: object
                    properties:
                      query: { type: string }
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            id: { type: string }
                            name: { type: string }
                            status: { type: string }
                            rdap_url: { type: string }
                            country: { type: string }
                            contact: { type: string }
                            website: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /status-guide:
    get:
      tags: [Tools]
      operationId: statusGuide
      summary: EPP domain status code reference
      description: Search by status name, alias, or category (e.g. clientHold, pending, security).
      parameters:
        - name: query
          in: query
          required: true
          schema: { type: string }
      responses:
        "200":
          description: Matching status codes with explanations.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  data:
                    type: object
                    properties:
                      query: { type: string }
                      results:
                        type: object
                        additionalProperties:
                          type: object
                          properties:
                            aliases:
                              type: array
                              items: { type: string }
                            category: { type: string }
                            description: { type: string }
                            action: { type: string }
                            severity: { type: string }
                            possible_reasons: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /tld-check:
    get:
      tags: [Tools]
      operationId: tldCheck
      summary: Registration status of a domain prefix across TLDs
      parameters:
        - name: prefix
          in: query
          required: true
          description: Domain prefix to check (e.g. abtdomain).
          schema: { type: string }
        - name: mode
          in: query
          description: Response mode.
          schema: { type: string, enum: [check, count, list], default: check }
        - name: tlds
          in: query
          description: "Comma-separated TLDs to check (mode=check only). Default: com,net,org,io,ai,bot,dev,app,pro,online."
          schema: { type: string }
      responses:
        "200":
          description: Registration status per TLD (check), total count (count), or list of registered TLDs (list).
          content:
            application/json:
              schema:
                type: object
                required: [success, data, total, prefix]
                properties:
                  success: { type: boolean }
                  data:
                    description: >-
                      mode=check returns an object keyed by TLD; mode=list returns an array of
                      registered TLDs; mode=count returns null and reports the figure in `total`.
                    oneOf:
                      - type: object
                        nullable: true
                        additionalProperties:
                          type: string
                          enum: [registered, for_sale, expiring, available]
                      - type: array
                        items: { type: string }
                  total:
                    type: integer
                    description: Number of TLDs the prefix is registered under.
                  prefix: { type: string }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  # ==================== Certificate Transparency ====================

  /ct/subdomains:
    get:
      tags: [Certificate Transparency]
      operationId: ctSubdomains
      summary: Subdomains observed in Certificate Transparency logs
      description: Returns certificate-derived subdomains for a registrable domain.
      parameters:
        - name: domain
          in: query
          required: true
          description: Registrable domain including a TLD.
          schema: { type: string, example: example.com }
        - $ref: '#/components/parameters/ctLimit'
        - $ref: '#/components/parameters/ctScope'
        - $ref: '#/components/parameters/ctAfter'
        - $ref: '#/components/parameters/ctBefore'
      responses:
        "200":
          description: Matching subdomains.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CertificateTransparencyEnvelope' }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }
        "502": { $ref: '#/components/responses/UpstreamError' }
        "503": { $ref: '#/components/responses/ServiceUnavailable' }

  /ct/certs:
    get:
      tags: [Certificate Transparency]
      operationId: ctCertificates
      summary: Certificates observed in Certificate Transparency logs
      description: At least one of `domain` or `fingerprint` is required.
      parameters:
        - name: domain
          in: query
          description: Domain name to match.
          schema: { type: string, example: example.com }
        - name: fingerprint
          in: query
          description: Certificate fingerprint to retrieve.
          schema: { type: string }
        - $ref: '#/components/parameters/ctLimit'
        - $ref: '#/components/parameters/ctScope'
        - name: issuer
          in: query
          description: Filter by certificate issuer.
          schema: { type: string }
        - $ref: '#/components/parameters/ctAfter'
        - $ref: '#/components/parameters/ctBefore'
        - name: cert_type
          in: query
          description: Filter by the certificate type accepted by the CT service.
          schema: { type: string }
      responses:
        "200":
          description: Matching certificates.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CertificateTransparencyEnvelope' }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }
        "502": { $ref: '#/components/responses/UpstreamError' }
        "503": { $ref: '#/components/responses/ServiceUnavailable' }

  /ct/search:
    get:
      tags: [Certificate Transparency]
      operationId: ctSearch
      summary: Search Certificate Transparency records
      description: Free-text CT search. The query must contain at least three characters.
      parameters:
        - name: keyword
          in: query
          required: true
          description: Search keyword (min 3 characters).
          schema: { type: string, minLength: 3 }
        - $ref: '#/components/parameters/ctLimit'
        - name: field
          in: query
          description: Field selector accepted by the CT search service.
          schema: { type: string }
        - name: sort
          in: query
          schema: { type: string }
        - $ref: '#/components/parameters/ctScope'
        - name: issuer
          in: query
          schema: { type: string }
        - $ref: '#/components/parameters/ctAfter'
        - $ref: '#/components/parameters/ctBefore'
        - name: cert_type
          in: query
          schema: { type: string }
        - name: tld
          in: query
          description: Filter by TLD.
          schema: { type: string }
      responses:
        "200":
          description: Matching CT records.
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CertificateTransparencyEnvelope' }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }
        "502": { $ref: '#/components/responses/UpstreamError' }
        "503": { $ref: '#/components/responses/ServiceUnavailable' }

  # ==================== Typosquat ====================

  /typosquat:
    get:
      tags: [Typosquat]
      operationId: typosquat
      summary: Find registered typo, combosquatting, IDN, and TLD variants
      description: |
        Generates character-level typo variants, combosquatting variants, Cyrillic
        IDN homographs encoded as Punycode, and TLD variants for an ASCII domain.
        Registration status is resolved in bulk. By default only registered variants
        are returned and the latest cached WHOIS snapshot is included when available.
        The input domain itself must be ASCII; IDN and Punycode inputs are rejected.
      parameters:
        - name: domain
          in: query
          required: true
          description: ASCII domain name including its public suffix.
          schema: { type: string, example: example.com }
        - name: whois
          in: query
          description: Include the latest cached WHOIS snapshot for registered variants.
          schema: { type: boolean, default: true }
        - name: type
          in: query
          description: Include the generated variant type in each result.
          schema: { type: boolean, default: true }
        - name: unregistered
          in: query
          description: Include generated variants that are not present in the registration dataset.
          schema: { type: boolean, default: false }
      responses:
        "200":
          description: Generated variants and their observed registration status.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TyposquatResponse'
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }
        "502": { $ref: '#/components/responses/UpstreamError' }

  # ==================== Monitor ====================

  /monitor/changes:
    get:
      tags: [Monitor]
      operationId: monitorChanges
      summary: Domain status changes (transfers, drops, renewals, nameserver updates)
      parameters:
        - name: keyword
          in: query
          schema: { type: string }
        - name: tld
          in: query
          schema: { type: string }
        - name: reason
          in: query
          description: Filter by change reason.
          schema: { type: string }
        - name: length
          in: query
          description: Filter by domain name length.
          schema: { type: integer }
        - $ref: '#/components/parameters/noNumber'
        - name: type
          in: query
          description: "Composition filter. Value: `all_number` (digits-only)."
          schema: { type: string, enum: [all_number] }
        - name: date_range
          in: query
          schema: { type: string }
        - name: sort
          in: query
          schema: { type: string }
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        "200":
          description: Change events.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  total: { type: integer }
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        domain: { type: string }
                        tld: { type: string }
                        reason: { type: string }
                        found_date: { type: string, format: date }
                        details_old: { type: string }
                        details_new: { type: string }
                        tld_count: { type: integer }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  # ==================== Trends ====================

  /trends/tlds/{type}:
    get:
      tags: [Trends]
      operationId: tldTrends
      summary: Daily registration volume trends for gTLDs
      description: gTLDs only; ccTLDs are not available. Provide `tld` for a single TLD or `tlds` to compare up to 5.
      parameters:
        - name: type
          in: path
          required: true
          description: active for total registered volume, newly for new registrations.
          schema: { type: string, enum: [active, newly] }
        - name: tld
          in: query
          description: The gTLD to query. Required unless `tlds` is used.
          schema: { type: string }
        - name: tlds
          in: query
          description: Compare multiple gTLDs (comma-separated, max 5). Replaces `tld`.
          schema: { type: string }
        - name: days
          in: query
          schema: { type: integer, enum: [7, 14, 30, 60, 90, 180], default: 30 }
      responses:
        "200":
          description: Daily data points with 7-day and 14-day moving averages. Single-TLD requests return an array; multi-TLD requests return an object keyed by TLD.
          content:
            application/json:
              schema:
                type: object
                required: [success, data, total]
                properties:
                  success: { type: boolean }
                  total: { type: integer }
                  tld: { type: string }
                  type: { type: string }
                  days: { type: integer }
                  data:
                    description: Array of points, or object keyed by TLD when using `tlds`.
                    oneOf:
                      - type: array
                        items:
                          type: object
                          properties:
                            date: { type: string, format: date }
                            original: { type: integer }
                            ma7: { type: integer }
                            ma14: { type: integer }
                      - type: object
                        additionalProperties: true
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /trends/keywords/{type}:
    get:
      tags: [Trends]
      operationId: keywordTrends
      summary: Trending domain registration keywords
      description: "hot: top keywords by total registrations. emerging: fastest growing keywords. prefix: trending domain prefixes with registration counts."
      parameters:
        - name: type
          in: path
          required: true
          schema: { type: string, enum: [hot, emerging, prefix] }
        - name: scope
          in: query
          description: all or com (.com only). hot and emerging only.
          schema: { type: string, enum: [all, com], default: all }
        - name: limit
          in: query
          description: "Number of results (default 20). Tier cap: Premium 50, Platinum 100."
          schema: { type: integer, default: 20, maximum: 100 }
      responses:
        "200":
          description: Ranked keyword or prefix list with weekly breakdowns.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  type: { type: string }
                  scope: { type: string }
                  total: { type: integer }
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  # ==================== Download ====================

  /nrds/download:
    get:
      tags: [Download]
      operationId: nrdsDownload
      summary: Download newly registered domains data files
      description: |
        Returns a 302 redirect to a signed download URL valid for 5 minutes.
        Each file can be downloaded up to 3 times per day per API key.
        File types: domains_only (.txt.gz), basic_info (.csv.gz),
        full_whois (.csv.gz, Platinum only).
      parameters:
        - name: tld
          in: query
          description: TLD to download. Defaults to all TLDs combined.
          schema: { type: string }
        - name: type
          in: query
          schema: { type: string, enum: [domains_only, basic_info, full_whois], default: domains_only }
        - name: date
          in: query
          description: Date in YYYY-MM-DD format. Defaults to today.
          schema: { type: string, format: date }
      responses:
        "302":
          description: Redirect to the signed file URL.
          headers:
            Location:
              schema: { type: string, format: uri }
        "400": { $ref: '#/components/responses/BadRequest' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  # ==================== Account ====================

  /usage:
    get:
      tags: [Account]
      operationId: usage
      summary: Current API key usage and per-endpoint counters
      responses:
        "200":
          description: Tier and per-endpoint usage. Unlimited values are returned as the string `unlimited`.
          content:
            application/json:
              schema:
                type: object
                required: [success, data]
                properties:
                  success: { type: boolean, example: true }
                  data:
                    type: object
                    required: [tier, endpoints]
                    properties:
                      tier: { type: string, enum: [premium, platinum] }
                      endpoints:
                        type: array
                        items: { $ref: '#/components/schemas/EndpointUsage' }
        "401": { $ref: '#/components/responses/Unauthorized' }
        "403": { $ref: '#/components/responses/Forbidden' }
        "429": { $ref: '#/components/responses/RateLimited' }

  /health:
    get:
      tags: [Account]
      operationId: health
      summary: Service health check (no authentication required)
      security: []
      responses:
        "200":
          description: Aggregate and per-service health.
          content:
            application/json:
              schema:
                type: object
                required: [success, status, services]
                properties:
                  success: { type: boolean, example: true }
                  status: { type: string, enum: [operational, degraded] }
                  services:
                    type: array
                    items:
                      $ref: '#/components/schemas/ServiceHealth'

components:

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: "API key as bearer token: Authorization: Bearer dk_xxx"
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API key in a custom header.

  parameters:
    keyword:
      name: keyword
      in: query
      description: Search keyword (min 3 characters, letters/digits/hyphens). Omit to use TLD browse mode.
      schema: { type: string, minLength: 3, maxLength: 64 }
    tldBrowse:
      name: tld
      in: query
      description: Filter by TLD (e.g. com, net, org). Without `keyword`, enters TLD browse mode (gTLDs only, ccTLDs not supported).
      schema: { type: string }
    position:
      name: position
      in: query
      description: Keyword position within the domain name.
      schema: { type: string, enum: [start, end, contain] }
    lengthRange:
      name: length
      in: query
      description: >-
        Domain name length, excluding the TLD. Accepts a preset band
        (`<5`, `5-10`, `10-15`, `15+`), an exact length (`10`), or a
        range (`8-12`, inclusive of both ends). Unrecognised values are
        ignored and no length filter is applied.
      schema:
        type: string
        pattern: '^(<5|15\+|\d+(-\d+)?)$'
      examples:
        band: { value: "5-10", summary: Preset band }
        exact: { value: "10", summary: Exactly 10 characters }
        range: { value: "8-12", summary: 8 to 12 characters }
    typeFilter:
      name: type
      in: query
      description: Composition filter.
      schema: { type: string, enum: [all_alpha, all_number] }
    noNumber:
      name: no_number
      in: query
      description: Exclude domains containing digits.
      schema: { type: string, enum: ["true", "false"] }
    noHyphen:
      name: no_hyphen
      in: query
      description: Exclude domains containing hyphens.
      schema: { type: string, enum: ["true", "false"] }
    exclude:
      name: exclude
      in: query
      description: Negative keywords to exclude from results (comma-separated).
      schema: { type: string }
    limit:
      name: limit
      in: query
      description: "Results per page (default: 40, max: 500)."
      schema: { type: integer, default: 40, maximum: 500 }
    offset:
      name: offset
      in: query
      description: Pagination offset.
      schema: { type: integer, default: 0 }
    export:
      name: export
      in: query
      description: |
        Download results as a file instead of JSON. Bypasses pagination, returns up to
        50,000 rows, and uses the separate Search Export rate limit. Works in keyword
        mode and TLD browse mode. csv columns are domain, registered_date, expiry_date,
        tld_count (active returns a single domain column); txt is one domain per line.
      schema: { type: string, enum: [csv, txt] }
    ctLimit:
      name: limit
      in: query
      description: Maximum number of CT records requested from the upstream service.
      schema: { type: integer, minimum: 1 }
    ctScope:
      name: scope
      in: query
      description: Scope selector accepted by the CT service.
      schema: { type: string }
    ctAfter:
      name: after
      in: query
      description: Lower time boundary accepted by the CT service.
      schema: { type: string }
    ctBefore:
      name: before
      in: query
      description: Upper time boundary accepted by the CT service.
      schema: { type: string }

  responses:
    BadRequest:
      description: Bad request (missing or invalid parameters).
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    Forbidden:
      description: The API key's plan cannot access the endpoint, or access is temporarily suspended.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    RateLimited:
      description: Rate limit exceeded. Check X-RateLimit-* response headers.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    UpstreamError:
      description: A required upstream data service timed out or returned an invalid response.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
    ServiceUnavailable:
      description: The endpoint's backing service is not configured or unavailable.
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }

  schemas:
    SearchSourceStatus:
      type: object
      required: [last_updated]
      properties:
        last_updated:
          type: string
          format: date-time
          nullable: true
        last_updated_ago:
          type: string
          description: Human-readable age rounded to minutes. Omitted when the source file is unavailable.

    CertificateTransparencyEnvelope:
      type: object
      required: [success, data, total]
      properties:
        success: { type: boolean, example: true }
        total:
          type: integer
          minimum: 0
          description: Number of CT records matched.
        data:
          description: CT records returned by the backing service.
          oneOf:
            - type: array
              items:
                type: object
                additionalProperties: true
            - type: object
              additionalProperties: true

    TyposquatResponse:
      type: object
      required: [success, data, total, domain, variants_generated, variants_registered]
      properties:
        success: { type: boolean, example: true }
        data:
          type: array
          items: { $ref: '#/components/schemas/TyposquatVariant' }
        total:
          type: integer
          description: Number of entries in `data`, affected by the `unregistered` option.
        domain:
          type: string
          description: Normalized ASCII input domain.
        variants_generated:
          type: integer
          description: Number of unique variants generated.
        variants_registered:
          type: integer
          description: Number of generated variants observed as registered.
        whois_note:
          type: string
          description: Present when WHOIS enrichment is enabled; clarifies that WHOIS is cached.

    TyposquatVariant:
      type: object
      required: [domain, registered]
      properties:
        domain: { type: string }
        type:
          type: string
          description: Omitted when `type=false`.
          enum:
            - omission
            - transposition
            - replacement
            - insertion
            - repetition
            - hyphenation
            - vowel-swap
            - homoglyph
            - plural
            - exact-tld
            - tld-swap
            - combosquatting
            - idn-homograph
        registered: { type: boolean }
        status:
          type: string
          description: Present for registered variants.
          enum: [registered, for_sale, expiring]
        latest_whois:
          allOf:
            - $ref: '#/components/schemas/CachedWhois'
          description: Present when WHOIS enrichment is enabled and a cached record exists.

    CachedWhois:
      type: object
      properties:
        created: { type: string }
        updated: { type: string }
        expires: { type: string }
        registrar_name: { type: string }
        status:
          type: array
          items: { type: string }
        nameservers:
          type: array
          items: { type: string }

    EndpointUsage:
      type: object
      required: [endpoint, rate_per_minute, daily_used, daily_limit, daily_remaining]
      properties:
        endpoint: { type: string }
        rate_per_minute:
          oneOf:
            - type: integer
            - type: string
              enum: [unlimited]
        daily_used: { type: integer, minimum: 0 }
        daily_limit:
          oneOf:
            - type: integer
            - type: string
              enum: [unlimited]
        daily_remaining:
          oneOf:
            - type: integer
            - type: string
              enum: [unlimited]
        page_limit:
          type: integer
          description: Present only for endpoints with a tier-specific page cap.

    ServiceHealth:
      type: object
      required: [name, status]
      properties:
        name: { type: string }
        status: { type: string, enum: [operational, degraded, down] }
        last_update:
          type: string
          description: Present for the NRDs download dataset when an update is available.

    Error:
      type: object
      properties:
        success: { type: boolean, example: false }
        error: { type: string }

    SearchEnvelope:
      type: object
      properties:
        success: { type: boolean }
        total:
          type: integer
          description: Total matching results.

    NrdsItem:
      type: object
      properties:
        domain: { type: string }
        registered_date: { type: string, format: date }
        expiry_date: { type: string, format: date }
        tld_count: { type: integer }
        status: { type: string, enum: [registered, for_sale] }

    AgedItem:
      type: object
      properties:
        domain: { type: string }
        age: { type: integer, description: Age in years }
        tld_count: { type: integer }
        status: { type: string, enum: [registered, for_sale] }

    ActiveItem:
      type: object
      properties:
        domain: { type: string }
        status: { type: string, enum: [registered, for_sale] }
        tld_count:
          type: integer
          description: Present when supplied by the active-domain search source.

    ExpiredItem:
      type: object
      properties:
        domain: { type: string }
        age: { type: integer }
        tld_count: { type: integer }
        status: { type: string, enum: [expired, redemption, pending delete] }

    DeletedItem:
      type: object
      properties:
        domain: { type: string }
        age: { type: integer }
        tld_count: { type: integer }
        status: { type: string, enum: [available] }

    MarketItem:
      type: object
      properties:
        domain: { type: string }
        tld: { type: string }
        components: { type: string }
        tld_count: { type: integer }
        status: { type: string, enum: [for_sale] }
