Courtyard API & Scraper: parameters and responses
This is the reference for the 7 Courtyard endpoints under /courtyard/v1 (search, asset, recent_pulls, sales, packs, pack and filters) and their 27 parameters. Each endpoint lists its parameters, required or optional, with allowed values and defaults, and comes with a cURL, Python and JavaScript call; every response uses the same { ok, data, meta, error } envelope.
The Courtyard API returns Courtyard.io's vault marketplace as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
search covers every item Courtyard holds - about 420,000 graded Pokémon, One Piece, Magic and sports cards, sealed booster packs, graded comics and coins - filtered by game, item type, grading company (PSA, CGC, BGS, SGC, TAG …), grade, year, set, language, the pack it was pulled from, buy-now price and fair market value, with ten sort orders including best deals and biggest discount to FMV. Each row has the card identity, grader, grade and cert number, the live buy-now price, Courtyard's FMV and the discount to it. asset returns one slab in full by asset id or cert number: every ask and bid, Courtyard's own instant-buyback offer, vault status, owner and the complete on-chain history with every sale price. recent_pulls is the live feed of pack openings, sales the marketplace-wide feed of recent sales split into collector-to-collector sales and buybacks, packs and pack give each pack's price, expected value, odds table and pulls per day, and filters returns every filter value with live counts. Prices in USD. No account, no wallet, no browser - one ReefAPI key and the standard { ok, data, meta, error } envelope.
Courtyard packs: price, expected value and how many people open them
The most-opened Courtyard packs on 2026-11-08, from one packs call. Every pack's expected value sits at or just under its price, and every card can be sold straight back to Courtyard for 84.6% of its fair market value.
| Pack | Price (USD) | Expected value | Pulls in 24 h | Pulls in 30 days | Chase odds |
|---|---|---|---|---|---|
| Pokémon Starter Pack | 25 | 25.00 | 7,088 | 245,208 | 1% for $100-400 |
| Pokémon Basic Pack | 15 | 14.40 | 6,697 | 49,978 | 1.1% for $60-240 |
| Pokémon Pro Pack | 50 | 48.00 | 3,102 | 80,212 | 1.1% for $200-800 |
| Wildcard Basic Pack | 15 | 14.40 | 2,599 | 158,042 | 1% for $60-240 |
| Pokémon Master Pack | 100 | 96.00 | 1,671 | 40,069 | 1.1% for $400-1,600 |
| One Piece PSA 10 | 59 | 56.64 | 1,468 | 9,611 | 1% for $236-944 |
Odds tables are Courtyard's own (value tiers base, common, uncommon, rare, chase); 10 of 106 packs publish none and come back with odds null. Expected value is Courtyard's figure, not ours.
Real request and response JSON
Captured from the indexed primary action, pack, on .
{
"method": "POST",
"url": "https://api.reefapi.com/courtyard/v1/pack",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"pack_id": "pkmn-starter-pack"
}
}{
"ok": true,
"meta": {
"api": "courtyard",
"endpoint": "pack",
"mode": "live",
"latency_ms": 396.5,
"record_count": 1,
"bytes": 31772,
"cache_hit": false,
"charged_credits": 1,
"version": "0.1.0",
"request_id": "5e8f037bdb4e4e84",
"queue_ms": 1.5,
"fetched_at": "2026-11-08T13:05:05.876Z"
},
"data": {
"pack": {
"pack_id": "pkmn-starter-pack",
"title": "Pokémon Starter Pack",
"description": "Each digital pack contains one graded Pokémon card that can be shipped to you. Don't like what you pull? Sell it back to us instantly or list it on our marketplace with 0% seller fees.",
"category": "Pokémon",
"category_id": "pkmn",
"category_group": "tcg-cards",
"tier": "Starter",
"status": "ACTIVE",
"featured": true,
"price_usd": 25,
"expected_value_usd": 25,
"expected_value_ratio": 1,
"buyback_ratio": 0.846,
"sale_closed": false,
"max_per_purchase": 5,
"out_of_stock": false,
"low_stock": false,
"min_card_value_usd": 15,
"odds": [
{
"tier": "base",
"min_value_usd": 15,
"max_value_usd": 20,
"odds_percent": 39
},
{
"tier": "common",
"min_value_usd": 20,
"max_value_usd": 25,
"odds_percent": 31
},
{
"tier": "uncommon",
"min_value_usd": 25,
"max_value_usd": 50,
"odds_percent": 27
}
],
"pulls_24h": 7096,
"pulls_7d": 54339,
"pulls_30d": 244914,
"pull_counts_at": "2026-11-08T13:02:21.279532Z",
"image_url": "https://api.courtyard.io/configs/vending-machine/pkmn-starter-pack/resources/sealed_pack_image.png",
"thumbnail_url": "https://api.courtyard.io/configs/vending-machine/pkmn-starter-pack/resources/vending_machine_thumbnail.png",
"url": "https://courtyard.io/vending-machine/pkmn-starter-pack",
"heavy_hitters": [
{
"tier": "epic",
"collectible_id": "CY_PSA_102875801",
"title": "2002 Pokémon Expedition #4 Blastoise - Reverse Foil (PSA 6 EX-MT)",
"fmv_usd": 397.6,
"image_url": "https://static.courtyard.io/graded-cards-renders/PSA%20102875801/nft_image.jpg",
"front_image_url": "https://static.courtyard.io/graded-cards-scans/PSA%20102875801/slab_front.jpg"
},
{
"tier": "epic",
"collectible_id": "CY_PSA_136488433",
"title": "2019 Pokémon Sun & Moon Unbroken Bonds #130 Gardevoir & Sylveon GX - Holo (PSA 10 GEM MINT)",
"fmv_usd": 396.4,
"image_url": "https://static.courtyard.io/graded-cards-renders/PSA%20136488433/nft_image.jpg",
"front_image_url": "https://static.courtyard.io/graded-cards-scans/PSA%20136488433/slab_front.jpg"
},
{
"tier": "epic",
"collectible_id": "CY_PSA_168338340",
"title": "2000 Pokémon Promo #006 Charizard - Premium File 2 (PSA 9 MINT)",
"fmv_usd": 395,
"image_url": "https://static.courtyard.io/graded-cards-renders/PSA%20168338340/nft_image.jpg",
"front_image_url": "https://static.courtyard.io/graded-cards-scans/PSA%20168338340/slab_front.jpg"
}
]
}
}
}What the Courtyard API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | 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. | Pricing teams call search to search Courtyard's marketplace - every graded slab, raw card, sealed pack, comic and coin in…. | query, category, collection, grader, grade, ... |
| asset | 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. | Marketplace operators call asset to get one Courtyard asset in full. | asset_id, grader, include_description, max_rotations |
| recent_pulls | 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. | Catalog enrichment teams call recent_pulls to get the live feed of pack openings ('pulls') on Courtyard. | pack_id, limit, max_rotations |
| sales | 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. | Retail analysts call sales to get recent sales across the whole Courtyard marketplace, newest first, from the on-chain transact…. | kind, limit, offset, max_rotations |
| packs | 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. | Pricing teams call packs to get every Courtyard pack (vending machine). | category, status, max_rotations |
| pack | 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. | Marketplace operators call pack to get one Courtyard pack in full. | pack_id, max_rotations |
| filters | 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`. | Catalog enrichment teams call filters to get the marketplace's filter vocabularies with live counts. | query, category, collection, grader, max_values, ... |
Call pack from your stack
curl -X POST https://api.reefapi.com/courtyard/v1/pack \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"pack_id":"pkmn-starter-pack"}'import os
import requests
REEF_KEY = os.environ["REEF_KEY"]
r = requests.post(
"https://api.reefapi.com/courtyard/v1/pack",
headers={"x-api-key": REEF_KEY},
json={
"pack_id": "pkmn-starter-pack"
},
timeout=90,
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/courtyard/v1/pack", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"pack_id": "pkmn-starter-pack"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.courtyard.pack with {"pack_id":"pkmn-starter-pack"}.Who uses this API and why
- Deal finding: listed slabs priced below Courtyard's fair market value, by grade and game
- Graded card comps: real on-chain sale prices with grader, grade and cert number
- Pack analytics: price vs expected value, odds and daily pull counts per pack
- Pull trackers: the live feed of what was just pulled, from which pack, and its FMV
- Arbitrage between Courtyard listings, Courtyard buyback offers and other marketplaces
Questions developers ask before integrating
Can I look up a slab by its PSA or CGC cert number?
Yes. asset takes the Courtyard asset id, the asset URL or the grading company's cert number (for example 64524940 for a PSA 10 Charizard VSTAR). search also matches a cert number typed as the query.
Is the fair market value a sale price?
No. fmv_usd is Courtyard's own estimate, returned with its confidence and source. Real prices paid are in sales and in each asset's sale_history: on 2026-11-08 the median collector-to-collector sale was 93% of FMV across 25 sales (range 71% to 147%).
What is a buyback?
Courtyard lets an owner sell a slab straight back to Courtyard. About 4 in 5 on-chain sales are buybacks, at 84.6% of FMV for every pack we measured. Every sale is labelled marketplace or buyback, and an asset's bids flag Courtyard's own standing buyback offer.
Does search return only items for sale?
By default it returns everything in the vault, like the site (about 420,000 items); listing is null for items that are not listed. Set listing_status to listed for buy-now items only (about 32,000). Courtyard serves the first 1,000 results of a search, so narrow by category, grader, grade or price to go deeper.
Can I watch new listings?
Yes. search with sort newest_listed and listed_after set to the time of your last check returns only the listings that appeared since then.
Is the price history chart included?
No. Courtyard shows the price chart to signed-in users only. Every on-chain sale price of the asset is in sale_history, and price_history comes back null.
What is the Courtyard API?
Courtyard API is a ReefAPI endpoint group for vaulted graded cards on courtyard.io: listings with psa/cgc/bgs grade and cert, fmv, bids, on-chain sales, pack pulls and odds. It returns live JSON through POST requests under /courtyard/v1.
Is the Courtyard API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Courtyard calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Courtyard login or account?
No login to Courtyard is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Courtyard data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Courtyard API use?
Courtyard actions currently cost 1-3 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Courtyard from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call courtyard actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Courtyard API a Courtyard scraper?
It is the managed alternative to a DIY Courtyard scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same vaulted graded cards on courtyard.io: listings with psa/cgc/bgs grade and cert, fmv, bids, on-chain sales, pack pulls and odds back as clean JSON.
Why does my Courtyard scraper keep getting blocked?
Most Courtyard scrapers break on anti-bot defenses, rate limits and IP bans that need rotating residential proxies and browser fingerprinting to clear. ReefAPI handles all of that for you — no proxies, no captchas, no maintenance — and returns live JSON. Blocked calls are free.