/api/v1/inventory/events read:inventory Cursor feed of the writes made by your API key — card.transferred, withdrawal.requested and declared_value.submitted — plus events we write: card.identity_corrected, recorded whenever a correction changes what one of your cards is after intake (its sports identity, or its TCG catalog card) and, usually, its declared value; card.removed, recorded when a card we added by mistake — the same physical card scanned in twice — is taken back out of your inventory: it stops appearing in GET /cards and GET /cards/unique-id returns 404 for it, so delete your copy; order.tracking_updated, recorded when we replace an order’s shipping label after you received its tracking number (a changed address, a label that failed to print) — the old number will never move, so update what your customer sees; order.tracking_status_changed, recorded as the carrier moves the parcel (in transit, delivered, returned); graded_card.added, recorded when a graded slab of yours is scanned into the warehouse — worth consuming because GET /cards is raw-only unless you pass ?type=, so this is how you learn a slab arrived without re-sweeping with a different query; inbound_shipment.received, recorded when the warehouse scans in a package you sent us (see Inbound shipments); and, when the carrier cannot deliver an order and sends the package back to us, card.returned, recorded as the warehouse scans each card out of that package and back into your inventory — the card is OFFCHAIN again, still under the same sub-account, and can be ordered, transferred or withdrawn — and order.returned, recorded once every card on that order has been accounted for (the order’s status is RETURNED from the first card on; see Get order). If you cache cards, names or values on your side, consume this feed: a correction payload carries the card’s unique_id, its old and new identity (sports.id for a sports card, card_id for a TCG card), the new identity block, and declared_value_cents when the value moved; a removal payload carries the unique_id to delete and, when known, the duplicate_of_unique_id we kept. A card you have already fetched is only ever removed within three hours of its intake. Other order activity (quotes, commits, cancellations) and service-credit requests are NOT in this feed; poll GET /orders/:id for order state. Note data is a bare array here, not an object. The feed is keyed to the API KEY, not to your account — a second key cannot see the first key’s history, and rotating a key starts the feed over, so drain the old key’s feed before retiring it. Correction, removal, tracking, return and inbound_shipment.received events are written to every key active at the time they happen.
Start a full sweep with GET /cards?type=raw&since=0 (or type=all for both streams), then pass each returned cursor unchanged. Upsert by unique_id and repeat full sweeps to refresh existing identity and pricing. since is a visible-sequence cursor, not an updated_at change feed. Historical rows newly included by a visibility-policy change can be behind a saved cursor; a real identity publication can return the same unique_id again. Reading inventory generates no receipt or confirmation events and changes no publication timestamp. GET /inventory/events alone does not guarantee historical-card or catalog-price updates.
GET /api/v1/inventory/events?limit=10 These inputs are shared across all docs pages, so an id entered here carries over.
Not run yet. Press Run to make a live call against https://service.rip.fun (through this demo's server-side proxy; the API key never reaches the browser).
curl -X GET 'https://service.rip.fun/api/v1/inventory/events?limit=10' \ -H 'X-API-Key: rip_…'
| Field | Type | Required | Description |
|---|---|---|---|
since | query cursor | — | Last event id received; only events with id > since are returned. Omit (or pass 0) to start from the beginning. A non-integer returns 400 rather than silently restarting the feed |
limit | query int | — | 1..100, default 50 |
data)| Field | Description |
|---|---|
data[].id / api_key_id | Event id (ascending — checkpoint the last one as your next since) + the key that wrote it |
data[].event_type | "card.transferred" | "withdrawal.requested" | "declared_value.submitted" | "card.identity_corrected" | "card.removed" | "graded_card.added" | "order.tracking_updated" | "order.tracking_status_changed" | "card.returned" | "order.returned" | "inbound_shipment.created" | "inbound_shipment.updated" | "inbound_shipment.cancelled" | "inbound_shipment.attachment_added" | "inbound_shipment.attachment_removed" | "inbound_shipment.received" |
data[].payload (graded_card.added) | A graded slab of yours was scanned in: tenant_graded_card_id, unique_id (fetch it with GET /cards/unique-id/:unique_id, or find it under ?type=graded), card_id (the catalog card, null while the cert is still being resolved), grading_company, cert_number, grade_numeric (tenths — 100 is a 10), verification_status, sub_account ({ slug, name } or null for your own inventory), inbound_shipment ({ id, tracking_number } of the package it arrived in, or null when no box was recorded) |
data[].payload (card.identity_corrected, sports card) | kind ("correction" = one card moved by an operator, "catalog_merge" = the provisional row it sat on was folded into a canonical one), tenant_card_id, unique_id, from_sports_card_id, to_sports_card_id, sports (the new identity, same shape as GET /cards), declared_value_cents (only when the value moved; null = cleared because the new row is unpriced), note |
data[].payload (card.identity_corrected, TCG card) | Same event, TCG shape — tell the two apart by which block is present: `card` here, `sports` above (there is no separate discriminator field). kind ("correction" = an operator refiled this one card), tenant_card_id, unique_id, from_card_id and to_card_id (catalog card ids, as card_id on GET /cards), card { id, name, set_id, card_number, variant ("Reverse" | "Holo" | "Non-foil", or null for a plain printing) }, declared_value_cents (only when the value moved to the new card’s price — a declared value you set yourself is never changed), note (why the operator changed it) |
data[].payload (card.removed) | kind ("duplicate_removed" = the same physical card was scanned in twice and this record is the extra one), tenant_card_id, unique_id (the card to delete on your side), duplicate_of_unique_id (the copy we kept — it stays in your inventory — or null when not recorded), removed_at, note (why). The current event writer requires published identity and released intake. An unpublished pending card can be removed without this event even if you previously fetched it; reconcile full sweeps and unique-id lookups rather than relying on removal events alone |
data[].payload (order.tracking_updated) | order_id, reason ("label_replaced"), tracking_number + tracking_url (the label the parcel ships on now), carrier, carrier_service, previous_tracking_number (the number it replaced), previous_tracking_numbers (every replaced number, oldest first) |
data[].payload (order.tracking_status_changed) | order_id, tracking_number, status (TRANSIT | DELIVERED | RETURNED | FAILURE, or PRE_TRANSIT after a re-label), previous_status (null on the first sighting), status_details, location ("City, ST"), occurred_at (carrier time). Written each time the carrier status of the order’s current label changes; checked every 2 hours. A status of RETURNED here is the parcel on its way back to us — the order itself stays COMPLETED until the warehouse receives it; see card.returned and order.returned below |
data[].payload (card.returned) | A card of yours came back to us: the carrier could not deliver the order it shipped on and sent the package back, and the warehouse has scanned this card out of that package and back into your inventory. tenant_card_id, unique_id, order_id and reference (the order it came back from, now RETURNED — the order_id GET /orders/:order_id takes), sub_account ({ slug, name } the card is still filed under, or null for your own inventory), status ("OFFCHAIN" — it is in GET /inventory’s default view again and can be ordered, transferred or withdrawn), returned_at (when it was scanned back in), note (the operator’s remark, or null). On the wire: tenantCardId, uniqueId, orderId, reference, subAccount, status, returnedAt, note. One event per card, written to every active key. The card is also re-delivered by a GET /cards ?since= sweep with a new position, so a saved cursor picks it up without a full re-sweep — upsert by unique_id |
data[].payload (order.returned) | Every card on a returned order has been accounted for: order_id, reference, tracking_number (the label the package came back under), carrier_reason (the carrier’s own wording for why it came back — "NO SUCH NUMBER", "REFUSED", … — or null when it gave none), returned_at (when the last card was accounted for: the order’s return.completed_at, not its returned_at, which is when the first card was handled), reinstated_unique_ids (the cards scanned back into your inventory — each also has its own card.returned event), missing_unique_ids (cards the order listed that were not in the package; they stay REDEEMED). On the wire: orderId, reference, trackingNumber, carrierReason, returnedAt, reinstatedUniqueIds, missingUniqueIds. Written once per order, to every active key. A missing card that turns up later is reinstated with a card.returned event of its own and this event is not re-written, so read GET /orders/:order_id return.cards for the current picture |
data[].payload (inbound_shipment.received) | A package you sent us was scanned in at the warehouse: inbound_shipment_id, tracking_number, carrier, card_count (what you declared, or null), reference, sub_account (the slug you said the cards are for, or null), source ("tenant" = you announced it; "warehouse" = it arrived unannounced and was logged against your account), destination_site and received_site (site codes — they differ when the box arrived at the other warehouse), received_at. The box is on our floor; its cards appear in GET /cards as they are intaken, each carrying this shipment as inbound_shipment — list them with GET /cards?inbound_shipment_id= |
data[].payload (inbound_shipment.created / .updated / .cancelled / .attachment_added / .attachment_removed) | Your own calls, written to the calling key only. All carry inbound_shipment_id; created adds tracking_number, card_count and sub_account; updated adds tracking_number, sub_account and changed (the field names you sent — declared_value_min_cents and declared_value_max_cents among them when you changed the box’s bounds); cancelled adds tracking_number; attachment_added adds attachment_id, type ("file" | "link"), kind and filename; attachment_removed adds attachment_id |
data[].payload / created_at | Event payload + when it was recorded |
pagination.cursor / has_more / limit | Pass cursor back as ?since for the next page |
| Status | Code | When |
|---|---|---|
| 400 | invalid since | since is not a non-negative integer |
| 403 | Tenant API key required | key is not tenant-scoped, or lacks read:inventory |
See Errors for the response envelope and the full code list.