Skip to content

Webhooks

Receive real-time notifications when events occur.

Overview

Webhooks allow you to:

  • Get instant event notifications
  • Automate workflows
  • Sync with external systems
  • Build reactive integrations

Plan Requirement

Webhook access requires a plan that includes API features.

How Webhooks Work

  1. You configure an endpoint URL
  2. Select events to subscribe to
  3. When events occur, we send HTTP POST requests
  4. Your server processes the payload
  5. You respond with 2xx status

Available Events

EventDescription
photo_request.createdNew photo request created
photo_request.first_viewedRequest viewed for the first time
photo_submission.createdPhotos submitted (Permanent Links)
photo_request.submittedOne-time request completed
photo_request.expiredRequest expired without submission
photo_submission.dropbox_syncedPhoto synced to Dropbox with shared link

Creating a Webhook

Steps

  1. Go to Webhooks in the sidebar
  2. Click Create Webhook
  3. Enter a descriptive name
  4. Provide your endpoint URL
  5. Select events to subscribe
  6. Toggle Active (default: on)
  7. Click Create

Endpoint Requirements

RequirementValue
ProtocolHTTPS required
AccessibilityPublic internet
Response2xx status code
Timeout30 seconds max

Private Networks

Private and internal network addresses (localhost, 10.x.x.x, 192.168.x.x) are not allowed.

Webhook Payload

Request Format

http
POST /your-endpoint HTTP/1.1
Host: your-server.com
Content-Type: application/json
X-Webhook-Signature: sha256=abc123...
X-Webhook-ID: wh_123456
X-Webhook-Timestamp: 1609459200

Payload Structure

json
{
  "event": "photo_request.submitted",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "id": "req_abc123",
    "type": "one_time",
    "instructions": "Send photos of the vehicle",
    "photos": [
      {
        "id": "photo_xyz789",
        "url": "https://...",
        "slot_instructions": "Front view",
        "metadata": {
          "gps_lat": 45.1234,
          "gps_lng": 12.5678,
          "captured_at": "2024-01-15T10:28:00Z"
        }
      }
    ],
    "submitted_at": "2024-01-15T10:30:00Z"
  }
}

Signature Verification

Why Verify

Verify webhook signatures to ensure:

  • Request came from Visiono
  • Payload wasn't tampered with
  • Prevent replay attacks

Signature Header

X-Webhook-Signature: sha256=abc123def456...

Verification Steps

php
// PHP example
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$secret = 'your-webhook-secret';

$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}
javascript
// Node.js example
const crypto = require('crypto');

const payload = JSON.stringify(req.body);
const signature = req.headers['x-webhook-signature'];
const secret = process.env.WEBHOOK_SECRET;

const expected = 'sha256=' + crypto
  .createHmac('sha256', secret)
  .update(payload)
  .digest('hex');

if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
  return res.status(401).send('Invalid signature');
}

Managing Webhooks

Test Webhook

Send a test event:

  1. Click Test on the webhook
  2. Confirm the action
  3. Check response status
  4. View in logs if failed

View Logs

See delivery history:

  1. Click Logs on the webhook
  2. View recent deliveries
  3. Check status and response
  4. Debug failures

Log Details

Each log shows:

  • Event type
  • Timestamp
  • Response status
  • Response time
  • Request/response body (for debugging)

Regenerate Secret

Get a new signing secret:

  1. Click Regenerate Secret
  2. Confirm the action
  3. Copy new secret immediately
  4. Update your server

Update Server First

After regenerating, the old secret stops working. Update your verification code before regenerating.

Deactivate Webhook

Temporarily stop receiving events:

  1. Click Deactivate
  2. Confirm the action
  3. Events are no longer sent
  4. Reactivate when ready

Delete Webhook

Permanently remove:

  1. Click Delete
  2. Confirm the action
  3. All logs are deleted

Retry Policy

Automatic Retries

Failed deliveries are retried:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours

Failure Criteria

A delivery fails if:

  • Connection timeout (30s)
  • Non-2xx response
  • Network error
  • SSL error

After Max Retries

If all retries fail:

  • Event is marked as failed
  • Logged for review
  • No further attempts

Best Practices

Endpoint Design

  • Respond quickly (< 5 seconds)
  • Process async if needed
  • Return 2xx immediately
  • Handle idempotency

Error Handling

javascript
// Recommended pattern
app.post('/webhook', async (req, res) => {
  // Verify signature first
  if (!verifySignature(req)) {
    return res.status(401).send('Invalid');
  }

  // Acknowledge immediately
  res.status(200).send('OK');

  // Process async
  processWebhookAsync(req.body);
});

Idempotency

Events may be sent more than once. Handle duplicates:

javascript
// Check if already processed
const eventId = req.headers['x-webhook-id'];
if (await isProcessed(eventId)) {
  return res.status(200).send('Already processed');
}

// Process and mark as handled
await processEvent(req.body);
await markProcessed(eventId);

Monitoring

  • Log all incoming webhooks
  • Alert on failures
  • Monitor response times
  • Track event volumes

Troubleshooting

Not Receiving Events

  1. Verify webhook is active
  2. Check endpoint URL is correct
  3. Ensure HTTPS is working
  4. Verify server is accessible
  5. Check selected events

Signature Mismatch

  1. Use the correct secret
  2. Compare full payload (not parsed)
  3. Check for encoding issues
  4. Verify HMAC algorithm (SHA256)

Timeouts

  1. Reduce processing time
  2. Acknowledge immediately
  3. Process asynchronously
  4. Check server resources

View Failed Deliveries

  1. Go to webhook logs
  2. Filter by status (failed)
  3. View request/response details
  4. Fix and retest

Webhook Limits

Per Plan

PlanMax Webhooks
Professional5 webhooks
EnterpriseUnlimited

Rate Limits

LimitValue
Events per minute100
Payload size1 MB

Professional Photo Documentation Platform