> ## 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.

# Webhooks

> Real-time event notifications for crypto deposits, withdrawals, swaps, cards, and more

Yativo Crypto fires webhook events for every significant state change across wallets, transactions, cards, IBAN accounts, and system events. Configure webhooks once and your server stays in sync without polling.

For webhook management (creating, updating, deleting webhook endpoints), see the [Webhook Management](/yativo/webhooks) docs. This page covers the crypto-specific event types and their payloads.

<Accordion title="Type Definitions">
  ```typescript theme={null}
  interface Webhook {
    webhook_id: string;
    url: string;
    events: string[];           // ["*"] for all events
    secret: string;             // only returned at create time or GET single
    enabled: boolean;
    description?: string;
    last_success_at?: string;
    last_failure_at?: string;
    consecutive_failures: number;
    created_at: string;
    updated_at: string;
  }

  interface CreateWebhookRequest {
    url: string;                // required — must be HTTPS
    events?: string[];          // default ["*"] — all events
    description?: string;
  }

  type WebhookEventType =
    // Deposits
    | "deposit.detected"
    | "deposit.confirmed"
    // Transactions
    | "transaction.initiated"
    | "transaction.submitted"
    | "transaction.failed"
    // IBAN
    | "iban.activated"
    | "iban.transfer.received"
    // KYC
    | "kyc.submitted"
    | "kyc.approved"
    | "kyc.rejected"
    | "kyc.pending_review"
    // Card lifecycle
    | "card.created"
    | "card.activated"
    | "card.frozen"
    | "card.unfrozen"
    | "card.voided"
    | "card.lost"
    | "card.stolen"
    | "card.cancelled"
    | "card.deactivated"
    // Card transactions
    | "transaction.authorized"
    | "transaction.declined"
    | "transaction.settled"
    | "transaction.reversed"
    | "transaction.refund.created"
    // Customer & master wallet funding
    | "customer.funded"
    | "customer.funding.failed"
    | "customer.balance.updated"
    | "master_wallet.deposit"
    | "master_wallet.swap"
    | "master_wallet.customer_funded";
  ```
</Accordion>

***

## Crypto Event Types

### Deposit Events

| Event               | Fired When                                                        |
| ------------------- | ----------------------------------------------------------------- |
| `deposit.detected`  | An inbound transaction is detected on-chain (unconfirmed)         |
| `deposit.confirmed` | An inbound transaction has reached sufficient block confirmations |

### Transaction Events

| Event                          | Fired When                                                                          |
| ------------------------------ | ----------------------------------------------------------------------------------- |
| `transaction.initiated`        | An outbound transaction has been created and queued                                 |
| `transaction.submitted`        | A transaction has been broadcast to the blockchain                                  |
| `transaction.failed`           | A transaction failed for any reason                                                 |
| `transaction.{type}.completed` | A transaction of the given type completed (e.g. `transaction.withdrawal.completed`) |

### Card Events

| Event                           | Fired When                                            |
| ------------------------------- | ----------------------------------------------------- |
| `card.created`                  | A new card has been issued                            |
| `card.activated`                | A card has been activated and is ready to use         |
| `card.frozen`                   | A card has been temporarily frozen                    |
| `card.unfrozen`                 | A frozen card has been re-enabled                     |
| `card.voided`                   | A card has been voided                                |
| `card.lost`                     | A card has been marked as lost                        |
| `card.stolen`                   | A card has been reported stolen                       |
| `card.cancelled`                | A card has been cancelled                             |
| `card.deactivated`              | A card has been permanently deactivated               |
| `transaction.authorized`        | A card transaction has been authorized                |
| `transaction.declined`          | A card transaction was declined                       |
| `transaction.settled`           | A card transaction has settled                        |
| `transaction.reversed`          | A card transaction has been reversed                  |
| `transaction.refund.created`    | A refund has been initiated for a card transaction    |
| `customer.funded`               | A card customer's balance has been topped up          |
| `customer.funding.failed`       | A funding transfer to a customer's card wallet failed |
| `customer.balance.updated`      | A card customer's balance has changed                 |
| `master_wallet.deposit`         | A deposit arrived in the card program master wallet   |
| `master_wallet.swap`            | A swap executed in the card program master wallet     |
| `master_wallet.customer_funded` | Master wallet funds allocated to a customer           |

### IBAN Events

| Event                    | Fired When                                                       |
| ------------------------ | ---------------------------------------------------------------- |
| `iban.activated`         | An IBAN account has been activated and is ready to receive funds |
| `iban.transfer.received` | A SEPA transfer has been received into the IBAN account          |

### KYC Events

| Event                | Fired When                                 |
| -------------------- | ------------------------------------------ |
| `kyc.submitted`      | A KYC submission has been received         |
| `kyc.approved`       | A KYC check has been approved              |
| `kyc.rejected`       | A KYC check has been rejected              |
| `kyc.pending_review` | A KYC submission is awaiting manual review |

***

## Webhook Payload Examples

All payloads share the same envelope structure:

```json theme={null}
{
  "id": "evt_01abc123",
  "type": "<event_type>",
  "created_at": "2026-03-26T10:05:00Z",
  "data": { ... }
}
```

### deposit.confirmed

```json theme={null}
{
  "id": "evt_01abc123",
  "type": "deposit.confirmed",
  "created_at": "2026-03-26T10:05:00Z",
  "data": {
    "asset_id": "asset_01xyz789",
    "account_id": "acc_01abc123",
    "chain": "solana",
    "ticker": "USDC_SOL",
    "amount": "250.00",
    "from_address": "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
    "to_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
    "tx_hash": "5KtP3jNHGXi8YmD2L9sRZVAoWqFcBe4TrKlUvJpMxNy",
    "confirmations": 1,
    "new_balance": "750.00"
  }
}
```

### transaction.failed

```json theme={null}
{
  "id": "evt_03ghi789",
  "type": "transaction.failed",
  "created_at": "2026-03-26T10:10:00Z",
  "data": {
    "transaction_id": "txn_02stu789",
    "chain": "ethereum",
    "ticker": "USDC",
    "amount": "1000.00",
    "error_code": "insufficient_balance",
    "error_message": "Wallet balance (400.00 USDC) is less than requested amount (1000.00 USDC)"
  }
}
```

### transaction.settled

```json theme={null}
{
  "id": "evt_05mno345",
  "type": "transaction.settled",
  "created_at": "2026-03-26T11:00:00Z",
  "data": {
    "card_id": "card_01abc",
    "transaction_id": "card_txn_01xyz",
    "merchant_name": "Amazon",
    "merchant_category": "Shopping",
    "amount": "49.99",
    "currency": "USD",
    "status": "settled",
    "new_balance": "450.01"
  }
}
```

### iban.transfer.received

```json theme={null}
{
  "id": "evt_06pqr678",
  "type": "iban.transfer.received",
  "created_at": "2026-03-26T12:00:00Z",
  "data": {
    "iban_id": "iban_01abc",
    "iban_number": "DE89370400440532013000",
    "amount": "1000.00",
    "currency": "EUR",
    "sender_name": "John Smith",
    "sender_iban": "GB29NWBK60161331926819",
    "reference": "Invoice #INV-2026-042",
    "received_at": "2026-03-26T12:00:00Z"
  }
}
```

### gas.low

```json theme={null}
{
  "id": "evt_07stu901",
  "type": "gas.low",
  "created_at": "2026-03-26T11:00:00Z",
  "data": {
    "station_id": "station_01abc123",
    "chain": "ethereum",
    "ticker": "ETH",
    "balance": "0.08",
    "balance_usd": "200.00",
    "threshold": "0.10"
  }
}
```

***

## Signature Verification

Every webhook delivery is signed with a timestamp to prevent replay attacks. Two headers are sent:

| Header               | Value                    |
| -------------------- | ------------------------ |
| `X-Yativo-Signature` | `sha256=<hmac>`          |
| `X-Yativo-Timestamp` | Unix timestamp (seconds) |

The HMAC is computed over `"${timestamp}.${JSON.stringify(payload)}"`:

```typescript theme={null}
import crypto from 'crypto';

function verifyWebhookSignature(
  payload: object,
  signature: string,       // value of X-Yativo-Signature header
  timestamp: string,       // value of X-Yativo-Timestamp header
  secret: string           // your webhook secret (starts with whsec_)
): boolean {
  // Reject if timestamp is more than 5 minutes old
  const ts = parseInt(timestamp, 10);
  if (Math.abs(Date.now() / 1000 - ts) > 300) return false;

  const signedPayload = `${timestamp}.${JSON.stringify(payload)}`;
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
```

See the [Webhook Integration guide](/guides/webhook-integration) for Python and PHP examples.

***

## Setting Up Webhooks

All events — deposits, swaps, card lifecycle, card transactions, customer funding — are delivered through a single webhook service. Register once at `POST /v1/webhook/create-webhook` and subscribe to any combination of event types.

<ParamField body="url" type="string" required>
  The HTTPS endpoint to receive events.
</ParamField>

<ParamField body="events" type="array">
  Event slugs to subscribe to. Pass `["*"]` (or omit) to receive all events.
</ParamField>

<ParamField body="description" type="string">
  Optional label for this subscription.
</ParamField>

```bash theme={null}
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://your-server.com/webhooks/yativo",
    "events": ["deposit.confirmed", "transaction.authorized", "transaction.settled", "card.created"],
    "description": "Production webhook"
  }'
```

```json Response theme={null}
{
  "status": true,
  "message": "Webhook created successfully",
  "data": {
    "webhook_id": "664abc123def456789000001",
    "url": "https://your-server.com/webhooks/yativo",
    "events": ["deposit.confirmed", "transaction.authorized", "transaction.settled", "card.created"],
    "secret": "whsec_abc123def456...",
    "created_at": "2026-03-26T10:00:00.000Z"
  }
}
```

<Warning>
  Store the `secret` securely. It is also retrievable later via `GET /v1/yativo-card/webhooks/:webhookId`. Use it to verify `X-Yativo-Signature` on every delivery.
</Warning>

#### List card webhooks

**GET** `/yativo-card/webhooks`

```bash theme={null}
curl -X GET https://crypto-api.yativo.com/api/v1/yativo-card/webhooks \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

#### Get a card webhook (includes secret)

**GET** `/yativo-card/webhooks/:webhookId`

```bash theme={null}
curl -X GET https://crypto-api.yativo.com/api/v1/yativo-card/webhooks/664abc123def456789000001 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

#### Update a card webhook

**PUT** `/yativo-card/webhooks/:webhookId`

```bash theme={null}
curl -X PUT https://crypto-api.yativo.com/api/v1/yativo-card/webhooks/664abc123def456789000001 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["*"],
    "enabled": true
  }'
```

Set `"enabled": false` to pause delivery without deleting the subscription.

#### Delete a card webhook

**DELETE** `/yativo-card/webhooks/:webhookId`

```bash theme={null}
curl -X DELETE https://crypto-api.yativo.com/api/v1/yativo-card/webhooks/664abc123def456789000001 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

#### Rotate the signing secret

**POST** `/yativo-card/webhooks/:webhookId/rotate-secret`

Generates a new secret and invalidates the old one immediately.

```bash theme={null}
curl -X POST https://crypto-api.yativo.com/api/v1/yativo-card/webhooks/664abc123def456789000001/rotate-secret \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

#### Delivery history

**GET** `/yativo-card/webhooks/:webhookId/deliveries`

Query params: `limit`, `offset`, `status`, `eventType`

```bash theme={null}
curl -X GET 'https://crypto-api.yativo.com/api/v1/yativo-card/webhooks/664abc123def456789000001/deliveries?limit=20&status=failed' \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

**GET** `/yativo-card/webhooks/deliveries/all` — All deliveries across all subscriptions.

#### Retry a failed delivery

**POST** `/yativo-card/webhooks/deliveries/:deliveryId/retry`

```bash theme={null}
curl -X POST https://crypto-api.yativo.com/api/v1/yativo-card/webhooks/deliveries/664abc000000000000000099/retry \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
