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
payment.refunded.