Vouch logovouch
Getting started

Verifying vouch webhooks

When using vouch to generate web verifications, you’ll receive webhook responses that include both the verification and the associated data. This guide shows you how to extract and verify webhook responses using the POST /api/v1/verify endpoint.

Webhook Response Structure

When a user completes verification through vouch, a webhook is sent to your configured webhookUrl containing:

  • requestId: Unique identifier for the verification request
  • dataSourceId: Identifier for the data source used
  • outputs: Aggregated extracted data from all web verifications
  • webProofs: Array of web verification objects, each containing:
    • outputs: Data extracted from this specific verification
    • presentationJson: The presentation object (for verification)
    • decodedTranscript: Human-readable HTTP request/response data

A single verification request can produce multiple web verifications. You’ll still receive one webhook payload, but webProofs will contain multiple entries, and top-level outputs is the aggregated data across all verifications.

Example:

{
  "requestId": "00000000-0000-0000-0000-000000000000",
  "dataSourceId": "11111111-1111-1111-1111-111111111111",
  "outputs": {
    "twitterLinked": true,
    "portfolioValueUsd": "6.97",
    "accountAgeDays": 360,
    "portfolioChange24h": "-0.29"
  },
  "webProofs": [
    {
      "outputs": {
        "twitterLinked": true,
        "accountAgeDays": 360
      },
      "presentationJson": { "...": "..." },
      "decodedTranscript": { "...": "..." }
    },
    {
      "outputs": {
        "portfolioValueUsd": "6.97",
        "portfolioChange24h": "-0.29"
      },
      "presentationJson": { "...": "..." },
      "decodedTranscript": { "...": "..." }
    }
  ]
}

To receive webhook responses, you need to configure a webhookUrl when initiating the verification flow. See the Getting Started guide or Integration Example for details on setting up webhooks.

Webhook Allowlist

If you allowlist inbound webhook traffic, add our static IPs:

  • 52.59.138.51
  • 3.78.83.192

Extracting and Verifying Webhook Response

Step 1: Extract the presentation from webhook response

The presentationJson field contains the cryptographic verification:

// Example webhook payload received at your endpoint
const webhookPayload = {
  requestId: "00000000-0000-0000-0000-000000000000",
  outputs: {
    // ...
  },
  webProofs: [
    {
      outputs: { /* ... */ },
      decodedTranscript: { /* ... */ },
      presentationJson: {
        data: "014000000000000000db...",
        meta: {
          notaryUrl: "https://notary.example.com/v0.1.0-alpha.12",
          websocketProxyUrl: "wss://proxy.example.com"
        },
        version: "0.1.0-alpha.12"
      }
    }
  ]
};

// Extract first verification - production apps should make sure to verify all delivered verifications
const presentation = webhookPayload.webProofs?.[0]?.presentationJson;
if (!presentation) throw new Error("No webProofs or presentationJson found");
# Example webhook payload received at your endpoint
WEBHOOK_PAYLOAD='{
  "requestId": "00000000-0000-0000-0000-000000000000",
  "dataSourceId": "11111111-1111-1111-1111-111111111111",
  "outputs": {
    // ...
  },
  "webProofs": [
    {
      "outputs": { "..." },
      "decodedTranscript": { "..." },
      "presentationJson": {
        "data": "014000000000000000db...",
        "meta": {
          "notaryUrl": "https://notary.example.com/v0.1.0-alpha.12",
          "websocketProxyUrl": "wss://proxy.example.com"
        },
        "version": "0.1.0-alpha.12"
      }
    }
  ]
}'

# Extract first verification - production apps should make sure to verify all delivered verifications
PRESENTATION=$(echo "$WEBHOOK_PAYLOAD" | jq '.webProofs[0].presentationJson')

Step 2: Verify the presentation

Send the extracted presentation to the verification endpoint:

const verifyResponse = await fetch('https://web-prover.vlayer.xyz/api/v1/verify', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-client-id': '4f028e97-b7c7-4a81-ade2-6b1a2917380c',
    'Authorization': 'Bearer jUWXi1pVUoTHgc7MOgh5X0zMR12MHtAhtjVgMc2DM3B3Uc8WEGQAEix83VwZ'
  },
  body: JSON.stringify(presentation)
});

const verificationResult = await verifyResponse.json();
console.log(JSON.stringify(verificationResult, null, 2));
curl -s -X POST https://web-prover.vlayer.xyz/api/v1/verify \
  -H "Content-Type: application/json" \
  -H "x-client-id: 4f028e97-b7c7-4a81-ade2-6b1a2917380c" \
  -H "Authorization: Bearer jUWXi1pVUoTHgc7MOgh5X0zMR12MHtAhtjVgMc2DM3B3Uc8WEGQAEix83VwZ" \
  -d "$PRESENTATION" | jq '.'

The included credentials are for limited public use. For production use, please contact our team.

Expected Result

You should receive a JSON response with "success": true and the decoded request/response data (see below). Any other result should be treated as an invalid verification and must halt further processing or workflows.

{
  "success": true,
  "serverDomain": "example.com",
  "notaryKeyFingerprint": "0000000000000000000000000000000000000000000000000000000000000000",
  "request": {
    "method": "POST",
    "url": "/api/v2/order/details",
    "version": "HTTP/1.1",
    "headers": [
      ["content-type", "application/json"],
      ["accept", "*/*"],
      ["host", "XXXXXXXXXXXXXXX"],
      ["connection", "XXXXX"]
    ],
    "body": "{\"orderNumber\":\"00000000000000000000\",\"createTime\":0}",
    "raw": "504f5354202f626170692f...",
    "parsingSuccess": true
  },
  "response": {
    "status": 200,
    "version": "HTTP/1.1",
    "headers": [
      ["content-type", "application/json"],
      ["content-length", "2543"],
      ["content-encoding", "gzip"],
      ["date", "Mon, 01 Jan 2024 00:00:00 GMT"]
    ],
    "body": "{\"code\":\"000000\",\"message\":null,\"data\":{\"orderNumber\":\"00000000000000000000\",\"asset\":\"USDT\",\"amount\":\"0.00000000\",...}}",
    "raw": "485454502f312e3120323030204f4b...",
    "parsingSuccess": true
  }
}

Sensitive header values are redacted with X characters in the response for privacy.

Verifying vouch webhooks | vouch Docs