Developers

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:

EventWhen
sale.completedA one-time or subscription purchase is paid.
sale.refundedA purchase is refunded. Revoke access.
subscription.updatedA subscription becomes active, past due, or canceled, or its renewal date changes.
testSent 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 for buyer.email and grant access to product.id.
  • On sale.refunded and subscription.updated with 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.

Start integrating

Create a business account and open Integrations.