Loyalty API
The developer reference is best viewed on a desktop — open loyalty.simpleapps.co.za/developers on your computer to integrate your POS or online store.
Loyalty API — developer reference
Connect your point-of-sale or online store to SimpleApps Loyalty. Add stamps automatically when a customer buys, check a customer’s balance at the till, redeem rewards, and enrol members — all from your own system.
1. Get an API key
In your dashboard go to Settings → Integrations and create a key. Pick the scopes it needs (see below). The full key is shown once — copy it and store it securely on your server. Keys can be revoked at any time.
Keys are secrets that issue value — never expose one in a browser, mobile app, or public repository. Keep it server-side only.
2. Authentication
Send your key as a Bearer token on every request:
Authorization: Bearer lk_xxxxxxxxxxxxxxxxxxxxxxxxAll endpoints accept and return application/json over POST. Base URL:
https://prod.simpleapps.co.za/webhook3. Identifying a customer
Customers are identified by their mobile number in international format (e.g. +27821234567). This is the same number they use on their loyalty card.
4. Idempotency (important)
Every call that issues value — accrue and redeem — requires an external_ref: a unique id from your system (typically your transaction/receipt id). If the same external_ref is sent twice for a business, the second call is a safe no-op that returns idempotent_replay: true instead of stamping or redeeming again. This makes retries safe.
5. Scopes
| Scope | Allows |
|---|---|
accrue | Add stamps from a purchase |
read | Look up a member’s balance |
redeem | Redeem a reward |
enroll | Enrol a new member |
6. Endpoints
/loyalty/api/v1/accruescope: accrueAdd one or more stamps to a member’s card after a purchase.
curl -X POST https://prod.simpleapps.co.za/webhook/loyalty/api/v1/accrue \
-H "Authorization: Bearer lk_..." \
-H "Content-Type: application/json" \
-d '{
"mobile": "+27821234567",
"qty": 1,
"external_ref": "receipt-10432"
}'Response
{
"ok": true,
"error": null,
"member_found": true,
"stamped": true,
"idempotent_replay": false,
"membership": { "progress": { "stamp_count": 3, "target": 10 }, "reward_available": false },
"member": { "mobile": "+27821234567", "first_name": "Nomsa" }
}Fields
mobile(required) — the customer’s number.qty(optional, default 1) — stamps to add (e.g. 2 items = 2).external_ref(required) — your unique transaction id.card_id(optional, defaultc1) — for businesses running more than one punch card.
If the member has not joined yet, accrue returns error: "member_not_found". Enrol them first (with consent) via /enroll.
/loyalty/api/v1/member/lookupscope: readCheck a member’s current balance and whether a reward is waiting — ideal for a prompt at the till.
curl -X POST https://prod.simpleapps.co.za/webhook/loyalty/api/v1/member/lookup \
-H "Authorization: Bearer lk_..." \
-H "Content-Type: application/json" \
-d '{ "mobile": "+27821234567" }'{
"ok": true,
"member_found": true,
"membership": { "progress": { "stamp_count": 9, "target": 10 }, "reward_available": false },
"member": { "mobile": "+27821234567", "first_name": "Nomsa", "surname": "Dlamini" }
}/loyalty/api/v1/redeemscope: redeemRedeem a reward the member has earned (e.g. hand over their free coffee at the till).
curl -X POST https://prod.simpleapps.co.za/webhook/loyalty/api/v1/redeem \
-H "Authorization: Bearer lk_..." \
-H "Content-Type: application/json" \
-d '{
"mobile": "+27821234567",
"reward": "punch",
"external_ref": "receipt-10433"
}'{
"ok": true,
"was_eligible": true,
"redeemed": true,
"idempotent_replay": false,
"membership": { "progress": { "stamp_count": 0, "target": 10, "rewards_pending": 0 } }
}reward(optional, defaultpunch) — the reward type to redeem:punch,game,birthdayorreferral.external_ref(required) — your unique transaction id.
If nothing is redeemable, returns error: "no_reward_available".
/loyalty/api/v1/enrollscope: enrollEnrol a customer as a member. Consent is required — you must have the customer’s agreement to receive loyalty messages (POPIA).
curl -X POST https://prod.simpleapps.co.za/webhook/loyalty/api/v1/enroll \
-H "Authorization: Bearer lk_..." \
-H "Content-Type: application/json" \
-d '{
"mobile": "+27821234567",
"first_name": "Nomsa",
"consent": true
}'{
"ok": true,
"enrolled": true,
"newly_created": true,
"member": { "mobile": "+27821234567", "first_name": "Nomsa" }
}Without consent: true, returns error: "consent_required" and does not enrol.
7. Errors
All responses are HTTP 200 with an ok boolean and an error code when ok is false:
| error | Meaning |
|---|---|
invalid_api_key | Key missing, wrong, or revoked. |
insufficient_scope | The key lacks the required scope. |
missing_external_ref | external_ref was not supplied. |
member_not_found | No member with that mobile at your business. |
no_reward_available | Nothing to redeem for that member. |
consent_required | Enrolment attempted without consent. |