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

# Webhooks

> Set up real-time notifications using webhooks

## Overview

Webhooks allow you to receive real-time notifications when specific events occur in the Zochil API. Instead of polling our API for changes, webhooks push data to your application as events happen.

## How Webhooks Work

1. **Configure**: Set up webhook endpoints in your application
2. **Subscribe**: Register your webhook URL for specific events
3. **Receive**: Get instant notifications when events occur
4. **Process**: Handle the webhook payload in your application

## Webhook Events

### User Events

| Event           | Description                  |
| --------------- | ---------------------------- |
| `user.created`  | New user registration        |
| `user.updated`  | User profile changes         |
| `user.deleted`  | User account deletion        |
| `user.verified` | Email verification completed |

### Order Events

| Event                     | Description                    |
| ------------------------- | ------------------------------ |
| `order.created`           | New order placed               |
| `order.updated`           | Order status changed           |
| `order.cancelled`         | Order cancelled                |
| `order.completed`         | Order fulfilled                |
| `order.payment_succeeded` | Payment processed successfully |
| `order.payment_failed`    | Payment processing failed      |

### Product Events

| Event               | Description                 |
| ------------------- | --------------------------- |
| `product.created`   | New product added           |
| `product.updated`   | Product information changed |
| `product.deleted`   | Product removed             |
| `inventory.updated` | Product inventory changed   |

### Cart Events

| Event               | Description                          |
| ------------------- | ------------------------------------ |
| `cart.item_added`   | Item added to cart                   |
| `cart.item_removed` | Item removed from cart               |
| `cart.abandoned`    | Cart abandoned (no activity for 24h) |

## Setting Up Webhooks

### 1. Create a Webhook Endpoint

Create an HTTP endpoint in your application to receive webhook notifications:

<CodeGroup>
  ```javascript Node.js/Express theme={null}
  const express = require("express");
  const crypto = require("crypto");
  const app = express();

  app.use(express.json());

  app.post("/webhooks/zochil", (req, res) => {
    const signature = req.get("X-Zochil-Signature");
    const payload = JSON.stringify(req.body);

    // Verify webhook signature (recommended)
    if (!verifySignature(payload, signature)) {
      return res.status(401).send("Unauthorized");
    }

    const { event, data } = req.body;

    // Handle the event
    switch (event) {
      case "user.created":
        console.log("New user:", data.user);
        // Send welcome email, create user profile, etc.
        break;

      case "order.created":
        console.log("New order:", data.order);
        // Update inventory, send confirmation, etc.
        break;

      default:
        console.log("Unhandled event:", event);
    }

    res.status(200).send("OK");
  });

  function verifySignature(payload, signature) {
    const webhookSecret = process.env.ZOCHIL_WEBHOOK_SECRET;
    const expectedSignature = crypto
      .createHmac("sha256", webhookSecret)
      .update(payload)
      .digest("hex");

    return crypto.timingSafeEqual(
      Buffer.from(signature),
      Buffer.from(`sha256=${expectedSignature}`)
    );
  }

  app.listen(3000);
  ```

  ```python Python/Flask theme={null}
  from flask import Flask, request, jsonify
  import hashlib
  import hmac
  import json
  import os

  app = Flask(__name__)

  @app.route('/webhooks/zochil', methods=['POST'])
  def handle_webhook():
      signature = request.headers.get('X-Zochil-Signature')
      payload = request.get_data(as_text=True)

      # Verify webhook signature
      if not verify_signature(payload, signature):
          return jsonify({'error': 'Unauthorized'}), 401

      data = request.json
      event = data.get('event')
      event_data = data.get('data')

      # Handle the event
      if event == 'user.created':
          print(f"New user: {event_data['user']}")
          # Handle user creation

      elif event == 'order.created':
          print(f"New order: {event_data['order']}")
          # Handle order creation

      else:
          print(f"Unhandled event: {event}")

      return jsonify({'status': 'success'}), 200

  def verify_signature(payload, signature):
      webhook_secret = os.environ.get('ZOCHIL_WEBHOOK_SECRET')
      expected_signature = hmac.new(
          webhook_secret.encode(),
          payload.encode(),
          hashlib.sha256
      ).hexdigest()

      return hmac.compare_digest(
          signature,
          f"sha256={expected_signature}"
      )

  if __name__ == '__main__':
      app.run(debug=True)
  ```
</CodeGroup>

### 2. Register Your Webhook

Register your webhook endpoint using the Admin API:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.zochil.io/admin/webhooks" \
    -H "access-token: YOUR_ACCESS_TOKEN" \
    -H "device-id: YOUR_DEVICE_ID" \
    -H "merchant-id: YOUR_MERCHANT_ID" \
    -H "Content-Type: application/json" \
    -d '{
      "url": "https://your-app.com/webhooks/zochil",
      "events": ["user.created", "order.created", "order.updated"],
      "active": true,
      "secret": "your-webhook-secret-key"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.zochil.io/admin/webhooks", {
    method: "POST",
    headers: {
      "access-token": "YOUR_ACCESS_TOKEN",
      "device-id": "YOUR_DEVICE_ID",
      "merchant-id": "YOUR_MERCHANT_ID",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      url: "https://your-app.com/webhooks/zochil",
      events: ["user.created", "order.created", "order.updated"],
      active: true,
      secret: "your-webhook-secret-key"
    })
  });

  const webhook = await response.json();
  console.log("Webhook created:", webhook.data.id);
  ```
</CodeGroup>

## Webhook Payload Structure

All webhook payloads follow this structure:

```json theme={null}
{
  "id": "evt_1234567890abcdef",
  "event": "user.created",
  "created": 1640995200,
  "data": {
    "user": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "email": "user@example.com",
      "name": "John Doe",
      "created_at": "2023-01-01T00:00:00Z"
    }
  },
  "api_version": "v1"
}
```

### Payload Fields

<ParamField name="id" type="string">
  Unique identifier for the webhook event
</ParamField>

<ParamField name="event" type="string">
  The event type that triggered the webhook
</ParamField>

<ParamField name="created" type="integer">
  Unix timestamp when the event occurred
</ParamField>

<ParamField name="data" type="object">
  Event-specific data payload
</ParamField>

<ParamField name="api_version" type="string">
  API version used for the webhook
</ParamField>

## Example Event Payloads

### User Created Event

```json theme={null}
{
  "id": "evt_user_created_123",
  "event": "user.created",
  "created": 1640995200,
  "data": {
    "user": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "email": "user@example.com",
      "name": "John Doe",
      "phone": "+1234567890",
      "is_verified": false,
      "created_at": "2023-01-01T00:00:00Z"
    }
  },
  "api_version": "v1"
}
```

### Order Created Event

```json theme={null}
{
  "id": "evt_order_created_456",
  "event": "order.created",
  "created": 1640995200,
  "data": {
    "order": {
      "id": "order_123e4567e89b12d3",
      "order_number": "ORD-2023-001",
      "user_id": "123e4567-e89b-12d3-a456-426614174000",
      "status": "pending",
      "total": 299.99,
      "currency": "USD",
      "items": [
        {
          "product_id": "prod_123",
          "quantity": 2,
          "price": 149.99
        }
      ],
      "created_at": "2023-01-01T00:00:00Z"
    }
  },
  "api_version": "v1"
}
```

### Inventory Updated Event

```json theme={null}
{
  "id": "evt_inventory_updated_789",
  "event": "inventory.updated",
  "created": 1640995200,
  "data": {
    "product": {
      "id": "prod_123e4567e89b12d3",
      "sku": "PWH-001",
      "name": "Premium Wireless Headphones"
    },
    "inventory": {
      "previous_quantity": 100,
      "current_quantity": 95,
      "reserved": 5,
      "available": 90
    }
  },
  "api_version": "v1"
}
```

## Security

### Signature Verification

All webhooks include an `X-Zochil-Signature` header for verification:

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

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(payload, "utf8")
    .digest("hex");

  const receivedSignature = signature.replace("sha256=", "");

  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(receivedSignature)
  );
}
```

### IP Whitelisting

Webhook requests come from these IP ranges:

```
198.51.100.0/24
203.0.113.0/24
```

## Handling Failures

### Retry Logic

If your webhook endpoint returns a non-2xx status code, we'll retry:

* **Immediate retry**: After 1 second
* **Exponential backoff**: 5s, 25s, 125s, 300s
* **Maximum attempts**: 5 retries
* **Timeout**: 30 seconds per attempt

### Failed Webhook Dashboard

Monitor failed webhooks in your admin dashboard:

```bash theme={null}
GET /admin/webhooks/{webhook_id}/deliveries
```

## Best Practices

### 1. Idempotency

Handle duplicate webhook deliveries gracefully:

```javascript theme={null}
const processedEvents = new Set();

app.post("/webhooks/zochil", (req, res) => {
  const eventId = req.body.id;

  // Check if we've already processed this event
  if (processedEvents.has(eventId)) {
    return res.status(200).send("Already processed");
  }

  // Process the event
  handleEvent(req.body);

  // Mark as processed
  processedEvents.add(eventId);

  res.status(200).send("OK");
});
```

### 2. Async Processing

Process webhooks asynchronously to respond quickly:

```javascript theme={null}
const Queue = require("bull");
const webhookQueue = new Queue("webhook processing");

app.post("/webhooks/zochil", (req, res) => {
  // Add to queue for async processing
  webhookQueue.add("process-webhook", req.body);

  // Respond immediately
  res.status(200).send("OK");
});

webhookQueue.process("process-webhook", (job) => {
  const { event, data } = job.data;
  // Process the webhook data
  return handleWebhookEvent(event, data);
});
```

### 3. Error Handling

Log errors and return appropriate status codes:

```javascript theme={null}
app.post("/webhooks/zochil", async (req, res) => {
  try {
    await processWebhook(req.body);
    res.status(200).send("OK");
  } catch (error) {
    console.error("Webhook processing failed:", error);

    // Return 5xx for temporary failures (will be retried)
    if (error.temporary) {
      return res.status(503).send("Temporary failure");
    }

    // Return 4xx for permanent failures (won't be retried)
    res.status(400).send("Invalid webhook data");
  }
});
```

## Testing Webhooks

### Local Development

Use tools like ngrok to expose your local server:

```bash theme={null}
# Install ngrok
npm install -g ngrok

# Expose your local server
ngrok http 3000

# Use the HTTPS URL for webhook registration
# https://abc123.ngrok.io/webhooks/zochil
```

### Webhook Testing Tool

Create a simple webhook tester:

<CodeGroup>
  ```javascript Webhook Tester theme={null}
  const express = require("express");
  const app = express();

  app.use(express.json());

  app.post("/test-webhook", (req, res) => {
    console.log("Received webhook:");
    console.log("Headers:", req.headers);
    console.log("Body:", JSON.stringify(req.body, null, 2));

    res.status(200).send("Webhook received");
  });

  app.listen(3000, () => {
    console.log("Webhook tester running on port 3000");
  });
  ```
</CodeGroup>

## Managing Webhooks

### List Webhooks

```bash theme={null}
GET /admin/webhooks
```

### Update Webhook

```bash theme={null}
PATCH /admin/webhooks/{webhook_id}
```

### Delete Webhook

```bash theme={null}
DELETE /admin/webhooks/{webhook_id}
```

### Test Webhook

Trigger a test webhook delivery:

```bash theme={null}
POST /admin/webhooks/{webhook_id}/test
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Admin API" icon="shield" href="/api-reference/admin">
    Learn about webhook management endpoints
  </Card>

  <Card title="Error Handling" icon="exclamation-triangle" href="/essentials/errors">
    Handle webhook errors gracefully
  </Card>
</CardGroup>
