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

# Loyalty console reference

> The /marketing/loyalty console end to end: earn rules and tiers, the member table columns, the Adjust and Redeem dialogs, the read-and-write permission split, and the API calls behind each control.

# Loyalty

The Loyalty console at `/marketing/loyalty` runs your standing membership program: you define how members earn points and which tiers they climb, and the console tracks every member's balance with the actions to adjust or redeem it. The [marketing hub overview](/marketing/overview) positions this console against the other three; the [Loyalty program guide](/guides/loyalty-program) designs earn rules, tiers, and the redemption flow; the [concept page](/concepts/loyalty-program-model) defines the model underneath.

Loyalty is a tenant-owned control. Points exist only because you defined the rules that mint them: until you configure a program, no member accrues anything.

## What you see on the page

The console stacks the program definition above the member table.

**Program header.** The program name with its current revision, plus the earn rules (for example *Per \$1* on the `order_paid` event) and the tier ladder with each tier's threshold and benefits. The header carries three controls: **Edit program** (or **Customize program** before you have touched the default), **Reset program**, and the member-level actions below.

**Members table.** One row per member in the program:

| Column | What it tells you |
| - | - |
| **Contact** | The member the balance belongs to |
| **Tier** | The highest tier whose threshold the member's lifetime points have crossed |
| **Available** | The spendable balance; redemption and debits draw from here |
| **Lifetime** | Every point ever earned, which is what tiers climb on |
| **Expiring soon** | Points inside the expiry window, when you have set `pointsExpiryDays` |
| **Adjust** | Open the adjust dialog for this member |
| **Redeem** | Open the redeem dialog for this member |

## Who can read and who can act

The dashboard gates the whole console at the workspace level; the API splits reads from writes at the scope level:

| Surface | Read | Write |
| - | - | - |
| Dashboard console | Workspace roles **owner** or **admin** | The same roles |
| Loyalty API | Key with the `contacts:read` scope | Key with the `contacts:write` scope |

A credential that clears the read scope but not the write scope can list balances and receives a `403` on program, adjust, and redeem writes.

## Worked examples

### Adjust a member balance with a reason

1. Find the member in the table and choose **Adjust**.
2. Pick a credit or a debit, enter the points, and write the reason, for example `goodwill — delayed order`.
3. Confirm. The available and lifetime figures move accordingly, and the reason is kept with the adjustment.

Use adjustments for corrections and goodwill: the program's earn rules stay the source of ordinary accrual.

### Redeem points through the incentives engine

1. Choose **Redeem** on the member's row.
2. Enter the points to burn. The dialog blocks overspend: you cannot redeem more than the **Available** figure.
3. Confirm. The balance drops, and the redemption posts to the [Incentives ledger](/marketing/incentives) as a record you can audit like any other reward.

### Set the program up against a wallet pass

Define at least one earn rule and a base tier at threshold 0 (the program form requires both), then issue loyalty cards from the [Wallet Passes console](/marketing/wallet-passes). Members accrue on the pass, and a balance update bumps the pass's generation counter so holder devices refresh without a re-save.

## API pairing

The console's program editor writes `POST /api/v1/loyalty/program`:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.orbit.devotel.io/api/v1/loyalty/program \
    -H "X-API-Key: dv_live_sk_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Club",
      "earnRules": [
        { "id": "purchase", "label": "Per $1", "type": "perUnit",
          "eventName": "order_paid", "field": "total",
          "pointsPerUnit": 1, "rounding": "floor" }
      ],
      "tiers": [
        { "id": "member", "name": "Member", "threshold": 0, "benefits": [] },
        { "id": "gold", "name": "Gold", "threshold": 5000,
          "benefits": ["Early access"] }
      ],
      "pointsExpiryDays": null
    }'
  ```
</CodeGroup>

The response carries the `revision_id` the program now reports. The full field lists live in the [Loyalty API reference](/api-reference/loyalty) — treat it as the contract for anything beyond the envelope above. The console's **Adjust** and **Redeem** dialogs write the adjust and redeem endpoints of the same surface.

## Tenant-owned controls

Earn rules, tier thresholds and benefits, point expiry, and every manual adjustment or redemption are values you set. The platform supplies the ledger and the enforcement, never the policy: until you configure a rule, nothing accrues, and until you reset or edit, the program keeps exactly the shape you last saved.


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