Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.yativo.com/llms.txt

Use this file to discover all available pages before exploring further.

Setup

Yativo sends webhook notifications to your registered HTTPS endpoint via HTTP POST whenever a program event occurs. Each request is signed with HMAC-SHA256 so you can verify it genuinely came from Yativo. Register your endpoint at the unified webhook endpoint. Card issuer events and general crypto events share the same service — subscribe to any combination.
curl -X POST 'https://crypto-api.yativo.com/api/v1/webhook/create-webhook' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://api.yourapp.com/webhooks/yativo",
    "events": ["customer.funded", "customer.funding.failed", "transaction.authorized", "transaction.settled"],
    "description": "Production card issuer webhook"
  }'
{
  "status": true,
  "message": "Webhook created successfully",
  "data": {
    "webhook_id": "68241abc2f3d4e5f6a7b8c9d",
    "url": "https://api.yourapp.com/webhooks/yativo",
    "events": ["customer.funded", "customer.funding.failed", "transaction.authorized", "transaction.settled"],
    "secret": "whsec_a8f3c2e1d4b7f9e2c5a3b6d8f1e4c7a2b5d8e1f4c7a2b5d8",
    "created_at": "2026-05-12T14:00:00.000Z"
  }
}
Store the secret securely — use a secrets manager or environment variable. The secret is also retrievable later via GET /v1/yativo-card/webhooks/:webhookId. If compromised, rotate it via POST /v1/yativo-card/webhooks/:webhookId/rotate-secret.
Pass "events": ["*"] to receive all event types. Other management endpoints:
MethodPathAction
GET/v1/yativo-card/webhooksList all subscriptions
GET/v1/yativo-card/webhooks/:webhookIdGet one subscription (returns secret)
PUT/v1/yativo-card/webhooks/:webhookIdUpdate URL, events, or enabled state
DELETE/v1/yativo-card/webhooks/:webhookIdDelete subscription
POST/v1/yativo-card/webhooks/:webhookId/rotate-secretRotate signing secret
GET/v1/yativo-card/webhooks/:webhookId/deliveriesDelivery history for one webhook
GET/v1/yativo-card/webhooks/deliveries/allAll deliveries across webhooks
POST/v1/yativo-card/webhooks/deliveries/:deliveryId/retryRetry a failed delivery

Event categories

CategoryEvents
Master WalletDeposits, token swaps, customer funding
Customer FundingFunds received or failed into a customer’s card wallet, balance updates
Card LifecycleCard created, activated, frozen, unfrozen, voided, lost, stolen, cancelled, deactivated
Card TransactionsAuthorization, settlement, decline, reversal, refund

Event reference

EventTrigger
master_wallet.depositFunds received into your master wallet
master_wallet.swapToken swap submitted (e.g. USD → EUR)
master_wallet.customer_fundedMaster wallet debited to fund a customer
customer.fundedCustomer’s card wallet received funds
customer.funding.failedFunding transfer failed (wallet misconfigured, insufficient balance, or network error)
customer.balance.updatedCustomer’s card balance changed (after spend, top-up, or authorization)
card.createdNew card issued to a customer
card.activatedCard activated
card.frozenCard frozen
card.unfrozenCard unfrozen
card.voidedCard voided (permanently disabled)
card.lostCard reported lost
card.stolenCard reported stolen
card.cancelledCard cancelled
card.deactivatedCard deactivated
transaction.authorizedCard transaction authorized
transaction.settledTransaction settled
transaction.declinedTransaction declined
transaction.reversedTransaction reversed
transaction.refund.createdRefund created

Payload structure

All webhook events share a common envelope. The data object contains event-specific fields. The event type is also sent in the X-Yativo-Event request header.
{
  "id": "evt_1747058400000_abc123",
  "type": "customer.funded",
  "created_at": "2026-05-12T14:30:00.000Z",
  "data": { ... }
}

Payload examples

master_wallet.deposit

You will receive this event twice for a single deposit: once immediately when funds are detected (processing), and again when settlement is confirmed (settled). The payload shape differs between the two states. status: "processing" — fired as soon as the incoming deposit is detected.
{
  "id": "evt_1747058400000_abc123",
  "type": "master_wallet.deposit",
  "created_at": "2026-05-12T14:00:00.000Z",
  "data": {
    "settlement_id": "dep_1745123456_2ea87af00de1",
    "source_amount": 500.00,
    "tx_hash": "5KtP3MzXYZABCDE1234567890abcdef12345678901234567890abcdef1234567",
    "status": "processing"
  }
}
status: "settled" — fired once the funds are settled into your master wallet.
{
  "id": "evt_1747058520000_def456",
  "type": "master_wallet.deposit",
  "created_at": "2026-05-12T14:02:00.000Z",
  "data": {
    "settlement_id": "dep_1745123456_2ea87af00de1",
    "source_amount": 500.00,
    "settled_amount": 499.75,
    "status": "settled"
  }
}

master_wallet.swap

Fired when a token swap is submitted from your master wallet.
{
  "id": "evt_1747058700000_def456",
  "type": "master_wallet.swap",
  "created_at": "2026-05-12T14:05:00.000Z",
  "data": {
    "swap_id": "0x4a1b2c3d...",
    "from_token": "USD",
    "to_token": "EUR",
    "amount": 1000.00,
    "expected_output": 921.50,
    "status": "submitted"
  }
}

customer.funded

Fired when a customer’s card wallet has been credited. The transfer_id can be looked up via Get Transfer.
{
  "id": "evt_1747059000000_ghi789",
  "type": "customer.funded",
  "created_at": "2026-05-12T14:10:00.000Z",
  "data": {
    "transfer_id": "tx_1745128800_9fc12ab3e4d5",
    "customer_id": "69f0bdf29a84752db9cc8ff9",
    "amount": 50.00,
    "currency": "USD",
    "status": "completed"
  }
}

customer.funding.failed

Fired when a funding transfer to a customer’s card wallet fails.
{
  "id": "evt_1747059000000_fail01",
  "type": "customer.funding.failed",
  "created_at": "2026-05-12T14:10:00.000Z",
  "data": {
    "customer_id": "69f0bdf29a84752db9cc8ff9",
    "yativo_card_id": "yativo_card_customer_8f9a...",
    "amount": 50.00,
    "currency": "USD"
  }
}

master_wallet.customer_funded

Fired alongside customer.funded whenever your master wallet is debited. Includes remaining_balance when the transfer settles immediately; omitted when the balance updates asynchronously.
{
  "id": "evt_1747059001000_mwf01",
  "type": "master_wallet.customer_funded",
  "created_at": "2026-05-12T14:10:00.000Z",
  "data": {
    "transfer_id": "tx_1745128800_9fc12ab3e4d5",
    "customer_id": "69f0bdf29a84752db9cc8ff9",
    "amount": 50.00,
    "currency": "USD",
    "status": "completed",
    "remaining_balance": 114.98
  }
}

card.frozen

Fired when a card is frozen, either by your program or by the customer.
{
  "id": "evt_1747059600000_mno345",
  "type": "card.frozen",
  "created_at": "2026-05-12T14:20:00.000Z",
  "data": {
    "yativo_card_id": "yativo_card_customer_8f9a...",
    "card_id": "card_token_abc123",
    "status": "Frozen",
    "timestamp": "2026-05-12T14:20:00.000Z"
  }
}
The card_id field in webhook events is the card token identifier. This may differ from the card_id returned by the Get Customer endpoint. Use yativo_card_id as the stable cross-reference between webhook events and API responses.

customer.balance.updated

Fired whenever the card provider reports a balance change — after a purchase authorization, settlement, top-up, or reversal. Provides the full balance breakdown so you can update your UI in real time without polling.
{
  "id": "evt_1747060200000_stu901",
  "type": "customer.balance.updated",
  "created_at": "2026-05-12T14:30:00.000Z",
  "data": {
    "yativo_card_id": "yativo_card_customer_8f9a...",
    "ledger_balance": 45.23,
    "available_balance": 38.50,
    "pending_balance": 6.73,
    "currency": "EUR",
    "timestamp": "2026-05-12T14:30:00.000Z"
  }
}

transaction.authorized

Fired when a card transaction is authorized at the point of sale. A customer.balance.updated event typically follows immediately.
{
  "id": "evt_1747059300000_jkl012",
  "type": "transaction.authorized",
  "created_at": "2026-05-12T14:15:00.000Z",
  "data": {
    "yativo_card_id": "yativo_card_customer_8f9a...",
    "card_id": "card_token_abc123",
    "transaction_id": "tx_9d8e7f...",
    "type": "purchase",
    "amount": 12.50,
    "currency": "EUR",
    "merchant": "Starbucks",
    "merchant_category": "5812",
    "merchant_city": "Paris",
    "merchant_country": "FR",
    "status": "AUTHORIZED",
    "timestamp": "2026-05-12T14:15:00.000Z"
  }
}

card.lost

Fired when a card is reported lost.
{
  "id": "evt_1747059900000_pqr678",
  "type": "card.lost",
  "created_at": "2026-05-12T14:25:00.000Z",
  "data": {
    "yativo_card_id": "yativo_card_customer_8f9a...",
    "card_id": "card_token_abc123",
    "status": "Lost",
    "timestamp": "2026-05-12T14:25:00.000Z"
  }
}

Signature verification

Every webhook request includes an X-Yativo-Signature header and an X-Yativo-Timestamp header. The event type is also in the X-Yativo-Event header and the unique delivery ID in X-Yativo-Delivery-Id. Verify signature and timestamp before processing the event. The signature is computed over the raw request body (the exact JSON bytes received), prefixed with the timestamp.
const crypto = require('crypto');

// Use express.raw({ type: 'application/json' }) so req.body is a Buffer, not a parsed object.
// req.headers['x-yativo-signature'] — the HMAC signature
// req.headers['x-yativo-timestamp'] — Unix timestamp (string)
function verifyWebhook(rawBody, signature, timestamp, secret) {
  if (!signature || !timestamp) return false;

  // Reject replays older than 5 minutes
  if (Math.abs(Date.now() / 1000 - parseInt(timestamp, 10)) > 300) return false;

  const signed = `${timestamp}.${rawBody.toString('utf8')}`;
  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(signed).digest('hex');
  try {
    return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
  } catch {
    return false;
  }
}
Always verify the signature before trusting the payload. Use express.raw({ type: 'application/json' }) (not express.json()) so you have the raw bytes for verification.

Retry policy

Yativo retries failed webhook deliveries using exponential backoff. Respond with any HTTP 2xx status code to acknowledge receipt and prevent retries.
AttemptDelay after previous attempt
1 (initial)
21 minute
35 minutes
430 minutes
52 hours
612 hours
724 hours
After 7 failed attempts the delivery is marked permanently failed — no further automatic retries. You can manually replay individual deliveries via POST /v1/yativo-card/webhooks/deliveries/:deliveryId/retry. If your endpoint fails 100 consecutive deliveries, Yativo will automatically disable the subscription to protect your program’s event queue. Re-enable it via PUT /v1/yativo-card/webhooks/:webhookId with { "enabled": true } after fixing the issue.
To avoid processing duplicate events, use the top-level id field (e.g. evt_1747058400000_abc123) as an idempotency key. The X-Yativo-Delivery-Id header carries the delivery record ID (a separate identifier used to retry individual deliveries via the API).