Grail

Grail API

Real eBay sold comps.
As an API.

Cleaned, deduped, summarized sold prices — what buyers actually paid, not asking prices. Keys are instant, with no approval queue. Build bots, repricers, portfolio apps and deal scanners on top.

Ask Grail

search the docs

Quickstart

curl -H "Authorization: Bearer gk_live_your_key" \
  "https://grail.solutions/v1/scrape?keyword=charizard%20base%20set&count=240&sold=true"

Every response is JSON. Sold data lives in the items array; the summary block gives you median / mean / min / max / p25 / p75 over the cleaned set.

Authentication

Pass your key as a Bearer token: Authorization: Bearer gk_live_…. Keys are instant — no app review, no waiting, commercial use included. A missing or invalid key returns 401 {"error":"unauthorized"}.

Endpoints

GET/v1/scrape

Sold (or active) listings for a keyword, cleaned and summarized.

  • keyword — required
  • count — 1–240 (default 240)
  • page — 1+
  • sold — true (default) | false
  • ebaySite — ebay.com today (more eBay sites on the roadmap)
  • minPrice · maxPrice · itemCondition · buyingFormat
  • soldAfter · soldBefore · sortOrder · exactMatch
POST/v1/scrape/jobs

Bulk / bursty work goes to an async job queue — paced so we never get blocked. Returns 202 with a job_id. Poll it with GET /v1/scrape/jobs/{job_id}.

GET/v1/usage

Current key usage, plan, monthly quota, per-minute limit and reset window.

GET/v1/ledger/stats

Ledger size and cache stats for the sold-data store.

Response

{
  "keyword": "charizard base set",
  "page": 1,
  "totalItems": 207,
  "totalResults": "240",
  "hasNextPage": true,
  "rawMedian": 215.0,
  "rawSampleCount": 240,
  "summary": {
    "count": 207,
    "currency": "USD",
    "median": 215.0,
    "mean": 268.42,
    "min": 42.0,
    "max": 1999.99,
    "p25": 128.5,
    "p75": 349.0,
    "avgShipping": 6.4
  },
  "items": [
  {
      "itemId": "1234567890",
      "title": "1999 Pokemon Base Set Charizard 4/102 Holo PSA 9",
      "url": "https://www.ebay.com/itm/1234567890",
      "condition": "Pre-Owned",
      "conditionId": 3000,
      "soldPrice": "1250.00",
      "shippingPrice": "0.00",
      "totalPrice": "1250.00",
      "endedAt": "2026-09-28",
      "buyingFormat": "buyItNow"
    }
  ]
}

Prices are decimal strings (exact, no float drift). Response headers: X-Grail-Source (live | ledger), X-Request-Id, X-Usage-Remaining.

Examples

Python

import requests

r = requests.get(
    "https://grail.solutions/v1/scrape",
    params={"keyword": "charizard base set", "count": 240, "sold": True},
    headers={"Authorization": "Bearer gk_live_your_key"},
)
data = r.json()
print(data["summary"]["median"], data["summary"]["count"])

JavaScript

const r = await fetch(
  "https://grail.solutions/v1/scrape?keyword=charizard%20base%20set&count=240",
  { headers: { Authorization: "Bearer gk_live_your_key" } }
)
const { items, summary } = await r.json()
console.log(summary.median, items.length)

Build tools

Import the Postman collection to hit every endpoint in seconds, or generate a typed client from the OpenAPI document.

Errors

  • 401 — missing / invalid key.
  • 429 — quota exceeded ({"error":"quota_exceeded"}); check X-Usage-Remaining.
  • 503 — upstream momentarily rate-limiting us (server_busy / upstream_blocked). Retry with backoff.

Pricing

Instant keys. Free tier. One request returns up to 240 rows. Overage credits are billed per 1,000 requests.

Free$0/mo
  • 100 requests / mo
  • 60 req / min
  • 1 key
Developer$9/mo
  • 2,000 requests / mo
  • 60 req / min
  • 2 keys
Pro$29/mo
  • 10,000 requests / mo
  • 60 req / min
  • 5 keys
Scale$79/mo
  • 50,000 requests / mo
  • 60 req / min
  • Unlimited

Need more volume or a custom plan? See all tiers →

MCP connector

Point Claude, Cursor, Codex or any MCP client at the Grail comps server and ask for sold prices in plain language. Four tools — search_sold, card_research, shipping_rates and usage — behind the same bearer key you already have. Hosted streamable-HTTP at https://grail.solutions/mcp, no local install.

MCP setup guide — Claude, Cursor & Codex →