Quickstart
Create a program, a partner and a link, then attribute a customer and commission a payment with curl.
This walkthrough runs the whole pipeline end to end with plain HTTP calls: program, commission rule, partner, link, click, referral, payment, commission. It takes about ten minutes. Every call uses an API key, so you can paste the commands into a terminal.
Set two shell variables first and reuse them throughout:
export BASE=https://referalli.com
export KEY=rk_your_key_here- Create an API key
Sign in at
https://referalli.com/loginwith Atlas. On first sign-in you create an organization. Then open Settings, find API keys, leave Access for the next key on Full, and click Create API key. This walkthrough writes data, so a read-only key won't do.The full key (
rk_…) is shown once. Copy it intoKEY. Only org owners and admins can create keys. - Create a program
curl -s -X POST $BASE/v1/programs \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{"name": "Acme Partners", "slug": "acme-partners"}'The response includes the program
id(prg_…) with the defaultsattributionModel: "last_click",cookieWindowDays: 60andsignupToConversionDays: 365. Save the id:export PROGRAM=prg_... - Publish a commission rule
A program pays nothing until it has a rule. This one pays 20% of every payment, for the customer's lifetime, after a 30-day hold:
curl -s -X POST $BASE/v1/commission-rules \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{ "programId": "'"$PROGRAM"'", "config": { "base": { "kind": "percent", "bps": 2000 } } }'bpsis basis points: 2000 = 20%.recurringdefaults tolifetimeandholdDaysto 30. See Commission rules for every option. - Create a partner and enroll them
curl -s -X POST $BASE/v1/partners \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{"email": "dana@example.com", "displayName": "Dana"}' export PARTNER=ptr_... curl -s -X POST $BASE/v1/programs/$PROGRAM/enrollments \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{"partnerId": "'"$PARTNER"'"}'Enrollments created this way are
approvedimmediately. - Create a tracked link
curl -s -X POST $BASE/v1/links \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{ "programId": "'"$PROGRAM"'", "partnerId": "'"$PARTNER"'", "code": "dana", "destinationUrl": "https://example.com/pricing" }'codeis optional (letters, digits and-, stored lowercased and matched in any case); leave it out to get a random one. Now fetch your org's tracking token, which forms the public link URL:curl -s $BASE/v1/org -H "Authorization: Bearer $KEY" # { "id": "org_...", "trackingToken": "tk_...", ... } export TOKEN=tk_...The partner's link is
$BASE/go/$TOKEN/dana. - Click the link
curl -s -o /dev/null -w '%{redirect_url}\n' \ -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0)" \ $BASE/go/$TOKEN/dana # https://example.com/pricing?via=dana&ref_click_id=clk_...The redirect appends
via(the link code) andref_click_id(the click id). Save the click id:export CLICK=clk_...Send a browser user agent. Clicks are fraud-scored. curl's default
curl/…user agent scores as a bot, which makes the click ineligible for attribution. The-Aflag above avoids that. - Attribute the customer at signup
When the visitor signs up, your server tells Referalli who they are.
customerRefmust be the id your billing provider uses for this customer (for Stripe, thecus_…id), because that is how payments are matched later.curl -s -X POST $BASE/v1/referrals/associate \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{ "programId": "'"$PROGRAM"'", "customerRef": "cus_123", "referralToken": "'"$CLICK"'" }'The response is
{ "referral": { ... } }withpartnerIdset to Dana,matchedVia: "deterministic"andstatus: "active". If nothing matched,referralisnull. - Record a payment
Payments arrive as billing webhooks. For this test, use the generic conversion API. Create a connection:
curl -s -X POST $BASE/v1/billing/connections \ -H "Authorization: Bearer $KEY" \ -H "content-type: application/json" \ -d '{"provider": "generic", "name": "quickstart"}' # { "id": "bcon_...", "provider": "generic", # "webhookSecret": "whsec_...", "webhookUrl": "/webhooks/billing/bcon_..." } export CONN=bcon_... export SECRET=whsec_...Then post a signed
invoice_paidevent for $99.00. The signature is the hex HMAC-SHA256 of the exact body bytes:NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) BODY='{"events":[{"providerEventId":"evt_001","type":"invoice_paid","customerRef":"cus_123","invoiceRef":"in_001","amountGross":9900,"currency":"usd","occurredAt":"'"$NOW"'"}]}' SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $NF}') curl -s -X POST $BASE/webhooks/billing/$CONN \ -H "content-type: application/json" \ -H "x-webhook-signature: $SIG" \ -d "$BODY" # { "received": 1, "results": [ { "duplicate": false, "conversions": 1, "linesCreated": 1, ... } ] }occurredAtmust not be earlier than the referral (a 5-minute clock-skew allowance applies), so this uses the current time. Sending the sameproviderEventIdagain returnsduplicate: trueand changes nothing. - Check the commission
curl -s "$BASE/v1/commissions?partnerId=$PARTNER" -H "Authorization: Bearer $KEY" curl -s $BASE/v1/partners/$PARTNER/balances -H "Authorization: Bearer $KEY" # [ { "currency": "usd", "pending": 1980, "approved": 0, "paid": 0, "reversed": 0 } ]20% of 9900 is 1980 minor units ($19.80), held as
pendingfor 30 days. After the hold,POST /v1/commissions/approve-duemoves it toapproved, and a payout run pays it. See Payouts.
What you built
A program with a commission rule, a partner, and a link at
/go/{token}/dana.A fraud-scored click, a referral that ties
cus_123to the partner, apaymentconversion and anearnedcommission line.
Next steps
Put the tracking script on your site so clicks are captured without manual ids.
Connect your real billing provider.
Subscribe to webhooks such as
referral.createdandcommission.earned.