Webhooks
Get notified when cards are identified, listed, or sold without polling the API.
Last updated May 11, 2026
Webhooks let the vault push events to your server in real time. Instead of polling GET /cards?updated_since=... every minute, register a webhook URL and we'll POST to it as events happen.
Status note. Webhooks are documented here as part of the Wave 5 KB rollout. The dashboard UI for registering webhooks at
/settings/webhooksis coming soon. Until then, contact us and we'll register one for you by hand.
What events fire
| Event | When |
|---|---|
card.identified | A card moves from imported to identified (AI or manual) |
card.priced | A card gets an asking price for the first time |
card.workflow_status_changed | Any workflow status transition |
listing.published | An eBay listing successfully goes live |
listing.sold | An eBay listing closes with a sale |
listing.ended | An eBay listing ends without selling |
batch.completed | A batch is marked complete |
identify.failed | Both CardSight and Gemini fail to identify a card |
Payload format
Every webhook POSTs JSON with a stable shape:
{
"id": "evt_01HX9...",
"event": "card.identified",
"created_at": "2026-05-11T15:32:01Z",
"account_id": "acc_01HX8...",
"data": {
"card_id": "card_01HX...",
"title": "2023 Crown Zenith Charizard VMAX",
"set": "Crown Zenith",
"number": "20/20"
}
}The data payload varies by event. Full schemas will live at /help/api/webhook-events once Wave 5 closes.
Signing
Every webhook is signed with an HMAC-SHA256 of the raw body using a secret unique to your endpoint. The signature is in the X-Vault-Signature header:
X-Vault-Signature: t=1715442721,v1=5257a869e7ecebeda32affa62cdca3fa...Verify by computing HMAC_SHA256(secret, "{t}.{body}") and constant-time-comparing to v1. Reject any request older than 5 minutes (the t timestamp) to prevent replay.
Delivery
We POST your endpoint with a 10-second timeout. Any non-2xx response (or a timeout) triggers retry with exponential backoff: 30s, 2m, 10m, 1h, 6h, 24h. After 24 hours of failures the event is dropped and surfaced in the dashboard.
Idempotency is your responsibility — the same event ID may arrive twice during a retry storm. Store the event.id on first receipt and skip duplicates.
When to use webhooks vs polling
- Webhooks: you have an externally-reachable HTTPS endpoint and want low-latency updates (a custom dashboard, a Slack notifier, your own ERP).
- Polling: you don't have an endpoint, or your workload is daily/weekly batch reconciliation.
GET /cards?updated_since=...works fine.