API version v1

PrizeNest Developer Documentation

Signed server-to-server purchase and refund events for approved partners. API keys stay separate in the partner dashboard.

Manage API Keys

Quickstart

Send a signed TEST purchase, then a matching refund.

Follow this sequence from the partner portal. TEST requests validate authentication, schemas, rules, idempotency, and logs without changing live financial or customer balances.

  1. 1Create or select an integrationOpen
  2. 2Generate a TEST API keyOpen
  3. 3Store the raw secret securelyOpen
  4. 4Create an earning ruleOpen
  5. 5Add required test funding if applicableOpen
  6. 6Build a signed purchase requestOpen
  7. 7Send a TEST purchaseOpen
  8. 8Inspect the responseOpen
  9. 9Send a matching refundOpen
  10. 10Verify integrationOpen
  11. 11Request or complete go-liveOpen
  12. 12Generate LIVE credentials when authorizedOpen

Request signing

Hash the exact raw JSON body with SHA-256. Build a five-line canonical string using version v1, uppercase HTTP method, pathname, timestamp, and body hash. Sign that string with HMAC-SHA256 and send the result as sha256=<hex digest>.

Canonical format
v1
POST
/api/v1/partner/purchases
<timestamp>
<sha256 body hash>
Node.js signed purchase
import crypto from "node:crypto";

// PRIZENEST_BASE_URL=https://www.prizenest.org for both TEST and LIVE keys.
const body = "{\n  \"externalOrderId\": \"ORDER-10052\",\n  \"customer\": {\n    \"email\": \"customer@example.com\",\n    \"phone\": \"+17185551234\"\n  },\n  \"order\": {\n    \"subtotalCents\": 7500,\n    \"currency\": \"USD\"\n  },\n  \"occurredAt\": \"2026-08-24T14:15:00.000Z\",\n  \"metadata\": {\n    \"channel\": \"online\"\n  }\n}";
const path = "/api/v1/partner/purchases";
const timestamp = String(Math.floor(Date.now() / 1000));
const bodyHash = crypto.createHash("sha256").update(body).digest("hex");
const canonical = ["v1", "POST", path, timestamp, bodyHash].join("\n");
const signature =
  "sha256=" +
  crypto.createHmac("sha256", process.env.PRIZENEST_SECRET).update(canonical).digest("hex");

const response = await fetch(`${process.env.PRIZENEST_BASE_URL}${path}`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-PrizeNest-Key": process.env.PRIZENEST_KEY,
    "X-PrizeNest-Timestamp": timestamp,
    "X-PrizeNest-Signature": signature,
    "Idempotency-Key": "ORDER-10052",
  },
  body,
});

const result = await response.json();
if (!response.ok) {
  throw new Error(`${result.error?.code}: ${result.error?.message}`);
}

Testing

Purchase payload
{
  "externalOrderId": "ORDER-10052",
  "customer": {
    "email": "customer@example.com",
    "phone": "+17185551234"
  },
  "order": {
    "subtotalCents": 7500,
    "currency": "USD"
  },
  "occurredAt": "2026-08-24T14:15:00.000Z",
  "metadata": {
    "channel": "online"
  }
}
Refund payload
{
  "externalOrderId": "ORDER-10052",
  "externalRefundId": "REFUND-9001",
  "reason": "Customer cancelled before fulfillment.",
  "occurredAt": "2026-08-24T15:20:00.000Z"
}

Going Live

Go-live is only appropriate after approval, profile completion, active earning rules, sufficient funding, an integration, and test purchase/refund evidence. LIVE requests create real financial, reward, point, and inventory-adjacent obligations.

Check readiness