Connecting your tracking link

How a partner's tracking link works end to end, where affiliates get it, and how to wire up postbacks so conversions land correctly in the dashboard.

How it works Concept

Every offer + affiliate pair has its own unique tracking link:

https://smthprj.xyz/t/<slug>

When someone opens that link:

  1. The server records a click and generates a unique click_id, along with IP, user-agent, and referer.
  2. The link's click count increases by one — visible immediately to both the partner and the affiliate.
  3. The visitor is 302-redirected to the offer's destination URL, with these params appended: ?click_id=...&offer_id=...&affiliate_id=...

Later, when a real conversion happens on the partner's site (a sale, lead, signup), the partner's site must send a postback — a server-side request carrying that same click_id plus the partner's api_key — so the conversion is authenticated and credited to the right affiliate.

How a click is counted

A click is recorded the moment a GET request hits /t/<slug> — i.e. at the moment of the redirect itself, before the visitor even sees the partner's site. One visit = one click.

If the offer isn't active (paused, or not yet approved by an admin), the link won't record a click — it just sends the visitor to the Something Project homepage instead.

Setting up a postback

A postback is a server-to-server request your site, CRM, or checkout sends to us at the moment of conversion. The base template a partner sees and copies from Settings → Global postback URL:

https://somethingproject.com/api/postback?api_key={api_key}&click_id={click_id}&status={status}&amount={amount}&commission={commission}
Your API key is required. Every postback must include your partner api_key — either as a query/body parameter (api_key=…) or the X-API-Key header. Find it under Settings → API & Webhooks. The server checks that the key belongs to the partner who owns the offer; a missing key returns 401 api_key_required, a wrong key returns 403 invalid_api_key. This stops anyone from spoofing conversions with a guessed click_id. Keep the key secret; regenerating it in Settings invalidates the old one immediately.
Common mistake: the URL must include /api/postback, not just /postback. Without /api/, the request will return a 200 response but the conversion will not be recorded — that path doesn't process anything.

Replace {click_id}, {status}, etc. with the actual macros from your platform (Keitaro, a landing page builder, your own backend), or with real values if you're calling it directly from code.

Idempotent by design. A conversion is keyed on the pair (click_id, transaction_id). Sending the same pair twice is safe — it returns ok and is not double-counted. To record several conversions from a single click (e.g. an upsell), send each with a distinct transaction_id. If you omit transaction_id, it defaults to the click_id — meaning a second postback for the same click with no transaction id is treated as a duplicate and ignored.

Postback parameters

ParamRequiredDescription
api_key (or X-API-Key header)YesYour partner API key from Settings → API & Webhooks. Must belong to the offer's owner
click_id (or cid)YesClick identifier from the redirect params on the landing page
statusNoConversion status. Defaults to confirmed. See statuses below — it decides whether the conversion counts toward earnings.
amountNoOrder/sale amount. Defaults to 0.
commissionNoAffiliate commission for this conversion. Defaults to 0.
currencyNoCurrency code, e.g. USD. Defaults to USD; stored uppercased.
transaction_id (or txn, order_id)NoYour own order/transaction ID, for reconciliation. Defaults to the click_id.

Both GET and POST are supported. Parameter names are read identically from the query string or the request body.

Conversion statuses & earnings

The status you send determines whether the conversion contributes to an affiliate's earned balance:

StatusCounts toward earnings?
confirmed · approved · paidYes
pendingNo — shown, awaiting confirmation
rejected (or any other value)No

Every conversion you send still appears in the partner's Conversions list and in the total/pending counters regardless of status — but only confirmed/approved/paid roll up into the affiliate's earned commission.

Status is final at first insert. A conversion is written once per (click_id, transaction_id) and is not updated by later postbacks for the same pair — re-posting a pending conversion as confirmed with the same transaction_id is ignored, so it stays pending and earns nothing. Send the status you actually want recorded. If you use a hold/approval period, send the postback only once the conversion is final (or send distinct transaction_ids for genuinely separate events).

Integration examples

Direct call from your backend (Node.js)

await fetch(
  "https://somethingproject.com/api/postback" +
  "?api_key=" + SOMETHING_API_KEY +   // from Settings → API & Webhooks
  "&click_id=" + clickId +
  "&status=confirmed" +
  "&amount=" + orderAmount +
  "&commission=" + commissionAmount +
  "¤cy=USD"
);

// Or pass the key as a header instead of a query param:
await fetch("https://somethingproject.com/api/postback?click_id=" + clickId + "&status=confirmed", {
  method: "POST",
  headers: { "X-API-Key": SOMETHING_API_KEY },
});

cURL (for testing or a server script)

curl "https://somethingproject.com/api/postback?api_key=sp_live_xxx&click_id=clk_xxx&status=confirmed&amount=99&commission=10"

Webhook from a payment provider / CRM

If your payment provider or CRM supports outgoing webhooks on payment, point it at the same URL with the real click_id substituted in. You'll need to persist that click_id on your side at the moment the visitor lands (e.g. a hidden form field or localStorage) and carry it through to the order.

Test your setup Recommended

1

Copy your tracking link from My Offers and open it in a browser.

2

Confirm you land on the real offer page and the address bar shows a click_id.

3

Copy that click_id, grab your api_key from Settings → API & Webhooks, and send a test postback (browser address bar or curl):

https://somethingproject.com/api/postback?api_key=YOUR_API_KEY&click_id=YOUR_CLICK_ID&status=confirmed&amount=10&commission=1
4

Check the Conversions section in the dashboard — the test conversion should show up immediately.

Troubleshooting

SymptomLikely cause
Clicks aren't increasingWrong link was used (e.g. the landing page URL was copied instead of the /t/... link), or the offer is inactive
Postback returns 200 but no conversion appearsThe URL is missing /api/ before postback — the request is hitting the wrong path
Postback returns api_key_requiredNo api_key parameter (or X-API-Key header) was sent. Add your key from Settings
Postback returns invalid_api_keyThe key is wrong, was regenerated, or doesn't belong to the partner who owns that offer
Postback returns click_not_foundThe click_id is wrong, stale, or was never captured on your side at the moment of the click
Postback returns click_id_requiredThe click_id / cid parameter is missing or empty in the request
Conversion shows but earnings stay at 0Its status is pending/rejected — only confirmed/approved/paid count. Status is fixed at first insert and won't change on re-post
Second conversion from the same click doesn't appearSame (click_id, transaction_id) pair was reused — it's deduplicated. Use a distinct transaction_id
Affiliate can't apply (offer_not_live)The offer isn't active yet — it still needs admin approval before it appears in the marketplace
The link redirects to the Something Project homepageThe offer is paused/not yet approved, or the affiliate's application hasn't been approved by the partner