Integration guide

Content Pay credits creators only for purchases your website reports. A redirect link on its own cannot see what happens at your checkout — your server must send a signed event for each qualifying order.

1. Register your website

In your business dashboard open My Websites → Register a website, confirm ownership, then run the initial compatibility checks with a product URL.

2. Configure the integration

An administrator issues test credentials first: a key ID and a signing secret. Reveal the secret from your website page and store it as a server-side environment variable. Never place it in browser code. Once testing passes, live credentials are issued and tracking is activated.

3. Keep the referral ID

When a shopper clicks a creator's link, Content Pay redirects them to your product page with a cp_ref query parameter:

https://shop.example.com/products/product-one?cp_ref=7b1e0c3a-5d2f-4f8e-9a51-2a0b7c4d9e10

Save cp_ref (for example in a first-party cookie or the cart/session) and attach it to the order. If several referral IDs arrive, keep the most recent one — Content Pay applies last-click attribution within each product's attribution window.

4. Send a purchase event

After the order is confirmed (payment captured), POST a JSON event from your server:

POST /api/public/v1/events
Content-Type: application/json
X-ContentPay-Key: <key ID>
X-ContentPay-Timestamp: 1767225600
X-ContentPay-Signature: <hex HMAC-SHA256>

{
  "event_id": "evt_100045_paid",
  "website_id": "<your website ID>",
  "external_order_id": "100045",
  "referral_id": "7b1e0c3a-5d2f-4f8e-9a51-2a0b7c4d9e10",
  "order_status": "completed",
  "currency": "USD",
  "order_value": 89.00,
  "purchased_at": "2026-10-24T10:15:00Z",
  "line_items": [
    { "product_id": "<Content Pay product ID>", "amount": 89.00, "quantity": 1 }
  ]
}

Send events to your Content Pay site address, for example https://your-content-pay-domain/api/public/v1/events.

Required fields

  • event_id — unique per event. Re-sending the same ID is safely ignored.
  • website_id — must match the credentials used.
  • external_order_id — your order number. One commission per order and product, ever.
  • referral_id — the saved cp_ref value (omit if none).
  • order_status — completed, paid, pending, failed, refunded, cancelled or chargeback.
  • currency (3-letter code) and order_value — the commission-eligible value, excluding tax and shipping if your terms say so.
  • purchased_at — ISO 8601 time. Optional; defaults to the time received.
  • line_items — optional. Use Content Pay product IDs for reliable multi-product attribution.

Commissions are always calculated by Content Pay using the product's configured rules — never from values in the request.

Authentication & signatures

Compute HMAC-SHA256(signing_secret, timestamp + "." + raw_body) as lowercase hex. The timestamp is Unix seconds and must be within 5 minutes of our clock.

// Node.js
import crypto from "node:crypto";
const body = JSON.stringify(event);
const ts = Math.floor(Date.now() / 1000).toString();
const sig = crypto.createHmac("sha256", process.env.CONTENT_PAY_SECRET)
  .update(`${ts}.${body}`).digest("hex");
await fetch(url, { method: "POST", body, headers: {
  "content-type": "application/json",
  "x-contentpay-key": process.env.CONTENT_PAY_KEY_ID,
  "x-contentpay-timestamp": ts,
  "x-contentpay-signature": sig,
}});
# PHP
$ts = (string) time();
$sig = hash_hmac('sha256', $ts . '.' . $body, getenv('CONTENT_PAY_SECRET'));

Refunds & cancellations

Send a new event (new event_id, same external_order_id) with order_status set to refunded, cancelled or chargeback. The related commission is reversed according to the product's refund rule, and the change is kept in a history. Failed and pending orders never create commissions.

Testing with sandbox orders

Use your test credentials. Test events never appear in live totals. To complete the compatibility checklist, send:

  1. A completed test order with a referral_id from a real click, or a sandbox ID starting with cp_test_.
  2. The exact same event again (same event_id) — it must come back as a duplicate.
  3. A cancelled test order — it must not create a commission.

Then press Request approval on your website page.

Responses

200 { "ok": true, "event_id": "…", "event_type": "purchase", "attribution": "attributed", "commissions_created": 1, "commissions_reversed": 0, "mode": "test" }
200 { "ok": true, "duplicate": true, "mode": "live" }

Common errors

  • 401 missing_auth_headers — one of the three headers is missing.
  • 401 invalid_credentials — unknown or revoked key ID.
  • 401 invalid_signature — wrong secret, body changed after signing, or clock skew over 5 minutes.
  • 422 validation_failed — see details for the field.
  • 403 website_mismatch — website_id doesn't match the key.
  • 409 tracking_not_active — live events are refused until an administrator activates tracking.
  • 429 rate_limited — slow down and retry with the same event_id.

Every request appears under Integration health on your website page.