# Webhooks

Webhooks allow you to receive real-time updates when new Variations are created. By setting up a webhook, your application can automatically receive information about these events without the need for constant polling.

### How Webhooks Work

When creating a Render or Variation, include a `webhook_url` parameter:

```
{
"config": { ... },
"image_url": "https://example.com/room.jpg",
"variation_count": 3,
"webhook_url": "https://your-app.com/webhooks/renders"
}
```

Your endpoint will receive separate POST requests for:

* Each Variation's completion or error state
* Analysis results (when using the analyze endpoint)

For example, if you create a render with 3 Variations, you'll receive 3 webhook responses once the Variations either complete or fail. You will not receive a separate webhook response for the parent Render.

### Variation Webhook Response Types

There are 2 Variation webhook payload types: `done` and `error`.

#### \`Done\` response schema

```
{
"render_id": "rnd_abc123", // the parent render id
"variation_id": "var_xyz789",
"variation_type": "staging",
"base_variation_id": "var_removal123", // if using a base variation from a removal
"timestamp": 1634567890123,
"event_type": "done",
"result": {
    "url":"https://results.example.com/image.jpg",
    "optimized_url":"https://results.example.com/image_optimized.webp",
    "thumbnail_url":"https://results.example.com/image_thumb.jpg"
    }
}
```

{% hint style="info" %}
When using **Multi-View Staging** the `result` object will be returned as an array of objects
{% endhint %}

#### \`Error\` response schema

```
{
"render_id": "rnd_abc123",
"variation_id": "var_xyz789",
"variation_type": "staging",
"timestamp": 1634567890123,
"event_type": "error",
"error_message": "Failed to process image"
}
```

### Analysis Webhook Response Types

### Best Practices

1. **Acknowledge Quickly**: Return a 200 status code as soon as you receive the webhook. Process the payload asynchronously if needed.
2. **Handle Retries**: Webhooks will be retried up to 3 times if your endpoint fails to respond with a 200 status.
3. **Store Base Variation IDs**: For staging variations, the `base_variation_id` links to the removal variation it was based on (if a base variation was used or the removal mode was set to `auto`).
4. **Track Event Types**: Different `event_type` values indicate different stages:
   * `update`: Status changes and progress
   * `done`: Processing complete
   * `error`: Processing failed
   * `analysis_completion`: Analysis complete
   * `analysis_error`: Analysis failed

### Testing Webhooks

We recommend using tools like [webhook.site](https://webhook.site) for testing webhook integration before setting up your production endpoint.

### Authenticating Webhooks

To ensure the security and authenticity of webhook payloads, we use HMAC (Hash-based Message Authentication Code) signatures. This helps verify that webhook requests are genuinely coming from our servers and haven't been tampered with.

### How HMAC Works

HMAC combines your secret key with the webhook payload to create a unique signature. The process works like this:

1. We take your webhook secret (which only you and our servers know)
2. We combine it with the exact payload data
3. We run this through a cryptographic hash function (SHA-256)
4. The result is a unique signature that can only be generated with both the correct secret and payload

This means that if anyone tries to:

* Send a fake webhook without knowing your secret
* Modify the payload in any way
* Use a different secret

The signature verification will fail, alerting you to the potential security issue.

#### Setting Up Webhook Authentication

1. Set your webhook secret using the `POST /user/webhook-secret` endpoint. You can remove it at any time using the `DELETE /user/webhook-secret` endpoint.
2. When receiving webhooks, verify the signature:<br>

   ```javascript
   const crypto = require('crypto');

   function verifyWebhookSignature(payload, signature, secret) {
     const calculatedSignature = crypto
       .createHmac('sha256', secret)
       .update(JSON.stringify(payload))
       .digest('hex');
       
     return signature === calculatedSignature;
   }

   // In your webhook handler:
   app.post('/webhook', (req, res) => {
     const signature = req.headers['x-vsai-signature'];
     const payload = req.body;
     
     if (!verifyWebhookSignature(payload, signature, 'your-secret-here')) {
       return res.status(401).json({ error: 'Invalid signature' });
     }
     
     // Process the webhook...
   });
   ```

The signature is sent in the X-VSAI-Signature header. Always verify this signature before processing any webhook payload to ensure it's legitimate.
