#LinkCodeDOCS
Docs/Conversion API

Server attribution

Controlled rollout

Report conversions from your server.

Use scoped, hashed server keys, idempotency, optional HMAC signatures and replay protection to submit merchant-asserted affiliate conversions.

01

Create a conversion event

POST/api/v1/affiliate/conversionsControlled rollout
PropertyTypeDescription
program_idUUIDrequired

Private affiliate program receiving the event.

eventstringrequired

Must match the rewarded event.

click_idUUID

Explicit LinkCode click attribution. Required unless promotion_code is supplied.

promotion_codestring

Fallback explicit attribution.

external_conversion_idstringrequired

Unique merchant order/conversion reference.

amount_minorintegerrequired

Eligible monetary base in minor units.

payment_statusenumrequired

unknown, pending, paid, refunded, partially_refunded or chargeback.

occurred_atISO-8601required

Authoritative event time with timezone.

curl --request POST https://app.linkcode.co/api/v1/affiliate/conversions \
  --header "Authorization: Bearer $LINKCODE_API_KEY" \
  --header "Idempotency-Key: ORDER-123:purchase" \
  --header "Content-Type: application/json" \
  --data '{"program_id":"PROGRAM_UUID","event":"purchase","click_id":"CLICK_UUID","external_conversion_id":"ORDER-123","amount_minor":14900,"currency":"CAD","payment_status":"paid","occurred_at":"2026-07-28T15:00:00Z","test":false}'
02

Authentication and scopes

API keys are shown once. LinkCode stores only the SHA-256 hash and a short prefix. Use the affiliate:conversions:write scope and restrict a key to one program whenever possible.

03

Optional or required HMAC

The exact raw body is signed with the API key. LinkCode rejects malformed signatures and timestamps outside the five-minute replay window.

const timestamp = Math.floor(Date.now() / 1000).toString();
const signature = createHmac("sha256", process.env.LINKCODE_API_KEY)
  .update(`${timestamp}.${rawBody}`)
  .digest("hex");

headers["x-linkcode-timestamp"] = timestamp;
headers["x-linkcode-signature"] = `sha256=${signature}`;
04

Idempotency and deduplication

Send a stable Idempotency-Key for every logical conversion. The database also enforces workspace + source + event + external_conversion_id uniqueness, so a double confirmation-page reload cannot double commission. Reusing a key or conversion ID with a different payload returns 409 idempotency_conflict.

05

Platform guidance

  • Stripe Checkout — report from a verified webhook after signature validation; pass lc_click_id through metadata.
  • Shopify — preserve lc_click_id in cart/order attributes and report from the server or approved webhook.
  • WooCommerce — store lc_click_id on the order and report after the relevant order status transition.
  • HTML/React — use the pixel only for pending browser-reported events.
  • Custom backends — use server API keys, idempotency and HMAC.
06

Test without financial side effects

Set test=true. Test events exercise validation and deduplication but never create production statistics, a payable commission or a settlement item.

07

Troubleshooting

PropertyTypeDescription
401 unauthorizedauth

Missing, invalid, revoked or expired key.

403 insufficient_scopescope

Key does not include affiliate:conversions:write or belongs to another program.

422 validation_failedpayload

Invalid type, missing attribution or non-integer amount.

409 idempotency_conflictdeduplication

A key or conversion ID was reused with a different payload.

429 rate_limitedretry

Retry with exponential backoff and jitter.

duplicateidempotent success

The logical event was already accepted; do not create a new order ID.