Batches
POST /v1/batches runs many Soldgraph searches in one call. Poll one batch ID for every result, get a price summary per search, or download all rows as CSV.
POST https://api.soldgraph.com/v1/batches
Send many searches in one call and get one batch ID back. Use it to price a whole list of items.
A batch is a list of ordinary searches. Each one is cached, charged and refunded exactly as if you had sent it by itself.
#Create a batch
curl -X POST "https://api.soldgraph.com/v1/batches" \ -H "Authorization: Bearer $SOLDGRAPH_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: gpu-prices-2026-10-05" \ -d '{ "defaults": { "endpoint": "ebay/sold", "country": "uk", "condition": "used", "count": 120 }, "searches": [ { "q": "RX 580 4GB" }, { "q": "GTX 1660 Ti" }, { "q": "Ryzen 7 5800X", "count": 60 } ] }'searchesis the list. Each search needs anendpoint, likeebay/soldormercari/sold, plus the same inputs that route takes as aGET.defaultsare inputs applied to every search. A search can override any of them.pagesis an eBay shorthand.{ "q": "RX 580", "pages": 3 }becomes three searches, for pages 1, 2 and 3. The most is 10. A page past the last one comes backfailedwithpage_out_of_rangeand costs nothing. A biggercountusually gets the same rows in fewer searches.- Send
Content-Type: application/json. The body can be up to 256 KB.
The answer is 202 with the batch, or 200 when every search was already cached. The Location header holds the batch's URL.
If any search is invalid, the whole batch is refused with 422 and nothing is charged. error.index says which search to fix:
{ "error": { "code": "unsupported_or_invalid_query", "index": 2 } }#Get the results
curl "https://api.soldgraph.com/v1/batches/BATCH_ID?wait=20" \ -H "Authorization: Bearer $SOLDGRAPH_KEY"wait holds the call open for up to 20 seconds and answers as soon as every search has settled. Poll again while status is pending.
{ "batch_id": "00000000-0000-4000-8000-000000000002", "status": "complete", "created_at": "2026-10-05T14:02:11+00:00", "counts": { "pending": 0, "complete": 2, "failed": 0, "rejected": 1 }, "credits": 2, "items": [ { "index": 0, "endpoint": "ebay/sold", "q": "RX 580 4GB", "request_id": "00000000-0000-4000-8000-000000000003", "status": "complete", "cached": false, "credits": 1, "rows": 120, "summary": { "priced_count": 120, "currency": "GBP", "median": 57.9, "low": 16.15, "high": 249.99, "earliest_sold_date": "2026-09-16", "latest_sold_date": "2026-10-04", "best_offer_accepted_count": 20 } }, { "index": 1, "endpoint": "ebay/sold", "q": "GTX 1660 Ti", "request_id": "00000000-0000-4000-8000-000000000004", "status": "complete", "cached": true, "credits": 1, "rows": 96, "summary": { "priced_count": 96, "currency": "GBP", "median": 74.5, "low": 30, "high": 140, "earliest_sold_date": "2026-09-20", "latest_sold_date": "2026-10-04", "best_offer_accepted_count": 11 } }, { "index": 2, "endpoint": "ebay/sold", "q": "Ryzen 7 5800X", "request_id": null, "status": "rejected", "cached": false, "credits": 0, "error": { "code": "too_many_pending" } } ]}Each search has one of four states:
status | Meaning | Cost |
|---|---|---|
pending | Still running. | Holds 1 request until it settles. |
complete | Done. rows and, on eBay, summary are filled in. | 1 request |
failed | The search ran and failed. error.code is a job error. | 0 |
rejected | The search was not accepted, for example because your allowance ran out. error.code says why. | 0 |
- By default you get each search's
summary, not its rows. That keeps a big batch small. - Add
include=resultsto get every search's fullresultin the same answer. - Each
request_idis an ordinary job. You can read one search at/v1/jobs/REQUEST_ID. indexis the position afterpagesis expanded.- A search with
error.codeofnot_submittedwas cut off before it was sent. Send the same batch again with the sameIdempotency-Keyand only the missing searches run.
#Download as CSV
curl "https://api.soldgraph.com/v1/batches/BATCH_ID?format=csv" \ -H "Authorization: Bearer $SOLDGRAPH_KEY" -o prices.csv- The file has one line per listing from every complete search, with
search_indexandqin the first two columns. - Prices become two columns, like
displayed_price_amountanddisplayed_price_currency. - CSV is ready once nothing is pending. Before that you get
409 result_not_ready. - One job works the same way:
/v1/jobs/REQUEST_ID?format=csv. - Text that starts with
=,+,-or@gets a leading', so a spreadsheet shows it as text.
#Limits and cost
- Size. A batch can hold as many searches as your plan allows pending at once: 10 on Free, 25 on Starter, 50 on Pro, 100 on Business and 200 on Scale.
pagescounts as one search per page. A bigger batch returns422 batch_too_large. - Cost. One request per search that completes, cache hits included. Failed and rejected searches are free.
- Rate limit. Creating a batch is one API call toward your 60 per minute, however many searches it holds. Each poll is one call.
- Pending cap. Searches in a batch count toward your pending cap like any others. If you already have searches pending, some of the batch can come back
rejectedwithtoo_many_pending. Send those again once the rest finish. - Retries. Send an
Idempotency-Key. A retry with the same key and body returns the same batch. The same key with a different body returns409 idempotency_conflict.