Affiliates
An organization's referral link and what it has earned. Three routes, all Owner only.
If you are integrating an accounting product with Syllevo, this page is probably not for you. It is here because the routes exist and every route is documented. The audience is a firm that refers other firms and wants to show its own people what that has earned.
Routes
| Method | Path | Needs |
|---|---|---|
| GET | /v1/affiliate |
Owner |
| PUT | /v1/affiliate/code |
Owner |
| GET | /v1/affiliate/commissions |
Owner |
No route here names an organization. Scope comes from X-Organization-Id, so there is no path
segment to change in order to read somebody else's numbers. See
Authentication.
Anyone below Owner gets 403.
Standard terms
| What | Value |
|---|---|
| Discount the referred customer gets | 15 percent of one month |
| Commission on every invoice they pay | 25 percent |
| Days before a commission can be paid | 40 |
Terms are per organization, and these are only the defaults. A partner who negotiated something
else carries their own two numbers, so read them off GET /v1/affiliate (discountPercent and
commissionPercent) rather than printing 15 and 25 on a screen. Most organizations are on the
standard terms; some are not.
The commission is flat. It applies to the first invoice and to every renewal after it, for as long as the referred organization keeps subscribing.
Commission is calculated on what the customer actually paid, before tax and after the referral discount. VAT was never the referrer's to share, and a commission on the list price would pay out on money that never arrived. Extras billed outside the subscription do not earn commission.
On an annual package the commission applies to the whole invoice rather than to one month of it, so a referral that brings in an annual subscriber earns more at once. The referred customer's discount stays worth one month either way: on an annual price it is applied as a flat amount worth one month's discount, not the percentage off the year.
GET /v1/affiliate
The organization's referral code. Owner.
| Field | Type | Means |
|---|---|---|
code |
string | The code in their link, upper case |
commissionPercent |
integer | What they earn on every invoice a referral pays |
createdAt |
date-time | When they first got one |
discountPercent |
integer | What a signup through their link gets off their first month |
isActive |
boolean | Whether the link still attributes new signups |
{
"code": "K7MQ3BDW",
"commissionPercent": 25,
"createdAt": "2026-09-01T08:00:00Z",
"discountPercent": 15,
"isActive": true
}
discountPercent and commissionPercent are this organization's own terms. They are 15 and 25
unless somebody negotiated otherwise, and a screen that states the offer should render these two
numbers rather than hard-code the standard ones. Changing them changes what the next checkout and the
next invoice do; commissions already earned keep the rate they were earned at.
The link is syllevo.com/r/{code}.
This GET creates the code the first time it is called. There is nothing to agree to and nothing to configure, so there is no enroll step. Calling it twice returns the same code.
isActive: false means an old link has been retired and stops stamping new signups. Commissions
already earned are untouched by it.
PUT /v1/affiliate/code
Changes the code in the link. Owner.
{ "code": "HANDY" }
Answers 200 with the same shape GET returns.
Every code the organization has ever held keeps working. A link on a flyer, in a newsletter that already went out, or in somebody's bookmarks still resolves to this organization after a rename. A code is never released back to the pool and never handed to anybody else.
Code rules:
| Rule | Value |
|---|---|
| Length | 4 to 32 characters |
| Alphabet | 34679BCDFGHJKMNPQRTVWXY only |
| Case | Upper-cased and trimmed for you. Send what you like |
| Reserved | Syllevo's own names and roles are refused |
| Renames | Ten per organization, ever |
The alphabet has no vowels and no lookalike characters, no 0 or O, no 1 or I, no S or 5.
A code gets read aloud on a call and copied off a slide, and both of those go wrong with a character
somebody has to guess at. No vowels also means a generated code cannot accidentally spell something.
Refusals:
| Code | Status | Means |
|---|---|---|
validation.affiliateCodeInvalid |
400 | Wrong length or a character outside the alphabet |
validation.affiliateCodeReserved |
400 | A name Syllevo keeps, SUPPORT or BILLING for instance |
affiliate_code_taken |
409 | Somebody else holds it, now or at some point in the past |
affiliate_code_limit_reached |
409 | Ten renames already used |
The two 400s arrive as field errors on code rather than as top-level codes. See
Conventions.
affiliate_code_taken covers a code somebody used to hold as well as one they hold now, because
old codes keep resolving. The namespace is every code anybody has ever been on.
The rename cap is a squatting guard, not a storage one. Ten is far more moves than a real referral link makes.
GET /v1/affiliate/commissions
Every commission the organization has earned, with totals. Owner.
| Field | Type | Means |
|---|---|---|
commissions |
array | One entry per commission |
totals |
array | One entry per state and currency |
Each commission:
| Field | Type | Means |
|---|---|---|
amountMinorUnits |
integer | What is owed, in minor units of currencyCode |
currencyCode |
string | ISO 4217, the invoice's own currency |
invoiceDate |
date | The referred customer's invoice date |
maturityDate |
date | invoiceDate plus 40 days |
paidAt |
date-time, null | When a person paid it out. Null until they did |
ratePercent |
integer | The affiliate's rate on the day it was earned |
state |
string | Accrued, Payable, or Paid |
Each entry in totals:
| Field | Type | Means |
|---|---|---|
state |
string | Which state the total covers |
currencyCode |
string | Which currency |
count |
integer | How many commissions |
totalMinorUnits |
integer | Their sum, in minor units |
state here is a string, not a number, unlike almost every other enum in this API. It is stored
as text because a person reads it during a payout conversation, and a reordered enum turning an
unpaid commission into a paid one is not a bug anybody wants to find out about afterwards. See
Conventions.
| State | Means |
|---|---|
Accrued |
Earned, and not yet owed. The customer's 40-day money-back window is open |
Payable |
The window closed. The amount is owed |
Paid |
A person sent the money and recorded it. The end of the line |
Nothing in the API moves money. Payable to paid is a human decision written down afterward, and there is no payout route.
totals is split by currency as well as by state, because a commission is paid in whatever the
customer was charged and is never converted. An organization with referrals in two currencies gets
two rows per state, and adding them together would be wrong.
Amounts are minor units. 12300 in RON is 123.00 lei. See
Conventions.
There is no clawback state, and that is on purpose. A commission is not payable until the 40-day guarantee on the invoice behind it has run out, so a refund inside those 40 days lands on money that was never payable. There is nothing to reverse and no negative row to explain.