cryptoinfraDocs

#Webhook events

The complete set of events cryptoinfra sends — 9 of them, generated from docs/openapi.yaml v1.0.0. Nothing outside this list is ever emitted. See Webhooks for signature verification, retries and the polling rules.

Open as MarkdownFor AI assistants
EventFires when
deposit.creditedA deposit cleared confirmations and was credited
withdrawal.confirmedA payout confirmed on-chain
withdrawal.failedA payout failed and the hold was refunded
card.kycA card holder's KYC status changed
card.statusA card's status changed (also emitted when an issue order settles)
card.topupA card top-up order reached a terminal state (confirmed or failed)
card.withdrawA card→wallet withdrawal order reached a terminal state (confirmed or failed)
card.transactionA card transaction was created
card.wallet_otpA live 3DS wallet OTP is available (notification only — the code is NOT in the payload)

#deposit.credited

A deposit cleared confirmations and was credited

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: deposit.credited and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

Sent to your registered endpoint. Headers: x-cryptoinfra-event: deposit.credited and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>. Verify the HMAC over the raw bytes before parsing.

#Payload

Schema WebhookDepositCredited.

FieldTypeDescription
depositIdinteger—
userExternalIdstring—
assetIdstring—
chainstringThe chain an address or asset is on. TRON is the only network the platform serves: btc, eth, bsc and sol were retired — historical addresses on them are never handed out again and nothing scans them. Read the value as an open string rather than a closed list, so a chain added later does not break your client. (one of tron)
amountstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
amountCreditedstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
txidstring—
addressstring—
fromAddressstringWho paid it. For a token (USDT, USDC), the from of the Transfer event that credited the user's address — not the transaction's signer, which for an exchange's batch or proxy payout is an operator address. For TRX, the transaction's sender. null only for a deposit recorded before 19 September 2026 whose sender could not be read.
json
{
  "depositId": 1,
  "userExternalId": "string",
  "assetId": "string",
  "chain": "tron",
  "amount": "1.5",
  "fee": "1.5",
  "amountCredited": "1.5",
  "txid": "string",
  "address": "string",
  "fromAddress": "string"
}

#withdrawal.confirmed

A payout confirmed on-chain

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: withdrawal.confirmed and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookWithdrawalConfirmed.

FieldTypeDescription
withdrawalIdinteger—
userExternalIdstring—
assetIdstring—
chainstringThe chain an address or asset is on. TRON is the only network the platform serves: btc, eth, bsc and sol were retired — historical addresses on them are never handed out again and nothing scans them. Read the value as an open string rather than a closed list, so a chain added later does not break your client. (one of tron)
amountstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feeAssetIdstringThe asset fee is charged in — always equals assetId (the option that could make it differ was retired on 2026-09-05; the field stays so an older consumer keeps working).
platformFeestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
toAddressstring—
txidstring | null—
json
{
  "withdrawalId": 1,
  "userExternalId": "string",
  "assetId": "string",
  "chain": "tron",
  "amount": "1.5",
  "fee": "1.5",
  "feeAssetId": "string",
  "platformFee": "1.5",
  "toAddress": "string",
  "txid": "string"
}

#withdrawal.failed

A payout failed and the hold was refunded

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: withdrawal.failed and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookWithdrawalFailed.

FieldTypeDescription
withdrawalIdinteger—
userExternalIdstring—
assetIdstring—
chainstringThe chain an address or asset is on. TRON is the only network the platform serves: btc, eth, bsc and sol were retired — historical addresses on them are never handed out again and nothing scans them. Read the value as an open string rather than a closed list, so a chain added later does not break your client. (one of tron)
amountstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feeAssetIdstringThe asset fee is charged in — always equals assetId (see withdrawal.confirmed).
platformFeestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
toAddressstring—
refundedbooleanAlways true — every hold, fee included, was refunded in full.
errorstringWhy. rejected from the dashboard when an owner or finance member refused an awaiting_approval send.
json
{
  "withdrawalId": 1,
  "userExternalId": "string",
  "assetId": "string",
  "chain": "tron",
  "amount": "1.5",
  "fee": "1.5",
  "feeAssetId": "string",
  "platformFee": "1.5",
  "toAddress": "string",
  "refunded": true,
  "error": "string"
}

#card.kyc

A card holder's KYC status changed

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: card.kyc and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

Signed like every tenant webhook: x-cryptoinfra-event: card.kyc and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookCardKyc.

FieldTypeDescription
userExternalIdstring—
providerstring—
kycStatusstringLegacy issuer-KYC lifecycle on a card holder. Distinct from KycStatus, the cryptoinfra-owned verdict at /v1/kyc/*. (one of none, pending, approved, rejected)
remarkstring | null—
json
{
  "userExternalId": "string",
  "provider": "string",
  "kycStatus": "none",
  "remark": "string"
}

#card.status

A card's status changed (also emitted when an issue order settles)

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: card.status and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookCardStatus.

FieldTypeDescription
cardIdinteger—
userExternalIdstring—
providerstringPresent on the generic path only.
statusinteger | stringProvider RAW status code (integer) on a card-lifecycle change; a CardOrderStatus string on the issue-order variant.
providerStatusstring—
reasonstringOptional; present on card status-change events.
refundAmountstringInformational remaining-balance figure on card close; no ledger entry is posted for it in v1.
orderIdintegerPresent only on the issue-order settlement variant.
kindstringclose_fee is the close fee charged to the cardholder on DELETE /v1/cards/{id}: amount is 0, fee is the charge. (one of topup, withdraw, issue_fee, close_fee)
assetIdstringPresent on the issue-order settlement variant.
amountstringPresent on the issue-order settlement variant.
feestringPresent on the issue-order settlement variant.
gasstringIssue-order variant — gas for the on-chain send.
merchantFeestringIssue-order variant — your own fee.
totalstringIssue-order variant — everything the cardholder was debited; mirror this
errorstringPresent on the issue-order settlement variant when it failed.
json
{
  "cardId": 1,
  "userExternalId": "string",
  "provider": "string",
  "status": 1,
  "providerStatus": "string",
  "reason": "string",
  "refundAmount": "string",
  "orderId": 1,
  "kind": "topup",
  "assetId": "string",
  "amount": "1.5",
  "fee": "1.5",
  "gas": "1.5",
  "merchantFee": "1.5",
  "total": "1.5",
  "error": "string"
}

#card.topup

A card top-up order reached a terminal state (confirmed or failed)

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: card.topup and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookCardOrder.

FieldTypeDescription
orderIdinteger—
kindstringclose_fee is the close fee charged to the cardholder on DELETE /v1/cards/{id}: amount is 0, fee is the charge. (one of topup, withdraw, issue_fee, close_fee)
txidstring | nullThe hash of the on-chain send behind the order, as on GET /v1/cards/orders/{id}; null when there was none.
userExternalIdstring—
cardIdinteger | null—
assetIdstring—
amountstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
gasstringThe network fee actually CHARGED for the on-chain send behind the order — what the cardholder was debited, not the quoted figure.
merchantFeestringYour own fee on this order, credited to your balance.
totalstringEverything the cardholder was debited — amount + fee + gas + merchantFee.
amountCreditedstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
amountCreditedBasestringExact integer amount in the asset's smallest unit. (pattern ^[0-9]+$)
statusstringfunding = the cardholder has been charged and the money is on its way to the card rail on-chain. requested = confirmed on-chain, waiting for the rail to show the credit. sent = the rail has been asked, outcome still pending. confirmed = settled. failed = definitively failed; the WHOLE charge — amount, fee, gas and merchant_fee, i.e. total — is refunded to the balance it was taken from, the cardholder's, in the same moment (top-up / issue only — a withdraw holds nothing). Nothing goes anywhere else: not to the card, not to your treasury. When the on-chain send behind a load reverted (provider_status: send_failed), no coins left the cardholder's address either, so on-chain and ledger agree. reversed is reserved for manual operator reversals of a confirmed order. (one of funding, requested, sent, confirmed, failed, reversed)
errorstring—
providerFeestring—
json
{
  "orderId": 1,
  "kind": "topup",
  "txid": "string",
  "userExternalId": "string",
  "cardId": 1,
  "assetId": "string",
  "amount": "1.5",
  "fee": "1.5",
  "gas": "1.5",
  "merchantFee": "1.5",
  "total": "1.5",
  "amountCredited": "1.5",
  "amountCreditedBase": "1500000000",
  "status": "funding",
  "error": "string",
  "providerFee": "string"
}

#card.withdraw

A card→wallet withdrawal order reached a terminal state (confirmed or failed)

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: card.withdraw and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookCardOrder.

FieldTypeDescription
orderIdinteger—
kindstringclose_fee is the close fee charged to the cardholder on DELETE /v1/cards/{id}: amount is 0, fee is the charge. (one of topup, withdraw, issue_fee, close_fee)
txidstring | nullThe hash of the on-chain send behind the order, as on GET /v1/cards/orders/{id}; null when there was none.
userExternalIdstring—
cardIdinteger | null—
assetIdstring—
amountstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
feestringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
gasstringThe network fee actually CHARGED for the on-chain send behind the order — what the cardholder was debited, not the quoted figure.
merchantFeestringYour own fee on this order, credited to your balance.
totalstringEverything the cardholder was debited — amount + fee + gas + merchantFee.
amountCreditedstringA monetary value as a decimal string. Always paired with a *_base field that carries the exact integer base-unit value; compute with the _base string.
amountCreditedBasestringExact integer amount in the asset's smallest unit. (pattern ^[0-9]+$)
statusstringfunding = the cardholder has been charged and the money is on its way to the card rail on-chain. requested = confirmed on-chain, waiting for the rail to show the credit. sent = the rail has been asked, outcome still pending. confirmed = settled. failed = definitively failed; the WHOLE charge — amount, fee, gas and merchant_fee, i.e. total — is refunded to the balance it was taken from, the cardholder's, in the same moment (top-up / issue only — a withdraw holds nothing). Nothing goes anywhere else: not to the card, not to your treasury. When the on-chain send behind a load reverted (provider_status: send_failed), no coins left the cardholder's address either, so on-chain and ledger agree. reversed is reserved for manual operator reversals of a confirmed order. (one of funding, requested, sent, confirmed, failed, reversed)
errorstring—
providerFeestring—
json
{
  "orderId": 1,
  "kind": "topup",
  "txid": "string",
  "userExternalId": "string",
  "cardId": 1,
  "assetId": "string",
  "amount": "1.5",
  "fee": "1.5",
  "gas": "1.5",
  "merchantFee": "1.5",
  "total": "1.5",
  "amountCredited": "1.5",
  "amountCreditedBase": "1500000000",
  "status": "funding",
  "error": "string",
  "providerFee": "string"
}

#card.transaction

A card transaction was created

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: card.transaction and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookCardTransaction.

FieldTypeDescription
cardIdinteger—
userExternalIdstring—
currencystring | null—
createAtinteger | nullProvider epoch timestamp.
transactionobject—
transaction.recordNostring | null—
transaction.transactionIdstring | null—
transaction.originalTransactionIdstring | nullOn a refund (171)
transaction.transTypeinteger | null170 payment, 171 refund, 172 card fee, 173 ATM withdrawal, 174 pre-authorization.
transaction.transStatusinteger | null1 processing, 2 success, 3 failed.
transaction.merchantNamestring | null—
transaction.merchantCategoryCodestring | null—
transaction.localCurrencystring | null—
transaction.localCurrencyAmtstring | null—
transaction.transCurrencystring | null—
transaction.transCurrencyAmtstring | null—
transaction.feeAmountstring | null—
transaction.feeCurrencystring | null—
transaction.balancestring | null—
transaction.respCodeDescstring | null—
json
{
  "cardId": 1,
  "userExternalId": "string",
  "currency": "string",
  "createAt": 1,
  "transaction": {
    "recordNo": "string",
    "transactionId": "string",
    "originalTransactionId": "string",
    "transType": 1,
    "transStatus": 1,
    "merchantName": "string",
    "merchantCategoryCode": "string",
    "localCurrency": "string",
    "localCurrencyAmt": "string",
    "transCurrency": "string",
    "transCurrencyAmt": "string",
    "feeAmount": "string",
    "feeCurrency": "string",
    "balance": "string",
    "respCodeDesc": "string"
  }
}

#card.wallet_otp

A live 3DS wallet OTP is available (notification only — the code is NOT in the payload)

Delivered as POST to each of your enabled endpoints with x-cryptoinfra-event: card.wallet_otp and x-cryptoinfra-signature: <hex hmac-sha256 of the raw body>.

#Payload

Schema WebhookCardWalletOtp.

FieldTypeDescription
cardIdinteger—
userExternalIdstring—
providerstring—
providerCardIdstring—
eventstring(one of wallet_otp_available)
namestringProvider event name.
otpKindstringWhich code it is — branch on this, not on name. (one of payment_3ds, wallet_provisioning)
retrievablebooleanTrue while the code can be fetched.
retrievalPathstring—
expiresInSecondsinteger—
json
{
  "cardId": 1,
  "userExternalId": "string",
  "provider": "string",
  "providerCardId": "string",
  "event": "wallet_otp_available",
  "name": "string",
  "otpKind": "payment_3ds",
  "retrievable": true,
  "retrievalPath": "/v1/cards/102/otp",
  "expiresInSeconds": 600
}