{"openapi":"3.1.0","info":{"title":"Profitr Catalogue API","version":"1.0.0","description":"UK resale market prices for the Profitr catalogue: true market, 30-day sold market, live market, trend and a plain-English summary. Server-to-server only — keep your key secret. Figures are estimates derived from eBay UK data."},"servers":[{"url":"https://api.profitr.co.uk/v1"}],"security":[{"bearer":[]}],"paths":{"/items/search":{"get":{"summary":"Search items by name","description":"Stored figures only — search never triggers a refresh. Common shorthand is understood (ETB, BB, UPC, SPC, PC ETB, set codes such as PFL or PE). 1 call. Max 25 results.","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":200}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":25,"default":10}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Item"}},"query":{"type":"object","description":"The query as sent, and what shorthand expanded it to (null if nothing expanded). Judge matches against `expanded` when set.","properties":{"q":{"type":"string"},"expanded":{"type":["string","null"]}}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"`trial_exhausted`, `insufficient_calls`, `no_plan` or `cap_reached`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account suspended (`suspended`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`); see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/items":{"get":{"summary":"Look up items by TCGplayer id","description":"1 call.","parameters":[{"name":"tcgplayer_id","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d+$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Item"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"`trial_exhausted`, `insufficient_calls`, `no_plan` or `cap_reached`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account suspended (`suspended`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`); see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/items/{id}":{"get":{"summary":"Get one item","description":"Figures older than 48 hours refresh in the background (`refreshing: true`); call again later for the newer figure. With `refresh=wait`, a figure older than 48 hours is refreshed before the response (can take ~5–20s). 1 call.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"refresh","in":"query","schema":{"type":"string","enum":["wait"]},"description":"Refresh figures older than 48h before responding."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Item"},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"`trial_exhausted`, `insufficient_calls`, `no_plan` or `cap_reached`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account suspended (`suspended`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`); see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/items/batch":{"post":{"summary":"Get many items","description":"Up to 100 ids. Charged 1 call per item returned (minimum 1). Unknown ids are listed in `not_found` and not charged. Send `\"refresh\": \"wait\"` to refresh up to 25 figures older than 48h before the response (allow up to ~50s); any not finished come back with `refreshing: true`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["ids"],"properties":{"ids":{"type":"array","maxItems":100,"items":{"type":"string","format":"uuid"}},"refresh":{"type":"string","enum":["wait"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Item"}},"not_found":{"type":"array","items":{"type":"string"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"`trial_exhausted`, `insufficient_calls`, `no_plan` or `cap_reached`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account suspended (`suspended`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`); see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/items/{id}/history":{"get":{"summary":"Daily price history","description":"Full history. 1 call.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"from","in":"query","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HistoryPoint"}},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"`trial_exhausted`, `insufficient_calls`, `no_plan` or `cap_reached`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Account suspended (`suspended`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited (`rate_limited`); see `Retry-After`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/usage":{"get":{"summary":"Your plan and usage","description":"Free — not counted.","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Usage"}}}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests":{"post":{"summary":"Request a new catalogue item","description":"Joins the Profitr review queue. Free, max 5 per day.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","category"],"properties":{"title":{"type":"string"},"category":{"type":"string"},"subcategory":{"type":"string"},"notes":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or invalid key (`invalid_key`)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Invalid body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"Your key: `Authorization: Bearer pk_live_…`"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"Meta":{"type":"object","properties":{"request_id":{"type":"string"},"plan":{"type":"string","enum":["trial","starter","growth","scale","custom"]},"calls_used":{"type":"integer"},"calls_included":{"type":"integer"},"overage_calls":{"type":"integer"}}},"Item":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"subtitle":{"type":["string","null"]},"category":{"type":"string"},"subcategory":{"type":["string","null"]},"rrp_gbp":{"type":["number","null"]},"tcgplayer_id":{"type":["string","null"]},"market":{"$ref":"#/components/schemas/Market"},"summary":{"type":"object","description":"Display-only English text (GBP). Wording may change with market.method — use the structured fields for logic.","properties":{"sold":{"type":"string"},"live":{"type":"string"},"seller_exclusions":{"type":["string","null"]}}},"links":{"type":"object","properties":{"market_page":{"type":"string","format":"uri"}}},"refreshing":{"type":"boolean"}}},"Market":{"type":"object","properties":{"true_market_gbp":{"type":["number","null"]},"basis":{"type":["string","null"],"enum":["blend","sold","sold_only","live_only",null]},"trend":{"type":["string","null"],"enum":["up","down","flat",null],"description":"Live listings vs sold market."},"spread_pct":{"type":["number","null"],"description":"(live − sold) / sold × 100"},"method":{"type":["string","null"],"description":"Valuation method version, e.g. profitr_market_v1"},"updated_at":{"type":["string","null"],"format":"date-time"},"sources":{"type":"array","items":{"oneOf":[{"type":"object","description":"Sold: trimmed median of the latest 10 UK sales within 30 days (90 when thin).","properties":{"type":{"const":"sold"},"value_gbp":{"type":["number","null"]},"count":{"type":"integer"},"window_days":{"type":"integer","enum":[30,90]},"confidence":{"type":["string","null"],"enum":["ok","thin","low",null]},"prior_gbp":{"type":["number","null"]},"momentum_pct":{"type":["number","null"]},"lowest_gbp":{"type":["number","null"]},"updated_at":{"type":["string","null"]}}},{"type":"object","description":"Live: median of the cheapest 10 UK fixed-price listings from sellers with >10 feedback and 100% positive.","properties":{"type":{"const":"live"},"value_gbp":{"type":["number","null"]},"check_gbp":{"type":["number","null"]},"count":{"type":"integer"},"confidence":{"type":["string","null"],"enum":["ok","low","unchecked",null]},"lowest_gbp":{"type":["number","null"]},"low_outlier_gbp":{"type":"array","items":{"type":"number"}},"seller_excluded_count":{"type":"integer"},"updated_at":{"type":["string","null"]}}}]}}}},"HistoryPoint":{"type":"object","properties":{"date":{"type":"string","format":"date"},"true_market_gbp":{"type":["number","null"]},"sold_market_gbp":{"type":["number","null"]},"live_market_gbp":{"type":["number","null"]},"sold_momentum_pct":{"type":["number","null"]},"trend":{"type":["string","null"]},"basis":{"type":["string","null"]},"sold_count":{"type":"integer"}}},"Usage":{"type":"object","properties":{"plan":{"type":"string"},"period_start":{"type":["string","null"]},"period_end":{"type":["string","null"]},"calls_used":{"type":"integer"},"calls_included":{"type":"integer"},"free_calls_remaining":{"type":["integer","null"]},"overage_calls":{"type":"integer"},"overage_rate_gbp":{"type":"number"},"overage_cap_calls":{"type":["integer","null"]},"rate_limit_per_min":{"type":"integer"}}}}}}