Payments & fees

A Payment represents a charge under Rollo's Merchant of Record model. Amounts are integers in the smallest currency unit (cents).

Pricing

Successful charges are billed at 7.9% + $0.75.

Who pays the fee

By default you absorb the Rollo fee. Enabling Pass fees to customers increases the charged amount so you net the product price: ceil((product + 50) / (1 − 0.059)).

Your own fees (platform / service fee)

Charge a named fee (for example "Platform fee" or "Handling") on top of the product. That fee is added to the buyer total and settles to you in full. Rollo's 7.9% + $0.75 still applies only to the product amount — your custom fee is not Rollo take.

Per checkout (recommended for platforms): pass merchant_fee on POST /v1/checkout_sessions. Set a fee name plus percent and/or fixed cents. This works even when Settings → Fees is off — only that session is charged. Pass merchant_fee: null to skip Settings defaults for one session.

Global default (optional): enable in Settings → Fees to apply the same fee to every checkout that does not send merchant_fee.

Accept a payment

Example request

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

{
  "amount": 4900,
  "currency": "usd",
  "mode": "payment",
  "success_url": "https://example.com/thanks"
}

Example response

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

How to handle it

Redirect to url. Deliver goods when you receive payment.succeeded.

Checkout with a per-session platform fee (no Settings required)

Example request

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

{
  "amount": 4900,
  "currency": "usd",
  "mode": "payment",
  "success_url": "https://example.com/thanks",
  "merchant_fee": {
    "label": "Platform fee",
    "percent": 2.5,
    "amount": 100
  }
}

Example response

{
  "id": "cs_...",
  "object": "checkout_session",
  "amount": 5430,
  "currency": "usd",
  "status": "open",
  "mode": "live",
  "plan_type": "one_time",
  "url": "https://rollopayments.com/pay/cs_...",
  "merchant_fee": { "label": "Platform fee", "amount": 223 },
  "expires_at": 1723014400000,
  "livemode": true
}

How to handle it

label (or name) is shown at checkout. percent is of the product; amount is fixed cents. Use either or both. Response merchant_fee.amount is the computed fee in cents. Omit merchant_fee to use Settings defaults (if enabled); send null to force no custom fee on that session.

Percent-only or fixed-only fee

Example request

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

{
  "amount": 10000,
  "currency": "usd",
  "success_url": "https://example.com/thanks",
  "merchant_fee": { "label": "Service fee", "percent": 3 }
}

# Fixed only:
# "merchant_fee": { "name": "Handling", "amount": 250 }

Example response

{
  "id": "cs_...",
  "amount": 10850,
  "merchant_fee": { "label": "Service fee", "amount": 300 },
  "url": "https://rollopayments.com/pay/cs_...",
  "livemode": true
}

How to handle it

Works with Settings fees disabled. Recurring checkouts keep the same fee name and percent/fixed on renewals.

Webhook: payment.succeeded

Example request

# Delivered to your subscribed endpoint

Example response

{
  "id": "evt_...",
  "type": "payment.succeeded",
  "created": 1723000000,
  "data": {
    "id": "pay_...",
    "amount": 4900,
    "currency": "usd",
    "status": "succeeded",
    "fee": 339,
    "net_amount": 4561,
    "customer_email": "buyer@example.com",
    "checkout_session": "cs_...",
    "payment_method_type": "card",
    "livemode": true
  }
}

How to handle it

Idempotently mark the order paid using data.id or data.checkout_session. Book revenue with net_amount.

Retrieve a payment

Example request

GET /v1/payments/pay_...
Authorization: Bearer rk_live_...

Example response

{
  "id": "pay_...",
  "object": "payment",
  "amount": 4900,
  "currency": "usd",
  "status": "succeeded",
  "fee": 339,
  "net_amount": 4561,
  "customer_email": "buyer@example.com",
  "refunded_amount": 0,
  "created": 1723000000000,
  "livemode": true
}

How to handle it

Statuses include succeeded, partially_refunded, refunded. There is no list endpoint yet — use the dashboard or webhooks for discovery.

Refunds

Issue refunds from Dashboard → Payments. See Issue a refund. Listen for payment.refunded.