Developers

Profitr Catalogue API

UK resale market prices for bots, cash-out servers and tools. The true market price, 30-day sold market, live market and trend, plus a plain-English summary for every item in the Profitr catalogue.

Getting started

  1. Sign in to Profitr and open Settings → API. Request access and tell us how you’ll use it.
  2. Once approved, generate your key. You get 50 free calls to try it.
  3. Pick a plan when you’re ready. Usage, billing and your overage cap live on the same page.

Send your key on every request as Authorization: Bearer pk_live_…. The API is server-to-server only: keep the key in a secret store (e.g. a Supabase secret), never in browser code. Base URL: https://api.profitr.co.uk/v1.

// Supabase edge function (Deno): price a member's cash-out submission
const API = "https://api.profitr.co.uk/v1";
const headers = {
  Authorization: `Bearer ${Deno.env.get("PROFITR_API_KEY")}`,
  "Content-Type": "application/json",
};

// 1. Find the item once and store its id
const search = await fetch(`${API}/items/search?q=${encodeURIComponent("ascended heroes bundle case")}`, { headers });
const [item] = (await search.json()).data;

// 2. Price many stored ids in one call (1 call per item returned)
const res = await fetch(`${API}/items/batch`, { method: "POST", headers, body: JSON.stringify({ ids: [item.id] }) });
if (res.status === 429) await new Promise((r) => setTimeout(r, Number(res.headers.get("Retry-After") ?? 5) * 1000));
const { data } = await res.json();
const offer = data[0].market.true_market_gbp * 0.8; // your cash-out rate

Pricing

Starter

£19/mo

1,000 calls

then £0.02375/call · 60 req/min

Growth

£49/mo

10,000 calls

then £0.006125/call · 300 req/min

Scale

£99/mo

50,000 calls

then £0.002475/call · 600 req/min

50,000+

Enquire

Custom allowance

GBP, billed monthly, no VAT. Overage is 125% of your plan’s per-call rate, with a default safety cap of 2× your allowance (adjustable). Trial keys are limited to 20 requests/min.

How prices work

  • Sold market: the latest 10 UK eBay sales within 30 days (highest and lowest trimmed when there are 5+), median, item price ex postage. Falls back to 90 days when sales are thin. momentum_pct compares it with sales 31–90 days ago.
  • Live market: the cheapest 10 UK fixed-price listings from sellers with more than 10 feedback and 100% positive, median. The lowest two only count if they’re within 20% of the rest.
  • True market: the average of sold and live when they’re within ±5% (trend: flat); otherwise the sold market, with trend up or down by where live sits.
  • Freshness: figures older than 48 hours refresh in the background when you request an item (refreshing: true). Add refresh=wait (item) or "refresh": "wait" (batch) to refresh them before the response instead. Search returns stored figures only.
  • summary is display-only English text. Build logic on the structured fields; wording can change with market.method.

Endpoints

get/items/search

Search items by name

Stored figures only — search never triggers a refresh. 1 call. Max 25 results.

  • q (query, required) — string
  • limit (query) — integer, max 25

get/items

Look up items by TCGplayer id

1 call.

  • tcgplayer_id (query, required) — string

get/items/{id}

Get one item

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.

  • id (path, required) — string
  • refresh (query) — string

post/items/batch

Get many items

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`.

get/items/{id}/history

Daily price history

Full history. 1 call.

  • id (path, required) — string
  • from (query) — string
  • to (query) — string

get/usage

Your plan and usage

Free — not counted.

post/requests

Request a new catalogue item

Joins the Profitr review queue. Free, max 5 per day.

Batch accepts up to 100 ids and is charged per item returned. Every response has meta with your usage, plus X-RateLimit-* and X-Request-Id headers.

Example item

{
  "data": {
    "id": "6f1c…",
    "title": "Ascended Heroes Booster Bundle Case",
    "category": "Sealed TCG",
    "rrp_gbp": 179.99,
    "tcgplayer_id": "593355",
    "market": {
      "true_market_gbp": 214.5,
      "basis": "blend",
      "trend": "flat",
      "spread_pct": 3.1,
      "method": "profitr_market_v1",
      "updated_at": "2026-10-25T09:12:00Z",
      "sources": [
        { "type": "sold", "value_gbp": 211.2, "count": 10, "window_days": 30, "confidence": "ok",
          "prior_gbp": 198.0, "momentum_pct": 6.67, "lowest_gbp": 189.99 },
        { "type": "live", "value_gbp": 217.8, "check_gbp": 229.0, "count": 25, "confidence": "ok",
          "lowest_gbp": 205.0, "low_outlier_gbp": [], "seller_excluded_count": 3 }
      ]
    },
    "summary": {
      "sold": "Current 30d market is £211.20 based on 10 sales. …",
      "live": "Current active market is £217.80 based on 25 qualifying listings. …",
      "seller_exclusions": "3 listings were excluded because the seller had 10 or fewer feedback or was under 100% positive."
    },
    "links": { "market_page": "https://app.profitr.co.uk/market/6f1c…" },
    "refreshing": false
  },
  "meta": { "request_id": "req_…", "plan": "growth", "calls_used": 4211, "calls_included": 10000, "overage_calls": 0 }
}

Errors

Errors return { "error": { "code", "message" } }.

CodeHTTPMeaning
invalid_key401Missing or wrong key.
trial_exhausted402All 50 free calls used — subscribe to a plan.
insufficient_calls402Not enough free calls left for this batch.
no_plan402No active plan.
cap_reached402Your overage safety cap for this period is reached.
suspended403Account suspended.
not_found404Item not found (or not approved).
invalid_request422Bad parameters or body.
rate_limited429Too many requests this minute — wait for Retry-After seconds.