# Webhooks

> Set up and handle VINR webhook events for real-time payment notifications.

## Overview

Webhooks notify your application in real-time when events occur on your VINR account — payments completed, refunds processed, disputes opened, etc.

## Setup

1. Navigate to **Dashboard → Developers → Webhooks**
2. Click **Add Endpoint**
3. Enter your endpoint URL (must be HTTPS)
4. Select the events you want to receive
5. Save — VINR will send a test event to verify connectivity

## Event Types

| Event                  | Description                   |
| ---------------------- | ----------------------------- |
| `payment.created`      | Payment intent created        |
| `payment.completed`    | Payment successfully captured |
| `payment.failed`       | Payment attempt failed        |
| `payment.expired`      | Payment session expired       |
| `refund.created`       | Refund initiated              |
| `refund.completed`     | Refund successfully processed |
| `dispute.opened`       | Chargeback/dispute opened     |
| `dispute.resolved`     | Dispute resolved              |
| `settlement.completed` | Funds settled to your account |

## Verifying Signatures

Always verify webhook signatures to ensure events are from VINR:

```typescript
import { Vinr } from '@vinr/sdk';
import { headers } from 'next/headers';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

export async function POST(req: Request) {
  const body = await req.text();
  const signature = req.headers.get('x-vinr-signature')!;
  const timestamp = req.headers.get('x-vinr-timestamp')!;

  try {
    const event = vinr.webhooks.constructEvent(body, signature, timestamp);
    // Process event...
    return new Response('OK');
  } catch (err) {
    return new Response('Invalid signature', { status: 401 });
  }
}
```

## Retry Policy

If your endpoint returns a non-2xx status code, VINR retries with exponential backoff:

| Attempt   | Delay      |
| --------- | ---------- |
| 1st retry | 1 minute   |
| 2nd retry | 5 minutes  |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours    |
| 5th retry | 24 hours   |

After 5 failed attempts, the webhook is marked as failed and you'll receive an email notification.

## Best Practices

1. **Return 200 quickly** — Process events asynchronously
2. **Handle duplicates** — Use the event ID for idempotency
3. **Verify signatures** — Never trust unverified webhooks
4. **Monitor failures** — Set up alerts for webhook delivery issues
