# Courtyard.io API scraper - the vaulted graded-card marketplace: search every slab Courtyard holds (Pokémon, One Piece, Magic, sports cards, sealed packs, comics, coins) by game, grader, grade, set, year, price and fair market value; full asset detail with cert number, FMV, asks, bids, Courtyard's buyback offer, vault status and on-chain sale history; live pack pulls; marketplace sales feed; packs with price, expected value and odds. USD. No account, no wallet, no browser.

> Search Courtyard's marketplace - every graded slab, raw card, sealed pack, comic and coin in Courtyard's vault - by name or cert number, and filter by game/category, item type, grader, grade, year, set, language, the pack it was pulled from, buy-now price range, fair-market-value range, listed or not, and listing date. Each row: the asset id, the card identity (name, set, number, year, variant), grader, grade and cert number, the live buy-now price (null when not listed), Courtyard's FMV and the discount to it, favorites, views, owner, image and courtyard.io link. 10 sort orders.
> ReefAPI engine `courtyard` · 7 endpoints · clean JSON, no scraping or browsers to manage.

## How to call
- **Endpoint:** `POST https://api.reefapi.com/courtyard/v1/<action>` with a JSON body.
- **Auth:** header `x-api-key: <YOUR_REEFAPI_KEY>` — create one free (1,000 credits, no card): https://reefapi.com/signup
- **Response (every call):** `{ ok: boolean, data: ..., meta: { record_count, credits, ... }, error: { code, message } }` — branch on `ok`. Failed calls are free.
- **One key + one shared credit pool** across every ReefAPI API. Per-call credits are listed on each endpoint below.
- **Use it from an AI agent (MCP):** connect `https://api.reefapi.com/mcp` (remote streamable-http). Clients that add connectors by URL, such as ChatGPT and the Claude app, connect with OAuth 2.1 (the user pastes their key once on a ReefAPI page; discovery at `/.well-known/oauth-protected-resource/mcp`). Config files send the key as `Authorization: Bearer <key>`. `?key=<key>` in the URL also works as a last-resort fallback.

## Endpoints

### POST https://api.reefapi.com/courtyard/v1/search — 2 credits
Search Courtyard's marketplace - every graded slab, raw card, sealed pack, comic and coin in Courtyard's vault - by name or cert number, and filter by game/category, item type, grader, grade, year, set, language, the pack it was pulled from, buy-now price range, fair-market-value range, listed or not, and listing date. Each row: the asset id, the card identity (name, set, number, year, variant), grader, grade and cert number, the live buy-now price (null when not listed), Courtyard's FMV and the discount to it, favorites, views, owner, image and courtyard.io link. 10 sort orders.

**Parameters:**
- `query` (string, optional) — Free text as typed in the site's search box: card or player name, set, card number or a grading cert number.
- `category` (string, optional) — Game, sport or theme (pokemon, one_piece, magic, baseball, basketball, football, soccer, marvel_comic, ancient_coins …) or the exact category name Courtyard shows. Several separated by commas. `filters` lists every category with counts. [one of: pokemon, one_piece, magic, yugioh, baseball, basketball, football, hockey, soccer, formula_1, wrestling, boxing, mma, golf, tennis, racing, marvel, marvel_comic, dc_comic, independent_comic, disney, star_wars, veefriends, weiss_schwarz, metazoo, dragon_ball, league_of_legends, ancient_coins, us_coins, shipwreck_coins, slam_magazine, sneakers, watches]
- `collection` (enum, optional) — Kind of item: graded cards, raw cards, sealed booster packs, graded comics, graded coins, sneakers, watches. [one of: graded_cards, raw_cards, sealed_packs, graded_comics, graded_coins, sneakers, watches, framed_jerseys]
- `grader` (string, optional) — Grading company (PSA, CGC, BGS, SGC, TAG, NGC, PCGS …). Several separated by commas. [one of: PSA, CGC, BGS, SGC, TAG, CSG, NGC, PCGS, CGC-COMIC, BVG, AGS, BCCG, GMA, HGA, ISA, PSA-DNA, DSG, CCG, DCS, FCG, FGA]
- `grade` (string, optional) — Grade: a number (10, 9.5, 9 … matches every label of that grade, e.g. 10 = GEM MINT, PRISTINE, BLACK LABEL, PERFECT) or an exact label such as '10 PRISTINE'. Several separated by commas.
- `year` (string, optional) — Year printed on the card. Several separated by commas.
- `set` (string, optional) — Exact set name as Courtyard shows it (`filters` lists them).
- `language` (string, optional) — Card language: English, Japanese, Chinese, Korean, German, French, Spanish, Italian, Indonesian, Thai, Portuguese …
- `pack` (string, optional) — Name of the Courtyard pack or event the item was pulled from (`filters` → pulled_from).
- `variant` (string, optional) — Parallel / variant label (Holo, 1st Edition, Refractor, Full Art …).
- `listing_status` (enum, optional, default "all") — All vault items (default, like the site) or only items listed for sale. [one of: all, listed]
- `price_min` (number, optional) — Lowest buy-now price, USD (implies listed items).
- `price_max` (number, optional) — Highest buy-now price, USD (implies listed items).
- `fmv_min` (number, optional) — Lowest Courtyard fair market value, USD.
- `fmv_max` (number, optional) — Highest Courtyard fair market value, USD.
- `listed_after` (string, optional) — Only items listed at or after this time (ISO date/time or unix seconds) - for incremental monitoring of new listings.
- `sort` (enum, optional, default "newest_listed") — Order of results. [one of: newest_listed, price_asc, price_desc, newest_pulled, recently_transferred, best_deals, discount_desc, fmv_desc, fmv_asc, most_favorited]
- `page` (integer, optional, default 1) — Page number. Courtyard serves the first 1,000 results of any search; narrow the filters to reach the rest.
- `limit` (integer, optional, default 48) — Rows per page (1-100; the site shows 48).
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** query, results[]{asset_id, title, collection, card{name, set, card_number, year, category, language, variant, brand, tags[], pulled_from, attributes{}}, grading{grader, grade, grade_value, grade_label, cert_number}, listing{order_id, price_usd, currency, listed_at, expires_at, maker_wallet, marketplace} (null when not for sale), for_sale, fmv_usd, fmv_confidence, fmv_source, discount_to_fmv_percent, favorite_count, view_count, owner{username, wallet, owned_since}, pulled_at, last_transfer_at, image_url, url}, count, total, page, limit, pages, has_more, sort, filters{}

**Example request body:**
```json
{
  "query": "charizard",
  "grader": "PSA",
  "listing_status": "listed"
}
```

### POST https://api.reefapi.com/courtyard/v1/asset — 2 credits
One Courtyard asset in full: card identity, grader, grade and cert number, Courtyard's fair market value and its confidence, the buy-now listing and every ask, every bid (Courtyard's own instant buyback offer flagged), minimum listing and bid prices, vault status and location, burned/redeemed status, owner, the pack it was pulled from, front and back slab scans, video, token and contract, likes, and the complete on-chain history with every sale price (marketplace sale vs buyback) and the pack price paid at the pull. Look up by asset id, asset URL or grading cert number.

**Parameters:**
- `asset_id` (string, required) — The 64-character Courtyard asset id (asset_id from search), the asset URL on courtyard.io, or the grading company's cert number.
- `grader` (string, optional) — Only with a cert number: which grader issued it, when two graders share the number.
- `include_description` (boolean, optional, default false) — Also return Courtyard's write-up of the card (headline, history, key facts, sources) when it has one.
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** asset{asset_id, title, collection, card{…}, grading{grader, grade, grade_value, grade_label, cert_number}, fmv_usd, fmv_confidence, minimum_listing_price_usd, minimum_bid_usd, listing{…}, for_sale, asks[]{order_id, side, price_usd, currency, maker_wallet, is_courtyard_buyback, created_at, expires_at, marketplace}, bids[]{…}, best_bid_usd, courtyard_buyback_offer_usd, vaulted, vault_location, burned, status, owner{username, wallet}, last_event{type, time}, pulled_at, pulled_from_pack_id, pulled_from_pack_url, images{front, back, render, render_cropped, video}, collectible_id, chain, contract, token_id, metadata_url, url, likes, sale_history[]{type, kind (marketplace|buyback|pack_pull|burn|transfer), time, price_usd, payment, from_wallet, to_wallet, tx_hash, block}, last_sale{…}, sales_count, description{headline, summary, collectible_notes, design_and_history, key_facts[], sources[]} (include_description=true)}, price_history (null: Courtyard shows it to signed-in users only)

**Example request body:**
```json
{
  "asset_id": "e7d931f461c939c4c10f5cd3cd114fa2dddbcd9b7cbafa4a50c0009b2573d98f"
}
```

### POST https://api.reefapi.com/courtyard/v1/recent_pulls — 2 credits
The live feed of pack openings ('pulls') on Courtyard: the newest cards, coins and comics pulled from packs, all packs or the ones you name, with the card identity, grade, cert number, FMV, the pack, who pulled it, whether it is still in the vault or was already sold back, and Courtyard's buyback offer. Up to 50 newest pulls per call.

**Parameters:**
- `pack_id` (string, optional) — Only pulls from these packs (ids from `packs`, comma-separated).
- `limit` (integer, optional, default 50) — How many of the newest pulls (1-50).
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** pulls[]{asset_id, title, collection, card{…}, grading{…}, fmv_usd, fmv_confidence, pulled_at, pack_id, pack_url, revealed, pulled_by{username, wallet} (null when unknown), current_owner{username, wallet}, status (in_vault | burned_or_redeemed), last_event{type, time}, courtyard_buyback_offer_usd, listing{…}, image_url, front_image_url, url}, count, packs[]

**Example request body:**
```json
{
  "limit": 20
}
```

### POST https://api.reefapi.com/courtyard/v1/sales — 3 credits
Recent sales across the whole Courtyard marketplace, newest first, from the on-chain transactions: sale price in USD, time, buyer and seller wallets, transaction hash, and whether it was a marketplace sale between collectors or an instant buyback by Courtyard - joined with the card (title, grader, grade, cert number, FMV at the time of the call). Roughly the last 1,000 sales are reachable.

**Parameters:**
- `kind` (enum, optional, default "marketplace") — Which sales. About 4 in 5 on-chain sales are buybacks. [one of: marketplace, buyback, all]
- `limit` (integer, optional, default 25) — How many sales to return (1-50).
- `offset` (integer, optional, default 0) — Skip this many of the newest on-chain sale transactions (use next_offset from the previous page).
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** sales[]{time, kind, price_usd, payment, seller_wallet, buyer_wallet, tx_hash, block, asset_id, title, card{…}, grading{…}, fmv_usd, collection, image_url, url}, count, scanned_transactions, next_offset, has_more

### POST https://api.reefapi.com/courtyard/v1/packs — 2 credits
Every Courtyard pack (vending machine): price, expected value and its ratio to price, buyback ratio, the odds table (value tiers with min/max value and odds percent), pulls in the last 24 hours, 7 and 30 days, stock status, category, tier and link. Filter by category or status.

**Parameters:**
- `category` (string, optional) — Only packs of this category (pokemon, one_piece, sports, baseball, basketball, football, comics, coins, watches, sneakers …; matches the category id or name).
- `status` (enum, optional, default "active") — Active packs only (default) or all. [one of: active, all]
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** packs[]{pack_id, title, description, category, category_id, category_group, tier, status, featured, price_usd, expected_value_usd, expected_value_ratio, buyback_ratio, sale_closed, max_per_purchase, out_of_stock, low_stock, min_card_value_usd, odds[]{tier, min_value_usd, max_value_usd, odds_percent} (null when Courtyard publishes no odds for the pack), pulls_24h, pulls_7d, pulls_30d, pull_counts_at, image_url, thumbnail_url, url}, count

**Example request body:**
```json
{
  "category": "pokemon"
}
```

### POST https://api.reefapi.com/courtyard/v1/pack — 1 credit
One Courtyard pack in full: everything in `packs` plus its heavy hitters - the top-tier chase cards Courtyard shows for the pack (up to 50, highest FMV first) with tier, title, FMV and images.

**Parameters:**
- `pack_id` (string, required) — Pack id from `packs`, or its courtyard.io/vending-machine/… URL.
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** pack{…packs fields, heavy_hitters[]{tier, collectible_id, title, fmv_usd, image_url, front_image_url}}

**Example request body:**
```json
{
  "pack_id": "pkmn-starter-pack"
}
```

### POST https://api.reefapi.com/courtyard/v1/filters — 1 credit
The marketplace's filter vocabularies with live counts: categories, item types, graders, grades, years, sets, languages, the packs/events items were pulled from and variants - for the whole vault or scoped to a search (query, category, item type, grader). Feed the values back into `search`.

**Parameters:**
- `query` (string, optional) — Scope the counts to a search.
- `category` (string, optional) — Game, sport or theme (pokemon, one_piece, magic, baseball, basketball, football, soccer, marvel_comic, ancient_coins …) or the exact category name Courtyard shows. Several separated by commas. `filters` lists every category with counts. [one of: pokemon, one_piece, magic, yugioh, baseball, basketball, football, hockey, soccer, formula_1, wrestling, boxing, mma, golf, tennis, racing, marvel, marvel_comic, dc_comic, independent_comic, disney, star_wars, veefriends, weiss_schwarz, metazoo, dragon_ball, league_of_legends, ancient_coins, us_coins, shipwreck_coins, slam_magazine, sneakers, watches]
- `collection` (enum, optional) — Kind of item: graded cards, raw cards, sealed booster packs, graded comics, graded coins, sneakers, watches. [one of: graded_cards, raw_cards, sealed_packs, graded_comics, graded_coins, sneakers, watches, framed_jerseys]
- `grader` (string, optional) — Grading company (PSA, CGC, BGS, SGC, TAG, NGC, PCGS …). Several separated by commas. [one of: PSA, CGC, BGS, SGC, TAG, CSG, NGC, PCGS, CGC-COMIC, BVG, AGS, BCCG, GMA, HGA, ISA, PSA-DNA, DSG, CCG, DCS, FCG, FGA]
- `max_values` (integer, optional, default 100) — Most values per vocabulary (largest counts first).
- `max_rotations` (integer, optional, default 3) — How many fresh exits to try before giving up.

**Returns:** total, categories[]{value, count}, collections[]{value, key, count}, graders[], grades[], years[], sets[], languages[], pulled_from[], variants[] (each list {value, count}, largest first; a list you filtered on keeps every value, counted under the other filters - what you would get by switching)

**Example request body:**
```json
{
  "query": "charizard"
}
```

## At scale
- **Volume:** 5M+ requests a day, measured at 60 requests a second across the fleet with no
  central bottleneck. Per-key limits are raised for high-volume accounts; volume pricing on request.
- **Missing a source:** tell us a site we do not cover and it becomes an engine. A customer asked
  for bestprice.gr on 21 Sep 2026 and it was in the catalog on 22 Sep.
- **Support:** 2 minute median time from a question in the live chat to the first answer. Setup
  help included, no support tier to buy.
- **One key, one credit pool** across every API. No per-site plans, no separate subscriptions.

## More
- Try it live, no code: https://reefapi.com/playground?engine=courtyard
- Human docs page: https://reefapi.com/docs/courtyard
- Overview page: https://reefapi.com/courtyard-api
- Every ReefAPI API in one file (for your AI): https://reefapi.com/llms-full.txt
