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

# Add to Wallet

> From a button on your page to a live pass in the customer's wallet

This flow puts a pass in the customer's wallet from your own touchpoint: a page, app screen, or email. Your backend orchestrates it, and the API key never leaves your server.

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant C as Customer
    participant B as Your backend
    participant S as Stell API
    C->>B: Taps Add to Wallet
    B->>S: GET /v1/passes?programId=…&externalId=…
    S-->>B: Existing pass, or none
    opt No existing pass
        B->>S: POST /v1/passes
        S-->>B: 201 with pass id (PREACTIVE)
    end
    B->>S: GET /v1/passes/{passId}/links/apple or /google
    S-->>B: Time-limited link
    B-->>C: Redirect to link, pass lands in the wallet
    S--)B: Webhook PASS_STATUS_CHANGED (PREACTIVE → ACTIVE)
```

**Look up first.** [List passes](/api-reference/passes/list-passes) filtered by `programId` and `externalId` makes the button idempotent: an existing pass is reused, never duplicated.

**Issue with context.** [Create new pass](/api-reference/passes/create-new-pass) carries `programId`, `walletType` (`APPLE_WALLET` or `GOOGLE_WALLET`), your `externalId`, `customer` details for personalization, and the customer's current `loyaltyState`, such as `pointsBalance` and `currentTierId`. The pass is correct the moment it lands in the wallet. An optional `payload` sets what the pass carries for in-store scans; see [In-store](/api-reference/integration/in-store). Returns `201` with the pass `id`.

**Two link endpoints.** [Generate Apple Wallet installation link](/api-reference/passes/generate-apple-wallet-installation-link) returns a `.pkpass` download URL valid for roughly 15 minutes. [Generate Google Wallet save link](/api-reference/passes/generate-google-wallet-save-link) returns a save link valid for roughly an hour. Each response carries the exact deadline in `expiresAt`. Request links at click time, and never cache them.

**Activation is confirmed for you.** When the customer adds the pass, it flips from `PREACTIVE` to `ACTIVE` and a signed `PASS_STATUS_CHANGED` [webhook delivery](/programs/webhook-deliveries) tells your backend. Write it back to your customer record from there.

<Note>
  Don't want to build this flow? The [wallet button
  widget](/enrollment/wallet-button-widget) does the same thing with no API
  code. Stell hosts the button, the enrollment page, and the pass issuing.
</Note>
