</> Developers

Record loyalty activity. Manage reward redemption.

Purchase events record points and stamps synchronously and return the member’s balance. Creating a discount or store-credit reward adds a merchant catalog item; a separate redemption records a member’s use of it. Provider gift-card payout remains unavailable.

Bearer-key auth, idempotent writes, HMAC-signed webhooks. Plain JSON over HTTPS, no SDK.

What arrives immediately, and what does not

Purchase and redemption responses acknowledge ledger changes. Reward creation instead returns a catalog record, not a member balance or externally issued value. Rewardfinity never holds reward funds; catalog creation and recorded redemption do not prove delivery by an external system.

Reward type
What the call does
Response boundary
Points
Ledger entry written; new balance in the response
Same request
Stamps
Accrued by the purchase event — milestone evaluated, remainder carried
Same request
Discount reward
Merchant catalog item created; no member issuance
Catalog record returned
Store credit
Merchant catalog item created; no external credit issued
Catalog record returned
Redemption
Race-safe balance check, then an atomic guarded write
Same request
Gift card, from your vault
Code allocated, spent and issued in one write
Same request
Gift card, by provider payout
Reward created; payout recorded as pending, provider unconfigured
Not today — no payout provider is enabled

If you are looking for a payout rail that buys and mails a gift card on your behalf, this is not one, and there is no setting that turns it into one. Rewardfinity records the entitlement; the merchant funds the value. The vault path works because the codes are already yours — see how the gift-card vault works before designing around it.

Authentication

Create API keys in Dashboard → Settings (owner keys have full access; staff keys are scanner-only). Keys are stored only as SHA-256 hashes, so a key is shown once and cannot be recovered — see Security. Send the key as a bearer token:

curl https://api.rewardfinity.com/v1/members \
  -H "authorization: Bearer lp_sk_…" \
  -H "content-type: application/json" \
  -d '{"email":"customer@example.com","name":"Priya"}'

Endpoints

POST
/v1/merchants
Sign up a merchant → returns the API key (shown once). Rate-limited.
POST
/v1/members
Enroll a member (idempotent by email). Optional referralCode.
GET
/v1/members/:id
Member with balance, lifetime points, tier and stamps.
POST
/v1/events/purchase
Record a purchase → points/stamps/referrals. Idempotent by (source, externalId). Offers & tier multipliers apply automatically.
POST
/v1/events/refund
Refund → clawback at the purchase-time earn rate. Idempotent.
POST
/v1/rewards
Create a reward (discount / store_credit / giftcard).
POST
/v1/redemptions
Redeem for a member — race-safe balance check, idempotencyKey supported.
POST
/v1/campaigns
Create a QR reward campaign (budget + per-person caps).
POST
/v1/campaigns/:id/codes
Generate single-use claim codes (≤1000).
PATCH
/v1/campaigns/:id
Kill switch — pause/resume/end.
GET
/v1/campaigns/:id
Campaign stats: codes, claims, spend vs budget.
POST
/v1/promos
Create promo codes; POST /v1/promos/redeem to apply.
POST
/v1/wheels/:id/spin
Spin-to-win (atomic daily caps).
POST
/v1/members/import
CSV member import — idempotent per importId, balances preserved.
GET
/v1/insights
Rule-based program suggestions.
GET
/v1/automations
Configured lifecycle automations: birthday, winback, welcome, anniversary, and expiry.

Public (no auth): GET /p/:slug member page · POST /p/:slug/join self-enroll · POST /p/:slug/redeem member self-redemption · GET /c/:code claim page. Money is integer cents; points are integers; the ledger is append-only.

Why the same purchase twice is safe

A till on a bad connection retries. That is the normal case, not the edge case, and it is why /v1/events/purchase is keyed on (source, externalId) rather than on arrival.

Work it through with a rate of 1 point per $1 — that is an illustrative setting, not a default, because the earn rate is yours to configure. A $40 sale posts once and the member's balance moves by 40. The till times out and posts the same order identifier twice more. The ledger still holds one entry for that order and the balance is still 40, not 120. Refund the order and /v1/events/refund claws back at the rate that applied when the purchase was recorded, so a rate change between sale and refund cannot leave the member up or down.

The same key protects redemptions: idempotencyKey on /v1/redemptions means a retried redeem spends the balance once. Balances come from an append-only integer ledger, so a correction is a new entry rather than an edit to an old one.

Webhooks

Set a webhook URL in Dashboard → Automations. Rewardfinity POSTs batched events — member.joined, points.earned, stamp.added, reward.redeemed, campaign.claimed, plus automation firings — signed with your secret:

// verify: hex(HMAC-SHA256(rawBody, secret)) === headers['x-torna-signature']
{ "type": "torna.outbox", "events": [
  { "id": "out_…", "kind": "points.earned",
    "payload": { "email": "…", "pointsEarned": 25, "balance": 125 },
    "createdAt": 1783380000000 } ] }

Automation kinds are lifecycle triggers (birthday, winback, welcome, anniversary, and expiry). Firings keep web push and signed webhook events, and queue each consented email, SMS, or WhatsApp leg through the first-party dispatcher. Provider submission occurs only when the corresponding operator-enabled provider path is configured. Failed webhook deliveries stay pending and are retried on the next flush rather than dropped; provider callbacks distinguish acceptance from delivery for direct channels.

POS connections

Square connects natively (Dashboard → Integrations: paste your own access token; Rewardfinity registers its webhook and matches payments to members by email). Shopify uses signed store order and refund webhooks; Shopify POS remains an order-ingestion boundary until a POS extension is separately shipped and verified. Other POS systems (Clover, Lightspeed, Loyverse, Zettle…) drive the signed inbound endpoint POST /webhooks/in/:merchantId — directly or through Zapier/Make. Do not read the Shopify, Square, or generic webhook paths as one shared POS integration.

A fuller map of what connects and what does not is on integrations; the Shopify app is live and approved. What each plan includes is on pricing.

Questions developers ask

Does Rewardfinity have an API for instant reward delivery?
Purchase events synchronously record points and stamp progress and return the member’s balance. POST /v1/rewards creates a merchant-level catalog item, not a member-specific discount or store-credit issuance, and does not return a balance. POST /v1/redemptions separately records an eligible member redemption and the resulting points balance. Neither catalog creation nor recorded redemption proves external discount or store-credit delivery. Gift-card provider payout remains unavailable; Rewardfinity does not hold reward funds.
How long does a reward take to reach the member?
Successful purchase and redemption writes are readable after the request completes. An already-open member page may need a refresh to display current progress or eligibility. Redemption checks the current server-side balance rather than trusting the displayed value. Creating a discount or store-credit catalog item does not itself issue value to a member.
Can the API send a gift card automatically?
Only from your own vault. Import gift-card codes you bought into the encrypted vault, and a redemption allocates, spends and issues one in the same write, with the member revealing it on their member page. The other reading of the question — Rewardfinity buying and sending a card for you — does not happen. That payout is recorded as pending and no provider is enabled, because Rewardfinity does not hold reward funds.
What happens if my POS sends the same purchase twice?
Nothing twice. Purchases are idempotent on the pair (source, externalId), so a retry after a timeout is recognised as the same order and does not stamp or award again. Redemptions take an idempotencyKey for the same reason. This matters more than it sounds: a till retrying on a weak connection is the ordinary case in a shop.
How do I verify a Rewardfinity webhook signature?
Compute hex(HMAC-SHA256(rawBody, secret)) with the secret from your dashboard and compare it to the x-torna-signature header. Use the raw request body, not a re-serialised object, or the bytes will differ and the comparison will fail. Failed deliveries stay pending and are retried on the next flush rather than dropped, so a brief outage on your side does not lose events. Note the asymmetry: the write is synchronous, the outbound webhook is queued, so do not treat your webhook as the confirmation that the write happened.
Do I need an SDK to use the Rewardfinity API?
No. It is plain JSON over HTTPS with a bearer key, so curl or any HTTP client is enough, and there is no client library to keep in step with the service. Money is expressed in integer cents and points as integers, which avoids the rounding drift that floating-point currency introduces in a ledger.