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:
pay --sandbox server start <file>.ymlThe 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:
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 listshows 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.
endpoints:
- method: GET
path: 'api/v1/pro/feed'
subscription:
period: '30d'
price_usd: 9.99
currency: USDCSubscriber flow:
# 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/feedWeekly content access ($1.99 / week)
Lower-priced, higher-cadence — a recurring content drop.
endpoints:
- method: GET
path: 'api/v1/daily-brief'
subscription:
period: '1w'
price_usd: 1.99
currency: USDCpay --sandbox curl http://127.0.0.1:1402/api/v1/daily-briefThe 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.
endpoints:
- method: GET
path: 'api/v1/research/{report}'
subscription:
period: '52w'
price_usd: 199.00
currency: USDC
expires_at: 2027-12-31T00:00:00Zpay --sandbox curl http://127.0.0.1:1402/api/v1/research/q4-2026After 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.
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# 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/AAPLPer-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.
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: USDCThe 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.
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# 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/AAPLInspecting active subscriptions
After activating, every subscription is tracked locally under the active wallet.
# 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 --jsonThe subscription_id is the one returned in the Payment-Receipt header at activation time.
Cancelling
pay subscriptions cancel BXQGmO5VwTrl5RfFr6Y8XQZ4nPj9QqMOiKkRn3pZ4ZEcancel 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 — the 402 challenge JSON, the activation transaction, and how renewal works under the hood.