Introduction
Storelayer holds loyalty state and runs loyalty logic for your application. Your backend stays the source of truth for orders and customers; it tells Storelayer what happened (events), asks what a cart is worth (promotions), and reads or moves balances (wallets).
The primitives
Section titled “The primitives”| Primitive | What it is | You interact by… |
|---|---|---|
| Project | The boundary for all config, rules, promotions, customers, and keys | One API key per integration, scoped to one project |
| Customer (external user) | Your customer, identified by your stable ID (userId) | POST /projects/{projectId}/users |
| Event | Something that happened: { type, userId, payload } | POST /ingest/events |
| Rule | Conditions over the event + actions to run when they match | POST /projects/{projectId}/rules |
| Wallet | Per-customer balances, one per asset type (points, stamps, …) | GET /projects/{projectId}/users/{userId}/wallet |
| Promotion | Cart-level discount logic, optionally behind coupons | POST /projects/{projectId}/promotions/evaluate |
| Referral | Codes, referrer/referee attribution, and completion | Referrals endpoints |
| Workflow | The recorded run of one event through your rules | Workflows endpoints |
How they connect
Section titled “How they connect”Earning (asynchronous):
your backend ──POST /ingest/events──▶ event accepted (201, id evt_…) │ queued ▼ active rules evaluated (conditions on $('event').payload…) │ match ▼ actions: reward → wallet earn, modify, integration, emit_event, … │ ▼ workflow run recordedIngesting returns before rules run. Never read the wallet immediately after sending an event and assume the reward is there — inspect the workflow run or poll the balance. See workflows.
Discounting (synchronous): send the cart to POST /projects/{projectId}/promotions/evaluate; the response contains the qualifying promotions and per-item discounts. Cart money is integer minor units ($25.00 = 2500). See creating promotions.
Referring: a referrer gets a code, a referee applies it, and a later event (for example a first purchase) completes the referral and rewards both sides through rule actions. See referral programs.
Direct wallet writes: when your backend already decided the outcome (customer-service credit, migration from another system), call the wallet endpoints (earn, spend, modify) directly instead of going through an event and rule.
Choosing between an event and a direct wallet call
Section titled “Choosing between an event and a direct wallet call”| Use an event + rule when… | Use a direct wallet call when… |
|---|---|
| Marketing or ops should change the reward without a deploy | The amount is computed by your backend and fixed |
| One business fact can trigger several outcomes (points, referral completion, webhook) | You need the new balance in the same request |
| You want a recorded, replayable decision per event | It is a one-off adjustment or import |
Identity
Section titled “Identity”Use one stable customer ID everywhere — events, wallets, referrals, carts. Wallets are keyed by project + userId; a different spelling of the same customer is a different wallet. Register customers with POST /projects/{projectId}/users before using their ID; wallet calls do not check registration.
- Quick start — first calls with curl.
- Authentication — keys and tokens.
- Projects, Wallets, Loyalty events, Promotions, Referrals.
Append .md to any page path for its Markdown source (for example /concepts/wallets.md); /llms.txt indexes all pages.