UserHero Docs
Integrations

Webhooks

Send feedback to custom endpoints

Webhooks

Send feedback data to any HTTP endpoint for custom integrations.

Setup

  1. Go to project SettingsIntegrations
  2. Find Webhooks and click "Add Webhook"
  3. Enter your webhook URL
  4. Optionally add a secret for verification
  5. Test the webhook
  6. Save

Webhook Payload

When feedback is submitted, we send a POST request:

{
  "event": "feedback.created",
  "timestamp": "2026-01-07T15:30:00Z",
  "data": {
    "id": "fb_abc123",
    "projectId": "proj_xyz",
    "widgetId": "w_default",
    "message": "The export button doesn't work",
    "category": "bug",
    "rating": 2,
    "status": "new",
    "screenshotUrl": "https://storage.userhero.co/...",
    "context": {
      "pageUrl": "/dashboard/reports",
      "referrer": "/dashboard",
      "browser": "Chrome",
      "browserVersion": "120",
      "os": "macOS",
      "deviceType": "desktop",
      "viewport": {
        "width": 1920,
        "height": 1080
      },
      "timezone": "America/New_York",
      "locale": "en-US",
      "country": "US"
    },
    "metadata": {
      "userId": "user_123",
      "plan": "pro",
      "company": "Acme Inc"
    },
    "createdAt": "2026-01-07T15:30:00Z"
  }
}

Verifying Webhooks

We sign webhook payloads with your secret. Verify the signature to ensure authenticity.

Signature Header

X-UserHero-Signature: sha256=abc123...

Verification Code

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler
app.post('/webhook/userhero', (req, res) => {
  const signature = req.headers['x-userhero-signature'];
  const isValid = verifyWebhook(
    JSON.stringify(req.body),
    signature,
    process.env.USERHERO_WEBHOOK_SECRET
  );
  
  if (!isValid) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the webhook
  const { event, data } = req.body;
  console.log('Received:', event, data);
  
  res.status(200).send('OK');
});

Event Types

EventDescription
feedback.createdNew feedback submitted
feedback.updatedFeedback status changed

Response Requirements

Your endpoint should:

  • Return a 2xx status code within 30 seconds
  • Return quickly (process asynchronously if needed)

Retry Policy

If your endpoint fails, we retry:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours
5th retry24 hours

After 5 failed attempts, the webhook is marked as failing and you'll receive an email notification.

Testing Webhooks

Test Button

  1. Go to your webhook configuration
  2. Click "Send Test"
  3. Check your endpoint received the test payload

Local Development

For local testing, use a tunnel service:

# Using ngrok
ngrok http 3000

# Then use the ngrok URL in your webhook config
https://abc123.ngrok.io/webhook/userhero

Use Cases

Zapier-style Automation

Connect to no-code tools:

UserHero → Webhook → Zapier → Google Sheets

Custom Dashboard

Store feedback in your own database:

app.post('/webhook/userhero', async (req, res) => {
  const { data } = req.body;
  
  await db.feedback.create({
    externalId: data.id,
    message: data.message,
    userId: data.metadata?.userId,
    createdAt: data.createdAt,
  });
  
  res.status(200).send('OK');
});

Issue Tracker Integration

Create tickets in your custom system:

app.post('/webhook/userhero', async (req, res) => {
  const { data } = req.body;
  
  if (data.category === 'bug') {
    await issueTracker.createTicket({
      title: `Bug Report: ${data.message.slice(0, 50)}...`,
      description: data.message,
      priority: data.rating <= 2 ? 'high' : 'normal',
      metadata: { userheroId: data.id },
    });
  }
  
  res.status(200).send('OK');
});

Managing Webhooks

Disable Temporarily

  1. Go to webhook settings
  2. Toggle "Enabled" off
  3. Webhook stops receiving events

Delete

  1. Go to webhook settings
  2. Click "Delete"
  3. Confirm deletion

Next Steps

On this page