compsapi-com Sold API

The Sold API from compsapi-com — 1 operation(s) for sold.

Operations 1

GET /v1/sold Sold listings for a search, newest sale first #

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/compsapi-com:compsapi-com-sold-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

compsapi-com-sold-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Comps Sold API
  version: 1.4.0
  description: 'Real eBay sold prices as JSON. Up to 3 years of history, real accepted Best Offer prices, and a trading card layer for graded cards and comps. Docs: https://compsapi.com/docs · Keys: https://app.compsapi.com'
  contact:
    name: CompsAPI support
    url: https://app.compsapi.com/support
    email: keys@compsapi.com
  termsOfService: https://compsapi.com/terms
  x-logo:
    url: https://compsapi.com/apple-touch-icon.png
    altText: CompsAPI
servers:
- url: https://api.compsapi.com
security:
- apiKey: []
- bearer: []
tags:
- name: Sold
paths:
  /v1/sold:
    get:
      summary: Sold listings for a search, newest sale first
      parameters:
      - $ref: '#/components/parameters/q'
      - $ref: '#/components/parameters/days'
      - $ref: '#/components/parameters/start'
      - $ref: '#/components/parameters/end'
      - $ref: '#/components/parameters/size'
      - name: page
        in: query
        schema:
          type: integer
          minimum: 1
          maximum: 200
          default: 1
        description: 'Page number. 1 to 200 on a paid plan, 1 to 50 on the free plan. Walk pages in order: each page is served from where the previous one stopped, so a deep page asked for on its own has to rebuild the whole walk and can time out. A walk stays resumable for 4 hours.'
      - $ref: '#/components/parameters/condition'
      - $ref: '#/components/parameters/best_offer'
      - $ref: '#/components/parameters/cards'
      - $ref: '#/components/parameters/grader'
      - $ref: '#/components/parameters/grade'
      - $ref: '#/components/parameters/graded'
      - $ref: '#/components/parameters/lang'
      - $ref: '#/components/parameters/first_edition'
      - $ref: '#/components/parameters/exclude'
      - $ref: '#/components/parameters/require'
      - $ref: '#/components/parameters/print_run'
      - $ref: '#/components/parameters/stats'
      - name: site
        in: query
        description: 'Pin one eBay marketplace, returning only sales made on that site. Omit it for the default, which is eBay US plus international coverage merged. A pin means that site alone, not listings a buyer there could see. All prices are USD whichever you pick: eBay converts before we receive them, so a pin changes which sales you get, never the currency.'
        schema:
          type: string
          enum:
          - US
          - UK
          - DE
          - FR
          - IT
          - ES
          - CA
          - AU
      - name: category
        in: query
        description: eBay category id(s), comma separated, e.g. 31387 for wristwatches.
        schema:
          type: string
          pattern: ^\d+(,\d+)*$
      - name: min_price
        in: query
        description: Keep only sales at or above this sold price (applied to the returned page).
        schema:
          type: number
          minimum: 0
      - name: max_price
        in: query
        description: Keep only sales at or below this sold price (applied to the returned page).
        schema:
          type: number
          minimum: 0
      - name: native_price
        in: query
        description: '1 adds native_price and native_currency: the amount in the currency the buyer actually paid. eBay US sales are free (already USD); each non US sale costs one extra read, so it is capped per request and native_price_info reports coverage.'
        schema:
          type: string
          enum:
          - '0'
          - '1'
      responses:
        '200':
          description: Sold listings.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SoldResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
      tags:
      - Sold
      operationId: getV1Sold
      x-operation-id-source: derived
components:
  parameters:
    best_offer:
      name: best_offer
      in: query
      schema:
        type: string
        enum:
        - '1'
        - only
        - verify
      description: 1 adds the best_offer flag with real accepted prices; only returns accepted offers exclusively; verify also reads the public sold page and adds best_offer_confidence, asking_price and asking_gap_pct, because eBay's own accepted offer filter misses some negotiated sales.
    days:
      name: days
      in: query
      schema:
        type: integer
        minimum: 1
        maximum: 1095
        default: 90
      description: How far back to search, up to 3 years.
    exclude:
      name: exclude
      in: query
      schema:
        type: string
      description: Flags to drop, e.g. junk or lot,sealed. none keeps everything.
    condition:
      name: condition
      in: query
      schema:
        type: string
      description: new, open_box, refurbished, used or parts. Comma separate to combine.
    lang:
      name: lang
      in: query
      schema:
        type: string
      description: en, ja, zh, ko, de, fr, it, es, pt. Comma separate to combine.
    graded:
      name: graded
      in: query
      schema:
        type: string
        enum:
        - 'true'
        - 'false'
      description: Only slabs, or only raw cards.
    grader:
      name: grader
      in: query
      schema:
        type: string
      description: PSA, BGS, CGC, SGC, TAG, ACE and others. Comma separate to combine.
    cards:
      name: cards
      in: query
      schema:
        type: string
        enum:
        - '1'
      description: Adds the card object to every item without filtering.
    start:
      name: start
      in: query
      schema:
        type: string
        format: date
        example: '2024-12-01'
      description: First day of an absolute window, written YYYY-MM-DD. Use start and end to ask for a fixed historical period instead of a lookback from today, for example start=2024-12-01&end=2025-12-01. Inclusive. Given on its own, the window runs to now. A start more than 1095 days ago is refused; on a plan with less history the start is pulled forward to that plan's limit and plan_limit says so. Slicing a long period into several short windows is faster and more reliable than walking deep pages.
    end:
      name: end
      in: query
      schema:
        type: string
        format: date
        example: '2025-12-01'
      description: Last day of an absolute window, written YYYY-MM-DD. Inclusive, so the whole of that day counts, and it never runs past today. Given on its own, the window starts days before it. The answer carries window with the period actually served.
    first_edition:
      name: first_edition
      in: query
      schema:
        type: string
        enum:
        - 'true'
        - 'false'
    stats:
      name: stats
      in: query
      schema:
        type: string
        enum:
        - '1'
      description: Adds price stats for the filtered results.
    grade:
      name: grade
      in: query
      schema:
        type: string
      description: Grade as text, e.g. 10 or 9.5. Comma separate to combine.
    q:
      name: q
      in: query
      required: true
      schema:
        type: string
        maxLength: 300
      description: Search terms. eBay matches every word in the title.
    require:
      name: require
      in: query
      schema:
        type: string
      description: Keep only sales whose title holds every one of these words or phrases, comma separated, for example require=lebron james or require=lebron james,red disco. Matching ignores case and punctuation and lands on whole words, so 2017 matches a 2017-18 title and ron jam matches nothing. Up to 6 terms. This is how you search broadly and then insist on the one thing that identifies your item. It can only remove rows, never find new ones, so the answer carries title_filter with the count before it ran and how many it removed. It runs on the page already retrieved, so on a broad query widen size or walk pages to see more.
    size:
      name: size
      in: query
      schema:
        type: integer
        minimum: 10
        maximum: 240
        default: 200
      description: Results per page.
    print_run:
      name: print_run
      in: query
      schema:
        type: string
        example: '125'
      description: 'The serial number a card is limited to, read from the title. A number keeps only that print run, for example print_run=125 for a /125 parallel. numbered keeps every serial numbered card. any filters nothing and just labels the rows. All three add print_run to every item. #098/125 reads as 125 and not as 98, a bare /85 reads as 85, and a season like 2025/26, a card number like #100, a 100 card lot and a date are all left alone. A print run is not an identity: a /125 parallel of the same player exists in several seasons at very different prices, so keep the year in q and use this to separate parallels within it. Reported in title_filter the same way as require.'
  responses:
    BadRequest:
      description: Missing or invalid parameter.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    Item:
      type: object
      properties:
        item_id:
          type: string
        title:
          type: string
        last_sold:
          type: string
          format: date-time
        price:
          type: number
          description: Average price actually paid per unit, USD. Accepted best offers show the real offer price.
        units_sold:
          type: integer
        total_sales:
          type: number
        format:
          type: string
          enum:
          - FIXED_PRICE
          - AUCTION
        bids:
          type: integer
        us_sale:
          type: boolean
          description: true when the sale was made on eBay US, false when it was made on another eBay site. The default search merges eBay US with international coverage, so this separates them. Which other site a false row came from is not reported, because eBay does not expose it per item. With site pinned, every row is true or every row is false.
        native_price:
          type:
          - number
          - 'null'
          description: Only with native_price=1. The amount in the currency the sale actually happened in. price is always USD; this is the untouched figure. null when it could not be confirmed, typically a listing that sold several units at different prices.
        native_currency:
          type:
          - string
          - 'null'
          description: Only with native_price=1. ISO 4217 code for native_price, for example GBP, EUR, AUD.
        best_offer:
          type:
          - boolean
          - 'null'
          description: Only present with the best_offer parameter. true means the sale was identified as an accepted offer; false means it was not identified as one, which is not the same as a full price sale.
        condition:
          type: string
          description: Only present with a single condition value.
        shipping_cost:
          type:
          - number
          - 'null'
        free_shipping_pct:
          type: number
        url:
          type: string
        image:
          type: string
        card:
          $ref: '#/components/schemas/Card'
        best_offer_confidence:
          type: string
          enum:
          - confirmed
          - likely
          - unlikely
          - unknown
          description: 'Only with best_offer=verify. confirmed: eBay identifies the sale as an accepted offer. likely: the listing accepted offers and the sale closed materially below the asking price. unlikely: neither holds. unknown: the sale was not on the public pages we read, or another marketplace was pinned, so no comparison was possible.'
        asking_price:
          type:
          - number
          - 'null'
          description: Only with best_offer=verify. The price eBay's public sold page displays for this listing.
        asking_gap_pct:
          type:
          - number
          - 'null'
          description: Only with best_offer=verify. How far the asking price sits above what the sale closed at, as a percentage of the amount paid. Negative when the public page reads low.
    Stats:
      type: object
      properties:
        count:
          type: integer
        used_for_stats:
          type: integer
        median:
          type: number
        mean:
          type: number
        p25:
          type: number
        p75:
          type: number
        min:
          type: number
        max:
          type: number
        outliers_removed:
          type: integer
        newest_sale:
          type: string
          format: date-time
        oldest_sale:
          type: string
          format: date-time
    Error:
      type: object
      properties:
        ok:
          type: boolean
          example: false
        error:
          type: string
    Card:
      type: object
      properties:
        graded:
          type:
          - boolean
          - 'null'
        grader:
          type:
          - string
          - 'null'
        grade:
          type:
          - string
          - 'null'
        grade_label:
          type:
          - string
          - 'null'
        card_number:
          type:
          - string
          - 'null'
        year:
          type:
          - integer
          - 'null'
        language:
          type:
          - string
          - 'null'
        first_edition:
          type:
          - boolean
          - 'null'
        flags:
          type: array
          items:
            type: string
    SoldResponse:
      type: object
      properties:
        ok:
          type: boolean
        query:
          type: string
        page:
          type: integer
        ms:
          type: integer
        count:
          type: integer
        no_results:
          type: boolean
        next_page:
          type: boolean
        days:
          type: integer
        size:
          type: integer
        cached:
          type: boolean
        cached_age_s:
          type: integer
        source:
          type: string
        filters:
          type: object
        count_before_filters:
          type: integer
        stats:
          $ref: '#/components/schemas/Stats'
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
    bearer:
      type: http
      scheme: bearer