<game>.<entity>.<action>. The pokemon. prefix leaves room for another game without
renaming anything you have already built against.
Every record shape below is the same shape /v1 already serves for that entity — a card in
pokemon.cards.updated is exactly what GET /v1/cards/{id} returns inside its data, and so on.
One definition, two transports: a webhook payload can never drift from what the REST API would
tell you about the same row.
A delivery carries these records directly. The { data, error } envelope belongs to a /v1
read, not to a delivery — nothing below is wrapped in it.
A group that changed more than 500 records in one run arrives split across several deliveries, each
carrying a chunk: { index, of } field alongside the records — see
the delivery body. A smaller group carries no chunk key
at all.
Cards
pokemon.cards.updated
Card details changed — a card’s own data moved: a new card appeared, or an existing one’s
name, rarity, illustrator, category, metadata or variants changed.
pokemon.cards.deleted
A card was removed. Ingest never deletes a card today — a payload that comes back empty is
treated as an upstream outage, not a deletion — so this event has no producer yet. It stays in the
catalogue so a mirror already knows how to handle a card deletion the day one becomes possible,
rather than that being a docs change, a console change and your own deploy all at once.
Card variants
pokemon.card_variants.deleted
A card printing was removed — one or more card_variants rows were pruned because the
printing they described no longer exists upstream. variant_ids are those variants’ own numeric
ids; the card itself is not necessarily deleted, only that printing of it.
Card prices
pokemon.card_prices.updated
Card prices changed — new current prices for one or more cards, all in the one currency named
by data.currency. Subscribe to this once and filter on currency rather than needing separate
subscriptions per currency.
USD rows carry the TCGplayer columns:
price_kind rather than condition:
cards entirely rather than
listed with an empty prices array.
Sealed products
pokemon.products.updated
Sealed product details changed — a booster box, ETB, collection or similar changed: its name,
number, image, the expansions it belongs to, or its current prices.
This product carries no Cardmarket link today, so cardmarket is null rather than an object —
the same nullability /v1/products/{id} returns for any product with no Cardmarket id on file.
pokemon.products.removed
A sealed product was removed — pruned from the catalogue, or detached from every expansion it
was listed under. product_ids are those products’ own numeric ids.
Sealed product prices
pokemon.product_prices.updated
Sealed product prices changed — the same currency-filtered shape as card_prices.updated, one
product_id and its priced rows per entry.
price_kind (a different product from the one above — product 502001, “151
Poster Collection” — since 476452 carries no Cardmarket link to show one):
Expansions
pokemon.expansions.created
A new expansion appeared — one we had never seen is now in the catalogue. It usually arrives
sparse, named and dated, with cards landing over the following days — treat it as “start
watching”, not “fetch everything now”.
pokemon.expansions.updated
Expansion details changed — an expansion’s own name, series, logo, symbol or legality was
corrected. Nothing about its cards or prices changes here; those arrive as their own events.
Series
pokemon.series.created
A new series appeared.
The sv series actually carries 19 expansions; trimmed to the first three below (still in
release-date order) to keep the example short.
pokemon.series.updated
Series details changed — a series’ own name or logo was corrected.
Trimmed the same way as above: the first three of sv’s 19 expansions, in release-date order.