Scope
subscriptions:writeorsubscriptions:read.
A plan is a price in one coin on one network, renewed every period_seconds. A subscription attaches one of your customers to a plan: they pay to their own permanent deposit address, and each payment is weighed against the current period (subscription.renewed).
Plans#
POST /subscriptions/plans
GET /subscriptions/plans?include_archived=true
GET /subscriptions/plans/:id
PATCH /subscriptions/plans/:id
DELETE /subscriptions/plans/:id # archives the plan → { "success": true }| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | At most 255 characters |
amount_decimal |
string | Yes | The price as a person writes it — "9.99" |
chain_id |
string | Yes | An EVM or Bitcoin chain_id from GET /chains — subscriptions do not run on Tron or the XRP Ledger |
asset_key |
string | Yes | "native", or the token's contract_address in lowercase |
period_seconds |
number | Yes | 2592000 for 30 days |
renewal_anchor |
string | No | from_payment (default — the next period starts when they pay) or from_period_end |
expiring_soon_lead_seconds |
number | No | When to send subscription.expiring_soon (default 259200, 3 days) |
amount |
string | — | Deprecated — the price in base units. Exactly one of amount_decimal / amount |
PATCH takes the same fields except chain_id and asset_key, all optional. A plan reads { "id", "name", "amount", "chain_id", "asset_key", "period_seconds", "renewal_anchor", "expiring_soon_lead_seconds", "archived_at", "created_at", "updated_at" }, with amount in base units.
Subscriptions#
POST /subscriptions { "external_ref": "user_123", "plan_id": "uuid", "label": "…" }
GET /subscriptions?status=active # pending | active | expired | canceled
GET /subscriptions/:id
PATCH /subscriptions/:id { "plan_id": "uuid" } # change plan
POST /subscriptions/:id/activate # activate by hand (e.g. paid off-platform)
POST /subscriptions/:id/cancel → { "success": true }
POST /subscriptions/:id/apply-credit # spend the subscription's credit on the next period
GET /subscriptions/:id/events
GET /subscriptions/events?since=2026-05-30T00:00:00Z&limit=100 # every subscription, max 500POST /subscriptions finds your customer by external_ref, or creates them (customer_created: true in the response), and gives them a deposit address on the plan's network when they have none. Idempotency-Key is optional, as for customers. A deleted customer's external_ref is refused 409 CUSTOMER_ARCHIVED.
A subscription:
{
"id": "uuid",
"customer_id": "uuid",
"customer_external_ref": "user_123",
"deposit_address": "0x...",
"deposit_tag": null,
"evm_address": "0x...",
"btc_address": null,
"plan_id": "uuid",
"plan_name": "Pro monthly",
"plan_amount": "9990000",
"chain_id": "1",
"asset_key": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"period_seconds": 2592000,
"renewal_anchor": "from_payment",
"status": "active",
"current_period_start": "2026-05-30T00:00:00.000Z",
"current_period_end": "2026-06-29T00:00:00.000Z",
"paid_amount_current_cycle": "9990000",
"credit_balance": "0",
"last_amount_status": "PAID",
"comped_at": null,
"expiring_soon_notified_at": null,
"canceled_at": null,
"created_at": "…",
"updated_at": "…"
}deposit_address is where the subscriber pays — the customer's address on the plan's network, or null when they have none there yet. deposit_tag is reserved for the XRP Ledger and is null today, as subscriptions run on EVM and Bitcoin networks only. apply-credit also returns credit_applied, new_period_start and new_period_end.
A subscription's public page data needs no key: GET /subscriptions/public/:id returns nothing merchant-internal.