Subscriptions & free trials

Recurring checkouts create Subscription objects. You bill on a schedule, optionally start with a free trial, then keep access in sync via webhooks and GET /v1/subscriptions/:id.

How to create a subscription

There is no POST /subscriptions. Create a checkout session with mode: "subscription" (or plan_type: "recurring"), redirect the customer to the returned url, then provision when webhooks arrive.

1. Create a subscription checkout

Example request

POST /v1/checkout_sessions
Authorization: Bearer rk_live_...
Content-Type: application/json

{
  "price": "price_01HPRO...",
  "mode": "subscription",
  "success_url": "https://example.com/welcome?cs={CHECKOUT_SESSION_ID}",
  "cancel_url": "https://example.com/pricing",
  "customer_email": "ada@example.com",
  "metadata": {
    "user_id": "usr_42"
  }
}

Example response

{
  "id": "cs_01HXYZ...",
  "object": "checkout_session",
  "amount": 2900,
  "currency": "usd",
  "status": "open",
  "mode": "live",
  "plan_type": "recurring",
  "url": "https://rollopayments.com/pay/cs_01HXYZ...",
  "expires_at": 1723014400000,
  "livemode": true
}

How to handle it

  1. Store id against your user (from metadata or your session).
  2. Redirect the browser to url. Do not invent a pay URL.
  3. Your success page may show “Thanks” but do not unlock paid features yet— wait for webhooks (or poll the subscription after you receive subscription.created).

2. With a free trial

Example request

POST /v1/checkout_sessions
Authorization: Bearer rk_live_...
Content-Type: application/json

{
  "price": "price_01HPRO...",
  "mode": "subscription",
  "trial_days": 14,
  "customer_email": "ada@example.com",
  "success_url": "https://example.com/welcome"
}

Example response

{
  "id": "cs_01HTRI...",
  "object": "checkout_session",
  "amount": 2900,
  "currency": "usd",
  "status": "open",
  "mode": "live",
  "plan_type": "recurring",
  "url": "https://rollopayments.com/pay/cs_01HTRI...",
  "expires_at": 1723014400000,
  "livemode": true
}

How to handle it

Checkout collects a card with setup-mode (no charge on day one). The subscription starts as trialing while Rollo tracks the trial in your workspace. When the trial ends, Rollo charges the saved card off-session and moves the subscription to active. Each email may use a free trial once per merchant workspace (Sandbox and Live separately). If they already used a trial, Rollo drops trial_days and charges the full price immediately.

3. Ad-hoc recurring (no catalog price)

Example request

POST /v1/checkout_sessions
Authorization: Bearer rk_live_...
Content-Type: application/json

{
  "amount": 2900,
  "currency": "usd",
  "mode": "subscription",
  "interval": "month",
  "trial_days": 7,
  "customer_email": "vip@example.com",
  "success_url": "https://example.com/welcome"
}

Example response

{
  "id": "cs_01HADH...",
  "object": "checkout_session",
  "amount": 2900,
  "currency": "usd",
  "status": "open",
  "mode": "live",
  "plan_type": "recurring",
  "url": "https://rollopayments.com/pay/cs_01HADH...",
  "expires_at": 1723014400000,
  "livemode": true
}

How to handle it

Same handling as catalog subscriptions. On success Rollo creates a subscription (and an internal price) so renewals work the same way.

Merchant fee on subscriptions

Pass merchant_fee on the recurring checkout the same way as one-time sessions. Settings → Fees does not need to be on. The fee name plus percent and/or fixed amount sticks on that subscription so renewals and trial conversion charges keep the same fee. Full reference: Payments & fees.

4. Recurring checkout with platform fee

Example request

POST /v1/checkout_sessions
Authorization: Bearer rk_live_...
Content-Type: application/json

{
  "amount": 2900,
  "currency": "usd",
  "mode": "subscription",
  "interval": "month",
  "customer_email": "seller@example.com",
  "success_url": "https://example.com/welcome",
  "merchant_fee": {
    "label": "Platform fee",
    "percent": 5
  }
}

Example response

{
  "id": "cs_01HFEE...",
  "object": "checkout_session",
  "amount": 3195,
  "currency": "usd",
  "status": "open",
  "mode": "live",
  "plan_type": "recurring",
  "url": "https://rollopayments.com/pay/cs_01HFEE...",
  "merchant_fee": { "label": "Platform fee", "amount": 145 },
  "expires_at": 1723014400000,
  "livemode": true
}

How to handle it

Works with catalog price or ad-hoc amount. Use percent, amount (fixed cents), or both. Omit merchant_fee to use Settings defaults; send null to force no custom fee on that subscription.

How to use the subscription after checkout

  1. Subscribe your webhook endpoint to at least subscription.created, subscription.updated, subscription.canceled, invoice.paid, and invoice.payment_failed.
  2. On subscription.created, map data.id (sub_...) to your user and grant access based on data.status.
  3. Optionally fetch the full object when you need period dates:

Retrieve a subscription

Example request

GET /v1/subscriptions/sub_01HXYZ...
Authorization: Bearer rk_live_...

Example response

{
  "id": "sub_01HXYZ...",
  "object": "subscription",
  "status": "trialing",
  "amount": 2900,
  "currency": "usd",
  "interval": "month",
  "cancel_at_period_end": false,
  "payment_collection_paused": false,
  "trial_ends_at": 1724211200000,
  "current_period_end": 1724211200000,
  "customer": "cus_01H...",
  "customer_email": "ada@example.com",
  "created": 1723000100000,
  "livemode": true
}

How to handle it

  • status: trialing, active, past_due, canceled, etc.
  • Gate paid features on active (and optionally trialing).
  • Timestamps are Unix milliseconds. Convert with new Date(trial_ends_at).
  • Cancel / pause / resume are done in the Dashboard today — see Managing subscriptions.

End-to-end lifecycle

  1. Free-trial checkout completes (card saved, $0 charged) → checkout_session.completed, subscription.created with status trialing. Paid checkouts also send payment.succeeded.
  2. When the trial ends, Rollo charges the saved card → payment.succeeded + subscription.updated (active). Rollo fee rules still apply (merchant absorbs or customer pays fees). Any merchant_fee from signup is included again on that charge and later renewals.
  3. Trial/renewal charge fails → subscription becomes past_due. The customer gets an email with a secure link to update their card (see Payment recovery).
  4. Later renewals → payment.succeeded / subscription.updated.
  5. Cancel → subscription.canceled (revoke access).
Webhook data is flat — e.g. event.data.id, not event.data.object.id. Full payload examples live in Webhooks.

One-time vs recurring

A one-time price creates a single charge. A recurring price (day / week / month / year) creates a Subscription when checkout completes.

Metrics

Dashboard Customers reports MRR/ARR from active subscriptions, plus projected figures that include trialing subscriptions expected to convert.

Next guides