DomainDrift Domains API

The Domains API from DomainDrift — 5 operation(s) for domains.

Operations 6

GET /v1/domains List tracked domains #
POST /v1/domains Add domain(s) to catalog #
GET /v1/domains/{domain} Latest signal snapshot for domain #
GET /v1/domains/{domain}/history Snapshot history #
GET /v1/domains/{domain}/provenance Provenance receipts #
GET /v1/domains/{domain}/bundle Evidence bundle #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/domaindrift-io:domaindrift-io-domains-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

domaindrift-io-domains-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: DomainDrift - Continuous Internet Telemetry Domains API
  version: 1.220.0
  description: Continuous internet telemetry across ~809,000 curated domains. DNS, TLS, WHOIS, HTTPS, subdomains, DNSSEC, ASN - every observation Ed25519-signed with provenance receipts. Public alpha.
servers:
- url: https://domaindrift.io
security:
- apiKey: []
tags:
- name: Domains
paths:
  /v1/domains:
    get:
      summary: List tracked domains
      description: Paginated list of domains in the catalog. Filter by category or search by name.
      parameters:
      - name: category
        in: query
        schema:
          type: string
        description: Filter by category slug (e.g. ai_ml, crypto_web3)
      - name: q
        in: query
        schema:
          type: string
        description: Substring search on the domain name (case-insensitive; % and _ are matched literally)
      - name: page
        in: query
        schema:
          type: integer
          default: 1
      - name: limit
        in: query
        schema:
          type: integer
          default: 50
          maximum: 200
      - name: format
        in: query
        schema:
          type: string
          enum:
          - json
          - csv
        description: csv returns the same filtered+paginated set as a text/csv download (flat columns).
      responses:
        '200':
          description: Paginated domain list (JSON), or a text/csv download when format=csv
          content:
            application/json:
              schema:
                type: object
                properties:
                  domains:
                    type: array
                    items:
                      $ref: '#/components/schemas/DomainSummary'
                  pagination:
                    type: object
                    properties:
                      page:
                        type: integer
                      limit:
                        type: integer
                      total:
                        type: integer
                      pages:
                        type: integer
      tags:
      - Domains
      operationId: getV1Domains
      x-operation-id-source: derived
    post:
      summary: Add domain(s) to catalog
      description: 'Add one or more domains (max 100 per request). Duplicates are NOT an error: they come back 200 with results[].status "exists". Per-domain outcomes: added, reactivated, exists, rejected.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              description: Provide either `domain` (single) or `domains` (bulk, max 100).
              properties:
                domain:
                  type: string
                  example: example.com
                domains:
                  type: array
                  items:
                    type: string
                  description: Bulk add (max 100)
                category:
                  type: string
                  example: dev_tools
      responses:
        '200':
          description: Nothing new added (every domain already exists or was rejected). Same body format as 201.
        '201':
          description: At least one domain added or reactivated - scanned on the next sweep
          content:
            application/json:
              schema:
                type: object
                properties:
                  service:
                    type: string
                    example: connor
                  version:
                    type: string
                  timestamp:
                    type: string
                    format: date-time
                  added:
                    type: integer
                    description: Count of added + reactivated domains
                  total:
                    type: integer
                    description: Count of processed domains
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        domain:
                          type: string
                        status:
                          type: string
                          enum:
                          - added
                          - reactivated
                          - exists
                          - rejected
                        error:
                          type: string
                          description: Present when status is rejected
        '400':
          description: Missing domain(s) or more than 100 domains in one request
      tags:
      - Domains
      operationId: postV1Domains
      x-operation-id-source: derived
  /v1/domains/{domain}:
    get:
      summary: Latest signal snapshot for domain
      description: Returns the most recent DNS, HTTPS probe, and enrichment data, from the recent-observation window (last 24h).
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Latest snapshot with DNS records, probe status, and services
        '404':
          description: Domain not in catalog
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      tags:
      - Domains
      operationId: getV1DomainsByDomain
      x-operation-id-source: derived
  /v1/domains/{domain}/history:
    get:
      summary: Snapshot history
      description: Time-series of scan snapshots from the recent-observation window (last 24h) - use the bundle endpoint for a signed 7-day (included) or 90-day (bought) export.
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
      - name: limit
        in: query
        schema:
          type: integer
          default: 20
          maximum: 100
      responses:
        '200':
          description: Array of snapshots ordered by time descending
      tags:
      - Domains
      operationId: getV1DomainsByDomainHistory
      x-operation-id-source: derived
  /v1/domains/{domain}/provenance:
    get:
      summary: Provenance receipts
      description: Ed25519-signed receipts from the recent-observation window (last 24h). Each receipt covers one scanning plane. Use the bundle endpoint for a signed 7-day (included) or 90-day (bought) export.
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
      - name: limit
        in: query
        schema:
          type: integer
          default: 20
          maximum: 100
      responses:
        '200':
          description: Provenance receipt chain
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: string
                  source:
                    type: string
                    enum:
                    - d1
                    description: 'Where these receipts came from: the recent-observation window (last 24h)'
                  receipts:
                    type: array
                    items:
                      $ref: '#/components/schemas/ProvenanceReceipt'
      tags:
      - Domains
      operationId: getV1DomainsByDomainProvenance
      x-operation-id-source: derived
  /v1/domains/{domain}/bundle:
    get:
      summary: Evidence bundle
      description: 'Self-contained signed evidence bundle for offline verification, read from the signed archive. TWO LANES. `window=short` (the default) covers the last 7 days and is included in your plan''s monthly bundle allowance. `window=deep` covers 90 days, is included in no plan, and is bought per export with DRM3 credits. A paid lane requires `pay=credits` in so many words: without it you get a 402 stating the price and the URL that pays it, and NOTHING is debited. A purchase is idempotent per account, lane, domain and UTC day, so a retried download never debits twice. Two modes: full (every receipt) or compact (Merkle rollup).'
      parameters:
      - name: domain
        in: path
        required: true
        schema:
          type: string
      - name: window
        in: query
        description: short = the included 7-day export. deep = the 90-day export, bought with credits.
        schema:
          type: string
          enum:
          - short
          - deep
          default: short
      - name: pay
        in: query
        description: 'Explicit consent to debit your DRM3 credit purse for this export. Only value: credits.'
        schema:
          type: string
          enum:
          - credits
      - name: mode
        in: query
        schema:
          type: string
          enum:
          - full
          - compact
          default: full
      responses:
        '200':
          description: 'JSON evidence bundle (Content-Disposition: attachment). A purchased export also carries X-DRM3-Charged-Credits, plus X-DRM3-Charge-Replay when the debit was a replay of an earlier identical purchase and X-DRM3-Credits-Overdraft when it drew the purse negative.'
        '402':
          description: 'Payment required, and nothing was charged: the monthly allowance is spent, the deep export needs consent, or the credit purse is empty. The body states the price in credits and money, and the URL that pays it.'
        '403':
          description: This account has no bundle entitlement
        '404':
          description: Domain not tracked
        '502':
          description: The credit ledger could not be reached. Nothing was charged.
        '503':
          description: The signed archive could not be read, or credit purchases are not configured. Nothing was charged.
      tags:
      - Domains
      operationId: getV1DomainsByDomainBundle
      x-operation-id-source: derived
components:
  schemas:
    ProvenanceReceipt:
      type: object
      properties:
        receipt_id:
          type: string
          format: uuid
        domain:
          type: string
        scanned_at:
          type: string
          format: date-time
        public_key:
          type: string
        output_hash:
          type: string
        plane:
          type: string
          enum:
          - fast
          - whois
          - asn
          - robots
          - dnssec
          - composite
        parent_receipt_id:
          type: string
          nullable: true
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
    DomainSummary:
      type: object
      properties:
        domain:
          type: string
          example: openai.com
        category:
          type: string
          nullable: true
          example: ai_ml
        last_scanned_at:
          type: string
          format: date-time
          nullable: true
        scan_count:
          type: integer
        ping_ms:
          type: number
          nullable: true
        http_status:
          type: integer
          nullable: true
        probe_verdict:
          type: string
          nullable: true
          enum:
          - ok
          - redirect
          - bot_blocked
          - not_found
          - method_blocked
          - rate_limited
          - client_error
          - server_error
          - cf_blocked
          - no_response
          - timeout
          - tls_error
          - connection_refused
          - network_error
          - dns_failed
          - nxdomain
          - dns_servfail
          - dns_refused
          - dns_timeout
          - dns_empty
        subdomain_count:
          type: integer
        service_count:
          type: integer
        has_dnssec:
          type:
          - integer
          - 'null'
          enum:
          - 0
          - 1
          - null
        dnssec_ok_at:
          type:
          - string
          - 'null'
          description: When the DNSSEC plane last succeeded. NULL means has_dnssec is unmeasured, not false.
        has_ipv6:
          type: boolean
        complexity_score:
          type: number
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-DomainDrift-Key
      description: 'API key with dd_ prefix (legacy keys and headers are still accepted). Rate limit: 100 req/min per key (default).'