POS integration.
Build a point-of-sale integration for member lookup, balance checks, purchases, rewards, stamps, and vouchers.
This guide shows the typical cashier workflow: identify the member, inspect their current loyalty state, record the sale, and optionally redeem a reward, stamp card, or voucher.
Use this guide for:
- in-store POS systems
- kiosk terminals
- cashier tablets
- back-office terminals that behave like a POS
Recommended scopes
Start with:
readwrite:transactionswrite:rewards
Add these only if you need them:
write:stampswrite:vouchers
Core flow
- Find or search the member.
- Check the member's balance on the active card.
- Record the purchase.
- Optionally redeem a reward, add stamps, or process a voucher.
- Persist the external order or ticket reference on your side for reconciliation.
Member lookup
The partner API supports multiple member identifier formats. This is useful because different POS systems know different identifiers at checkout time.
Accepted forms:
- member UUID
- member number
- unique identifier
Examples:
{ "member_identifier": "[email protected]" }
{ "member_identifier": "MEM-2024-00001" }
{ "member_identifier": "550e8400-e29b-41d4-a716-446655440000" }
{ "member_identifier": "344-319-665-971" }
Exact lookup:
GET /api/agent/v1/partner/members/[email protected] HTTP/1.1
Host: your-domain.com
Accept: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
Search fallback:
GET /api/agent/v1/partner/members?search=jane&per_page=25 HTTP/1.1
Host: your-domain.com
Accept: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
Balance check
Once you know the member and the active card, fetch the live balance:
GET /api/agent/v1/partner/members/550e8400-e29b-41d4-a716-446655440000/balance/3598a5db-f008-477c-ac4d-5365c662ad62 HTTP/1.1
Host: your-domain.com
Accept: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
{
"error": false,
"data": {
"member_id": "550e8400-e29b-41d4-a716-446655440000",
"card_id": "3598a5db-f008-477c-ac4d-5365c662ad62",
"balance": 420,
"currency": "USD"
}
}
Record the purchase
Use POST /partner/transactions/purchase to award points for the sale.
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,
"staff_id": "9a126c5f-8737-4f0a-83b2-11a6b7e8f901",
"note": "Order #12345"
}
{
"error": false,
"data": {
"transaction_id": "019cce5d-c950-71d7-8f6f-731f06c3cf56",
"points_awarded": 2450,
"member_balance": 2870,
"purchase_amount": 24.5,
"card_id": "3598a5db-f008-477c-ac4d-5365c662ad62",
"member_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
staff_id delegation
This is an important design detail.
- Without
staff_id, the operation is recorded as an agent or system transaction. - With
staff_id, the operation is attributed to that staff member. - The
staff_idmust belong to the same partner.
Use staff_id when the terminal knows which cashier is currently signed in.
Points-only adjustments
If your POS needs to grant a manual point amount instead of calculating from a purchase amount, send points.
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": "MEM-2024-00001",
"points": 500,
"note": "Manual goodwill adjustment"
}
Redeem a reward
Use POST /partner/transactions/redeem when the member spends points at checkout.
POST /api/agent/v1/partner/transactions/redeem 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",
"reward_id": "7f1335c0-b6f1-4c82-8655-c5148d3fd3be",
"member_identifier": "[email protected]",
"staff_id": "9a126c5f-8737-4f0a-83b2-11a6b7e8f901",
"note": "Redeemed on POS ticket #12345"
}
{
"error": false,
"data": {
"transaction_id": "019cce5d-cae0-70b8-9af1-7158fca5bcdb",
"points_deducted": 100,
"member_balance": 2770,
"new_balance": 2770,
"reward_id": "7f1335c0-b6f1-4c82-8655-c5148d3fd3be",
"reward": {
"id": "7f1335c0-b6f1-4c82-8655-c5148d3fd3be",
"title": "Free Coffee"
},
"card_id": "3598a5db-f008-477c-ac4d-5365c662ad62",
"member_id": "550e8400-e29b-41d4-a716-446655440000"
}
}
Typical failure branch:
{
"error": true,
"code": "INSUFFICIENT_POINTS",
"message": "Member does not have enough points for this reward.",
"retry_strategy": "no_retry",
"details": {
"required": 100,
"available": 20
}
}
Stamp cards
Add stamps:
POST /api/agent/v1/partner/stamp-cards/{stampCardId}/stamps HTTP/1.1
Host: your-domain.com
Accept: application/json
Content-Type: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
{
"member_identifier": "[email protected]",
"stamps": 1,
"purchase_amount": 12.00,
"note": "POS ticket #12345"
}
Redeem a completed stamp reward:
POST /api/agent/v1/partner/stamp-cards/{stampCardId}/redeem HTTP/1.1
Host: your-domain.com
Accept: application/json
Content-Type: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
{
"member_identifier": "[email protected]",
"note": "POS redemption"
}
Vouchers
Validate the code before the order is finalized:
POST /api/agent/v1/partner/vouchers/validate HTTP/1.1
Host: your-domain.com
Accept: application/json
Content-Type: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
{
"code": "WELCOME10",
"member_identifier": "[email protected]",
"club_id": "019cce5d-bd81-7096-9118-9cb360ab9008",
"order_amount": 2450
}
Then redeem the voucher:
POST /api/agent/v1/partner/vouchers/{voucherId}/redeem HTTP/1.1
Host: your-domain.com
Accept: application/json
Content-Type: application/json
X-Agent-Key: rl_agent_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0
{
"member_identifier": "[email protected]",
"order_amount": 2450,
"order_reference": "12345"
}
Safe retry behavior
Do not blindly retry purchase or redemption requests. These flows are not idempotent.
- Use your own external order reference tracking.
- Pass the order or ticket ID in
notewhere available. - Reconcile ambiguous failures before replaying.
If you hit a rate limit:
{
"error": true,
"code": "RATE_LIMITED",
"message": "Too many requests. Please slow down.",
"retry_strategy": "backoff"
}
Honor Retry-After.