Skip to main content

Overview

Cartevo webhooks notify your system in near real‑time about account events (card creation, funding, withdrawals, errors, etc.).
  • Method: POST
  • Format: JSON
  • Headers: Content-Type: application/json
  • Expected response: any HTTP 2xx is treated as success (response body is ignored)
Your webhook URL is configured on your company account. For every event, Cartevo sends an HTTP request with the following shape:

Webhook Headers

  • Content-Type is always application/json.
  • X-Cartevo-Signature is present only when webhook signing is enabled for your company (a signing secret is configured). When signing is disabled, no signature header is sent.
  • No other custom headers (e.g. User-Agent, X-Webhook-Id, X-Webhook-Timestamp) are guaranteed — do not depend on them.

Retry policy

If delivery fails (non‑2xx response or network error), Cartevo automatically retries. There is 1 initial attempt + 3 retries = 4 total deliveries, spaced 5 seconds apart.
  • Max retries: 3 (4 total attempts including the initial delivery)
  • Timeout: 10 seconds per attempt
  • Logging: every attempt is logged; after the final retry fails, delivery is marked permanently failed.

Verifying webhook signatures

When webhook signing is enabled for your company, every delivery carries an X-Cartevo-Signature header so you can confirm the request genuinely came from Cartevo and was not tampered with. Header format:
How the signature is computed:
  1. Take the raw request body exactly as received — do not re-serialize the JSON.
  2. Build the signed string "{t}.{rawBody}" — the timestamp, a literal dot (.), then the raw body.
  3. Compute HMAC-SHA256(signed_string, your_signing_secret) and hex-encode it. That value is v1.
Your signing secret is a 64-character hex string available in your company webhook settings. The signature is generated once when the event is enqueued and replayed verbatim on retries, so the same t/v1 may arrive on more than one delivery attempt. Verification (Node.js):
Always verify against the raw, unparsed body. If your framework parses JSON before you can read the raw bytes, configure it to expose the raw body (e.g. Express: express.json({ verify: (req, _res, buf) => { req.rawBody = buf; } })). Re-serializing the parsed object changes the bytes and the signature will not match.

Field naming convention

All webhook payload keys use snake_case (e.g. transaction_id, card_id, created_at). A small number of legacy events still emit a few camelCase keys (e.g. cardId, transactionId); these are flagged inline in each event’s field table and will be migrated to snake_case in a future release. Always consult the field table for the canonical key spelling per event. 🚨 Tip: treat webhooks as at‑least‑once deliveries. Implement idempotency/deduplication on your receiver using stable business identifiers (e.g., transaction_id, card.id, wallet_id).

Setting Up Webhooks

Configure Your Webhook URL

Set your webhook URL in your company settings:

Supported Events

Payment Events

payment.collect

Emitted when a payment collection (pay‑in) is initiated. Note: this fires when collection begins; the eventual outcome (SUCCESS / FAILED) reaches you via the polled GET /payment/transactions/{id}/status endpoint or via your notify_url if one was supplied.
Fields:

Card Events

card.created

Emitted when a new card is successfully created for a customer. Payload:
card fields: card_issuance fields: card_fund fields:

card.fund

Emitted when a card is funded with money from a wallet. Payload:
Fields:

card.withdraw

Emitted when money is withdrawn from a card back to the wallet. Payload:
Fields:

card.withdraw.failed

Emitted when a card withdrawal attempt fails. Payload:
Fields:

card.terminated

Emitted when a card is permanently terminated and any remaining balance is refunded to the company’s USD wallet. Payload:
Fields: Important Notes:
  • When a card is terminated, any remaining balance is automatically refunded to the company’s USD wallet
  • The card balance is set to zero and the card becomes unusable
  • This action is irreversible - once terminated, a card cannot be reactivated
  • Webhook failures do not prevent card termination from completing
  • A termination may be customer/company-initiated or provider-initiated (e.g. a fraud/risk block). For provider-initiated terminations the payload is lighter and carries reason: "provider_terminated" and previousBalance instead of the refund fields:

card.verification.completed

Emitted when a card account is successfully verified by a merchant — a $0.00 verification hold some merchants place when a card is added (e.g. to a wallet or subscription). Payload:
Fields:

Transaction Events

transaction.settlement.completed

Emitted when a transaction is settled/cleared.

transaction.authorization.created

Emitted when a card payment authorization succeeds. Payload:
Fields:

transaction.authorization.declined

Emitted when a payment authorization is declined. Payload:
Fields:

transaction.preauthorization.created

Emitted when a pre-authorization hold is placed on a card — an amount is reserved at the merchant but not yet finally captured (common for hotels, car rentals, fuel pumps, etc.). The hold is later either settled (transaction.settlement.completed) or released/reversed (transaction.reversal.completed). Payload:
Fields:

transaction.reversal.completed

Emitted when a transaction is reversed (usually within 24 hours). Payload:
Fields:

transaction.refund.completed

Emitted when a refund is processed (usually after settlement). Payload:
Fields:

transaction.funding.completed

Emitted when a card funding transaction completes.

transaction.withdrawal.completed

Emitted when a withdrawal from card completes.

transaction.crossborder.charged

Emitted when a cross‑border charge related to a purchase is recorded.

transaction.terminated

Emitted when a termination‑type transaction is recorded for a card.

Fee Events

fee.payment_failure.charged

Emitted when a fee is charged for a failed payment transaction. Payload:

fee.crossborder.charged

Emitted when a cross-border transaction fee is charged. Payload:

Debt Events

debt.recovery.pending

Notifies you in real time when a payment fee debt has been created because the fee could not be collected from the card or wallet at the time of the transaction. Triggered in two scenarios:
  • Payment failure fee — A card payment fails, and the company wallet cannot cover the failure fee.
  • Cross-border fee — A cross-border transaction occurs, and the company wallet cannot cover the fee.
Payload:
Fields: Purpose:
  • Maintain transparency throughout the debt recovery process.
Cross-border fee calculation:
Fee collection priority:
  1. Card balance — Fees are first deducted from the available card balance.
  2. Wallet balance — If the card balance is insufficient, the company USD wallet is debited.
  3. Debt creation — If both are insufficient, the remaining amount is recorded as a debt to be settled, and debt.recovery.pending is sent.

Customer Events

customer.created

Emitted when a new customer is created in the system. Payload:
Fields:

Best Practices

Response Handling

Always return 200 OK within 10 seconds, before processing:

Idempotency

Webhooks may be delivered more than once. Always check for duplicates using transaction_id, card.id, or wallet_id:

Security

  • Use HTTPS only - HTTP endpoints are not supported
  • Verify webhook signatures (when enabled) using the X-Cartevo-Signature header — see Verifying webhook signatures
  • Validate request format - Ensure payload matches expected structure
  • Implement rate limiting - Protect your endpoint from abuse
  • IP whitelisting - Whitelist Cartevo IP addresses (when available)

Error Handling

Handle errors gracefully without exposing internal details:

Logging

Record important fields for supportability:

Sample Receiver Response

Troubleshooting

Complete Event Reference

Payment Events (1)

  • payment.collect — Payment collection (pay-in) initiated.

Card Events (6)

  • card.created — Card successfully created.
  • card.verification.completed — Card account verified by a merchant ($0 hold).
  • card.fund — Card funded from a wallet.
  • card.withdraw — Money withdrawn from a card to a wallet.
  • card.withdraw.failed — Card withdrawal failed.
  • card.terminated — Card terminated (customer- or provider-initiated); remaining balance refunded.

Transaction Events (10)

  • transaction.authorization.created — Card payment authorized at a merchant.
  • transaction.authorization.declined — Card payment authorization declined.
  • transaction.preauthorization.created — Pre-authorization hold placed on a card.
  • transaction.reversal.completed — Authorization reversed (typically within 24h).
  • transaction.refund.completed — Refund processed (after settlement).
  • transaction.settlement.completed — Authorized transaction cleared.
  • transaction.funding.completed — Card funding transaction completed.
  • transaction.withdrawal.completed — Card withdrawal transaction completed.
  • transaction.crossborder.charged — Cross-border charge recorded against a card.
  • transaction.terminated — Termination-type transaction recorded.

Fee Events (2)

  • fee.payment_failure.charged — Failure-payment fee charged ($0.50).
  • fee.crossborder.charged — Cross-border fee charged (2.5% + $0.50).

Debt Events (1)

  • debt.recovery.pending — Fee debt created because the fee could not be deducted from the card or wallet.

Customer Events (1)

  • customer.created — Customer created.
Total: 21 webhook events