Affiliates
Cursiva models three relationships a person can have with your school: a member (staff — someone who works in the dashboard), a learner (someone who studies), and now an affiliate — someone who promotes your courses and earns a commission on the sales they bring. An affiliate is not staff: they never see your dashboard, hold no organization role, and touch nothing beyond their own links and earnings. The same person can be all three at once — your best affiliate may well be a learner of the very course they promote.
One honest line before anything else: in this phase Cursiva tracks commissions — who drove which sale and what is owed — but does not move affiliate money. You pay your affiliates directly (Pix, bank transfer, however you settle) and then mark it paid in the dashboard.
Turning the program on
The program lives at Settings → Affiliates (/dashboard/settings/affiliates), open to organization owners and admins. Two controls:
| Setting | What it does |
|---|---|
| Joining | Off — no one can join (the default). Open — anyone joins instantly and starts active. By approval — joins land pending until staff approves them. |
| Default commission | The org-wide percent of each attributed sale. An offer's own rate or a negotiated per-affiliate rate overrides it — see The commission. |
While the mode is off, nothing shows publicly and no code attributes. Once the program is open or by approval, your organization's public page grows a "Become an affiliate" strip advertising the default rate and pointing at the join page.
How people join
The join page lives on the apex — cursiva.io/affiliates/join/{your-slug} — and requires nothing but a Cursiva account. Any user can join: a stranger, a learner of the very course, even one of your own members (their affiliation is separate from their role — but note self-referrals below).
- In an open program, joining activates instantly — the affiliate gets their code and can start sharing links.
- In a by approval program, the join lands pending: the code exists but attributes nothing until you approve it on the affiliate roster.
- Joining again is harmless — asking twice just returns the existing affiliation. A blocked affiliate cannot rejoin.
Each affiliate gets a short, unique code — 8 lowercase characters, URL-safe, with no ambiguous characters. That code is the affiliate's public identity: it is what travels in their links.
Links and attribution
An affiliate link is nothing exotic: the course's public sales page with ?ref=CODE appended. The affiliate portal generates these links ready to copy, but any hand-built URL works the same.
Visiting any page with a valid ?ref= sets a 30-day cookie, last click wins — a newer code overwrites an older one. At checkout, the code is resolved server-side against the organization being bought from. The sale is attributed only when everything lines up; in every other case it simply completes unattributed:
- Wrong organization — a code from another organization doesn't match here.
- Affiliate not active — pending or blocked affiliates don't attribute.
- Program off — turning the program off silences every code at once.
- Self-referral — buying through your own link doesn't attribute: no one earns commission on themselves.
The commission
The rate for a sale is picked by strict precedence:
- The affiliate's negotiated rate, when one is set on the affiliate roster;
- else the offer's own rate, when the sold offer sets one (in its Pricing section);
- else the program's default commission.
The commission is computed on the sale price — what the buyer actually paid, after any campaign discount — and comes out of your producer share, not on top of the price. A rate of zero still attributes: you see who drove the sale even when nothing is owed.
Frozen at the sale
The resolved rate and the computed amount are written onto the purchase itself at sale time — the same snapshot discipline as the platform fee. Changing the program default, an offer's rate, or a negotiated rate later never rewrites past sales; it only applies to sales from then on.
Settling up
The roster at Settings → Affiliates shows every affiliate with their earnings, per currency: pending (owed and not yet paid) and paid. From each row's menu you can:
- Approve a pending affiliate (or unblock a blocked one) — their links start attributing.
- Block — their links stop attributing; commissions already earned stay on the books.
- Set commission… — a negotiated rate for this affiliate only. Leave it empty to fall back to the program default.
- Mark commissions paid — after you have actually paid them (Pix, transfer — outside Cursiva), one click marks everything pending as paid, per currency.
Refunds keep the numbers honest: a refunded sale drops out of pending automatically. If a sale is refunded after its commission was already marked paid, it shows as reversed — Cursiva won't pretend the money came back; it tells you that you overpaid so you can settle it on the next round.
The affiliate portal
Affiliates get their own user-level page at cursiva.io/affiliates — like the learner home, outside any dashboard. Per organization it shows the affiliation's status, the code, ready-to-copy links for every published course (already carrying the code), and earnings — pending and paid, per currency. A pending affiliation says so and starts counting once approved.
Webhooks and audit
The purchase.created webhook now carries the attribution snapshot — all three fields are null on an unattributed sale:
| Field | Meaning |
|---|---|
affiliateId | The attributed affiliate |
affiliateBps | The frozen commission rate, in basis points (1% = 100 bps) |
affiliateAmount | The frozen commission amount, in the currency's smallest unit |
This is not the pre-existing referralId field, which keeps serving bring-your-own trackers (Rewardful, FirstPromoter — under Settings → Integrations → Affiliates). The two travel independently.
Every administrative action on the program is recorded in the audit log with organization visibility: affiliate.program.updated, affiliate.joined, affiliate.approved, affiliate.blocked, affiliate.commission.updated, and affiliate.settled.