Skip to Content
DocsAPIWebhook

Webhook

Use webhooks to receive near real-time event notifications from HeyPeers in your system.

1) Configure your webhook

You can configure webhooks in either of these ways:

  • manually in the HeyPeers organization dashboard
  • programmatically via API

Manual setup in HeyPeers dashboard

  1. Sign in to HeyPeers with an organization admin account.
  2. Open your organization and go to the Webhooks settings page.
  3. Add your endpoint URL (must be HTTPS), choose events, and enable webhook delivery.
  4. Save your settings.
  5. Copy the signing secret when it is shown and store it securely in your system.

Note: The signing secret is only shown once when created or regenerated. If lost, use Regenerate Secret.

Configure via API

Endpoint

  • GET: /organizations/:organization_id/webhook
  • POST: /organizations/:organization_id/webhook
  • PATCH: /organizations/:organization_id/webhook

Request Body (POST/PATCH)

{ "webhook": { "url": "https://your-domain.com/webhooks/heypeers", "enabled": true, "events": ["user.registered"] } }

Fields

FieldRequiredDescription
webhook.urlRequired when enabled=trueMust be a valid HTTPS URL.
webhook.enabledEnables/disables event delivery.
webhook.eventsRequired when enabled=trueList of subscribed events.
regenerate_secretOptionalIf present ("1"), rotates the webhook signing secret.

Supported Events

  • user.registered

Example (Create/Update)

curl -X PATCH "https://heypeers.com/api/v2/organizations/{ORG_ID}/webhook" \ -H "Authorization: Bearer {TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "webhook": { "url": "https://your-domain.com/webhooks/heypeers", "enabled": true, "events": ["user.registered"] } }'

Success Response

{ "success": true, "webhook": { "id": 123, "url": "https://your-domain.com/webhooks/heypeers", "enabled": true, "events": ["user.registered"], "secret": "webhook_signing_secret", "created_at": "2026-02-12T15:00:00Z", "updated_at": "2026-02-12T15:05:00Z" }, "available_events": ["user.registered"] }

Error Responses

  • 401 Unauthorized
    • { "error": "Unauthorized Access" } (invalid or missing token)
    • { "error": "Not Authorized" } (organization ID does not match token organization)
  • 422 Unprocessable Entity
    • { "success": false, "errors": [...] }
    • Common cases: non-HTTPS URL, unsupported events, missing URL when enabled, empty event list when enabled

2) What HeyPeers sends to your endpoint

When an event occurs, HeyPeers sends an HTTP POST request to your configured webhook.url.

Request Headers

HeaderDescription
Content-Typeapplication/json
User-AgentHeyPeers Webhook
X-HeyPeers-SignatureHMAC SHA256 signature with prefix sha256=
X-HeyPeers-EventEvent name (for example user.registered)
X-HeyPeers-Event-IdUnique event ID (UUID)

Payload Example (user.registered)

{ "event": "user.registered", "event_id": "3426822d-d9ac-4aa9-8f92-be9f360d2647", "timestamp": "2026-02-12T15:32:22Z", "organization": { "id": 15, "name": "MHA Ohio" }, "user": { "id": 2085, "uuid": "cb230631-ff44-45b8-bdc2-d253a7337eb3", "email": "webhook-test@example.com", "first_name": "Webhook", "last_name": "Test", "created_at": "2026-02-12T15:32:21Z" } }

3) Delivery behavior

  • Delivery method is always HTTP POST.
  • Connection timeout: 5s
  • Read timeout: 10s
  • A delivery is treated as successful only when your endpoint returns 2xx.
  • Failed deliveries are logged by HeyPeers; automatic retry is not currently performed.

4) Verify webhook signature

Compute:

HMAC_SHA256(secret, raw_request_body)

Then compare with X-HeyPeers-Signature (sha256=<digest>).

Important: use the raw request body string exactly as received before JSON parsing.

Next.js (Route Handler) Example

import crypto from 'crypto'; import { NextRequest, NextResponse } from 'next/server'; function safeCompare(a: string, b: string) { const aBuf = Buffer.from(a); const bBuf = Buffer.from(b); if (aBuf.length !== bBuf.length) return false; return crypto.timingSafeEqual(aBuf, bBuf); } export async function POST(req: NextRequest) { const rawBody = await req.text(); const signatureHeader = req.headers.get('x-heypeers-signature') || ''; const secret = process.env.HEYPEERS_WEBHOOK_SECRET || ''; const digest = crypto.createHmac('sha256', secret).update(rawBody).digest('hex'); const expected = `sha256=${digest}`; if (!safeCompare(signatureHeader, expected)) { return NextResponse.json({ success: false, error: 'Invalid signature' }, { status: 401 }); } const payload = JSON.parse(rawBody); // Queue async processing here; return 200 quickly. return NextResponse.json({ success: true, received_event: payload.event }); }

5) Receiver Best Practices

  • Return a 2xx response quickly (do heavy work asynchronously).
  • Treat event_id as an idempotency key to avoid duplicate processing.
  • Enforce HTTPS and IP/network controls in your environment.
  • Rotate your webhook secret immediately if you suspect exposure.

Support

For onboarding, event expansion, or troubleshooting, contact support@heypeers.com with:

  • organization name
  • approximate event timestamp
  • your endpoint URL
  • any error logs from your receiver
Last updated on