Orishare
Loyalty guides

VIP tiers with yearly windows and benefits

Qualify members per calendar or membership year, keep a tier through the following year, add a grace period, declare benefits and gate offers by tier.

A tier program ranks members by what they earned in one currency. This guide covers the yearly programs most VIP schemes use: a member qualifies during a year, keeps the tier for the rest of that year and the whole next one, and sees what each tier gives them.

1. Choose the qualification window

basis says what counts towards a tier.

basis.typeWhat counts
lifetime_earnedEverything the member ever earned
balanceThe available balance right now
earned_rolling_daysEarned in the last days days
earned_calendar_yearEarned since 1 January, in the environment time zone
earned_anniversary_yearEarned since the member's latest anniversary of the day they were created

Earned amounts are net of reversals: a refunded purchase stops counting in the year it was earned. A member created on 29 February has their anniversary on 28 February in other years.

2. Create the program

curl -X POST "$ORISHARE_API/v1/tier_programs" -H "Authorization: Bearer $SECRET_KEY" \
  -H "Idempotency-Key: vip-program" -H "Content-Type: application/json" \
  -d '{
    "name": "VIP",
    "currency": "points",
    "basis": { "type": "earned_calendar_year" },
    "downgrade_check": "daily",
    "retention": { "mode": "through_next_period", "grace_days": 14 },
    "levels": [
      { "name": "Member", "threshold": 0 },
      { "name": "Silver", "threshold": 500,
        "benefits": [{ "key": "birthday_gift", "title": "Birthday gift" }] },
      { "name": "Gold", "threshold": 1000,
        "benefits": [
          { "key": "free_shipping", "title": "Free shipping", "description": "On every order", "icon": "truck" },
          { "key": "early_access", "title": "Early access to sales" }
        ] }
    ]
  }'

Members move up as soon as they qualify: a rule with the tier.evaluate action, or POST /v1/tier_programs/{id}/evaluate for one customer. Moving down only happens in the scheduled check (downgrade_check: daily, monthly or never).

3. Retention and grace

retention is optional. Without it a program behaves as it always did.

  • mode: "through_next_period" keeps a tier earned in a year until the end of the following year. Gold earned in 2026 lasts through 2027. If the member reaches Gold again in 2027 it lasts through 2028; if they only reach Silver in 2027 they move to Silver at the start of 2028, and if they earn nothing they move to the first level. It needs a calendar or anniversary basis.
  • grace_days (0 to 366) delays any downgrade. The first check that finds a member below their tier records a date that many days ahead instead of moving them. Qualifying again before that date cancels it. Grace works with every basis.

Use downgrade_check: "daily" with a grace period. A monthly check only looks once a month, so the downgrade would wait for the first check after the grace date.

Setting a member's tier by hand (POST /v1/customers/{id}/tiers) is not protected by retention: the next scheduled check moves them to the tier they qualify for, after the grace period if there is one.

4. Read a member's tier

curl "$ORISHARE_API/v1/customers/user_42/tiers" -H "Authorization: Bearer $SECRET_KEY"
{
  "data": [
    {
      "customer_id": "cust_...",
      "program_id": "tp_...",
      "level": "Silver",
      "since": "2026-10-04T15:02:11.000Z",
      "last_evaluated_at": "2026-10-04T15:02:11.000Z",
      "source": "evaluate",
      "qualifies_until": "2028-01-01T05:00:00.000Z",
      "grace_until": null,
      "benefits": [{ "key": "birthday_gift", "title": "Birthday gift" }],
      "next_level": {
        "name": "Gold",
        "threshold": 1000,
        "benefits": [{ "key": "free_shipping", "title": "Free shipping" }]
      }
    }
  ],
  "next_cursor": null,
  "has_more": false
}
  • qualifies_until is when the tier is next up for review: the end of the year it was earned in, or of the following year with through_next_period. It is null for programs without a yearly window and while a downgrade is pending.
  • grace_until is set while a downgrade is pending and says when it takes effect.
  • next_level is null at the top tier.

5. Benefits

Benefits are a declared list per level (up to 20), for your storefront and emails to show. Each has a key (lowercase letters, digits and underscores, unique within the level), a title, and an optional description and icon. Declaring a benefit grants nothing by itself: deliver it with a rule, a tier-gated offer, or your own code reading the member's tier.

When you update a program, a level sent without benefits keeps the list it has; send "benefits": [] to clear it. Config export and import carry retention and benefits.

6. Offers for a tier and above

A catalogue offer can require a minimum tier in its eligibility:

{
  "eligibility": {
    "audience": [],
    "minimum_assurance": "authenticated_customer",
    "minimum_tier": { "tier_program": "VIP", "min_level": "Gold" }
  }
}

tier_program is the program's id or name. Members at min_level or any higher level may redeem; everyone else sees the offer as not available to them. A member who was never evaluated counts as the first level.

Changing an existing program

Changing basis re-evaluates every member, so it needs "reevaluate": true on the update. Changing retention or benefits does not move anyone; retention takes effect at the next scheduled check.

On this page