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

# Webhooks

> Event notifications and signature verification

ToffeePay uses webhooks to notify your backend when important events occur, such as successful payments, completed refunds or successful wallet deposits. All webhooks are signed using [Standard Webhooks](https://www.standardwebhooks.com/).

## Webhook Structure

All ToffeePay webhooks follow a consistent structure:

```json theme={null}
{
  "type": "session.created",
  "timestamp": "2023-06-01T12:05:00Z",
  "data": {
    // Event-specific data
  }
}
```

**Fields:**

* **`type`**: Event type (e.g., `session.created`, `payment.succeeded`, `deposit.succeeded`)
* **`timestamp`**: ISO 8601 timestamp when the event occurred
* **`data`**: Event-specific payload containing the relevant entity data

***

## Webhook Events

### Payment Events

| Event                                                              | Description                                   |
| ------------------------------------------------------------------ | --------------------------------------------- |
| [`session.created`](/api-reference/webhooks/session.created)       | A payment session was created                 |
| [`session.paid`](/api-reference/webhooks/session.paid)             | A session was successfully paid               |
| [`session.failed`](/api-reference/webhooks/session.failed)         | A payment attempt related to a session failed |
| [`session.expired`](/api-reference/webhooks/session.expired)       | A session expired without payment             |
| [`session.cancelled`](/api-reference/webhooks/session.cancelled)   | A session was cancelled                       |
| [`payment.created`](/api-reference/webhooks/payment.created)       | A payment was created                         |
| [`payment.succeeded`](/api-reference/webhooks/payment.succeeded)   | A payment was successfully processed          |
| [`payment.failed`](/api-reference/webhooks/payment.failed)         | A payment attempt failed                      |
| [`payment.authorized`](/api-reference/webhooks/payment.authorized) | A payment was authorized for later capture    |
| [`payment.cancelled`](/api-reference/webhooks/payment.cancelled)   | A payment was cancelled                       |
| [`refund.created`](/api-reference/webhooks/refund.created)         | A refund was created                          |
| [`refund.succeeded`](/api-reference/webhooks/refund.succeeded)     | A refund was processed successfully           |
| [`refund.failed`](/api-reference/webhooks/refund.failed)           | A refund attempt failed                       |

### Wallet Events

| Event                                                            | Description                             |
| ---------------------------------------------------------------- | --------------------------------------- |
| [`deposit.succeeded`](/api-reference/webhooks/deposit.succeeded) | A wallet deposit completed successfully |
| [`deposit.failed`](/api-reference/webhooks/deposit.failed)       | A wallet deposit failed                 |

***

## Webhook Signature Verification

All webhooks are signed using [Standard Webhooks](https://www.standardwebhooks.com/). Each request includes these headers:

| Header              | Description                                         |
| ------------------- | --------------------------------------------------- |
| `webhook-id`        | Unique message identifier for idempotency           |
| `webhook-timestamp` | Unix timestamp of the event                         |
| `webhook-signature` | Signature in format `v1,{base64-encoded-signature}` |

### Verification

Use the official [Standard Webhooks libraries](https://github.com/standard-webhooks/standard-webhooks/tree/main/libraries) to verify webhook signatures:

```typescript theme={null}
import { Webhook } from "standardwebhooks";

const wh = new Webhook(process.env.WEBHOOK_SECRET);

function handleWebhook(req: Request) {
  const payload = wh.verify(req.body, req.headers);

  switch (payload.type) {
    case 'session.paid':
      handleSessionPaid(payload.data);
      break;
    case 'payment.succeeded':
      handlePaymentSuccess(payload.data);
      break;
    case 'refund.succeeded':
      handleRefundSuccess(payload.data);
      break;
    case 'deposit.succeeded':
      handleDepositSuccess(payload.data);
      break;
  }
}
```

***

## Idempotency

Webhooks may be delivered more than once. Use the `webhook-id` header to deduplicate:

```typescript theme={null}
const webhookId = req.headers['webhook-id'];

if (await isProcessed(webhookId)) {
  return; // Skip duplicate
}

// ... verify and process

await markProcessed(webhookId);
```

***

## Webhook Configuration

You can configure and manage your webhook settings:

1. **Webhook URL**: The endpoint where ToffeePay will send webhooks
2. **Webhook Secret**: Used to sign webhook payloads (can be rotated)
3. **Event Selection**: Choose which events to receive (payments, refunds, deposits, or all)

***

## Best Practices

1. **Always verify signatures**: Never process webhooks without signature verification
2. **Handle duplicate events**: While rare, webhooks may be sent multiple times — use the `webhook-id` header for [idempotency](#idempotency)
3. **Respond quickly**: Return a 200 status code within 10 seconds to acknowledge receipt
4. **Retry logic**: ToffeePay will retry failed webhooks, but implement your own retry logic for critical operations
5. **Log webhook events**: Keep audit logs of all webhook events for debugging and compliance
6. **Use HTTPS**: Always use HTTPS endpoints for webhook URLs

***

## Troubleshooting

### Common Issues

* **Signature verification fails**: Check that you're using the correct webhook secret and following the verification steps exactly
* **Timeout errors**: Ensure your webhook endpoint responds within 10 seconds
* **Missing webhooks**: Check your webhook URL configuration and ensure your endpoint is accessible

### Testing Webhooks

Use tools like ngrok for local development to expose your local webhook endpoint to ToffeePay:

```bash theme={null}
ngrok http 3000
```
