Receive real-time CardMind events pushed directly to your server. Webhooks fire whenever a tracked signal triggers, a price threshold is crossed, or your collection value changes significantly. Requires a Premium subscription.
Coming Soon
The webhook system is currently in development. The interface described below reflects the intended API design. Subscribe to updates at cardmind.app to be notified when webhooks launch.
403 PREMIUM_REQUIREDSend a POST to /api/webhooks with the destination URL and the event types you want to subscribe to.
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | required | Your HTTPS endpoint that will receive webhook POST requests |
| events | string[] | required | Array of event types to subscribe to (see Event Types below) |
curl -X POST "https://api.cardmind.app/api/webhooks" \
-H "Authorization: Bearer cm_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/webhooks/cardmind",
"events": ["signal.buy", "signal.sell", "price.spike"]
}'{
"data": {
"id": "wh_01hwqbc34xem9e4b3kga70x7v2",
"url": "https://your-server.com/webhooks/cardmind",
"events": ["signal.buy", "signal.sell", "price.spike"],
"created_at": "2026-04-17T12:00:00Z",
"signing_secret": "whsec_aB3cD4eF5gH6iJ7kL8mN9oP0"
},
"error": null
}The signing_secret is shown only once at registration time. Store it securely — you will need it to verify incoming webhook signatures.
| Event | Fires when… |
|---|---|
| signal.buy | A BUY signal is generated for a card in the market |
| signal.sell | A market signal is generated for a tracked card |
| signal.watch | A WATCH signal is generated (unusual volume or activity) |
| price.spike | A card price increases more than 20% within 24 hours |
| price.drop | A card price decreases more than 20% within 24 hours |
CardMind delivers a POST request to your endpoint with a JSON body. Every payload shares the same top-level shape regardless of event type.
{
"event": "signal.buy",
"data": {
"card_id": "e3285e6b-3e79-4d7c-bf96-d920f973b122",
"card_name": "Lightning Bolt",
"signal_type": "BUY",
"reason": "34% price increase over 7 days with rising tournament play",
"price_at_signal": "1.49"
},
"timestamp": "2026-04-17T18:30:00Z",
"signature": "sha256=a1b2c3d4e5f6..."
}| Field | Type | Description |
|---|---|---|
| event | string | The event type that triggered this delivery (e.g. "signal.buy") |
| data | object | Event-specific payload. Shape varies by event type (see Event Types table) |
| timestamp | string (ISO 8601) | UTC timestamp of when the event was generated on the CardMind server |
| signature | string | HMAC-SHA256 signature of the raw request body, prefixed with "sha256=" |
Every webhook delivery includes a signature field computed as HMAC-SHA256(raw_body, signing_secret). Always verify the signature before processing a webhook to prevent spoofed requests.
import hmac
import hashlib
def verify_webhook(raw_body: bytes, signature: str, signing_secret: str) -> bool:
expected = "sha256=" + hmac.new(
signing_secret.encode(),
raw_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)import crypto from 'crypto'
function verifyWebhook(rawBody, signature, signingSecret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', signingSecret)
.update(rawBody)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
)
}CardMind retries failed webhook deliveries with exponential backoff. A delivery is considered successful if your endpoint returns any 2xx HTTP status code within 10 seconds.
| Attempt | Delay after previous failure |
|---|---|
| 1 (initial) | Immediate |
| 2 | 30 seconds |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 (final) | 2 hours |
After 5 failed attempts the webhook registration is marked inactive. You can reactivate it at any time via PATCH /api/webhooks/:id.