> ## Documentation Index
> Fetch the complete documentation index at: https://tapace.lk/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Points cards

> Issue loyalty points cards and add or subtract points as customers spend.

A points card shows the holder's points balance, such as `350 / 1,000` toward a reward, or a running total like `1,250`. TapAce keeps each pass's balance and updates it in the holder's wallet whenever it changes.

## Set up the card

Create a template from the **Points Card** starter in the dashboard, then change it in the designer. A points card template has the type `points_card`. In the designer you choose:

* The starting balance for new passes, such as `0` or a welcome bonus.
* Optional limits: a **minimum**, which may be negative, a **goal**, and a **maximum**. The balance stops at the goal; the maximum only applies when there is no goal.
* A strip image for Apple Wallet and a banner for Google Wallet, both optional.
* Where the points field sits on the pass. In the large primary spot, Apple Wallet draws the balance over the strip in white, so use a strip dark enough to read it on.
* The text of the notification sent when points change, and optionally a different one for when the balance reaches the goal.
* For Google Wallet, the fields shown as **Member ID** (a required per-pass field) and **Member name**.

Balances can have up to 2 decimal places and range from `-9,999,999.99` to `9,999,999.99`. With a goal the card shows `350 / 1,000`; without one, just `350`. Google Wallet shows the same text as the card's balance.

## Issue a card

Issue it like any pass with [`POST /v1/passes`](https://tapace.lk/docs/api-reference/passes/issue). It starts at the template's starting balance, or send `points` to start somewhere else:

```bash theme={null}
curl https://api.tapace.lk/v1/passes \
  -H "Authorization: Bearer $TAPACE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tmpl_Q4vN8xT2mLr7KpZs3Wd1",
    "fieldValues": { "memberNumber": "TC-00284", "memberName": "Nimal Perera" },
    "points": 100
  }'
```

The pass's `points` holds the balance and the template's limits: `{ "balance": 100, "min": 0, "max": null, "goal": 1000 }`. A limit that isn't set is `null`.

## Add or subtract points

When the holder earns points, call [Add points](https://tapace.lk/docs/api-reference/passes/add-points.md):

```bash theme={null}
curl https://api.tapace.lk/v1/passes/pass_7hGk2LmQ9xVt4RnB8cYe/points \
  -H "Authorization: Bearer $TAPACE_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "add": 50 }'
```

* TapAce adds to the pass's current balance, so two changes at the same time both count.
* A negative `add` subtracts points, for example when the holder redeems a reward. TapAce doesn't track rewards, so subtract the points the reward costs.
* A change that would pass a limit stops at it: adding 50 to `980 / 1,000` gives `1,000 / 1,000`.

To set an exact balance, send `points` to [Update a pass](https://tapace.lk/docs/api-reference/passes/update.md). A value outside the limits is also stopped at the nearest one:

```json theme={null}
{ "points": 0 }
```

## Notify the holder

Points changes are silent unless you send `"notificationMode": "notify"`. The notification uses the text set on the template, where `{change}` becomes the amount you asked for, such as `+50` or `−20`, and `{balance}` the new balance. For example, "{change} points, you now have {balance}" becomes "+50 points, you now have 400 / 1,000".

On Apple Wallet it appears on the lock screen; on a card without a field showing the points, it replaces the pass's **Message for you**.

### When the goal is reached

A template with a goal can also set goal texts, such as "You reached 1,000 points! Show this card for your voucher." They're sent instead of the usual text when a notifying change takes the balance up to the goal, whether through [Add points](https://tapace.lk/docs/api-reference/passes/add-points.md) or by setting `points`.

* On Apple Wallet the text replaces the pass's **Message for you**, and the holder gets just this one alert.
* On Google Wallet it has its own title and message.
* A silent change that reaches the goal stays silent.
* If the template has no goal text, the usual one is sent.

> [!NOTE]
>
> Google Wallet allows 3 notifications per pass in 24 hours. Beyond that, the pass still updates but no alert is shown.

## Change the design

If you narrow the limits, such as lowering the goal, and [deploy the template](https://tapace.lk/docs/api-reference/deployments/create.md), each pass outside the new limits moves to the nearest one. The change shows in each pass's [update history](https://tapace.lk/docs/api-reference/passes/list-updates.md).

## Use the Node.js SDK

Call `tapace.passes.addPoints(passId, { add: 25, notificationMode: "silent" }, options)` to credit 25 points. The response contains the updated pass and an optional wallet update record. Read `result.pass.points?.balance` to inspect the stored balance; confirm the display separately on the phone.

Supply a stable idempotency key derived from the saved sale or award ID, and reuse the same body for retries. A new purchase needs a new operation ID. See the [SDK loyalty example](https://tapace.lk/docs/sdk/node/resources.md#credit-loyalty-balances).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.