Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.nudj.cx/llms.txt

Use this file to discover all available pages before exploring further.

Nudj emits HTTP POST webhooks for domain events your downstream systems care about — reward earned, reward delivered, subscription updates, Shopify-driven achievement triggers, and more. This page covers the protocol — signatures, retries, and endpoint implementation. For the full list of emitted events, see the events catalog. To debug a delivery, see the delivery logs page.

Configuring a webhook

Webhook configurations are managed via the Admin API under /api/v2/admin/webhooks/configs. Each config specifies:
  • url — your endpoint. Must be HTTPS in production.
  • events — list of event types the config subscribes to. See Webhook Events Catalog.
  • secret — used to compute the HMAC signature on each delivery.
  • active — pause or resume deliveries without deleting the config.
Example config:
{
  "url": "https://your-api.example.com/webhooks/nudj",
  "events": ["reward.earned", "reward.delivered", "reward.delivery_failed"],
  "secret": "whsec_...",
  "active": true
}

Request shape

Every delivery is an HTTP POST with a JSON body:
{
  "event": "reward.earned",
  "timestamp": "2026-04-17T14:30:00.000Z",
  "data": {
    "reward": { "id": "reward_abc123", "type": "asset", "value": 100, "name": "Weekly Bonus" },
    "user": { "id": "user_xyz789", "externalUserId": "customer_456" },
    "challenge": { "id": "challenge_def456", "name": "Weekly Shopping Challenge" }
  }
}
Headers:
  • Content-Type: application/json
  • X-Nudj-Signature: sha256=<hex> — HMAC-SHA256 of the raw body, signed with your configured secret.
  • X-Nudj-Event — convenience header mirroring event in the payload.
  • X-Nudj-Delivery-Id — unique per delivery attempt, stable across retries. Use this to idempotency-key your processing.

Signature verification

Compute HMAC-SHA256 over the raw request body using your configured secret, then compare against the value after sha256= in the X-Nudj-Signature header. Use a timing-safe comparison.
import express from "express";
import crypto from "crypto";

const app = express();

// Raw body is required for signature verification
app.post(
  "/webhooks/nudj",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = (req.headers["x-nudj-signature"] || "").replace(
      "sha256=",
      ""
    );
    const expected = crypto
      .createHmac("sha256", process.env.NUDJ_WEBHOOK_SECRET)
      .update(req.body)
      .digest("hex");

    if (
      signature.length !== expected.length ||
      !crypto.timingSafeEqual(
        Buffer.from(signature, "hex"),
        Buffer.from(expected, "hex")
      )
    ) {
      return res.status(401).send("invalid signature");
    }

    const event = JSON.parse(req.body.toString("utf8"));
    // process event here, ideally async via a queue
    res.status(200).send("ok");
  }
);
Verify the signature against the raw request body before parsing as JSON. Re-serialising the parsed body will produce a different byte sequence and the HMAC will never match.

Response and retry semantics

  • Respond with 2xx within 30 seconds to acknowledge receipt.
  • Any 5xx response, connection failure, or timeout triggers a retry.
  • Retries use exponential backoff.
  • A delivery that fails every retry attempt is marked failed in the delivery logs.

Idempotency

Process events idempotently. The X-Nudj-Delivery-Id header is stable across retries of the same delivery attempt, and the payload’s data.*.id fields identify the underlying entity. Storing processed delivery IDs in your side lets you no-op duplicates safely.

Local development

Use a tunnel such as ngrok or cloudflared to expose your local endpoint:
ngrok http 3000
# paste the HTTPS forwarding URL into your webhook config's `url`

Webhook events catalog

Reference of every event type Nudj emits, with example payloads.

Webhook delivery logs

Inspect retry state, bodies, and failures via the Admin API.

Reward integration

Higher-level integration patterns for getting rewards to downstream systems.
Last reviewed: 2026-04