# Webhooks — registration and verification

**Base URL:** `https://www.strawberryid.com/api`

## Register an endpoint

Replace `<merchant_id>` with your merchant id.

```bash
curl -X POST https://www.strawberryid.com/api/merchants/<merchant_id>/webhooks \
  -H "Content-Type: application/json" \
  -d '{"url":"https://merchant.example.com/webhooks/strawberryid"}'
```

The response includes a **secret** (shown once) used to verify signatures.

Store this secret on your backend only (for example `STRAWBERRY_WEBHOOK_SECRET`).

## Verify `X-Strawberry-Signature`

Strawberry ID signs the **raw JSON body** with HMAC-SHA256. Compare your computed digest to the header (hex).

```javascript
import crypto from 'node:crypto';

function verifySignature(secret, rawBody, signature) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

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

## Headers on each delivery

- `X-Strawberry-Signature`
- `X-Strawberry-Event`
- `X-Strawberry-Event-Id`

## Event topics

| Topic | Meaning |
| --- | --- |
| `transaction.settled` | Merchant-linked transaction settled |
| `refund.completed` | One Wallet refund completed (ledger reversed to customer) |
| `merchant.identity.consent_granted` | User granted identity access to the merchant |
| `merchant.identity.request.approved` | Pending identity request approved |
| `merchant.identity.request.denied` | Pending identity request denied |

### `refund.completed` payload (illustrative)

Fields are JSON inside the signed body. Common keys:

| Field | Description |
| --- | --- |
| `merchantId` | Strawberry merchant id |
| `refundId` | Refund record id |
| `transactionId` | Original payment transaction id |
| `reference` | Original checkout `reference`, if set |
| `amount` | Refunded amount (number) |
| `currency` | e.g. `NGN` |
| `reason` | Optional refund reason |
| `status` | e.g. `COMPLETED` |
| `strawberryId` | Customer SR1-… when available |
| `completedAt` | ISO-8601 timestamp |
| `merchantReference` | Value from `merchant_reference` on `POST /v1/refunds`, when provided |

Use this event to reconcile order state in your backend after automated refunds. See [payments-refunds.md](./payments-refunds.md).
