# CompSniper API reference

Companion to SKILL.md. Base URL `https://api.compsniper.com`. Auth `Authorization: Bearer cs_...`.

## Endpoint index

| Method | Endpoint | Purpose |
| --- | --- | --- |
| GET | `/v1/scrape` | Keyword sold search or active listing search |
| GET | `/v1/scrape/category` | Browse sold listings by eBay category |
| GET | `/v1/poshmark/sold` | Public Poshmark US sold listings (up to 48 per page) |
| GET | `/v1/mercari` | Public Mercari US sold or active listings (up to 100 per page) |
| GET | `/v1/summary` | Cleaned price intelligence summary |
| GET | `/v1/account/usage` | Plan, quota, and remaining usage |
| POST | `/v1/bulk-search` | Stream up to 20 independent keyword searches |
| GET | `/v1/bulk-search/:runId/download.csv` | Export one keyword or the combined bulk run |
| POST | `/v1/cards/batch` | Start an asynchronous card-pricing batch (up to 100 cards) |
| GET | `/v1/cards/batch/:jobId` | Poll a card-pricing batch |
| DELETE | `/v1/cards/batch/:jobId` | Cancel unfinished card work |
| POST | `/v1/scrape/max` | Start Max Mode (deeper async run) |
| GET | `/v1/scrape/max/results/:jobId` | Poll Max Mode results |
| DELETE | `/v1/scrape/max/:jobId` | Cancel Max Mode |
| GET | `/v1/scrape/max/:jobId/download.csv` | Download a signed Max Mode CSV |
| POST | `/v1/shipping/rates` | US shipping-rate estimates (separate plan) |
| GET | `/v1/shipping/usage` | Independent Shipping Rates plan and quota |

## GET /v1/scrape parameter defaults

| Parameter | Type | Default |
| --- | --- | --- |
| keyword | string | required |
| page | integer | 1 |
| count | integer | 240 (max 240) |
| ebaySite | enum | ebay.com |
| categoryId | string | 0 |
| sortOrder | enum | endedRecently |
| sold | boolean | true |
| relevance | boolean | true |
| exactMatch | boolean | false |
| minPrice / maxPrice | number | none |
| itemLocation | default / domestic / worldwide | default |
| itemCondition | any / new / used | any |
| conditionId | integer | none |
| buyingFormat | all / auction / buyItNow / acceptsOffers | all |
| sellerType | private / business | none |
| includeCompleteListing | boolean | none |
| soldAfter / soldBefore | date | none |
| aspectFilter | string | none |

`count` is a ceiling. Valid responses can contain fewer rows after baseline listing hygiene, date filters, or relevance cleanup.

## Response body (ScrapeResponse)

- `keyword`, `page`, `totalItems`, `totalResults`, `hasNextPage`
- `autoSelectedCategory`: `{ id, name }` or null
- `rawMedian`, `rawSampleCount`: median and sample size after optional exact-section parsing but before relevance cleaning
- `items`: array of listing objects
- `summary`: `{ count, currency, median, mean, min, max, p25, p75, avgShipping }` or null

### Sold item fields (sold=true)
`itemId`, `url`, `thumbnailUrl`, `fullResThumbnailUrl`, `epid`, `title`, `condition`, `conditionId`, `sellerType` (private or business), `buyingFormat` (auction, buyItNow, auctionWithBIN), `bestOfferAccepted`, `bidCount`, `categoryId`, `listingType` (sold), `shippingPrice`, `shippingCurrency`, `shippingType` (free, paid, pickup, unknown), `totalPrice`, `sellerUsername`, `sellerPositivePercent`, `sellerFeedbackScore`, `productRating`, `productReviewCount`, `itemLocation`, `scrapedAt`, `endedAt`, `soldPrice`, `soldCurrency`.

### Active listing fields (sold=false)
The sold-only fields (`soldPrice`, `soldCurrency`, `endedAt`) are replaced by `currentPrice`, `currentPriceMax`, `currentCurrency`, `watcherCount`, `unitsSold`, `acceptsOffers`, and `timeLeft`. All shared fields above still apply.

## Marketplaces (ebaySite)

`ebay.com` (US), `ebay.co.uk` (UK), `ebay.de` (Germany), `ebay.fr` (France), `ebay.it` (Italy), `ebay.es` (Spain), `ebay.ca` (Canada), `ebay.com.au` (Australia). Only the marketplace changes; authentication, quota usage, response fields, and parsing stay the same.

## Poshmark and Mercari

`GET /v1/poshmark/sold` and `GET /v1/mercari` cover their US marketplaces and do not require customer marketplace accounts. They use dedicated response schemas because their native fields differ from eBay. Poshmark returns up to 48 public sold listings per page; Mercari returns up to 100 public sold or active listings per page. See https://compsniper.com/docs/marketplaces for filters, response fields, pagination, and limitations.

## Errors

JSON shape: `{ error, code, hint?, retry_after?, reset_at?, plan?, quota?, used?, remaining?, rollover_balance?, credit_balance?, upgrade_url?, purchase_credits_url? }`.

| HTTP | code | Meaning and handling |
| --- | --- | --- |
| 401 | unauthorized | Missing or invalid `cs_` key |
| 400 | invalid_params | Fix the parameter and retry |
| 429 | rate_limited | Per-minute limit. Respect `Retry-After`, back off with jitter |
| 429 | quota_exceeded | Monthly quota and credits exhausted. Do not retry. Upgrade, buy credits, or wait for `reset_at` |
| 502 | upstream_blocked | eBay challenged the request. Short delay, then retry. Not charged |
| 503 | server_busy | Temporary capacity. Respect `Retry-After`, reduce parallelism, bounded retries |
| 502 | upstream_unavailable | Transient upstream failure. Bounded retry |
| 500 | server_error | Transient. Bounded retry |

## Response headers

`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`, `X-Cache` (HIT or MISS), `X-Request-ID`. Successful uncached responses also include a `Server-Timing` header breaking down queue, lease, pacing, eBay fetch, parsing, cleanup, and total engine time.

## Plans and rate limits (public list pricing)

| Plan | Price | Monthly requests | Per-minute |
| --- | --- | --- | --- |
| Basic | $0 | 100 | 30 |
| Starter | $9 | 2,000 | 60 |
| Growth | $29 | 10,000 | 60 |
| Scale | $79 | 50,000 | 60 |
| 100K | $129 | 100,000 | 120 |
| 150K | $179 | 150,000 | 120 |
| 250K | $299 | 250,000 | 120 |
| 500K | $549 | 500,000 | 120 |

Purchased credits: $5.00 per 1,000 requests, from 1,000 to 1,000,000 in increments of 100, non-expiring. Successful searches use eligible rollover, then the subscription allowance, then purchased credits. `X-Credit-Source: credits` selects purchased credits directly. Credits do not fund Shipping Rates quotes.
