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.
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.
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
| Method | Limit | Window |
|---|---|---|
GET | 120 requests | per minute, per key |
POST | 30 requests | per 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
/api/v1/affiliatesReturns a paginated list of affiliates in your program.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
limit | integer | 50 | Results 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..."/api/v1/conversionsReturns a paginated list of conversions. Includes both Stripe-attributed and manually recorded conversions.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
limit | integer | 50 | Results per page (max 100) |
affiliate_id | string | — | Filter to a single affiliate |
status | string | — | pending 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..."/api/v1/conversionsRecords 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
| Field | Type | Required | Description |
|---|---|---|---|
affiliate_id | string | Yes | ID of the affiliate to credit |
amount_cents | integer | Yes | Sale amount in cents, must be a positive integer |
external_id | string | No | Your 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
| Status | Meaning |
|---|---|
400 | Missing or invalid fields |
401 | Missing or invalid API key |
404 | Affiliate not found |
409 | Duplicate external_id — conversion already recorded |
429 | Rate 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"
}'