audit.domains Sales API

Recorded domain sales search

Operations 2

GET /api/v1/sales Search recorded domain sales (spends nothing, read scope; paid plan required) #
HEAD /api/v1/sales Same as GET without the body #

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/audit-domains:audit-domains-sales-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

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

audit-domains-sales-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: audit.domains public Sales API
  version: 1.3.0
  description: 'Deterministic domain appraisals, comparable sales, bulk valuation, and recorded-sales search. Document version 1.3.0. Since 1.3.0, `GET /api/v1/sales` serves only the curated verified corpus; the legacy `source=ledger` research source was retired so no browser-reachable database RPC can bypass the paid row-level research boundary. Since 1.0.0 the surface gained `GET /api/v1/usage`, a per-key request limiter (answered with `Retry-After` and `X-RateLimit-Reset`), and a monthly API call allowance separate from the site''s appraisal credits - reported by the `X-Credits-*` headers and refused with `402 api_quota_exhausted`. The path prefix stays `/v1`: the locked appraisal projection has not changed, key for key. What this document covers: the five key-authenticated paths listed below - `/api/v1/appraise`, `/api/v1/comps`, `/api/v1/bulk`, `/api/v1/usage`, `/api/v1/sales`. One further route exists under the same prefix and is NOT part of the public contract: `/api/v1/historical-sales/snapshots/active` is an internal serving seam for the website''s own comparables snapshot - anonymous, unmetered, edge-cached, does not use the error envelope described here, and may change without a version bump. Do not build against it. No key? A keyless $5 card lane for single appraisals is described in https://audit.domains/api/openapi-machine.json (POST https://audit.domains/api/machine/resolve); it is not part of this contract. API access is included with paid plans: every request requires an `ad_live_` API key (create one at https://audit.domains/profile?tab=api), keys work only on paid plans, and appraisal-producing calls consume the account''s monthly API allowance. That allowance is SEPARATE from the appraisal credits the website meters: spending one does not spend the other, and a large batch through the API leaves the site quota untouched. When it is spent, calls answer `402 api_quota_exhausted` until the monthly reset. `X-Credits-Limit` / `X-Credits-Remaining` / `X-Credits-Reset` response headers report that allowance and the date it refills, on every response that reached the meter (a 200, or a 402 for a spent allowance); requests rejected before metering - a malformed body, a missing key, a per-IP 429 - carry no meter to report, and `GET /api/v1/usage` reads the same figures without spending a call. `X-RateLimit-Limit` / `X-RateLimit-Remaining` currently repeat those credit figures; those names will be redefined to report the per-key request limiter after an announced notice period of at least 30 days. Key scopes: a key is created with `read` or `write` scope. Endpoints that spend an API call (`/appraise`, `/comps`, `/bulk`) require a `write` key and answer `403 insufficient_scope` otherwise; `/sales` and `/usage` accept either. Issue read-scoped keys to anything that only searches recorded sales or polls the allowance, so a leaked key from that integration cannot spend the account''s API allowance. Request limits: two limiters apply, and the tighter one decides. A per-address token bucket runs BEFORE the key is verified and is sized per endpoint - `/appraise` and `/comps` allow a burst of 10 then about 30 requests per minute, `/bulk` a burst of 4 then about 6 per minute, `/sales` and `/usage` a burst of 30 then about 60 per minute. Behind it, each key has a fixed limit per 60-second window, by plan: Plus 60/min, Pro 120/min, Max 300/min. Because the per-address bucket sits in front, one address cannot reach the per-key figure on `/appraise`, `/comps` or `/bulk` at all: on `/appraise` a single address is held near 30/min whatever the plan allows, and the Max figure of 300/min is reachable only by calling from several addresses. Both limiters answer `429 rate_limited` with `Retry-After` (seconds); only the per-key limiter also sends `X-RateLimit-Reset` (Unix seconds), so the presence of that header is what distinguishes the two. Determinism guarantee: the same domain on the same engine version always returns the same result.'
  contact:
    url: https://audit.domains/contact
  termsOfService: https://audit.domains/terms
servers:
- url: https://audit.domains
security:
- bearerKey: []
- headerKey: []
tags:
- name: Sales
  description: Recorded domain sales search
paths:
  /api/v1/sales:
    parameters:
    - name: q
      in: query
      schema:
        type: string
      description: Substring match on domain (verified source also matches category/venue).
    - name: tld
      in: query
      schema:
        type: string
    - name: minPrice
      in: query
      schema:
        type: integer
    - name: maxPrice
      in: query
      schema:
        type: integer
    - name: yearFrom
      in: query
      schema:
        type: integer
    - name: yearTo
      in: query
      schema:
        type: integer
    - name: venue
      in: query
      schema:
        type: string
    - name: sort
      in: query
      schema:
        type: string
        enum:
        - price
        - date
        - domain
        default: price
    - name: dir
      in: query
      schema:
        type: string
        enum:
        - asc
        - desc
        default: desc
    - name: page
      in: query
      schema:
        type: integer
        minimum: 1
        default: 1
    - name: pageSize
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 50
    - name: source
      in: query
      schema:
        type: string
        enum:
        - verified
        default: verified
      description: Recorded-sales source. `verified` is the curated, screened corpus used by audit.domains. The legacy `ledger` source is retired and returns 503 source_unavailable.
    get:
      summary: Search recorded domain sales (spends nothing, read scope; paid plan required)
      operationId: searchSales
      responses:
        '200':
          description: One page of curated verified recorded sales, including facets and aggregates over the filtered result set.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            X-Credits-Limit:
              $ref: '#/components/headers/X-Credits-Limit'
            X-Credits-Remaining:
              $ref: '#/components/headers/X-Credits-Remaining'
            X-Credits-Reset:
              $ref: '#/components/headers/X-Credits-Reset'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            Link:
              description: 'RFC 8288 pagination: present when hasMore is true, carrying rel="next" for the following page. A convenience view of the page/pageSize/hasMore body fields.'
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
                properties:
                  source:
                    type: string
                    enum:
                    - verified
                  total:
                    type: integer
                    description: Rows matching the filters across all pages.
                  page:
                    type: integer
                  pageSize:
                    type: integer
                  hasMore:
                    type: boolean
                  rows:
                    type: array
                    items:
                      $ref: '#/components/schemas/SaleRecord'
                  stats:
                    type:
                    - object
                    - 'null'
                    description: Aggregates over the whole filtered set, not just this page. null when nothing matched.
                    properties:
                      median:
                        type: number
                      highest:
                        type: number
                      totalValue:
                        type: number
                  facets:
                    type: object
                    description: Filter values present in the curated verified corpus.
                    properties:
                      tlds:
                        type: array
                        items:
                          type: string
                      years:
                        type: array
                        items:
                          type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequiredReadOnly'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/SalesUnavailable'
        '503':
          description: source_unavailable when a retired sales source such as source=ledger is requested, or api_auth_unavailable when key verification is unreachable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
      - Sales
    head:
      summary: Same as GET without the body
      operationId: headSales
      description: HEAD runs the real GET handler and discards the body (RFC 9110). It spends no API call. Status codes and headers are those of GET.
      responses:
        '200':
          description: Headers only, per RFC 9110. The GET handler runs and its status and headers are returned with no body, so every status GET can answer is reachable here too.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            X-Credits-Limit:
              $ref: '#/components/headers/X-Credits-Limit'
            X-Credits-Remaining:
              $ref: '#/components/headers/X-Credits-Remaining'
            X-Credits-Reset:
              $ref: '#/components/headers/X-Credits-Reset'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequiredReadOnly'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/SalesUnavailable'
        '503':
          description: source_unavailable (the research ledger is not published yet; the body carries `source`) or api_auth_unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      tags:
      - Sales
components:
  responses:
    SalesUnavailable:
      description: 'sales_unavailable - the recorded-sales index could not be read. Retryable: retry with backoff, and quote the requestId if it persists.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: key_required (no key sent) or invalid_key (unknown, revoked, or expired). key_required also carries withoutKey (what works with no key) and plans (what a key costs).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
      headers:
        WWW-Authenticate:
          description: Bearer realm="audit.domains" on key_required; adds error="invalid_token" on invalid_key (RFC 6750).
          schema:
            type: string
    RateLimited:
      description: rate_limited - either the per-address token bucket in front of key verification tripped, or the key is over its plan's per-minute limit (Plus 60, Pro 120, Max 300). See the request-limits note in the document description for the per-endpoint per-address figures. Both carry Retry-After; only the per-key limiter carries X-RateLimit-Reset and a `plan` field in the body, so that header is what tells you which limiter refused the call.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
        X-RateLimit-Reset:
          description: Unix seconds at which the current 60-second window ends. Present when the per-key limiter tripped.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequiredReadOnly:
      description: paid_plan_required - the account is on the free plan, which does not include API access. This endpoint spends no API calls, so it never answers an allowance code.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    MethodNotAllowed:
      description: method_not_allowed - this path does not serve that HTTP method. The `Allow` response header and the body's `allowed` array both list the methods it does serve.
      headers:
        Allow:
          description: Comma-separated methods this path serves.
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  headers:
    X-Credits-Reset:
      description: 'ISO 8601 instant the allowance refills: the first instant of the next UTC month.'
      schema:
        type: string
        format: date-time
    X-RateLimit-Limit:
      description: Currently repeats X-Credits-Limit. Read X-Credits-Limit for the allowance.
      schema:
        type: integer
    X-Request-Id:
      description: Correlation id for this request, on every response including successes. Quote it in support requests.
      schema:
        type: string
    X-Credits-Limit:
      description: Monthly API call allowance for this account's plan.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Currently repeats X-Credits-Remaining. Read X-Credits-Remaining for the allowance.
      schema:
        type: integer
    X-Credits-Remaining:
      description: API calls left in the current monthly allowance, after this call.
      schema:
        type: integer
  schemas:
    SaleRecord:
      type: object
      properties:
        domain:
          type: string
        price:
          type: number
        saleDate:
          type: string
          description: ISO date, a bare year, or empty when unknown.
        venue:
          type:
          - string
          - 'null'
        category:
          type:
          - string
          - 'null'
        verified:
          type: boolean
        source:
          type: string
          description: Corpus provenance. The paid sales API currently serves "curated".
    PlanOffer:
      type: object
      description: One paid plan whose key can call /api/v1, derived from the billing configuration (the same figures as https://audit.domains/pricing).
      properties:
        id:
          type: string
          description: Plan id, as /checkout?plan= names it.
        name:
          type: string
        usdPerTerm:
          type: number
          description: Price of one term in USD.
        term:
          type: string
          enum:
          - month
        monthlyCalls:
          type: integer
          description: /api/v1 calls included per term; a separate allowance from site appraisals.
        usdPerCall:
          type: number
          description: Effective USD per included call, rounded to 4 places.
        burstPerMinute:
          type: integer
          description: Per-key request limit per minute.
        checkout:
          type: string
          format: uri
          description: Where a person signs in and pays. An agent cannot complete it.
      required:
      - id
      - name
      - usdPerTerm
      - term
      - monthlyCalls
      - usdPerCall
      - burstPerMinute
      - checkout
    Error:
      type: object
      properties:
        error:
          type: string
          description: Stable machine-readable code; the only field a client should match on. The full catalogue is published at https://audit.domains/developers#errors
        message:
          type: string
          description: Human-readable and safe to display; never contains internals.
        detail:
          type: string
          description: The actionable next step, when there is one.
        requestId:
          type: string
          description: Correlation id for this request, always present; also sent as the X-Request-Id header on every response. Quote it in support requests.
        docsUrl:
          type: string
          format: uri
          description: Deep link to this code's entry in the published error catalogue.
        retryable:
          type: boolean
          description: Whether repeating the identical request can succeed.
        plan:
          type: string
          description: The account's plan id. Present on the per-key 429 rate_limited, on 403 insufficient_scope, and on the 402 codes.
        scope:
          type: string
          description: The scope the key was created with. Present on 403 insufficient_scope.
        requiredScope:
          type: string
          description: The scope this endpoint needs. Present on 403 insufficient_scope.
        max:
          type: integer
          description: Maximum domains one bulk call accepts. Present on 400 too_many_domains.
        allowed:
          type: array
          items:
            type: string
          description: Methods this path serves, matching the Allow header. Present on 405 method_not_allowed.
        source:
          type: string
          description: The sales source that is not published. Present on 503 source_unavailable.
        withoutKey:
          type: array
          items:
            $ref: '#/components/schemas/FreeRoute'
          description: What works with no key. Present on 401 key_required.
        plans:
          type: array
          items:
            $ref: '#/components/schemas/PlanOffer'
          description: The plans whose keys can call this API, cheapest first. Present on 401 key_required and 402 paid_plan_required.
        planTerms:
          type: string
          description: Whether a paid term renews. Present on 401 key_required.
        pricing:
          type: string
          format: uri
          description: The keyless API index, which carries the same plans. Present on 401 key_required.
      required:
      - error
      - message
      - requestId
      - docsUrl
      - retryable
    FreeRoute:
      type: object
      description: A route that works with no key. {name} stands for the domain.
      properties:
        what:
          type: string
        how:
          type: string
      required:
      - what
      - how
  securitySchemes:
    bearerKey:
      type: http
      scheme: bearer
      description: 'Authorization: Bearer ad_live_...'
    headerKey:
      type: apiKey
      in: header
      name: x-api-key