This quickstart shows the minimum integration loop most developers need:
- Authenticate from your backend.
- Create a user in your tenant.
- Receive the webhook that confirms the event.
- 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:
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.
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.