---
name: compsniper
description: Retrieve real completed-sale (sold) prices and active listings from eBay, Mercari, Poshmark, and TCGplayer through the CompSniper REST API, plus up to 3 years of eBay sold history, with deterministic price summaries (median, mean, p25, p75). Use this whenever you need resale or market value, sold comps, price history, or listing data for a product, trading card, or collectible.
---

# CompSniper API

CompSniper is an independent REST API that returns real eBay, Mercari, and Poshmark listing evidence (up to 240 completed eBay sales per request) plus a deterministic price summary. It replays authenticated sold-search access so you do not have to scrape HTML yourself.

- Base URL: `https://api.compsniper.com`
- Auth: every request needs `Authorization: Bearer cs_...` (create a key at https://compsniper.com/dashboard). A missing or invalid key returns 401 `unauthorized`.

## Core endpoint: GET /v1/scrape

Keyword search of eBay sold listings (default) or active listings.

Query parameters:
- `keyword` (string, required): the search term.
- `ebaySite` (enum, default `ebay.com`): one of `ebay.com`, `ebay.co.uk`, `ebay.de`, `ebay.fr`, `ebay.it`, `ebay.es`, `ebay.ca`, `ebay.com.au`. Set it explicitly for a local marketplace; the API does not guess location.
- `sold` (boolean, default `true`): `true` for completed sales, `false` for active listings.
- `count` (integer, default `240`, range 1 to 240): a ceiling. Fewer valid rows may remain after baseline validation, date filters, or relevance cleanup.
- `page` (integer, default `1`).
- `relevance` (boolean, default `true`): query-aware cleanup that removes likely accessories, parts, broken units, empty boxes, and mismatched variants before the summary. Set `false` for broad valid matches without semantic cleanup.
- `exactMatch` (boolean, default `false`): `true` removes eBay's explicit "Results matching fewer words" section before relevance cleanup.
- `sortOrder` (enum, default `endedRecently`): `endedRecently`, `timeNewlyListed`, `pricePlusPostageLowest`, `pricePlusPostageHighest`, `distanceNearest`.
- `minPrice`, `maxPrice` (number).
- `itemCondition` (`any`, `new`, `used`), `conditionId` (integer).
- `buyingFormat` (`all`, `auction`, `buyItNow`, `acceptsOffers`).
- `sellerType` (`private`, `business`).
- `itemLocation` (`default`, `domestic`, `worldwide`).
- `categoryId` (string, default `0`), `aspectFilter` (string).
- `soldAfter`, `soldBefore` (date), `includeCompleteListing` (boolean).

Response (JSON): `keyword`, `page`, `totalItems`, `totalResults`, `hasNextPage`, `autoSelectedCategory`, `items` (array), and `summary` (`count`, `currency`, `median`, `mean`, `min`, `max`, `p25`, `p75`, `avgShipping`). With relevance on, `rawMedian` and `rawSampleCount` preserve the evidence before cleanup. Sold items include `soldPrice`, `soldCurrency`, `endedAt`, `totalPrice`, `condition`, `shippingPrice`, seller fields, and `url`. With `sold=false`, sold-only fields are replaced by `currentPrice`, `currentPriceMax`, `currentCurrency`, `timeLeft`, and `watcherCount`. Full field list: references/api-reference.md.

Minimal example:
```
curl -H "Authorization: Bearer cs_YOUR_KEY" \
  "https://api.compsniper.com/v1/scrape?keyword=nintendo+switch+oled&sold=true&ebaySite=ebay.com"
```

Tip for the fullest set of comps: search the base product name (brand plus product). Very narrow phrasings, such as multi-pack quantities or exact variants, match far fewer sold listings.

## Other endpoints

- `GET /v1/scrape/category`: browse sold listings by eBay `categoryId`.
- `GET /v1/mercari`: public Mercari US sold or active listings, up to 100 per page. Dedicated response schema.
- `GET /v1/poshmark/sold`: public Poshmark US sold listings, up to 48 per page. Dedicated response schema.
- `GET /v1/summary`: cleaned price-intelligence summary for a keyword.
- `GET /v1/account/usage`: plan, quota, and remaining usage.
- `POST /v1/bulk-search`: stream up to 20 independent keyword searches in one run. `GET /v1/bulk-search/:runId/download.csv` exports one keyword or the combined run.
- `POST /v1/cards/batch`: start an asynchronous batch that prices up to 100 trading or sports cards. `GET /v1/cards/batch/:jobId` polls, `DELETE /v1/cards/batch/:jobId` cancels. Results expire after 30 days.
- `POST /v1/scrape/max`: start a deeper asynchronous Max Mode run. `GET /v1/scrape/max/results/:jobId` polls, `DELETE /v1/scrape/max/:jobId` cancels, `GET /v1/scrape/max/:jobId/download.csv` exports.
- `GET /v1/research/sold`: up to 3 years of eBay sold history on every plan including free. Requires `keyword`, `startDate`, `endDate` (YYYY-MM-DD, no earlier than 3 years ago). Max 50 rows per page; follow `nextPage` while `hasNextPage` is true. Rows are listing-level, prices in USD, no AI cleanup. One page = one request; separate cap of 20 history searches per minute.
- `GET /v1/tcgplayer/sold` and `GET /v1/tcgplayer/listings`: TCGplayer completed sales (full history, optional market price history) and active listings, by `keyword` or exact `productId`.
- `POST /v1/shipping/rates` and `GET /v1/shipping/usage`: US shipping-rate estimates. These use a separate subscription and quota and are never funded by sold-comps requests or credits.

Keyword tips for history and TCGplayer (most empty answers come from the request):
- History matches only listings whose title contains every word. Send brand plus model or set number (`CyberPower PDU81001` returns 12, the longer `CyberPower PDU81001G switched metered by outlet PDU 8 outlet 1U` returns 0). Never pass a whole listing title; if a long keyword returns 0, retry it shorter before treating the item as unsold.
- History: a window of a few days often holds few or no sales. Widen `startDate` (up to 3 years) for rare items.
- TCGplayer matches TCGplayer product names, not eBay titles. Use card or product name, set and number (`Pokemon Japanese 151 booster box`), one product per call, then reuse the returned `productId`.

Poshmark and Mercari use dedicated field schemas that differ from eBay. See references/api-reference.md.

## Error handling

Errors return JSON `{ error, code, hint?, retry_after?, ... }` with these codes:
- 401 `unauthorized`: missing or invalid API key.
- 400 `invalid_params`: a parameter is invalid.
- 429 `rate_limited`: per-minute limit reached. Respect the `Retry-After` header, back off with jitter, and retry a bounded number of times.
- 429 `quota_exceeded`: monthly quota and purchased credits are exhausted. Do not retry. Fields include `quota`, `used`, `remaining`, `reset_at`, `rollover_balance`, `credit_balance`, `upgrade_url`, and `purchase_credits_url`.
- 502 `upstream_blocked`: eBay challenged the request. Retry after a short delay; a re-query usually succeeds. Failed searches are not charged.
- 503 `server_busy`: temporary capacity limit. Respect `Retry-After`, reduce parallel requests, and use a bounded retry count.
- 502 `upstream_unavailable` and 500 `server_error`: transient. Use a bounded retry.

## Billing and quota

A successful search consumes one request, drawn in order from eligible rollover, then the monthly plan allowance, then non-expiring purchased credits. Failed searches release the reservation and are not charged. Send the optional header `X-Credit-Source: credits` to use purchased credits first; when they run out the request falls back to the monthly allowance instead of failing (the only accepted value is `credits`; omit the header for automatic selection).

Responses expose `X-Plan`, `X-Usage-Limit`, `X-Usage-Used`, `X-Usage-Remaining`, `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`, `X-Credit-Source`, `X-Rollover-Balance`, `X-Credit-Balance`, and `X-Request-ID`. Paid subscriptions and accounts using purchased credits receive priority in the live-search queue during busy periods.

## References
- references/api-reference.md: full endpoint reference, complete response field list, Poshmark and Mercari schemas.
- references/examples.md: worked examples in curl, JavaScript, and Python.
- Hosted MCP connector (live calls without managing keys): https://compsniper.com/docs/mcp
