UserHero Docs
Integrations

Incoming Webhooks

Receive feedback from external services via HTTP

Incoming Webhooks

Receive feedback from external services like Zapier, GitHub Actions, or any system that can send HTTP requests.

Unlike outgoing webhooks (which send data out when feedback is submitted), incoming webhooks let you send feedback into UserHero from external sources.

Setup

  1. Go to SettingsIntegrations tab
  2. Scroll to Incoming Webhooks
  3. Click Create Incoming Webhook
  4. Enter a name (e.g. "Zapier", "GitHub Actions")
  5. Copy the Webhook URL and Secret — the secret is only shown once

Each webhook gets a unique URL in the format:

https://userhero.co/api/hooks/{slug}

You can optionally assign a default project. If set, all feedback sent to this webhook is routed to that project unless overridden in the request body.

Sending Feedback

Send a POST request to your webhook URL with a JSON body and an HMAC-SHA256 signature.

Request Format

curl -X POST https://userhero.co/api/hooks/{slug} \
  -H "Content-Type: application/json" \
  -H "X-UserHero-Signature: sha256=$SIGNATURE" \
  -d '{
    "message": "Bug report from external tool",
    "category": "bug",
    "rating": 3,
    "userEmail": "user@example.com",
    "tags": ["external", "zapier"],
    "metadata": {
      "source": "zapier",
      "zap_id": "123"
    }
  }'

Payload Fields

FieldTypeRequiredDescription
messagestringYesFeedback text
projectIdstringNoTarget project ID. Required if the webhook has no default project
categorystringNoFeedback category (e.g. bug, feature, question)
ratingnumberNoNumeric rating
userEmailstringNoEmail of the person who submitted the feedback
tagsstring[]NoArray of tags
contextobjectNoArbitrary context object (page URL, browser info, etc.)
metadataobjectNoArbitrary metadata stored with the feedback item

Response

On success:

{
  "success": true,
  "feedbackId": "abc123"
}

On error:

StatusMeaning
400Invalid JSON, missing message, or missing projectId
401Missing or invalid signature
404Webhook not found or disabled
500Server error

Signature Verification

Every request must include an X-UserHero-Signature header. This proves the request comes from someone who knows the webhook secret.

Computing the Signature

Sign the raw JSON body with HMAC-SHA256 using your webhook secret:

const crypto = require('crypto');

const body = JSON.stringify({ message: 'Bug report' });
const signature = crypto
  .createHmac('sha256', 'whsec_your_secret')
  .update(body)
  .digest('hex');

// Send as header:
// X-UserHero-Signature: sha256=<signature>
import hmac, hashlib, json

body = json.dumps({"message": "Bug report"})
signature = hmac.new(
    b"whsec_your_secret",
    body.encode(),
    hashlib.sha256
).hexdigest()

# Send as header:
# X-UserHero-Signature: sha256=<signature>
BODY='{"message":"Bug report"}'
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "whsec_your_secret" | awk '{print $2}')

curl -X POST https://userhero.co/api/hooks/{slug} \
  -H "Content-Type: application/json" \
  -H "X-UserHero-Signature: sha256=$SIGNATURE" \
  -d "$BODY"

The header value can be sha256=<hex> or just <hex>.

Use Cases

Zapier / Make / n8n

Connect any trigger (new form submission, new email, Slack message) to UserHero:

  1. Create an incoming webhook in UserHero
  2. In your automation tool, add an HTTP POST action
  3. Set the URL to your webhook URL
  4. Add the X-UserHero-Signature header with the computed HMAC
  5. Map fields from the trigger to the JSON body

CI/CD Pipelines

Automatically log deployment feedback or test results:

# In your GitHub Actions workflow
- name: Send deployment feedback
  run: |
    BODY='{"message":"Deployed v1.2.3 to production","category":"deployment","tags":["ci","production"]}'
    SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "${{ secrets.USERHERO_WEBHOOK_SECRET }}" | awk '{print $2}')
    curl -X POST ${{ secrets.USERHERO_WEBHOOK_URL }} \
      -H "Content-Type: application/json" \
      -H "X-UserHero-Signature: sha256=$SIG" \
      -d "$BODY"

Custom Applications

Forward feedback from internal tools, support systems, or other products:

const crypto = require('crypto');

async function sendToUserHero(message, metadata) {
  const body = JSON.stringify({ message, metadata });
  const signature = crypto
    .createHmac('sha256', process.env.USERHERO_WEBHOOK_SECRET)
    .update(body)
    .digest('hex');

  const res = await fetch(process.env.USERHERO_WEBHOOK_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-UserHero-Signature': `sha256=${signature}`,
    },
    body,
  });

  return res.json();
}

Managing via REST API

You can also create and manage incoming webhooks programmatically using the REST API:

# List webhooks
curl -H "Authorization: Bearer sk_live_..." \
  "https://userhero.co/api/v1/webhooks?workspaceId=ws_123"

# Create webhook
curl -X POST https://userhero.co/api/v1/webhooks \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"workspaceId":"ws_123","name":"My Webhook","projectId":"proj_456"}'

# Delete webhook
curl -X DELETE "https://userhero.co/api/v1/webhooks/{id}?workspaceId=ws_123" \
  -H "Authorization: Bearer sk_live_..."

On this page