Skip to main content

Overview

Grapevine Webhooks allow you to receive real-time notifications whenever new data is indexed into Grapevine - allowing you to build real-time company-aware integrations. Currently, Grapevine can send HTTP POST requests to your specified endpoint whenever documents change in any of your connected sources.

Creating a webhook

1

Navigate to webhooks

Go to the Webhooks page in your dashboard and click Create Webhook.
2

Configure your endpoint

Enter the URL where you want to receive webhook events. This should be a publicly accessible HTTPS endpoint.
3

Save and get your secret

Click Save. You’ll receive a webhook secret with the format wh_xxxxx. Save this secret securely - you’ll need it to verify webhook signatures.

Event types

Currently, we only support 1 event type. In the future, we may support others. If you have an event type you’re interested in seeing us support, let us know!

document.changed

document.changed fires whenever a document is updated and its changes are fully indexed into Grapevine. You can fetch the new version of the document by issuing a get_document call with the document_id referenced in this event.
{
  "event": "document.changed",
  "timestamp": "2024-01-15T10:30:00Z",
  "tenant_id": "tenant_abc123",
  "data": {
    "document_id": "doc_123",
    "source": "notion"
  }
}

Retry policy

If your endpoint returns a non-2xx status code or times out, Grapevine will automatically retry with exponential backoff:
  • Total attempts: 5 attempts
  • Timeout: 5 seconds per request
  • Backoff schedule: 0.5s, 1s, 2s, 4s, 8s between attempts
  • Maximum duration: ~15.5 seconds for all retry attempts
After 5 failed attempts, Grapevine will stop trying to deliver this event.

Verifying webhooks

Grapevine signs all webhook requests using HMAC-SHA256.

Signature verification

The X-Grapevine-Signature header contains sha256={signature} where the signature is computed from the JSON payload with no spaces.
const crypto = require('crypto');

function verifyWebhook(payload, signatureHeader, secret) {
  const payloadString = JSON.stringify(payload);

  // Compute HMAC-SHA256 signature
  const hmac = crypto.createHmac('sha256', secret);
  const digest = hmac.update(payloadString).digest('hex');

  // Compare with signature from header (format: "sha256={hex_digest}")
  const expectedSignature = `sha256=${digest}`;
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/grapevine', express.json(), (req, res) => {
  const signatureHeader = req.headers['x-grapevine-signature'];

  if (!signatureHeader) {
    return res.status(401).send('Missing signature');
  }

  if (!verifyWebhook(req.body, signatureHeader, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Process the webhook
  console.log('Received event:', req.body.event);
  res.status(200).send('OK');
});

Best practices

Verify signatures

Always verify webhook signatures using HMAC-SHA256 to ensure requests are from Grapevine.

Respond quickly

Return a 200 status code within 5 seconds. Process the webhook payload asynchronously.

Handle failures gracefully

Implement your own retry logic for failed processing. Grapevine retries delivery, but you should handle processing failures.

Log events

Log all webhook events with timestamps and payloads for debugging and auditing.