Skip to main content

Conversions API

Report conversions to Affilync via server-side API calls, JavaScript pixel, postback URLs, or platform integrations. All conversion methods support deduplication via order_id and automatic fraud detection.

Overview

Affilync provides two conversion tracking pipelines:

  1. Public Pixel/API (/api/track/*) — Merchant websites, tracking pixels, third-party networks
  2. E-commerce Integrations (/api/conversions/*) — WooCommerce, Shopify, TikTok Shop (authenticated)

All public endpoints require HMAC-SHA256 signature verification in production.

Server-Side Conversion (Direct Pixel)

The recommended approach for accurate, fraud-resistant attribution.

curl -X POST https://api.affilync.com/api/track/conversion \
-H "Content-Type: application/json" \
-H "X-Affilync-Signature: {signature}" \
-d '{
"click_id": "550e8400-e29b-41d4-a716-446655440000",
"transaction_id": "txn_abc123xyz",
"order_id": "order_456",
"order_value": 99.99,
"currency": "USD",
"conversion_type": "sale",
"customer_email": "[email protected]",
"products": [
{
"sku": "PROD-001",
"name": "Widget",
"quantity": 2,
"price": 49.99
}
]
}'

Signature Computation

HMAC signatures protect against unauthorized conversion reporting. Compute the signature as:

HMAC-SHA256(POSTBACK_SECRET_DIRECT, "{click_id}.{transaction_id}.{order_value}")

Example (Python):

import hashlib
import hmac

canonical = f"{click_id}.{transaction_id}.{order_value}"
signature = hmac.new(
POSTBACK_SECRET_DIRECT.encode(),
canonical.encode(),
hashlib.sha256
).hexdigest()

Response (201):

{
"success": true,
"data": {
"conversion_id": "conv_abc123",
"status": "pending",
"message": "Conversion tracked successfully"
},
"message": "Success"
}

Request Fields

Required:

FieldTypeDescription
click_idstring (UUID)The Affilync click ID from the redirect
transaction_idstringUnique transaction ID (for deduplication)
order_valuedecimalTotal conversion value

Highly Recommended:

FieldTypeDescription
order_idstringMerchant order ID (prevents duplicate reporting)
signaturestringHMAC-SHA256 signature (required in production)

Optional:

FieldTypeDescription
currencystringISO 4217 code (default: USD)
conversion_typestringsale, lead, signup, download, subscription, custom (default: sale)
customer_emailstringHashed for privacy; enables cross-device attribution
customer_idstringCustomer identifier from merchant
referer_urlstringReferrer URL
productsarrayProduct details (see below)
metadataobjectCustom key-value pairs
conversion_timestampdatetimeWhen conversion occurred (ISO 8601)

Product Object (in products array):

{
"sku": "PROD-001",
"name": "Product Name",
"quantity": 1,
"price": 49.99,
"category": "Electronics"
}
FieldTypeRequiredDescription
skustringYesProduct SKU
namestringYesProduct name
quantityintegerYesQuantity purchased (≥ 1)
pricedecimalYesUnit price (≥ 0)
categorystringNoProduct category

Third-Party Network Postbacks

Handle conversion postbacks from affiliate networks (Impact, CJ, ShareASale, Rakuten, Awin).

curl -X POST https://api.affilync.com/api/track/postback/impact \
-H "Content-Type: application/json" \
-d '{
"tracking_code": "aff_abc123",
"order_id": "order_789",
"order_value": 150.00,
"currency": "USD",
"signature": "{hmac_signature}"
}'

Valid Sources: impact, cj, shareasale, rakuten, awin, custom

Signature Computation

HMAC-SHA256(POSTBACK_SECRET_<SOURCE>, "{tracking_code}.{order_id}.{order_value}")

Example for CJ postbacks:

signature = hmac.new(
os.environ["POSTBACK_SECRET_CJ"].encode(),
f"{tracking_code}.{order_id}.{order_value}".encode(),
hashlib.sha256
).hexdigest()

Request Fields

FieldTypeDescription
tracking_codestringAffiliate tracking code from order cart/metadata
order_idstringMerchant order ID (dedup key)
order_valuedecimalOrder/sale amount
currencystringISO 4217 code (default: USD)
signaturestringHMAC-SHA256 signature (required in production)
custom_parametersobjectOptional custom parameters from network

Response (200):

{
"success": true,
"data": {
"status": "recorded",
"conversion_id": "conv_xyz123"
},
"message": "Postback processed"
}

Conversion Adjustments (Refunds/Chargebacks)

Reverse affiliate commission(s) when an attributed order is refunded or charged back.

curl -X POST https://api.affilync.com/api/track/adjustment \
-H "X-Affilync-Signature: {signature}" \
-H "Content-Type: application/json" \
-d '{
"original_order_id": "order_456",
"adjustment_type": "refund",
"adjustment_amount": 50.00,
"refund_id": "ref_123"
}'

Request Fields

FieldTypeDescription
original_order_idstringOrder ID of the original conversion
adjustment_typestringrefund, chargeback, or partial_refund
adjustment_amountdecimalRefunded amount (for partial refunds)
refund_idstringOptional refund/chargeback ID
metadataobjectOptional metadata

Response:

{
"success": true,
"data": {
"status": "reversed",
"order_id": "order_456",
"reversed_commissions": 1,
"adjusted_commissions": 0
},
"message": "Adjustment processed"
}

For full refunds/chargebacks, all commissions are reversed (including already-paid ones, which are clawed back via ledger). For partial refunds, unpaid commissions are scaled proportionally.

E-commerce Integration (WooCommerce)

For brand-authenticated e-commerce plugins that hold the click_id from their own cookie.

curl -X POST https://api.affilync.com/api/conversions/track \
-H "Authorization: Bearer {BRAND_JWT}" \
-H "Content-Type: application/json" \
-d '{
"click_id": "550e8400-e29b-41d4-a716-446655440000",
"order_reference": "woo_order_12345",
"order_total": 99.99,
"currency": "USD",
"platform": "woocommerce",
"customer_email": "[email protected]"
}'

Request Fields

FieldTypeDescription
click_idstring (UUID)Click UUID from integration cookie
order_referencestringMerchant order ID
order_totaldecimalOrder total amount
currencystringISO 4217 code (default: USD)
platformstringIntegration platform (e.g., woocommerce)
customer_emailstringCustomer email
commission_amountdecimalOptional: pre-calculated commission
affiliate_idstring (UUID)Optional: affiliate UUID for fallback

Response: Same as direct pixel tracking above.

E-commerce platforms (Shopify, TikTok Shop, BigCommerce): conversions are reported automatically by the managed Affilync app for each platform — no manual API calls required. Install the integration from Settings > Integrations and conversions (including refunds, cancellations, and chargebacks) sync on their own. See Integrations.


Affiliate Endpoints

Get Affiliate's Conversions

curl "https://api.affilync.com/api/affiliate/conversions?status=approved&page=1&per_page=50" \
-H "Authorization: Bearer {AFFILIATE_JWT}"

Query Parameters:

ParameterTypeDescription
statusstringFilter by status: pending, approved, rejected, reversed
campaign_idstring (UUID)Filter by campaign
date_fromdatetimeISO 8601 start date
date_todatetimeISO 8601 end date
pageintegerPage number (≥ 1, default: 1)
per_pageintegerResults per page (1-100, default: 50)

Response:

{
"success": true,
"data": {
"conversions": [
{
"id": "conv_123",
"order_id": "order_456",
"campaign_id": "camp_789",
"click_id": "clk_abc123",
"order_amount": 99.99,
"commission_amount": 10.00,
"commission_rate": 10.0,
"commission_type": "percentage",
"status": "approved",
"converted_at": "2026-03-20T14:30:00Z",
"created_at": "2026-03-20T14:25:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 42,
"pages": 1
}
}
}

Get Affiliate's Conversion Analytics

curl "https://api.affilync.com/api/affiliate/conversions/analytics?start_date=2026-03-01&end_date=2026-03-31" \
-H "Authorization: Bearer {AFFILIATE_JWT}"

Query Parameters:

ParameterTypeDescription
start_datedatetimeISO 8601 start date
end_datedatetimeISO 8601 end date
campaign_idstring (UUID)Filter by campaign

Response: Analytics summary including conversion rates, revenue, top products, and trends.


Brand Endpoints

Get Brand's Conversions

curl "https://api.affilync.com/api/brand/conversions?status=pending&page=1" \
-H "Authorization: Bearer {BRAND_JWT}"

Query Parameters:

ParameterTypeDescription
statusstringFilter by status
campaign_idstring (UUID)Filter by campaign
affiliate_idstring (UUID)Filter by affiliate
date_fromdatetimeStart date
date_todatetimeEnd date
min_valuedecimalMinimum order value
max_valuedecimalMaximum order value
conversion_typestringFilter by type
requires_reviewbooleanShow only flagged conversions
pageintegerPage number
per_pageintegerResults per page

Response:

{
"success": true,
"data": {
"conversions": [
{
"id": "conv_456",
"order_id": "order_789",
"campaign_id": "camp_abc",
"affiliate_id": "usr_xyz",
"click_id": "clk_def456",
"order_amount": 150.00,
"commission_amount": 15.00,
"commission_rate": 10.0,
"status": "pending",
"conversion_type": "sale",
"fraud_score": 0.15,
"requires_review": false,
"converted_at": "2026-03-21T10:15:00Z",
"created_at": "2026-03-21T10:10:00Z"
}
],
"pagination": {
"page": 1,
"per_page": 50,
"total": 127,
"pages": 3
}
}
}

Get Conversions Pending Review

curl "https://api.affilync.com/api/brand/conversions/pending-review?campaign_id=camp_abc" \
-H "Authorization: Bearer {BRAND_JWT}"

Returns conversions flagged for manual review (high fraud score, unusual patterns, or still pending approval).

Query Parameters:

ParameterTypeDescription
campaign_idstring (UUID)Optional: filter by campaign

Response:

{
"success": true,
"data": {
"conversions": [
{
"id": "conv_789",
"order_id": "order_101",
"campaign_id": "camp_def",
"affiliate_id": "usr_abc",
"order_amount": 500.00,
"commission_amount": 50.00,
"status": "pending",
"fraud_score": 0.72,
"requires_review": true,
"converted_at": "2026-03-21T09:00:00Z"
}
],
"total": 5
}
}

Review a Conversion

curl -X PUT https://api.affilync.com/api/brand/conversions/conv_456/review \
-H "Authorization: Bearer {BRAND_JWT}" \
-H "Content-Type: application/json" \
-d '{
"decision": "approved",
"notes": "Verified in customer database"
}'

Request Fields:

FieldTypeDescription
decisionstringapproved or rejected
notesstringOptional review notes

Response:

{
"success": true,
"data": {
"id": "conv_456",
"status": "approved",
"commission_created": true
}
}

Bulk Review Conversions

curl -X POST https://api.affilync.com/api/brand/conversions/bulk-review \
-H "Authorization: Bearer {BRAND_JWT}" \
-H "Content-Type: application/json" \
-d '{
"conversion_ids": ["conv_456", "conv_789"],
"decision": "approved",
"notes": "Batch approval"
}'

Request Fields:

FieldTypeDescription
conversion_idsarrayConversion UUIDs to review
decisionstringapproved or rejected
notesstringOptional review notes

Response:

{
"success": true,
"data": {
"processed": 2,
"failed": 0,
"results": [...],
"errors": []
}
}

Update Attribution Settings

Configure attribution model and lookback windows for a campaign.

curl -X PUT https://api.affilync.com/api/brand/conversions/campaigns/camp_abc/attribution \
-H "Authorization: Bearer {BRAND_JWT}" \
-H "Content-Type: application/json" \
-d '{
"model": "last_click",
"lookback_window_days": 30,
"enable_cross_device": false,
"fingerprinting_enabled": false
}'

Request Fields:

FieldTypeDescription
modelstringAttribution model: last_click, first_click, linear, time_decay, position_based, data_driven
lookback_window_daysintegerAttribution window in days (1-365, default: 30)
time_decay_half_life_hoursintegerHalf-life for time decay model
position_based_weightsobjectWeights for position-based model (must sum to 100)
enable_cross_devicebooleanEnable cross-device tracking
fingerprinting_enabledbooleanEnable device fingerprinting

Response:

{
"success": true,
"data": {
"campaign_id": "camp_abc",
"attribution_settings": {
"model": "last_click",
"lookback_window_days": 30,
"enable_cross_device": false,
"fingerprinting_enabled": false
}
}
}

Get Fraud Analysis

curl "https://api.affilync.com/api/brand/conversions/fraud-analysis?start_date=2026-03-01&end_date=2026-03-31" \
-H "Authorization: Bearer {BRAND_JWT}"

Query Parameters:

ParameterTypeDescription
start_datedatetimeISO 8601 start date
end_datedatetimeISO 8601 end date
campaign_idstring (UUID)Optional: filter by campaign

Response:

{
"success": true,
"data": {
"average_fraud_score": 22.5,
"high_risk_conversions": 3,
"fraud_patterns": [
{
"pattern": "high_fraud_score",
"count": 3,
"description": "Conversions scored above 0.5 by fraud detection"
},
{
"pattern": "flagged_for_review",
"count": 2,
"description": "Conversions flagged requiring manual review"
}
],
"suspicious_affiliates": [
{
"affiliate_id": "usr_xyz",
"conversions": 5,
"average_fraud_score": 65.0
}
],
"recommendations": [
"Manually review high-fraud-score conversions before approval.",
"Investigate affiliates whose conversions average a high fraud score."
]
}
}

Fraud Detection

All conversions are automatically scored for fraud (0-1 scale, displayed as 0-100%). Factors include:

  • Velocity checks — Multiple conversions from same IP/email in short timeframe
  • Cross-device attribution — Unusual device fingerprint combinations
  • Bot detection — Click patterns and user agent analysis
  • Geographic anomalies — Mismatches between click location and conversion location
  • Affiliate history — Past conversion approval rates and chargebacks

Conversions scoring above 0.5 (50%) are flagged for manual review (requires_review=true).


Deduplication

Conversions are deduplicated by:

  • Order ID — Primary dedup key; resubmitting same order_id returns original conversion
  • Transaction ID — Secondary dedup key for direct pixel tracking

Submitting the same order twice returns the original conversion without creating a duplicate, ensuring idempotent conversion reporting.


Attribution Window

Conversions are attributed to clicks within the campaign's attribution window (default: 30 days). The window is configured per-campaign via the Update Attribution Settings endpoint.

Attribution Priority:

  1. click_id — Direct click attribution (most accurate)
  2. tracking_code — Last recent click for affiliate link
  3. affiliate_id — Fallback to affiliate ID if no click

Conversion Statuses

StatusDescriptionCommission Created
pendingAwaiting brand approvalNo (held pending)
approvedBrand approvedYes (if not already)
rejectedBrand rejectedNo
reversedRefund/chargeback processedNo (clawed back if paid)

Error Handling

Common HTTP Status Codes:

CodeReasonAction
201Conversion createdSuccess
400Invalid request (missing required field, validation error)Fix payload and retry
401Missing or invalid signatureCompute correct HMAC-SHA256 signature
403Insufficient permissionsUse correct auth token for your role
404Click/conversion not foundVerify click_id exists
409Duplicate order_idIdempotent — previous conversion returned
429Rate limited (60 requests per hour per IP)Retry with backoff
503Postback source not configured (production only)Configure POSTBACK_SECRET env var

Error Response:

{
"success": false,
"data": {
"error": "Invalid signature"
},
"message": "Failed to track conversion"
}

Best Practices

  1. Use click_id for accuracy — Always pass the click_id from the pixel's afk_cid cookie when available
  2. Include order_id — Prevents accidental duplicate submission
  3. Sign in production — Always include HMAC signature in production; it's required and fails-closed
  4. Use consistent currency — Report all orders in the same currency as configured in campaigns
  5. Validate before posting — Check order_value > 0, valid email format
  6. Retry with exponential backoff — Network errors on 5xx responses (jitter randomness)
  7. Monitor conversion latency — Aim for < 30 seconds between purchase and conversion tracking
  8. Test postbacks — Use test mode networks (staging Impact accounts, etc.) before live deployment