Docs

Integration & API Reference

Add the attribution snippet to your checkout, then use the Scale plan REST API to push manual conversions or sync affiliate data with your own systems.

Base URL | https://affilut.com/api/v1

Checkout integration

To attribute conversions, your checkout page must read the affiliate ref from the URL and pass it to Stripe as payment metadata. Copy this snippet into your checkout page (or find it in Settings → Program):

(function () {
  var p = new URLSearchParams(location.search);
  var ref = p.get('ref'), sess = p.get('aff_sess');
  if (ref) sessionStorage.setItem('aff_ref', ref);
  if (sess) sessionStorage.setItem('aff_sess', sess);
})();

// At Stripe checkout creation, add to payment_intent_data.metadata:
//   affiliate_id: sessionStorage.getItem('aff_ref'),
//   affiliate_session_id: sessionStorage.getItem('aff_sess')

When a referred visitor clicks an affiliate link and reaches your landing page, their ?ref= and ?aff_sess= params are stored in sessionStorage. The snippet above keeps them alive across page navigations so they're available at checkout time.

Subscription renewals

To attribute commission on recurring subscription charges, also set affiliate_id on the Stripe Customer object at initial checkout (via customer_update.metadata). affilut will attribute commission on all future renewal invoices automatically.

Authentication

All requests require a Bearer token in the Authorization header. Generate keys in Settings → API Keys. Keys are scoped to your account — they cannot access other tenants' data.

Authorization: Bearer aff_a1b2c3d4...

The plaintext token is shown once on creation and never stored. Revoke compromised keys immediately from Settings → API Keys.

Rate limits

MethodLimitWindow
GET120 requestsper minute, per key
POST30 requestsper minute, per key

Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix timestamp) headers. Exceeded limits return 429 with a Retry-After header (seconds).

Endpoints

GET /api/v1/affiliates

Returns a paginated list of affiliates in your program.

Query parameters

ParameterTypeDefaultDescription
pageinteger1Page number (1-based)
limitinteger50Results per page (max 100)

Response

{
  "data": [
    {
      "id": "aff_01hx...",
      "name": "Jane Smith",
      "email": "jane@example.com",
      "shortCode": "jane-smith-a1b2",
      "status": "active",          // pending | active | paused | banned
      "commissionOverride": null,  // string (%) or null (uses program default)
      "createdAt": "2026-01-15T09:00:00.000Z",
      "activatedAt": "2026-01-16T10:30:00.000Z"
    }
  ],
  "page": 1,
  "limit": 50
}

Example

curl https://affilut.com/api/v1/affiliates \
  -H "Authorization: Bearer aff_a1b2c3d4..."
GET /api/v1/conversions

Returns a paginated list of conversions. Includes both Stripe-attributed and manually recorded conversions.

Query parameters

ParameterTypeDefaultDescription
pageinteger1Page number (1-based)
limitinteger50Results per page (max 100)
affiliate_idstringFilter to a single affiliate
statusstringpending approved paid rejected

Response

{
  "data": [
    {
      "id": "cnv_01hx...",
      "affiliateId": "aff_01hx...",
      "stripeChargeId": "ch_3P...",  // or "manual:<external_id>"
      "amountCents": 4900,
      "commissionCents": 490,
      "status": "pending",           // pending | approved | paid | rejected
      "createdAt": "2026-01-20T14:22:00.000Z"
    }
  ],
  "page": 1,
  "limit": 50
}

Example

curl "https://affilut.com/api/v1/conversions?status=approved&affiliate_id=aff_01hx..." \
  -H "Authorization: Bearer aff_a1b2c3d4..."
POST /api/v1/conversions

Records a manual conversion — use this for revenue that doesn't flow through Stripe (e.g. wire transfers, PayPal, offline sales). Commission is calculated automatically using the affiliate's rate.

Request body

FieldTypeRequiredDescription
affiliate_idstringYesID of the affiliate to credit
amount_centsintegerYesSale amount in cents, must be a positive integer
external_idstringNoYour internal order or invoice ID. Used for idempotency — submitting the same external_id twice returns 409. Omit only if you don't need idempotency.

Response — 201 Created

{
  "id": "cnv_01hx...",
  "commissionCents": 490
}

Error responses

StatusMeaning
400Missing or invalid fields
401Missing or invalid API key
404Affiliate not found
409Duplicate external_id — conversion already recorded
429Rate limit exceeded — see Retry-After header

Example

curl -X POST https://affilut.com/api/v1/conversions \
  -H "Authorization: Bearer aff_a1b2c3d4..." \
  -H "Content-Type: application/json" \
  -d '{
    "affiliate_id": "aff_01hx...",
    "amount_cents": 4900,
    "external_id": "inv_2026_00142"
  }'
Questions or integration issues? Reply to your welcome email or contact support.