Core concepts

Rewards & Redemptions

Rewards are items that customers can purchase with their accumulated loyalty points. When a customer spends points on a reward, a redemption is created with a unique confirmation code.


Reward types

Discount

A monetary discount applied to a future purchase:

FieldDescription
discount_valueThe discount amount
discount_typepercent (e.g., 10% off) or fixed (e.g., EUR 5.00 off)

Free product

A complimentary product or service:

FieldDescription
product_referenceReference to the free product (vendor-defined)

Reward properties

FieldTypeDescription
idintegerUnique reward ID
namestringReward name
descriptionstringReward description
typestringdiscount or free_product
point_costintegerNumber of points required to redeem
total_stockintegerTotal available stock (null = unlimited)
remaining_stockintegerRemaining stock
statusstringactive or inactive
available_fromdatetimeStart of availability window (optional)
available_untildatetimeEnd of availability window (optional)
image_pathstringUploaded reward image
code_valid_for_hoursintegerHours the confirmation code is valid (optional)
branchesarray|nullThe branches this reward may be redeemed at, each { "external_id", "name", "type" }. null means every branch

Availability

Rewards can have a limited availability window defined by available_from and available_until. The API only returns rewards that are currently within their availability window and have remaining stock.


Redemption flow

1. Customer selects a reward

The POS system lists available rewards and the customer chooses one. Use the list rewards endpoint to fetch active rewards.

2. Submit a redemption

POST /api/v1/redemptions
{
    "identifier": "CARD-001",
    "reward_id": 5,
    "idempotency_key": "redeem-2024-0042"
}

The API validates:

  • The customer has sufficient wallet balance
  • The reward is active and available
  • The reward has remaining stock
  • The reward allows the branch the redemption is recorded at

The idempotency_key makes the call safe to retry: re-sending the same key returns the original redemption instead of deducting points twice.

Where the redemption happened

branch is your own key for the shop: the external_id you gave it. It follows the same chain a transaction's branch does: the key in the payload wins, otherwise the API credential's default branch, otherwise none. A key matching none of your branches is refused with BRANCH_NOT_FOUND (422), so a typo cannot pass for an unattributed redemption.

A reward that names branches may only be redeemed at one of them. Send no branch, or a branch outside its set, and the call is refused with BRANCH_REQUIRED (422). One code for both, because both have the same fix: name a branch the reward allows.

The branch is recorded once. A replay of the same idempotency_key returns the original redemption with the branch the first call recorded, even when the replay names a different one.

3. Confirmation code issued

On success, the API deducts points from the customer's wallet and returns a redemption with a confirmation code:

{
    "data": {
        "redemption_id": 12,
        "confirmation_code": "PNTJ-K4MP7QRS",
        "reward": {
            "name": "Free Coffee",
            "type": "free_product"
        },
        "points_deducted": 500,
        "remaining_balance": 1000,
        "redeemed_at": "2024-03-15T12:30:00+00:00",
        "expires_at": "2024-03-15T14:30:00+00:00"
    }
}

4. Verify the redemption

When the customer presents their confirmation code, verify it:

POST /api/v1/redemptions/{code}/verify

This transitions the redemption status from pending to verified.


Redemption status

StatusDescription
pendingCode issued, awaiting verification at POS
verifiedCode verified and reward delivered

Confirmation code expiration

If code_valid_for_hours is set on a reward, the confirmation code expires after that duration. Expired codes cannot be verified. The expires_at field in the redemption response indicates when the code will expire.


Looking up a redemption

You can look up a redemption by its confirmation code:

GET /api/v1/redemptions/{code}

This is useful for POS systems that need to display redemption details before verifying.

See Redemption endpoints for the complete API reference.

Previous
Earn Rules