# Manage Subscriptions

> Activate, list, inspect, and cancel MPP subscription delegations.

A **subscription** in `pay` is an MPP subscription delegation: an on-chain authority that lets a specific server (`puller`) pull a fixed stablecoin amount from your account on a recurring schedule. Once activated, the server charges you on its own — you don't sign each renewal.

That convenience means active subscriptions can drain your wallet quietly. Audit them with `pay subscriptions list` regularly.

## How a subscription gets activated

You don't usually run `pay subscriptions new` to start one — activation happens automatically as a side effect of a paid request.

```sh
pay --sandbox curl https://example.gateway/v1/premium
```

1. The server returns `402 Payment Required` with an MPP `subscription` challenge: a Plan PDA, a mint, a recipient, a per-period amount, and a period (e.g. `30d`).
2. `pay` decodes the challenge, builds an activation transaction signed by the active account, and retries the request with the credential.
3. The server verifies the on-chain `SubscriptionDelegation`, returns the response, and includes a `Payment-Receipt` header with the new `subscription_id` (the PDA in base58).
4. `pay` persists the subscription locally under that account in `~/.config/pay/accounts.yml`, so subsequent `pay subscriptions list` calls show it.

From here on, the server pulls funds on its own each period. No further action on your side until you want to inspect or cancel.

## List your subscriptions

```sh
pay subscriptions                       # default: list + show available subcommands
pay subscriptions list                  # same, scriptable
pay subscriptions list --account work
pay subscriptions list --network mainnet
pay subscriptions list --json
```

`list` walks every account in `accounts.yml`, dereferences each subscription's local record, and prints the schedule, recipient, amount per period, status, and base58 `subscription_id`. Use `--account` or `--network` to scope.

## Inspect a single subscription

```sh
pay subscriptions status <subscription_id>
pay subscriptions status <subscription_id> --json
```

The `subscription_id` is the `SubscriptionDelegation` PDA — the same base58 string `list` shows, and the one returned in the server's `Payment-Receipt` header at activation time.

`status` prints the plan, mint, puller, recipient, amount per period, period unit, activation signature, and current cancellation state.

## Backfill on-chain data

If the local record is missing a field (e.g. `activation_signature` because the call was interrupted), reconcile it from the chain:

```sh
pay subscriptions refresh
pay subscriptions refresh --account work --network mainnet
```

`refresh` reads the on-chain `SubscriptionDelegation` for each local entry and fills in any gaps. Read-only — never mutates on-chain state.

## Cancel a subscription

```sh
pay subscriptions cancel <subscription_id>
```

Cancellation flips the subscription's local state to `cancelled` **and** broadcasts an on-chain cancel transaction so the puller can no longer charge you. Two paths reach the same final state.

### Direct (requires SOL)

Default path. The subscriber signs and pays the Solana network fee from its own SOL balance. Fast and simple — but the account needs at least `50,000` lamports (~0.00005 SOL) on hand.

### Via the pay-api gateway (no SOL needed)

If the subscriber has less than `50,000` lamports, `pay` automatically routes through the pay-api gateway. The gateway returns a 402 charge challenge, you settle a small stablecoin fee, and the gateway broadcasts the cancel on your behalf as fee-payer.

Force the gateway path even when you have enough SOL:

```sh
pay subscriptions cancel <subscription_id> --via-gateway https://pay-api.gateway-402.com
```

| Flag                           | Description                                                                                                           |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `--via-gateway <URL>`          | Force routing through the named pay-api gateway. Auto-applied when subscriber SOL `< 50,000` lamports.                |
| `--gateway-fee-payer <BASE58>` | Gateway operator pubkey signing as fee-payer. Required when `--via-gateway` is set. Defaults to `$PAY_API_FEE_PAYER`. |
| `--rpc-url <URL>`              | RPC override. Defaults to `$PAY_RPC_URL` or the canonical RPC for the subscription's network.                         |

### Local-only cancel

If the on-chain side is already cancelled out of band (e.g. you closed the `SubscriptionAuthority` directly), skip the broadcast and just clean up the local record:

```sh
pay subscriptions cancel <subscription_id> --local-only
```

## Manual activation (advanced)

You normally don't run this — the 402 flow above is the user-facing path. Use `subscriptions new` when you already have the Plan PDA from another source and want to activate without making a request to the server.

```sh
pay subscriptions new \
  --plan <PLAN_PDA_BASE58> \
  --mint <USDC_MINT_BASE58> \
  --puller <SERVER_PULLER_BASE58> \
  --recipient <WALLET_BASE58> \
  --amount 1000000 \
  --period 30d
```

Every required flag corresponds to a field the on-chain program checks. `--amount` is in **mint base units** (1 USDC = 1,000,000 base units). `--period` accepts forms like `30d` or `2w`; `month` is rejected per the Solana subscription profile. See [Commands → subscriptions new](/docs/toolchain/commands/accounts#pay-subscriptions-new) for the full flag list.

## Where subscriptions live on disk

Each account's row in `~/.config/pay/accounts.yml` has an optional `subscriptions:` map keyed by `subscription_id`:

```yaml
version: 2
accounts:
  mainnet:
    work:
      keystore: apple-keychain
      pubkey: 96WoyH3JmANSMsQLGC3MKyiGiXCymZyM9SLaWjcRrKuD
      subscriptions:
        4xZk…:
          plan: 7nP…
          mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
          amount: '1000000'
          period_count: 30
          period_unit: day
          status: active
          activation_signature: 5Hk…
```

`pay subscriptions refresh` is what reconciles this map with the chain. If you `pay account remove <name>`, the subscription entries go with it — but the on-chain authority survives until you cancel each one.

## See also

- [Commands → subscriptions](/docs/toolchain/commands/accounts#pay-subscriptions) — full flag reference.
- [Manage Accounts](/docs/using-pay/manage-accounts) — switching accounts and moving stablecoins between them.
- [Pass-through commands](/docs/using-pay/pass-through-commands) — making the paid request that triggers activation.
