Connect any POS.
Award points from a till or checkout system that can call an HTTPS API, then send confirmations back, using the purchase API and outbound webhooks together.
A loyalty program only pays off if the till feeds it. This recipe connects a point-of-sale system, or a Zapier/Make flow standing in for one, to the app in both directions: a sale goes in through an API, and a confirmation comes back out through an outbound webhook.
Will this work with my POS? This recipe needs one thing from the till: a way to call an HTTPS endpoint when a sale closes, either directly or through middleware, n8n, Make, or Zapier. A till that cannot do that, itself or through a tool it already connects to, cannot use this recipe. No till product has a native connector here: Shopify and WooCommerce have their own store integrations, and everything else arrives through this recipe.
APIs write to the app; webhooks only notify. The till (or the Zap standing in for it) calls the purchase endpoint to record a sale, the app applies the normal earning rules and writes the ledger entry, and outbound webhooks tell the till what happened. A webhook can never award points or approve a redemption by itself.
What you need
- At least one active loyalty card for the till to post against
- Either an Integration API key with the Point of Sale preset (preferred), or an existing session-token REST API integration
- An outbound webhook endpoint if the till should hear back. Webhooks comes with the partner's plan (Gold and Platinum include it by default) or from a per-partner grant; if Integrations → Webhooks is missing, ask your operator to turn it on.
Step 1: send the sale
Preferred: the Agent API
The Agent API is the preferred path for a POS or a Zap: a long-lived key instead of a login session, and its member_identifier field accepts whatever the till already knows about the customer, an email address, a phone number, a member number, or the unique identifier code, rather than requiring the app's own internal id.
Create an Integration API key with the Point of Sale preset (read, write:transactions, write:rewards) from Integrations → Integration API keys in the partner dashboard. See Enabling & Managing Keys.
POST /api/agent/v1/partner/transactions/purchase HTTP/1.1
Host: your-domain.com
Accept: application/json
Content-Type: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
{
"card_id": "3598a5db-f008-477c-ac4d-5365c662ad62",
"member_identifier": "[email protected]",
"purchase_amount": "24.50",
"currency": "EUR",
"source_completed_at": "2026-08-26T09:41:07+02:00",
"source_reference": "pos:store-1:till-3:98441",
"note": "Order #12345"
}
The card_id is fixed for a given till, set once during setup. member_identifier is the one value that changes per sale; match it on whatever the checkout already collects.
source_reference is what makes the call safe to send twice. Automation platforms and middleware retry on their own after a timeout, and without a reference each retry awards the points again. Build it from the sale's own facts, in the shape platform:store:till:sale-id, and reuse it for every retry of that one sale. The first call returns 201; an identical retry returns 200 with the original transaction and balance and awards nothing further. Keep customer data out of it.
The full flow, including member lookup, balance checks, reward redemption, stamps, and vouchers, is in POS integration, the field and response rules are in Record a purchase, and reusable request patterns live in Common workflows.
Alternative: an existing REST integration
A system already authenticating against the session-token REST API can use the equivalent partner endpoint instead of adding an Integration API key:
POST /api/en-us/v1/partner/cards/{cardUID}/{memberUID}/transactions/purchases HTTP/1.1
Host: your-domain.com
Authorization: Bearer your-partner-token
Accept: application/json
Content-Type: application/json
{
"purchase_amount": 24.50,
"note": "Order #12345"
}
This route takes the member's own unique identifier code in the URL rather than an email address or phone number, so it suits a system that already stores that code better than a POS built from scratch. See the REST API overview for authentication and the full endpoint list.
Step 2: The app applies the rules
Either call runs the same rules a staff member triggers at the counter: the card's points-per-currency ratio, rounding, the minimum and maximum per purchase, tier multipliers, and bonus hours all apply, and the ledger entry it writes is the one true record. A webhook never decides whether a sale counts; it only reports on it afterward.
Step 3: send a confirmation back
Subscribe the till, the Zap, or the middleware to the events it should react to, from Integrations → Webhooks. Two events matter most on this recipe, and they are not the same thing:
purchase.recordedmeans one accepted purchase: a sale posted by staff, an API call like the one above, or a connected store. If the till needs one trigger per sale, to print a receipt line or light up a confirmation, subscribe to this event.points.earnedis broader. It fires for every points increase: purchases, but also welcome bonuses, redeemed points codes, received transfers, and store-integration credits. Use it for a balance mirror, never to infer a sale.
When one sale triggers both, the two deliveries share a correlation_id (and the same transaction_id), so middleware that listens to both can tie them back to one purchase. Add voucher.redeemed or pass.used to acknowledge redemptions at the counter. See the event catalog and envelope shape and signature verification.
No developer on your team?
Before building anything by hand, check Automation templates: this recipe already exists as an importable Make blueprint, an importable n8n workflow, and a Zapier recipe, each with the in-person gating and the retry-safe reference built in.
An automation platform can stand in for custom code on both sides. One flow calls the purchase endpoint above through its own HTTP action when a sale closes in whatever tool is already in use; a second flow catches the outbound event and updates a spreadsheet, a Slack channel, or a display. See the Zapier and Make steps on the Webhooks overview and setup page for the catch-hook half of this pairing.
Two things to plan for before you start:
- Zapier needs a paid plan to publish this recipe. Sending a sale takes a webhook trigger, a filter, and an HTTP action in one Zap, and multi-step Zaps, Webhooks by Zapier, and Filter are paid features. You can build and test it on the free plan, but turning it on needs the paid one. Make and self-hosted n8n have no such gate.
- Whatever you pick sees the sale. The platform receives your base URL, the Integration API key, the card id, the member identifier, the amount, the currency, the sale reference, the completion time, the note, and the app's answer, and it may keep those values in its own run history. Prefer a member UUID or unique identifier over an email address, and choose self-hosted n8n when that data has to stay on infrastructure you control.
Related topics
- Webhooks overview and setup: Add an endpoint, then browse the event catalog, security, and delivery guides
- POS integration: The full cashier workflow, member lookup, rewards, stamps, and vouchers
- Common workflows: QR resolution, follow/unfollow, adjustments, and reconciliation
- Enabling & Managing Keys: Create an Integration API key with the Point of Sale preset
- REST API overview: The session-token alternative for existing integrations