Overview
CryptoMate pushes real-time events to an HTTPS endpoint you register. Every event (card authorization, deposit, withdraw, transfer, ramp, KYC status change, and more) is sent as aPOST with a JSON envelope and an event-specific data payload.
All JSON field names use snake_case.
Setup
1
Expose an HTTPS endpoint
Host a publicly reachable HTTPS URL that accepts
POST requests with a JSON body.2
Register the URL
Configure the webhook URL on your company via the Subscribe webhook URL endpoint, or from the Portal.
3
Configure a webhook_key secret
Set a shared secret via the Subscribe webhook key endpoint. CryptoMate sends this value in the
X-Webhook-Key header on every request so your endpoint can authenticate it.4
Acknowledge quickly
Return
200 OK with the expected body as soon as possible. Heavy processing should happen asynchronously.5
Handle retries idempotently
Deduplicate on
operation_id — the same event may be delivered more than once.Authentication
CryptoMate authenticates itself to your endpoint using a shared secret — yourwebhook_key.
On every request, CryptoMate sets:
Your endpoint should compare the
X-Webhook-Key header against the secret you stored when you configured it. Reject any request where the value does not match.
Rotate the key at any time via the Subscribe webhook key endpoint. CryptoMate uses the new value on the very next delivery.
Request envelope
Every webhook body has the same top-level shape:Example envelope
Expected response
Respond with HTTP200 OK and a JSON body:
200 status is treated as a delivery failure and triggers a retry (except on the card authorization path — see below).
Card external authorization response
Whenproduct=cards and event_type=authorization, the response_code you return determines whether the card transaction is approved or declined:
The response must arrive within the deadline described below or CryptoMate applies the default behavior configured on the card.
Delivery and retries
Notes:
- The authorization path uses a pre-warmed HTTP/2 client with TLS 1.3 and connection pooling — but the business deadline for your full response is 1,200 ms.
- CryptoMate may deliver the same event more than once (after retries, or following an internal redelivery). Always deduplicate using
operation_id. X-Request-Timestamplets you measure network skew and reject events that arrive well past their useful window.
Event catalog
Cards
Emitted withproduct: "cards".
authorization — external authorization request
Sent when a card transaction needs your approval before it is authorized by the network. Your response’s response_code drives the decision. Hard 1,200 ms deadline, no retries.
data additionally carries a signature field.
authorized — transaction authorized
Sent after a transaction has been approved and is being processed internally. No approval decision required.
cleared — transaction cleared
Sent when a previously authorized transaction clears (settles). Same data shape as authorized.
declined — transaction declined
Sent when a transaction is declined by the network or by CryptoMate. data shape as authorized, with decline_reason populated:
reversal — authorization reversed
Sent when a prior authorization is reversed (released) by the network. Same data shape as authorized.
refund — refund received
Sent when a merchant issues a refund. Same data shape as authorized.
deposit — card deposit credited
Sent when a deposit is credited to the card-linked wallet (after fees).
visa_direct_deposit — Visa Direct deposit credited
Sent when a Visa Direct push funds transfer credits the card. data mirrors the authorized transaction shape.
warranty_withdraw — warranty withdrawal
Sent on a warranty/holding-wallet withdrawal, success or failure (see status).
card_blocked_by_velocity — card blocked by velocity rule
Sent exactly once when a card transitions from ACTIVE to BLOCKED because a velocity rule was triggered. Indicates a possible fraud attempt or card probing. Up to 10 retries with exponential backoff.
Notes:
operation_idequalscard_idbecause the block is not tied to a specific transaction.- Subsequent authorizations on an already-blocked card do not emit another
card_blocked_by_velocity— they are declined via the normal card status flow. - Use the tuple
(company_id, card_id, blocked_at)as an idempotency key in your handler. - To unblock the card, call
PATCH /api/cards/{id}/unblock. Unblocking also resets the velocity counter.
- Notify the cardholder by email or SMS.
- Optionally block other cards linked to the same user in your system.
- Open a case in your fraud management system for investigation.
notification_3ds_authorization — 3DS challenge code
Informational event containing the code the cardholder needs for a 3DS challenge. No retry, no approval decision.
Virtual Wallets
Emitted withproduct: "virtual_wallets".
deposit — on-chain deposit detected
withdraw — withdrawal executed
Sent on both success and failure (see status). reason is populated on failures.
ramp_on — fiat-to-crypto ramp credited
Sent when a fiat deposit has been converted to crypto and credited to the customer’s wallet.
Treasury
Emitted withproduct: "treasury".
transfer — treasury transfer executed
Sent on both success and failure (see status).
ramp_on — fiat-to-crypto ramp credited
Same shape as the Virtual Wallets ramp_on event, with product: "treasury".
Company Activity
Emitted withproduct: "company_activity".
client_status — customer KYC status changed
Sent when a company client’s KYC/KYB status changes (for example, rejected by the ramp provider). status is failed when the client is rejected; data is the full client record with status, rejection_code and rejection_description populated.
data object carries the full CompanyClient record; additional fields (address, document type, business fields, etc.) are included when present.
