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

# Handling Webhooks

> Implement webhook handlers for real-time event notifications

# Handling Webhooks

Receive real-time notifications when events occur in your account. Webhooks are delivered via HTTP POST to your endpoint.

## Webhook Structure

All webhook events use this envelope:

```json theme={null}
{
  "event": "cardaccount.transaction.created",
  "id": "7dd3a60c-b0f3-416f-aacc-b64661a3a909",
  "time": "2023-01-10T00:57:38.585Z",
  "data": {
    // Event-specific payload
  }
}
```

**Fields:**

* `event`: Event type identifier
* `id`: Unique event ID (use for deduplication)
* `time`: ISO 8601 timestamp
* `data`: Event-specific payload

See [Webhook Events](/issuing/guides/webhook-events-1) for complete event catalog.

## Signature Verification

Webhooks include an RSA-SHA256 signature in the `x-access-signature` header. Verify signatures using the webhook public key.

**Header:** `x-access-signature`\
**Algorithm:** RSA-SHA256\
**Key:** Public key provided when creating webhook endpoint

**Verification Process:**

1. Extract signature from `x-access-signature` header (Base64-encoded)
2. Load webhook public key (PEM format)
3. Verify signature against raw request body using RSA-SHA256 with PKCS1v15 padding
4. Return HTTP 401 if verification fails

**Important:**

* Use raw request body before JSON parsing
* Signature is Base64-encoded
* Public key is provided at webhook creation time

<Note>
  For language-specific verification examples, see the [Recipes section](/issuing/recipes).
</Note>

## Endpoint Requirements

Your webhook endpoint must:

* Accept POST requests over HTTPS
* Return HTTP 200 within 5 seconds
* Parse JSON request bodies
* Verify signatures before processing

**Response:** Return HTTP 200 immediately after signature verification. Process events asynchronously if needed.

## Event Processing

### Deduplication

Use the `id` field to detect duplicate deliveries. Store processed event IDs and check before processing.

**Storage options:**

* Database table with event ID index
* Distributed cache (Redis) with TTL
* In-memory set (development only)

**TTL:** 24-48 hours (events won't be redelivered after this period)

### Async Processing

Process events asynchronously to meet the 5-second response requirement:

1. Verify signature
2. Check for duplicate (event ID)
3. Acknowledge with HTTP 200
4. Queue event for async processing

**Queue options:** Message queues (Redis, RabbitMQ, AWS SQS), background jobs, or event buses.

### Error Handling

* Log errors without preventing acknowledgment
* Implement retry logic in your queue/worker
* Make handlers idempotent (safe to retry)

## Webhook Statuses

Webhooks transition through these statuses:

| Status      | Description                                 |
| ----------- | ------------------------------------------- |
| `created`   | Newly created, pending initial health check |
| `healthy`   | Active, deliveries successful               |
| `unhealthy` | Degraded, retries in progress               |
| `error`     | Suspended due to repeated failures          |
| `removed`   | Deleted from system                         |

**Status transitions:**

* `created` → `unhealthy` → `healthy` (on first success)
* `healthy` → `unhealthy` (on failures)
* `unhealthy` → `error` (after 10+ consecutive failures)
* `error` → `healthy` (on successful auto-recovery ping)
* `error` → `removed` (after 24 hours of failed pings)

See [Webhooks Overview](/issuing/guides/webhooks-1) for detailed lifecycle.

## Testing

### Local Development

Use tunneling tools to expose local endpoints:

* ngrok
* Cloudflare Tunnel
* localtunnel

Configure the tunnel URL as your webhook endpoint in the dashboard.

### Test Events

Send test events from the dashboard:

1. Navigate to **Settings** → **Webhooks**
2. Select your endpoint
3. Click **Send Test Event**
4. Choose event type

## Monitoring

**Log:**

* Event ID and type
* Processing status
* Errors and latency
* Full payload (for debugging)

**Monitor:**

* Success rate
* Processing latency
* Queue depth (if using queues)
* Endpoint availability

## Troubleshooting

**Webhooks not arriving:**

* Verify HTTPS endpoint is publicly accessible
* Check firewall rules
* Confirm endpoint URL in dashboard

**Signature verification failing:**

* Verify correct public key
* Use raw body before JSON parsing
* Check Base64 encoding

**Duplicate events:**

* Normal behavior (retries)
* Implement deduplication using event ID

## Next Steps

* [Webhooks Overview](/issuing/guides/webhooks-1) - Webhook lifecycle and status management
* [Webhook Events](/issuing/guides/webhook-events-1) - Complete event catalog
* [API Reference](/issuing/api-reference/openapi) - Webhook management endpoints
