Available on Standard, Pro and Shop. Create a key in Settings in the dashboard; the secret is shown once. You can hold up to ten active keys at a time and revoke any of them without affecting the others.
Base URL and authentication
https://api.listrune.com/v1
Send the key as a bearer token on every request:
curl https://api.listrune.com/v1/status \
-H "Authorization: Bearer lr_xxxxxxxx_xxxxxxxx"
A key is scoped to the organisation that created it and can only ever see that organisation's data. Two endpoints are deliberately closed to keys and need a signed-in session: managing API keys themselves, and connecting or disconnecting an eBay account.
Errors
| Status | Body | Meaning |
|---|---|---|
| 400 | {"error":{"formErrors":[],"fieldErrors":{…}}} | The request body or query failed validation. The object names the fields. |
| 401 | {"error":"unauthorized"} | Missing or unrecognised key. |
| 402 | {"error":"subscription_required"} | No active subscription. |
| 402 | {"error":"trial_over"} | The Starter trial has ended. |
| 402 | {"error":"scan_limit","scans":{…}} | This month's AI photo scans are used up. The scans object carries used and limit. |
| 403 | {"error":"api_plan_required"} | The key is valid but the organisation is no longer on a plan that includes API access. |
| 404 | {"error":"not_found"} | No such record in your organisation. |
There are no rate-limit or allowance headers. Read GET /v1/status for what is left.
Catalogue
GET /v1/games- Every supported game with its languages. Returns an array of
{ id, name, languages }. GET /v1/sets- Query:
game(required),lang(defaulten),qto filter by name or code,limit1–1000 (default 500). Returns{ count, sets }, newest release first. GET /v1/cards/search- Query:
game(required),lang,q,set,number,limit1–50 (default 10). Returns{ count, results }where each result is a printing with its set, rarity, finishes and external ids. GET /v1/cards/{game}/{sourceId}- One printing. Query:
lang.
Batches
GET /v1/batches- Every batch with its card count and value.
POST /v1/batches- Body:
name(1–120 characters, required),note(≤2000),defaults—{ game, lang, condition, finish, merge }, inherited by cards added to the batch. Returns 201. GET /v1/batches/{id}- One batch.
GET /v1/batches/{id}/dashboard- Current estimated value of recorded batch cards, recorded 7–90 day third-party market-price history for comparable holdings, biggest movers and card/price activity. History begins with the first batch dashboard check; earlier prices are not reconstructed. The chart uses only batch quantities and Cardmarket/TCGplayer quotes, never eBay orders or eBay quotes.
POST /v1/batches/{id}/market-quotes/refresh- Refresh only Cardmarket/TCGplayer quotes for cards in a batch. Does not change asking prices or contact eBay.
PATCH /v1/batches/{id}- Body: any of
name,status(open,exported,done),note,defaults. DELETE /v1/batches/{id}- Returns 204. A batch holding cards needs
?cards=Nmatching the real count as confirmation, otherwise 409batch_not_empty. A batch with cards live on eBay returns 409live_on_ebay.
Inventory
GET /v1/inventory- Query:
batchIdto scope to one batch. Each item carries its printing, condition, finish, quantity, cost, quotes, ask price, photo,statusand anyissues. POST /v1/inventory- Body:
batchId,game,sourceId(all required), pluslang,condition,finish,quantity(default 1),costEur,price(default true),merge,scanId. Returns 201, or 200 withmerged: truewhen it merged into an identical row already in the batch. Adding and pricing cards do not consume AI scan allowance. PATCH /v1/inventory/{id}- Body: any of
quantity,askEur,costEur,condition,finish,cardmarketId. PasscostEur: nullorcardmarketId: nullto clear them. If you change condition, finish or cost without settingaskEur, the price is recalculated. POST /v1/inventory/{id}/reprice- Reprice one card against the current rule. Costs no allowance.
POST /v1/inventory/{id}/photomultipart/form-datawith a single field namedimage— JPG, PNG or WebP, up to 15 MB. Replaces the listing photo.DELETE /v1/inventory/{id}- Returns 204, or 409
live_on_ebayif the card is listed. GET /v1/inventory/export.csv- Your own inventory as a plain CSV. Query:
batchId. Never counts against allowance.
Pricing
GET /v1/pricing/rule- Returns
{ rule, default, fx }— your rule, the shipped default, and the conversion rates in use. PUT /v1/pricing/rule- Partial update. Fields:
anchor(one or two ofcardmarket,tcgplayer, in order of preference),multiplier0.1–5,minMargin0–10,floorEur,conditionFactor(per condition, 0–5),rounding(psychologicalorcents). DELETE /v1/pricing/rule- Back to the default.
POST /v1/pricing/preview- Body:
marketEur(required),condition,costEur. Returns{ askEur }without touching anything. POST /v1/pricing/reprice-all- Body:
batchIdoritemIds; omit both for everything. Returns{ repriced, failed, items }. Costs no allowance.
Listings and export
POST /v1/listings/check- Body:
marketplace(ebayorcardmarket, required), plusbatchIdoritemIds. Returns what would be exported, what would be skipped and why, and any account-levelblockers— missing eBay business policies, a disconnected account, a site the CSV template does not cover. Call this before exporting. POST /v1/listings/preview- Same body. Returns just the listings that would go out.
POST /v1/listings/export- Same body. Returns the CSV itself, with the filename in
Content-Dispositionand the number of held-back rows inX-Listrune-Skipped. Given abatchId, it records the export and moves an open batch toexported.
Status
GET /v1/status- Everything about the account in one call: live games, price sources, marketplaces, plan,
interval, trial state and
usage.scansThisMonthagainst your AI scan allowance. This is where you check remaining scans before a bulk run.
A worked example
# 1. make a batch
curl -X POST https://api.listrune.com/v1/batches \
-H "Authorization: Bearer $LR_KEY" -H "content-type: application/json" \
-d '{"name":"Obsidian Flames ETB","defaults":{"game":"pokemon","lang":"de"}}'
# 2. find the printing
curl -G https://api.listrune.com/v1/cards/search \
-H "Authorization: Bearer $LR_KEY" \
--data-urlencode game=pokemon --data-urlencode lang=de \
--data-urlencode "q=Glurak ex"
# 3. add it, priced
curl -X POST https://api.listrune.com/v1/inventory \
-H "Authorization: Bearer $LR_KEY" -H "content-type: application/json" \
-d '{"batchId":"…","game":"pokemon","sourceId":"…","lang":"de","condition":"NM"}'
# 4. see what would be held back
curl -X POST https://api.listrune.com/v1/listings/check \
-H "Authorization: Bearer $LR_KEY" -H "content-type: application/json" \
-d '{"marketplace":"ebay","batchId":"…"}'
# 5. take the file
curl -X POST https://api.listrune.com/v1/listings/export \
-H "Authorization: Bearer $LR_KEY" -H "content-type: application/json" \
-d '{"marketplace":"ebay","batchId":"…"}' -OJ
