Skip to main content
Hopae sends an HTTP POST to your endpoint when a verification or a connection activation changes. Webhooks carry no personal data: fetch the result from userinfo with your app credentials.

Set up

In the Console, open Developers → Webhooks. An app has two endpoints, one per payload format: Every event goes to each enabled endpoint in that endpoint’s format, so with both enabled you receive it on both. Each endpoint has its own Signing Secret, in sandbox and production apps alike.
For qr and push verifications created with the REST API, events follow your status polls. If you stop polling, no terminal event is sent. See REST API Integration.

Events

A verification sends at most one terminal event. There is no expiry event: a verification that has not finished by its expiresAt has expired. See Expiry.

Payload

Every event has the same envelope: id, type, apiVersion (v2), occurredAt, environment (sandbox or production), appId, and data.
  • id is the same on every redelivery of an event. Use it to deduplicate.
  • Verification events always carry data.verificationId, workflowId, connection, and createdAt.
verification.succeeded
activation.activated

Headers

Signing secret

Under Developers → Webhooks, find the endpoint’s Signing Secret:
  • Rotate secret (rotate icon) creates or replaces the secret. Store it on your server, for example as an environment variable.
  • Remove secret (trash icon) stops signing.
An endpoint without a secret sends unsigned deliveries.

Verify the signature

The signature is an HMAC-SHA256, keyed with the endpoint’s secret, over <t>.<raw request body>. Recompute it and compare. Reject deliveries whose t is more than 5 minutes old.
Use the raw request body bytes. Parsing the JSON and serializing it again changes the bytes and breaks the comparison.
In Express, use express.raw({ type: 'application/json' }) on the webhook route and call verifyWebhookSignature({ headers: req.headers, body: req.body.toString('utf8') }, secret).