Skip to Content
CheckoutAPI ReferenceSubscription CheckoutsCreate a subscription checkout

Create a subscription checkout

POST/subscription-checkouts

Create a single-use intent that authorizes a customer to start a recurring subscription. The merchant declares an optional per-window budget (defaults to 10x price) and an optional per-charge cap (defaults to budget); all amounts are in price_currency's minor units. The subscriber picks the settlement token at subscribe time. Returns a checkout_url — redirect the customer there to complete the subscribe and first-charge flow. No signed request is needed at creation; the customer's on-chain signature authorizes the subscription and first charge atomically.

Headers

HeaderDescriptionRequired
AuthorizationBearer token with your secret API keyyes

Request Body

FieldTypeRequiredDescription
supported_chainsstring[]—
pricestringyesThe recurring per-cycle amount, in price_currency's ISO 4217 minor units (e.g. cents for USD, centavos for ARS; CLP has no minor unit, so CLP 15,000 is 15000). At most 9007199254740991.
price_currencyenum: USD | ARS | BRL | COP | UYU | CLP | VES | MXN | BOB | EURyesRequired ISO-4217 pricing currency; price, cap, and budget are all denominated in its minor units. Crypto-settled businesses price in USD and ARS, and test businesses also in BRL, COP, UYU, CLP, VES, MXN and BOB. Fiat-settled businesses price in their settlement currency. The subscriber picks the settlement token and chain at subscribe time.
period_durationintegeryes
capstring—Per-charge ceiling, in price_currency's minor units. Optional -- defaults to budget (provided or derived). At most 9007199254740991.
budgetstring—Per-window spend ceiling, in price_currency's minor units. Optional -- defaults to 10x price. At most 9007199254740991.
initial_chargeboolean—Whether the customer is charged the first period at subscribe time. When false, the subscribe signature only registers the subscription on-chain (no funds move) and billing starts with the first merchant-relayed charge. Chargeless subscriptions are EVM-only: when supported_chains is omitted, chains without chargeless subscribe support are dropped from the resolved set; naming one explicitly in supported_chains is rejected, as is a merchant with no chargeless-capable deployment at all.
subscriberstring—
external_customer_idstring—
success_urlstring—Where to redirect the subscriber after a successful subscribe. Automatic countdown redirect and the primary CTA on the completed screen.
cancel_urlstring—Where to redirect the subscriber if the subscription checkout was actually cancelled. Also used on the expired terminal screen.
return_urlstring—Where to send the subscriber if they leave a still-pending subscription checkout. Purely navigational — no side effects. Distinct from cancel_url (the subscription checkout was actually cancelled) and success_url (the post-subscribe confirmation destination).
metadataobject—Flat map of merchant-defined references. Up to 50 keys; keys up to 40 characters; values are strings up to 500 characters (nested values are rejected). Echoed back on the intent and on every subscription_checkout.* webhook. Two keys are also rendered on the hosted subscribe page: plan_name at the end of the summary card, below the economic terms, with plan_description as supporting copy directly beneath it. Only those two exact keys are read — every other key, including any other plan_* key, stays opaque to Exodus and is never shown. The two are independent: pass one, both, or neither.
expires_atstring · date-time—

Example Request

Request

const response = await fetch('https://checkout-api.exodus.com/subscription-checkouts', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer sk_live_xxxxxxxxxxxxxxxx',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "supported_chains": [
      "eip155:1",
      "eip155:137"
    ],
    "price": "250000",
    "price_currency": "ARS",
    "period_duration": 2592000,
    "cap": "1000000",
    "budget": "2500000",
    "initial_charge": true,
    "success_url": "https://merchant.com/subscribed",
    "cancel_url": "https://merchant.com/cancelled",
    "return_url": "https://merchant.com/plans/pro",
    "metadata": {
      "external_plan_ref": "pro_monthly",
      "plan_name": "Pro",
      "plan_description": "Unlimited projects and priority support"
    }
  }),
});

Responses

StatusDescription
201The created subscription checkout.
400Validation error
401Missing or invalid authentication
403API key lacks the required scope

Response body

FieldTypeRequiredDescription
objectenum: subscription_checkoutyes
idstringyes
statusenum: pending | completed | expired | cancelledyes
onchain_idstringyes
subscription_idstring | nullyesThe on-chain id of the subscription created from this checkout, usable with GET /subscriptions/{id}, or null until one exists. Always equal to onchain_id once a subscription is bound: onchain_id is reserved when the checkout is created, so subscription_id is the field that tells you a subscription exists. Present even when the checkout is cancelled or expired, because a subscriber whose subscribe landed after a cancel keeps a live subscription.
business_idstringyesYour Exodus business id. Stable for the life of the business and also returned by GET /settings.
business_namestringyesThe merchant name shown to subscribers on the hosted subscribe page: your display_name from GET /settings when set, otherwise your registered business name.
background_colorstring | nullyes
primary_colorstring | nullyes
subscriberstring | nullyes
external_customer_idstring | nullyes
subscription_optionsobject[]yesEvery chain/token combination the subscriber may pick at subscribe time. Always an array -- do not assume a single entry.
pricestringyesThe recurring per-cycle amount, in price_currency's minor units. price, cap, and budget share one unit system; fiat figures convert to exact-out token amounts at subscribe/charge time via a quote, never pre-converted here. At most 9007199254740991.
price_currencystring | nullyesISO-4217 pricing currency. Always set on checkouts created after fiat-only creation shipped; null only on legacy rows.
period_durationnumberyes
capstring | nullyesPer-charge ceiling, same unit system as price.
budgetstringyesPer-window spend ceiling, same unit system as price.
initial_chargebooleanyes
checkout_urlstringyes
success_urlstring | nullyes
cancel_urlstring | nullyes
return_urlstring | nullyes
metadataobject | nullyes
expires_atstringyes
created_atstringyes
updated_atstringyes
completed_atstring | nullyes
cancelled_atstring | nullyes
expired_atstring | nullyes
cancellation_reasonstring | nullyes

subscription_options

FieldTypeRequiredDescription
chainstringyes
tokenstringyes
subscription_manager_addressstringyes
relayer_addressstringyes

Example Response

{
  "object": "subscription_checkout",
  "id": "schk_1234567890abcdef",
  "status": "completed",
  "onchain_id": "0x9f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a",
  "subscription_id": "0x9f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a",
  "business_id": "clzk3n8x50000qw3f7h2p9r1b",
  "business_name": "Acme Inc",
  "background_color": "#0f172a",
  "primary_color": "#7c3aed",
  "subscriber": "0x742d35Cc6634C0532925a3b844Bc9e7595f8fE21",
  "external_customer_id": "cus_42",
  "subscription_options": [
    {
      "chain": "eip155:1",
      "token": "USDC",
      "subscription_manager_address": "0xa1b2c3d4e5f6789012345678901234567890abcd",
      "relayer_address": "0x9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b"
    },
    {
      "chain": "eip155:137",
      "token": "USDC",
      "subscription_manager_address": "0xb2c3d4e5f67890123456789012345678901234cd",
      "relayer_address": "0x9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b"
    }
  ],
  "price": "250000",
  "price_currency": "ARS",
  "period_duration": 2592000,
  "cap": "1000000",
  "budget": "2500000",
  "initial_charge": true,
  "checkout_url": "https://checkout.exodus.com/subscribe/schk_1234567890abcdef",
  "success_url": "https://merchant.com/subscribed",
  "cancel_url": "https://merchant.com/cancelled",
  "return_url": "https://merchant.com/plans/pro",
  "metadata": {
    "external_plan_ref": "pro_monthly",
    "plan_name": "Pro",
    "plan_description": "Unlimited projects and priority support"
  },
  "expires_at": "2026-05-19T12:05:00Z",
  "created_at": "2026-05-19T12:00:00Z",
  "updated_at": "2026-05-19T12:02:18Z",
  "completed_at": "2026-05-19T12:02:18Z",
  "cancelled_at": null,
  "expired_at": null,
  "cancellation_reason": null
}

Error Response

Error (e.g. 400)

{
  "error": {
    "type": "validation_error",
    "message": "amount must be a positive number",
    "param": "amount"
  }
}
Last updated on

Start building

XO

Request Demo

Schedule a call with our team

Select a productArrow right

Start building
Grateful

Contact Us

We're here to help