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 minor units (e.g. cents for USD, centavos for ARS).
price_currencyenum: ARS | BRL | EUR | USDyesRequired ISO-4217 pricing currency; price, cap, and budget are all denominated in its minor units. Must be quotable by the business's FX source (currently ARS). The subscriber picks the settlement token and chain at subscribe time.
period_durationintegeryes
capstringPer-charge ceiling, in price_currency's minor units. Optional -- defaults to budget (provided or derived).
budgetstringPer-window spend ceiling, in price_currency's minor units. Optional -- defaults to 10x price.
initial_chargebooleanWhether 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.
subscriberstring
external_customer_idstring
success_urlstringWhere to redirect the subscriber after a successful subscribe. Automatic countdown redirect and the primary CTA on the completed screen.
cancel_urlstringWhere to redirect the subscriber if the subscription checkout was actually cancelled. Also used on the expired terminal screen.
return_urlstringWhere 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).
metadataobjectFlat 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).
expires_atstring · date-time

Example Request

Request

const response = await fetch('https://checkout-api.exodus-int.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"
    }
  }),
});

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
business_namestringyes
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.
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",
  "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-int.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"
  },
  "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"
  }
}

Start building

XO

Request Demo

Schedule a call with our team

Select a product
Arrow right

Start building
Grateful

Contact Us

We're here to help