Skip to Content
NovoDIDNovoDIDdocumentation
Ready-to-use integrations

Webhooks: a secure Node.js receiver

Start with minimal permissions and downloadable examples. The files contain no credentials and do not buy numbers or send SMS. Configure secrets in your integration’s private environment.

Download the executable receiver. It verifies signatures, rejects old replays and persists an SQLite inbox before acknowledgement. Requires Node.js 24 or later, with no additional packages.

Setup

  1. Set NOVODID_WEBHOOK_SECRET in a secret manager or private environment file. Use the webhook signing secret, not an API token.
  2. Set NOVODID_WEBHOOK_DB to a file on private persistent storage; default: ./data/events.sqlite. PORT defaults to 8787.
  3. Run the file with Node.js. Place an HTTPS reverse proxy in front and expose /webhook.
  4. Register that HTTPS URL in Desenvolvedores → Webhooks and select the necessary events. The platform rejects localhost, private networks and redirects as destinations.
  5. Use the dashboard test and inspect deliveries. The receiver returns 202 only after persistence.

What it verifies

  • HMAC-SHA256 of timestamp + dot + raw body, compared in constant time against X-Novodid-Signature.
  • X-Novodid-Timestamp within five minutes. Keep your server clock synchronized.
  • A maximum 256 KiB body, version v1 and a known event type.
  • Deduplication by event id, not attempt/delivery id. The same id with different content is refused.

The inbox table stores JSON, type and pending status. The example receives and persists; implement your own separate worker to process pending rows idempotently. Mark processed only after successful business processing. Do not assume ordering or exactly-once delivery.

Security and maintenance

Payloads may include personal data and SMS. Restrict storage, backups and access, and define retention. Do not commit the database. When rotating the secret, update the receiver environment and restart it. Preserve the database across restarts. Never put tokens, secrets, full bodies or signatures in public logs.

401 indicates a signature/clock issue; 413, excessive size; 409, an id conflict; 503, persistence failure. Inspect dashboard deliveries before retrying. The platform allows eight seconds per delivery; acknowledge promptly after storage and leave expensive work to the worker. See the API guide for payloads, events and retries.

On this page