audit.domains Appraisals API

Deterministic valuations and comparable sales for one domain

Operations 3

POST /api/v1/appraise Appraise one domain (1 API call, write scope) #
GET /api/v1/comps Comparable sales for a domain (1 API call, write scope) #
HEAD /api/v1/comps Same as GET without the body - still spends 1 API call #

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-appraisals-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-appraisals-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: audit.domains public Appraisals 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: Appraisals
  description: Deterministic valuations and comparable sales for one domain
paths:
  /api/v1/appraise:
    post:
      summary: Appraise one domain (1 API call, write scope)
      operationId: appraiseDomain
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - domain
              properties:
                domain:
                  type: string
                  examples:
                  - example.com
                  pattern: ^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$
                  maxLength: 253
      responses:
        '200':
          description: The locked public appraisal projection.
          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'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Appraisal'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/AppraisalFailed'
        '503':
          $ref: '#/components/responses/AuthUnavailable'
      tags:
      - Appraisals
  /api/v1/comps:
    parameters:
    - name: domain
      in: query
      required: true
      schema:
        type: string
        pattern: ^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$
        maxLength: 253
    - name: limit
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 5
        default: 5
    get:
      summary: Comparable sales for a domain (1 API call, write scope)
      operationId: getComps
      responses:
        '200':
          description: Top comparable sales, indexed by the published methodology.
          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'
          content:
            application/json:
              schema:
                type: object
                properties:
                  domain:
                    type: string
                  comps:
                    type: array
                    items:
                      $ref: '#/components/schemas/Comp'
                  methodologyVersion:
                    type:
                    - string
                    - 'null'
                  dataEdition:
                    type:
                    - string
                    - 'null'
                  generatedAt:
                    type: string
                    format: date-time
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/CompsFailed'
        '503':
          $ref: '#/components/responses/AuthUnavailable'
      tags:
      - Appraisals
    head:
      summary: Same as GET without the body - still spends 1 API call
      operationId: headComps
      description: 'HEAD runs the real GET handler and discards the body (RFC 9110), so it runs the engine and debits one API call from the monthly allowance exactly as GET does. Do NOT use it as an uptime probe: GET /api/v1/usage spends nothing and is the probe to use. 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'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/InsufficientScope'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/CompsFailed'
        '503':
          $ref: '#/components/responses/AuthUnavailable'
      tags:
      - Appraisals
components:
  schemas:
    Comp:
      type: object
      properties:
        domain:
          type: string
        priceUsd:
          type: number
        year:
          type: string
        venue:
          type:
          - string
          - 'null'
        similarity:
          type: integer
          minimum: 0
          maximum: 100
        basis:
          type:
          - string
          - 'null'
          description: Why this sale was matched, naming the channel the matcher scored on (shared keyword, word family, same industry, structural cohort, spelling, length/zone). null means the basis was not recorded for this comp - the match is unexplained, not explained by something unstated.
    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
    Appraisal:
      type: object
      description: The locked v1 projection. Keys are contract-locked; new keys only arrive with a version bump.
      properties:
        domain:
          type: string
        valueUSD:
          type: number
        valueRange:
          type: object
          properties:
            low:
              type: number
            mid:
              type: number
            high:
              type: number
        tier:
          type: string
        confidence:
          type: number
        factors:
          type: array
          items:
            $ref: '#/components/schemas/Factor'
        methodologyVersion:
          type:
          - string
          - 'null'
        engineVersion:
          type: string
        comps:
          type: array
          items:
            $ref: '#/components/schemas/Comp'
          maxItems: 5
        appraisalHash:
          type: string
          description: SHA-256 over {commitment, result, hashVersion} - the appraisal's stable id (ODVS).
        inputCommitment:
          type: string
          description: SHA-256 over {domain, engineId, engineVersion} - identity of the computation (ODVS).
        resultDigest:
          type: string
          description: SHA-256 over the canonical numeric outputs (ODVS).
        generatedAt:
          type: string
          format: date-time
        dataEdition:
          type:
          - string
          - 'null'
          description: Version of the comparables snapshot in effect, when known.
    Factor:
      type: object
      properties:
        key:
          type: string
        label:
          type: string
        score:
          type: integer
          minimum: 0
          maximum: 100
    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
    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
  headers:
    X-Request-Id:
      description: Correlation id for this request, on every response including successes. Quote it in support requests.
      schema:
        type: string
    X-Credits-Remaining:
      description: API calls left in the current monthly allowance, after this call.
      schema:
        type: integer
    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-Remaining:
      description: Currently repeats X-Credits-Remaining. Read X-Credits-Remaining for the allowance.
      schema:
        type: integer
    X-RateLimit-Limit:
      description: Currently repeats X-Credits-Limit. Read X-Credits-Limit for the allowance.
      schema:
        type: integer
    X-Credits-Limit:
      description: Monthly API call allowance for this account's plan.
      schema:
        type: integer
  responses:
    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'
    PaymentRequired:
      description: 'paid_plan_required (the account is on the free plan, which does not include API access), upgrade_required (the plan does not include the requested feature - only the bulk endpoint is gated this way), or a spent allowance.


        The code for a spent monthly API allowance is `api_quota_exhausted`. A deployment not yet running the separate API credit pool answers the older `quota_exhausted` for the same condition, so a client should treat both as "allowance spent" and branch the same way. Either way the website''s appraisal credits are a separate allowance and are unaffected by API calls.


        The X-Credits-* headers are present on the two allowance codes, which are refused after the meter was read, and absent on paid_plan_required and upgrade_required, which are refused before it.'
      headers:
        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'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    BadRequest:
      description: invalid_json (the body is not valid JSON) or invalid_domain (the domain is missing or not a registrable hostname). /api/v1/comps reads no body, so it can only answer invalid_domain.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InsufficientScope:
      description: insufficient_scope - the endpoint spends an API call and the key has read scope only. Create a write-scoped key at https://audit.domains/profile?tab=api. The body carries `scope` (the key's) and `requiredScope`.
      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
    AppraisalFailed:
      description: 'appraisal_failed - the appraisal could not be completed. Retryable: retry with backoff, and quote the requestId if it persists.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    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'
    AuthUnavailable:
      description: api_auth_unavailable - key verification is unreachable; the API fails closed rather than serving unmetered.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    CompsFailed:
      description: 'comps_failed - the comparables could not be computed. Retryable: retry with backoff, and quote the requestId if it persists.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerKey:
      type: http
      scheme: bearer
      description: 'Authorization: Bearer ad_live_...'
    headerKey:
      type: apiKey
      in: header
      name: x-api-key