> ## 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.

# Orchestrate a product launch across loyalty, wallet passes, referrals, and incentives

> Run the four reward surfaces as one campaign: build the loyalty program first, carry the card as a wallet pass, trigger the referral ask after first redemption, approve payouts in the incentives ledger, and measure the whole loop.

# Orchestrate a product launch across four surfaces

Orbit's four marketing surfaces each have their own guide: [loyalty](/guides/loyalty-program), [referrals](/guides/referrals-campaign-setup), [wallet passes](/guides/wallet-passes), and the [incentives ledger](/guides/incentives-ledger). Each explains its surface in isolation. This guide is the join: the order to build them in for a launch, a worked campaign that uses all four, the exact seams where one surface hands off to the next, who is allowed to touch what, and the go/no-go checklist for launch day.

## 1. The orchestration map

Each surface owns exactly one job in a campaign:

| Surface | Job | What it holds |
| - | - | - |
| [Loyalty](/guides/loyalty-program) | State | Points, tiers, and balances computed from your CDP event stream |
| [Wallet passes](/guides/wallet-passes) | Artifact | The card on the customer's phone and the barcode your POS scans |
| [Referrals](/guides/referrals-campaign-setup) | Acquisition | Per-contact share links, visits, signups, and conversions |
| [Incentives](/guides/incentives-ledger) | Payout rail | Every reward issued, redeemed, or voided, from any source |

Build in this order:

1. **Loyalty first.** Everything else reads from it: the pass displays the balance, the referral ask targets members who have redeemed, and the ledger records each redemption.
2. **Wallet passes second.** Pass content (points, tier, barcode) comes from loyalty reads, so the pipeline has nothing to render until the program exists.
3. **Referrals third.** The ask lands best after a member has redeemed once, so stage the program early but issue codes only after the first loyalty loop completes.
4. **Incentives is not a build step.** It is the rail the other three pay out on, and it holds rows from day one. The one setup item it owns is provider credentials for gift-card rewards, which must be provisioned before you promise gift cards.

What cannot run in parallel:

* Wallet-pass field mapping before the loyalty program is configured; the fields mirror loyalty reads.
* Referral code issuance before the landing URL is live and absolute `https`.
* Any payout promise (referral rewards, redemption rewards) before you have budgeted earn rates against the rewards you plan to honor.

## 2. Worked example: the "Spring Drop" launch

A fashion brand launches a seasonal drop and runs all four surfaces as one campaign.

**Step 1 — Enroll existing contacts with a double-points window (loyalty).** Configure the program with a `perUnit` earn rule on `order-completed`. For the launch window, raise `pointsPerUnit` (or add a `perEvent` rule for the drop) through the same `PUT /api/v1/loyalty/program` call, and run `POST /api/v1/loyalty/preview` against sample orders before adopting the change so the window math is checked with no database write. Existing contacts accrue the moment their order events land; there is no enroll call because balances derive from the event stream.

**Step 2 — Issue the loyalty-card pass (wallet passes).** At each enrollment, issue a `loyalty_card` pass with an `idempotency_key` built from the enrollment event, points and tier in `fields`, and the member number as `barcode_message`. Deliver the `save_url` in the welcome SMS, shortened through the [links endpoint](/api-reference/links). Follow [Issue and deliver a wallet pass end to end](/guides/wallet-passes) for the issue, update, and void lifecycle.

**Step 3 — Trigger the referral ask after first redemption (referrals + incentives).** A member's first redemption routes through the incentives engine and lands in the ledger as `source: "loyalty"`. Use that first redemption as the trigger: pick the cohort with loyalty traits (`loyalty_points_balance`, `loyalty_tier`) via [Segments](/api-reference/segments), mint a referral code per member with `POST /api/v1/referrals/programs/{id}/codes` (mint-or-get, safe to re-run nightly), and send the ask carrying the member's `https://api.orbit.devotel.io/r/…` share link.

**Step 4 — Redeem at POS via the pass (wallet).** The member presents the pass and the scanner reads `barcode_message`. The operator calls `POST /api/v1/loyalty/members/{contactId}/redeem` with the order id as `reference`, then posts the new balance to `POST /wallet-passes/{id}/update`; the generation counter moves and the phone refreshes without a re-save. The reward the member earns shows in the ledger under `source: "loyalty"`, and any referral conversion the member later produces is approved separately in the referrals console.

## 3. The seams: where you switch guides, and what flows across

* **Loyalty → wallet passes.** The contact id and the read from `GET /api/v1/loyalty/members/{contactId}` (`available`, `lifetimeEarned`, `expiringSoon`) become the pass `fields` at issue and on every update. Two identifiers travel into the wallet-passes guide: the `wps_…` pass id and the `idempotency_key` you chose at issue.
* **Wallet pass → POS.** `barcode_message` plus `barcode_format` is the entire seam to the physical store; scanner compatibility lives in the wallet-passes production checklist.
* **Loyalty redemption → incentives.** The redeem call's `reference` (the order id) is stamped onto the incentive row. Switch to the incentives-ledger guide to filter `source=loyalty&contact_id=…`, redeem, or void.
* **Referrals → incentives.** Approving a conversion with **Pay reward** fulfills non-credit rewards through the same engine; those rows carry `source: "referral"`. The acquisition seam is the per-contact code and its public `r/…` link.
* **Incentives → campaigns.** A `discount_code` row's `code` splices into an outbound template, or let the `{{coupon_code}}` merge tag derive a per-recipient code.

If an identifier stops making sense, you are reading the wrong guide: `wps_…` ids and generation counters belong to wallet passes, `ipo_…` ids and minted codes to incentives, `r/…` links to referrals, and contact ids to everything.

## 4. Permissions and roles split

| Surface | Who builds and writes | Who approves money | Reads |
| - | - | - | - |
| Loyalty | owner and admin on the dashboard (**Marketing → Loyalty**); a `contacts:write` key over the API | Redemptions and adjustments are writes, so owner or admin | `contacts:read` |
| Wallet passes | a `contacts:write` key for issue, update, and void, plus message-send permission to deliver; the dashboard builder under **Marketing → Wallet passes** | No payout lives on this surface | `contacts:read` |
| Referrals | owner, admin, and billing see the page at `/marketing/referrals` | **Pay reward** needs owner, admin, or billing; read-only roles cannot open the create dialog or the pay controls | Off-role users do not see the page at all |
| Incentives | console writes need owner, admin, or developer | Fulfillment follows the reward's provider | The ledger is readable otherwise |

The viewer-versus-write gap a marketing lead should plan around: a read-only seat can watch loyalty balances but cannot open the program, redeem, or adjust dialogs; on referrals that same seat does not see the page at all; on incentives it can read the ledger but not issue or void. Name your payout approver (an owner, admin, or billing seat) and your incentives writer (an owner, admin, or developer seat) before launch day, not during the first pending-conversions queue.

## 5. Measurement

* **Loyalty balances.** The Members panel under **Marketing → Loyalty**, or `GET /api/v1/loyalty/members/{contactId}` per member: `available`, `lifetimeEarned`, `expiringSoon`, and `nextExpiryAt`.
* **Wallet-pass delivery and installs.** Gate batch sends on `GET /wallet-passes/platforms`. Shorten each `save_url` through the [links endpoint](/api-reference/links) and read save-link click-through in [link tracking analytics](/guides/link-tracking-analytics) as your install proxy; the click is the last hop you can observe before the wallet app takes over.
* **Referral conversions.** The program page's stat cards and leaderboard, `GET /programs/{id}/totals` for aggregates, and the conversions table filtered to `pending` for the approval queue. The leaderboard doubles as the channel comparison when you issue codes per cohort.
* **Payout attribution.** The incentives ledger filtered by `source` separates what loyalty paid out from what referrals paid out from one-off promos; page with `limit` and `offset` and follow `has_more`.
* **Uplift.** For the double-points window and the referral ask, hold out a cohort and measure the difference the way [holdout uplift measurement](/guides/campaign-holdout-uplift-measurement) describes; loyalty traits in [Segments](/api-reference/segments) give you the member-versus-non-member split to compare.

## 6. Launch checklist, ordered by what breaks first

1. **Events.** Earn rules match the event names you actually send; a renamed event accrues nothing and fails silently.
2. **Program shape.** `POST /api/v1/loyalty/preview` passes, including the base tier at threshold `0`; a missing base tier is a `422` here rather than a production surprise.
3. **Economics.** Earn rates budgeted against the rewards you will honor, referral rewards on both sides included.
4. **Wallet platforms.** `GET /wallet-passes/platforms` checked before bulk delivery; a paused credential connection means messages carrying a link that goes nowhere.
5. **POS hardware.** Barcode format tested against the actual scanners, not assumed.
6. **Pass lifecycle hooks.** Update after every earn and redeem, void on cancellation, and treat `409 CONFLICT` as terminal rather than retryable.
7. **Referral staging.** Landing URL absolute `https` and live; the program staged with `enabled: false` until the ask is ready; codes issued per cohort so attribution does not blend.
8. **Approvers named.** An owner, admin, or billing seat for **Pay reward**; an owner, admin, or developer seat for incentives writes; a weekly pass over `pending` conversions on the calendar.
9. **Send gates.** Quiet hours, suppression lists, and frequency caps confirmed to fire on every message that carries a pass link or a referral link.
10. **Dress rehearsal.** One contact through the whole loop: preview the earn, issue the pass, click the save link, redeem at POS, update the pass, and see the ledger row with `source: "loyalty"` before you open the loop to the audience.

## Related reading

* [Loyalty program setup: points, tiers, and redemption](/guides/loyalty-program)
* [Set up a referral campaign from the dashboard](/guides/referrals-campaign-setup)
* [Issue and deliver a wallet pass end to end](/guides/wallet-passes)
* [Run the incentives ledger: promos and support credits](/guides/incentives-ledger)
* [Segments](/api-reference/segments) — loyalty traits as entry conditions
* [Campaign holdout uplift measurement](/guides/campaign-holdout-uplift-measurement) — attributing the lift each surface produced


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