Referrals
The referral module records who referred whom. It does not pay rewards. A referrer owns a code, a referee applies it, and Storelayer stores a referral record linking the two. Points for either side are paid by rules that react to your business events and read the referral record.
| Code type | Created with | referrerId | Typical use |
|---|---|---|---|
| User-owned | POST /referrals with referrerId | The customer who shares it | “Invite a friend” codes. One code per referrer: a second create returns error 3100 |
| System | POST /referrals without referrerId, or POST /referrals/bulk (1–1000 codes) | null | Influencer, partner or campaign codes. Applying one records a referral with no referrer to reward |
A code has status (active or inactive), maxUses (null = unlimited), currentUses, expiresAt and tags. You can supply your own code string or let Storelayer generate one from the project config. Codes are unique per project and matched exactly, including case. Generated codes are upper-case.
Validate, apply, reward
Section titled “Validate, apply, reward”| Step | How | Changes data? | Important distinction |
|---|---|---|---|
| Validate | POST /referrals/validate with code and optionally refereeId | No | Use it to show “code accepted” in a signup form. Pass refereeId to also check self-referral and already-referred |
| Apply | POST /referrals/apply with code and refereeId, or the rule action apply_referral | Yes: creates the referral record and increments currentUses | Attribution only. No points are paid |
| Reward | A rule on your qualifying event (e.g. order_completed) that reads the referral and runs reward actions | Wallets | The only step that moves value |
Applying runs the same checks as validating. Failures come back as errors:
| Code | Error | Meaning |
|---|---|---|
| 3101 | CODE_NOT_FOUND | No such code (or it was deleted) |
| 3103 | CODE_NOT_ACTIVE | Code is inactive |
| 3104 | CODE_EXPIRED | expiresAt has passed |
| 3105 | CODE_MAX_USES_REACHED | currentUses reached maxUses |
| 3106 | SELF_REFERRAL | Referee is the code’s owner |
| 3107 | REFEREE_ALREADY_REFERRED | A customer can be referred only once, by any code |
The referral record
Section titled “The referral record”{ "id": "ref_…", "codeId": "rcode_…", "code": "K7M2QX9A", "referrerId": "cus_alice", "refereeId": "cus_bob", "completedAt": "2026-10-11T09:30:00.000Z", "expiresAt": null, "createdAt": "2026-10-11T09:30:00.000Z", "updatedAt": "2026-10-11T09:30:00.000Z"}A referral has no pending/qualified state: it exists from the moment the code is applied. “Has the referee qualified?” and “has the reward been paid?” are questions your rules answer, for example with a customer metadata flag. See the worked example in the referral program guide. The complete_referral rule action only looks up the referee’s referral and reports its referrerId; it changes nothing.
Project config
Section titled “Project config”GET/PUT /projects/{projectId}/referrals/config. PUT merges the fields you send.
| Field | Default | Effect |
|---|---|---|
defaultMaxUsesPerCode | null | Cap for user-owned codes. Changing it rewrites maxUses on every existing user-owned code |
defaultMaxUsesPerSystemCode | null | Cap applied to new system codes |
defaultCodeExpirationDays | null | Sets expiresAt on new codes created without one |
referralExpirationDays | null | Sets expiresAt on new referral records. Stored for your rules to check; Storelayer does not enforce it |
codeLength | 8 | Total generated length including prefix (4–20) |
codePrefix | "" | Upper-case letters/digits, max 10, e.g. "FRIEND" |
codeCharset | alphanumeric | alphanumeric (no look-alike 0 O 1 I), alphabetic, numeric, hex |
codeSeparator / codeSeparatorInterval | "" / 4 | "", - or _ inserted every N characters of the random part |
Reporting
Section titled “Reporting”GET /referrals/stats:totalCodes,activeCodes,totalReferralsGET /referrals/stats/{userId}: codes created and referrals made by one customerGET /referrals/leaderboard: referrers ranked by number of referralsGET /referrals/events: audit log (code.created,code.deactivated,code.reactivated,referral.created)
See also
Section titled “See also”- Integrating referrals: request bodies and lookups
- Referral program guide: a complete “both get 500 points” program
- Referrals in the API reference