Connect your product
When a buyer pays, Power Vibe Sales needs to tell your system to grant access. Two mechanisms do that: a signed fulfillment webhook we send you, and an entitlement API you can call to verify a buyer. Both use one API key and one signing secret, generated in your dashboard under Integrations.
Get your credentials
Sign in as a business, open Integrations, and:
- Click Generate API key. Copy it once; it is shown only at creation. Rotating it invalidates the old key.
- Set your webhook endpoint URL. Saving it generates a signing secret, shown in full on the page.
- Use Send test event to fire a sample payload at your endpoint, and watch it in the deliveries table.
Fulfillment webhook
We POST JSON to your endpoint on these events:
| Event | When |
|---|---|
sale.completed | A one-time or subscription purchase is paid. |
sale.refunded | A purchase is refunded. Revoke access. |
subscription.updated | A subscription becomes active, past due, or canceled, or its renewal date changes. |
test | Sent by the "Send test event" button. |
Payload
{
"id": "evt_9c1e...",
"type": "sale.completed",
"createdAt": "2026-08-28T14:01:33.000Z",
"data": {
"saleId": "021c06a1-7c2b-4227-8afb-79288a223f52",
"product": { "id": "6660...", "name": "NEXUS AI", "billingType": "ONE_TIME" },
"buyer": { "email": "buyer@example.com", "name": "Sam Buyer" },
"quantity": 1,
"amount": 29,
"currency": "USD",
"salesCode": "PVS-125215",
"subscription": null
}
}
Verify the signature
Every request carries x-pvs-signature: sha256=<hex>, an HMAC SHA256 of the raw request body using your signing secret. Also sent: x-pvs-event-id and x-pvs-event-type. Respond with a 2xx within 8 seconds. Non 2xx or a timeout is retried 3 times, then daily for 24 hours; you can also resend from the dashboard.
import crypto from "node:crypto";
app.post("/webhooks/powervibe", express.raw({ type: "application/json" }), (req, res) => {
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.PVS_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
const got = req.get("x-pvs-signature") || "";
if (got.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
return res.status(400).send("bad signature");
}
const event = JSON.parse(req.body.toString());
// grant, revoke, or update access for event.data.buyer.email
res.sendStatus(200);
});
Entitlement API
Check what a buyer is entitled to, by email. Use it to gate access when someone shows up without a fresh webhook, or to reconcile.
curl -H "Authorization: Bearer $PVS_API_KEY" \
"https://vibe.nexusai.run/api/v1/entitlements?email=buyer@example.com"
{
"entitlements": [
{
"type": "one_time",
"productId": "6660...",
"productName": "NEXUS AI",
"status": "active",
"saleId": "021c06a1-...",
"purchasedAt": "2026-08-28T14:01:33.000Z"
},
{
"type": "subscription",
"productId": "7a2b...",
"productName": "Growth Plan",
"status": "active",
"subscriptionId": "sub_1U9...",
"currentPeriodEnd": "2026-09-28T00:00:00.000Z",
"saleId": "8c4d-...",
"purchasedAt": "2026-08-10T09:00:00.000Z"
}
]
}
An empty array means no active entitlement for that email under your account. A missing or wrong key returns 401. The endpoint is rate limited to 120 requests per minute per key.
Recommended flow
- On
sale.completed, create or link an account forbuyer.emailand grant access toproduct.id. - On
sale.refundedandsubscription.updatedwith a non active status, revoke. - When a buyer visits your product and you cannot identify them, ask for their email and call the entitlement API.