# API Web Hook

You need configure a webhook url for each agent you create.  Long running text responses from agents and configured functions  are sent to webhooks.

To securely consume a webhook response, you can optionally validate the webhook using the x-signature token sent with the response. The token must  be validated with the same api key  used to make the request to the agent.

```
// Header
'x-signature': xxxxxxxxxxxxxxx
```

```json
// Webhook Text Response
{
    "message": {
        "id": "duH7f5mOItDIlpYRbMPDE",
        "agentId": "hyeyry3mOItehdsfp373hhs",
        "role": "assistant",
        "content": "The diagnosis of Pediculus Capitis (head lice) is a valid medical condition. The details provided do not indicate any fraudulent activity."
    }
}
```

Here is a smaple code to securely verify your hooks

{% tabs %}
{% tab title="Node.js" %}

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

function verifyWebhookSignature(req, secret) {
  const signature = req.headers['x-signature'];
  const payload = JSON.stringify(req.body);
  
  // Compute the hash using HMAC with SHA256 and the shared secret
  const hash = crypto.createHmac('sha256', secret).update(payload).digest('hex');

  // Compare the computed hash with the signature
  return hash === signature;
}

// Usage in Express.js
app.post('/webhook', (req, res) => {
  const secret = 'your_api_key';
  
  if (!verifyWebhookSignature(req, secret)) {
    return res.status(403).send('Forbidden');
  }
  
  // Handle the webhook
  res.status(200).send('Webhook received');
});

```

{% endtab %}

{% tab title="Java" %}

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;

public class WebhookVerifier {

    public static boolean verifyWebhookSignature(HttpServletRequest req, String secret) throws Exception {
        String signature = req.getHeader("x-signature");
        StringBuilder payload = new StringBuilder();
        
        try (BufferedReader reader = req.getReader()) {
            String line;
            while ((line = reader.readLine()) != null) {
                payload.append(line);
            }
        }

        Mac sha256HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        sha256HMAC.init(secretKey);
        byte[] hashBytes = sha256HMAC.doFinal(payload.toString().getBytes(StandardCharsets.UTF_8));
        String hash = bytesToHex(hashBytes);

        return hash.equals(signature);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder(2 * bytes.length);
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
}

```

{% endtab %}

{% tab title="Python" %}

```python
import hmac
import hashlib

def verify_webhook_signature(req, secret):
    signature = req.headers.get('x-signature')
    payload = req.data.decode('utf-8')  # Assuming you're using Flask, this will give you the raw payload
    
    # Compute the HMAC SHA256 hash
    hash = hmac.new(secret.encode('utf-8'), payload.encode('utf-8'), hashlib.sha256).hexdigest()

    # Compare the computed hash with the signature
    return hash == signature

# Usage in Flask
from flask import Flask, request, abort

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    secret = 'your_shared_secret'
    
    if not verify_webhook_signature(request, secret):
        abort(403)  # Forbidden
    
    # Handle the webhook
    return 'Webhook received', 200

```

{% endtab %}

{% tab title="Ruby" %}

```ruby
require 'openssl'

def verify_webhook_signature(req, secret)
  signature = req.headers['x-signature']
  payload = req.body.read
  
  # Compute the HMAC SHA256 hash
  hash = OpenSSL::HMAC.hexdigest('SHA256', secret, payload)

  # Compare the computed hash with the signature
  hash == signature
end

# Usage in Sinatra
require 'sinatra'

post '/webhook' do
  secret = 'your_shared_secret'
  
  halt 403, 'Forbidden' unless verify_webhook_signature(request, secret)
  
  # Handle the webhook
  status 200
  'Webhook received'
end

```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"io/ioutil"
	"net/http"
)

func verifyWebhookSignature(r *http.Request, secret string) bool {
	signature := r.Header.Get("x-signature")

	body, _ := ioutil.ReadAll(r.Body)
	defer r.Body.Close()

	h := hmac.New(sha256.New, []byte(secret))
	h.Write(body)
	hash := hex.EncodeToString(h.Sum(nil))

	return hash == signature
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
	secret := "your_shared_secret"
	
	if !verifyWebhookSignature(r, secret) {
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	// Handle the webhook
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Webhook received"))
}

func main() {
	http.HandleFunc("/webhook", webhookHandler)
	http.ListenAndServe(":8080", nil)
}

```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

function verifyWebhookSignature($request, $secret) {
    // Get the signature from the request headers
    $signature = $request->getHeader('x-signature')[0]; // Assuming you're using PSR-7 Request
    $payload = $request->getBody()->getContents(); // Get the raw body payload

    // Compute the HMAC SHA-256 hash
    $hash = hash_hmac('sha256', $payload, $secret);

    // Compare the computed hash with the signature
    return hash_equals($hash, $signature);
}

// Usage in a PSR-7 compatible framework like Slim or Laravel (with Request injection)
$app->post('/webhook', function ($request, $response) {
    $secret = 'your_shared_secret';

    if (!verifyWebhookSignature($request, $secret)) {
        return $response->withStatus(403)->write('Forbidden');
    }

    // Handle the webhook
    return $response->withStatus(200)->write('Webhook received');
});

```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
You  can optionally use this approach to seurely consume a hook, or ensure that your webhook url is on a secured https certificate.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.vorsto.io/api/api-web-hook.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
