> ## Documentation Index
> Fetch the complete documentation index at: https://docs.otim.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

Webhooks allow you to receive real-time notifications when events happen on your Platform. Instead of polling the API, you can configure a URL that Otim will send POST requests to whenever a relevant event occurs.

## Setup

Configure your webhook URL via the [Update Platform Settings](/api-reference/update-platform-settings) endpoint:

```bash theme={null}
curl -X PATCH https://api.otim.com/v0/platform/settings \
  -H "Authorization: Bearer sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "webhookUrl": "https://yourapp.com/webhooks/otim"
  }'
```

Set `webhookUrl` to `null` to disable webhooks.

## Payload format

All webhook payloads follow the same structure:

```json theme={null}
{
  "id": "evt_01JA1B2C3D4E5F6G7H8J9K0L",
  "type": "transfer.completed",
  "createdAt": "2025-01-15T12:00:00Z",
  "data": { }
}
```

| Field       | Type   | Description                                    |
| ----------- | ------ | ---------------------------------------------- |
| `id`        | string | Unique identifier for the event.               |
| `type`      | string | The event type.                                |
| `createdAt` | string | ISO 8601 timestamp of when the event occurred. |
| `data`      | object | The full object associated with the event.     |

## Event types

### Transfers

| Event                 | Description                              |
| --------------------- | ---------------------------------------- |
| `transfer.created`    | A new transfer has been initiated.       |
| `transfer.processing` | The transfer is being processed.         |
| `transfer.completed`  | The transfer has completed successfully. |
| `transfer.failed`     | The transfer has failed.                 |

### Entities

| Event                 | Description                                     |
| --------------------- | ----------------------------------------------- |
| `entity.kyc.approved` | An Entity has passed identity verification.     |
| `entity.kyc.rejected` | An Entity's identity verification was rejected. |
| `entity.tos.approved` | An Entity has accepted the terms of service.    |

### Accounts

| Event             | Description                         |
| ----------------- | ----------------------------------- |
| `account.created` | A new Account has been provisioned. |

### IBANs

| Event                   | Description                                                                   |
| ----------------------- | ----------------------------------------------------------------------------- |
| `iban.deposit.received` | A fiat deposit has been received at an IBAN and routed to the linked Account. |

## Responding to webhooks

Your endpoint should return a `200` status code within 10 seconds. If Otim does not receive a `200` response, the webhook will be retried up to 5 times with exponential backoff.

## Verifying signatures

Each webhook request includes a `X-Otim-Signature` header containing an HMAC-SHA256 signature of the request body. Verify this signature to ensure the request came from Otim.

```javascript theme={null}
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}
```

Your webhook signing secret is available in the Developer section of your dashboard.
