# Examples

> Drop-in subscription specs — monthly access, weekly content, tiers, expiry caps, custom routing, mixed pricing — each downloadable and runnable with pay server start.

Each example below is a **full, runnable provider spec**. Click the download button, save the file, then in one terminal:

```sh
pay --sandbox server start <file>.yml
```

The first launch prompts you to publish each subscription's on-chain `Plan` PDA (sandbox covers the rent). Subsequent launches reuse the same PDAs.

From another terminal, activate as a subscriber with `pay curl`:

```sh
pay --sandbox curl http://127.0.0.1:1402/<path-from-the-spec>
```

Every spec uses `routing.type: respond` so it boots without any upstream service — the gateway returns 200 with the verified payment signature once the subscription activates. Each one also has a commented-out `proxy` block ready to flip on when you wire in a real upstream.

## Agent summary

- Every spec validates with `pay --sandbox server start` (verified locally before publishing this page).
- The first call activates the subscription; subsequent calls within the period skip the activation prompt entirely.
- `pay subscriptions list` shows every subscription the local wallet has activated.

## Monthly API access ($9.99 / 30 days)

The canonical recurring API plan — one endpoint, $9.99 USDC every 30 days.

<DownloadSpec file="monthly.yml">

```yaml
endpoints:
  - method: GET
    path: 'api/v1/pro/feed'
    subscription:
      period: '30d'
      price_usd: 9.99
      currency: USDC
```

</DownloadSpec>

Subscriber flow:

```sh
# First call — activates the subscription, $9.99 charge settles.
pay --sandbox curl http://127.0.0.1:1402/api/v1/pro/feed

# Same call within 30 days — no payment prompt, just the response.
pay --sandbox curl http://127.0.0.1:1402/api/v1/pro/feed
```

## Weekly content access ($1.99 / week)

Lower-priced, higher-cadence — a recurring content drop.

<DownloadSpec file="weekly.yml">

```yaml
endpoints:
  - method: GET
    path: 'api/v1/daily-brief'
    subscription:
      period: '1w'
      price_usd: 1.99
      currency: USDC
```

</DownloadSpec>

```sh
pay --sandbox curl http://127.0.0.1:1402/api/v1/daily-brief
```

The merchant's renewal worker pulls $1.99 every 7 days until cancellation.

## Annual access with an expiry cap

`52w` is the longest supported period. Combine with `expires_at` to put a hard HTTP-layer ceiling on how long renewals keep firing.

<DownloadSpec file="annual-with-expiry.yml">

```yaml
endpoints:
  - method: GET
    path: 'api/v1/research/{report}'
    subscription:
      period: '52w'
      price_usd: 199.00
      currency: USDC
      expires_at: 2027-12-31T00:00:00Z
```

</DownloadSpec>

```sh
pay --sandbox curl http://127.0.0.1:1402/api/v1/research/q4-2026
```

After `2027-12-31T00:00:00Z` the gateway stops renewing — the next gated request returns 402 with a fresh challenge regardless of on-chain state.

## Multiple tiers on the same provider

Subscription tiers are just separate endpoints. Each tier gets its own on-chain `Plan` PDA.

<DownloadSpec file="tiers.yml">

```yaml
endpoints:
  - method: GET
    path: 'api/v1/basic/quote/{symbol}'
    subscription:
      period: '30d'
      price_usd: 5.00
      currency: USDC

  - method: GET
    path: 'api/v1/pro/quote/{symbol}'
    subscription:
      period: '30d'
      price_usd: 25.00
      currency: USDC

  - method: GET
    path: 'api/v1/enterprise/quote/{symbol}'
    subscription:
      period: '30d'
      price_usd: 199.00
      currency: USDC
```

</DownloadSpec>

```sh
# A basic subscriber can read /basic/ — but /pro/ still 402s for them.
pay --sandbox curl http://127.0.0.1:1402/api/v1/basic/quote/AAPL
```

## Per-product revenue routing

Different endpoints can settle to different wallets via `subscription.recipient`. The operator-level recipient acts as the default; any endpoint can override.

<DownloadSpec file="per-product-routing.yml">

```yaml
operator:
  # recipient: '<your-default-revenue-wallet>'

endpoints:
  - method: GET
    path: 'api/v1/data/{stream}'
    subscription:
      period: '30d'
      price_usd: 49.00
      currency: USDC
      # recipient: '<dedicated-data-product-wallet>'

  - method: GET
    path: 'api/v1/ai/{model}'
    subscription:
      period: '30d'
      price_usd: 99.00
      currency: USDC
```

</DownloadSpec>

The recipient overrides are commented out in the downloadable spec so it boots cleanly under sandbox — uncomment and substitute real wallet addresses for production.

## Subscription alongside metered pricing

Subscription and metered endpoints can live in the same spec. The two paths are independent — a `pro/quote` subscriber still pays $0.01 per call if they ever hit the metered `/quote` path.

<DownloadSpec file="with-metered.yml">

```yaml
endpoints:
  - method: GET
    path: 'api/v1/quote/{symbol}'
    metering:
      dimensions:
        - direction: usage
          unit: requests
          tiers:
            - price_usd: 0.01

  - method: GET
    path: 'api/v1/pro/quote/{symbol}'
    subscription:
      period: '30d'
      price_usd: 9.99
      currency: USDC
```

</DownloadSpec>

```sh
# Per-call: pays $0.01 every time.
pay --sandbox curl http://127.0.0.1:1402/api/v1/quote/AAPL

# Flat-fee: pays $9.99 once, free for 30 days.
pay --sandbox curl http://127.0.0.1:1402/api/v1/pro/quote/AAPL
```

## Inspecting active subscriptions

After activating, every subscription is tracked locally under the active wallet.

```sh
# Every subscription the local wallet has activated, any network.
pay subscriptions list

# Just the mainnet ones.
pay subscriptions list --network mainnet

# Full detail for a specific subscription.
pay subscriptions status BXQGmO5VwTrl5RfFr6Y8XQZ4nPj9QqMOiKkRn3pZ4ZE

# JSON for scripting.
pay subscriptions list --json
```

The `subscription_id` is the one returned in the `Payment-Receipt` header at activation time.

## Cancelling

```sh
pay subscriptions cancel BXQGmO5VwTrl5RfFr6Y8XQZ4nPj9QqMOiKkRn3pZ4ZE
```

`cancel` submits an on-chain `cancel_subscription` instruction. The currently-paid period is honored until its end; renewals stop after that. Use `--local-only` to flip the local status without an on-chain transaction (e.g. when the subscription has already been revoked on-chain through another path).

## Next

- [Protocol & internals](/docs/building-with-pay/subscriptions/protocol) — the 402 challenge JSON, the activation transaction, and how renewal works under the hood.
