Skip to main content
The discovery endpoint answers a buyer-side question: which sellers have this card in stock, and where can I buy it? Give it a card reference (or a list), and it returns — per card — the sellers across Hoard’s consented network who currently stock it, with the lowest price, total quantity, store name, and an affiliate-wrapped buy link. This is the demand-layer surface: an AI assistant grounds a buyer’s fuzzy card guess to an exact catalog printing, then looks up live availability. Two properties make it safe to expose:
  • Network-wide, consented-only. Results come from the whole seller network that has opted in to discovery and published its binder — never the calling bearer’s own inventory. The token identifies who is asking, not what is searched. A seller who has not opted in never appears.
  • No silent wrong pick. An underspecified reference (e.g. just Charizard, which has dozens of printings at wildly different prices) returns ranked candidates, not a guess. The assistant disambiguates the exact printing before any buy link is produced.
The endpoint is mounted at /api/discovery/availability (not /api/v1/...) and uses Bearer authentication (Authorization: Bearer YOUR_API_KEY). It is read-only — mcp:read is sufficient.

Find availability

Provide a single card reference:
…or a batch (a decklist) under cards (max 25 per request):
Resolved product ids are batched into a single availability lookup, so a decklist costs one supply query regardless of length.

Response

Every response is explicitly tagged as discovery, not own-inventory: This matters for a seller’s own store assistant: discovery results are the whole consented network, so an assistant must never present them as “your stock.” Use the per-result owned_by_caller flag (below), not the presence of results, to tell whether the caller’s own listing appears. There is one results entry per input reference, in input order. The status field drives how to read it: On candidates, the ranked candidates array (lowest-surprise printing first) lets the assistant ask the buyer which one they mean, or re-query with a set / number. total is how many printings matched and truncated is true when that list was capped — a signal to narrow the query rather than assume the list is complete. availability.min_price and total_quantity aggregate across the consented sellers; each sellers entry is one store with its own price, quantity, and buy link. as_of is when the snapshot was computed (availability may be a few minutes stale, but the staleness is always visible, never silent). A listing without a known price carries price: null — never 0.0 — and is excluded from min_price (which is null when no seller has a listed price). The stock is still real: the buy link resolves to the seller’s live TCGplayer listing, where the actual price is shown.

owned_by_caller: is this your listing in the network?

Each resolved result carries owned_by_caller. It is true only when the calling bearer is itself a consented, published seller whose own listing is part of these network results for that product — so a seller’s assistant can tell which of the network results are the seller’s own stock. It is a pure annotation. It never changes what’s returned: a consented seller who owns the card and a stranger querying the same card get identical availability — the same sellers, the same min_price, the same buy links — and differ only in this flag. Discovery always returns the whole consented network; owned_by_caller just labels the caller’s own row within it. owned_by_caller is false for candidates and no_match results (there is no single product to own) and for a resolved miss (no network listing exists to own).

No consented seller? A useful fallback, never a dead end

When a card resolves but no consented seller is currently exposing it, availability is null and a fallback object takes its place. It keeps the buyer moving instead of returning an empty result:
fallback is only present on a resolved miss. A candidates or no_match result never carries it.
in_network_unexposed is a boolean and nothing more. It tells you whether the product exists somewhere in the network, never who holds it, their price, their quantity, or their store. A seller who has not opted in to discovery is never identifiable through this flag.
Every buy_url is wrapped through the TCGplayer affiliate program (partner.tcgplayer.com). Surface it as-is — rewriting it through a different URL shortener or stripping the wrapper removes the seller’s affiliate revenue from any purchase the assistant drives.

Over the MCP

The hosted MCP exposes this as discovery.findAvailability — a read tool, so it runs in hoard_read. The argument shape mirrors the REST body (a single { name, set?, number?, finish? } or a cards list, with game defaulting to pokemon).