This quickstart shows the minimum integration loop most developers need:
  1. Authenticate from your backend.
  2. Create a user in your tenant.
  3. Receive the webhook that confirms the event.
  4. Verify the webhook signature.

Before you start

You need these values from the dashboard:
ZQUENCE_PUBLIC_KEY=pk_test_...
ZQUENCE_SECRET_KEY=sk_test_...
ZQUENCE_WEBHOOK_SECRET=whsec_test_...
ZQUENCE_BASE_URL=https://api.zquence.com/v1
Keep ZQUENCE_SECRET_KEY and ZQUENCE_WEBHOOK_SECRET on your backend only. Never ship them to a browser or mobile app.

1. Check your keys

Call your tenant profile endpoint first. It is the fastest way to confirm that your base URL and keys are correct.
curl "$ZQUENCE_BASE_URL/tenants/me" \
  -H "x-api-key: $ZQUENCE_PUBLIC_KEY" \
  -H "x-api-secret: $ZQUENCE_SECRET_KEY"
Expected response:
{
  "tenantId": "tnt_01HX3Z8MQW...",
  "name": "Acme Escrow",
  "status": "active"
}

2. Create a user

Users are the starting point for KYC and transactions.
curl "$ZQUENCE_BASE_URL/tenants/add-user" \
  -H "x-api-key: $ZQUENCE_PUBLIC_KEY" \
  -H "x-api-secret: $ZQUENCE_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: user_ada_example_com" \
  -d '{
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "phone": "+14155552671"
  }'
Store the returned id in your system. You will use it when starting KYC or creating transactions.

3. Add your webhook URL

In the dashboard, go to Developers -> Webhooks and add a public URL from your backend, for example:
https://api.example.com/webhooks/zquence
For local development, use a tunnel:
ngrok http 3000
Subscribe to tenant.users.invite for this quickstart. Later, subscribe to the event families your product needs, such as kyc.* or transaction.*.

4. Verify incoming webhooks

Zquence sends signed POST requests to your webhook URL:
POST /webhooks/zquence HTTP/1.1
X-Zquence-Event: tenant.users.invite
X-Zquence-Webhook-Id: evt_01HX3ZC...
zquence-signature: t=1745311982,v1=b8a7e1c4...
Your handler must verify the signature before trusting the event.
Node.js
import express from "express";
import crypto from "crypto";

const app = express();

app.post("/webhooks/zquence", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.headers["zquence-signature"] as string;
  const parts = Object.fromEntries(signature.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", process.env.ZQUENCE_WEBHOOK_SECRET!)
    .update(`${parts.t}.${req.body.toString("utf8")}`)
    .digest("hex");

  const expectedBuffer = Buffer.from(expected);
  const receivedBuffer = Buffer.from(parts.v1 ?? "");

  if (
    expectedBuffer.length !== receivedBuffer.length ||
    !crypto.timingSafeEqual(expectedBuffer, receivedBuffer)
  ) {
    return res.status(400).send("Invalid signature");
  }

  const event = JSON.parse(req.body.toString("utf8"));
  console.log("Received", event.type);
  res.sendStatus(200);
});
For more framework examples, see Verify webhooks.

Next steps

Add an API helper

Centralize auth headers, JSON parsing, and error handling.

Start KYC

Create a verification session and handle the result webhook.

Review webhooks

Learn delivery rules, retries, and event handling.

Browse endpoints

Look up exact request and response shapes.