Every endpoint, with the request and response you can expect. All examples use test keys; swap in a live key and the same calls move real money.
The people who pay you. Created automatically at checkout, or by hand.
/v1/portal/sessionsscope: customers:writeA customer-portal link for a customer who is signed in to your product — redirect them to url and they can update their card, see payments, cancel or pause (as your portal settings allow). Valid for an hour. Pass return_url (http or https) and the portal shows a "Back to" link to it. Secret key only.
{ "customer": "cus_1b4c…", "return_url": "https://yourapp.am/account" }{
"object": "portal_session",
"customer": "cus_1b4c…",
"url": "https://ronda.am/portal/session/…",
"return_url": "https://yourapp.am/account",
"expires_at": 1790361234,
"mode": "test"
}/v1/customersscope: customers:writeCreate a customer
{
"email": "anna@example.am",
"name": "Anna Hakobyan",
"metadata": { "crm_id": "8891" }
}{
"id": "cus_1b4cf2ceec9356f1e53a3cab",
"object": "customer",
"email": "anna@example.am",
"name": "Anna Hakobyan",
"credit_balances": [],
"metadata": { "crm_id": "8891" },
"created": 1786998562
}/v1/customersscope: customers:readList customers — supports ?email=
/v1/customers/:idscope: customers:readRetrieve a customer
/v1/customers/:idscope: customers:writeUpdate a customer — including default_payment_method (pm_…), the card renewals fall back to when a subscription's own card is removed
/v1/customers/:idscope: customers:writeDelete a customer — clears personal data, deactivates saved cards, keeps the financial record
What you sell. A product owns its prices, so one product can be sold monthly and yearly without pretending to be two unrelated things.
/v1/productsscope: plans:writeCreate a product
{
"name": "Pro",
"description": "For growing teams"
}{
"id": "prod_6f21…",
"object": "product",
"name": "Pro",
"description": "For growing teams",
"active": true,
"created": 1786998563
}/v1/productsscope: plans:readList products
/v1/products/:idscope: plans:readRetrieve a product
/v1/products/:idscope: plans:writeUpdate a product
/v1/products/:idscope: plans:writeArchive a product and every price under it. Existing subscriptions keep billing.
An amount and an interval, belonging to a product. Changing a price's amount applies to its existing subscribers from their next renewal — never to a period already paid. Omit `product` and the `name` creates one, so selling something takes a single call.
/v1/plansscope: plans:writeCreate a price
{
"product": "prod_6f21…",
"name": "Monthly",
"amount": 12900,
"currency": "AMD",
"interval": "month",
"interval_count": 1,
"trial_days": 14
}{
"id": "plan_3911175476653e621be07025",
"object": "plan",
"product": "prod_6f21…",
"product_name": "Pro",
"nickname": "Monthly",
"name": "Pro — Monthly",
"amount": 12900,
"currency": "AMD",
"interval": "month",
"interval_count": 1,
"trial_days": 14,
"active": true,
"created": 1786998563
}/v1/plansscope: plans:readList prices
/v1/plans/:idscope: plans:readRetrieve a price
/v1/plans/:idscope: plans:writeUpdate or archive a price
The recurring core. A customer, a plan, a saved card and a schedule.
/v1/subscriptionsscope: subscriptions:writeCreate a subscription. Without a trial, a payment method is required and the first period is charged now. The response carries that charge as latest_payment. If it was declined the subscription is past_due and the recovery ladder retries it; latest_payment.failure_code says why. Statuses: trialing, active, past_due, paused, canceled — and incomplete, briefly, while the first charge is in flight (subscription.created can carry it).
{
"customer": "cus_1b4c…",
"plan": "plan_3911…",
"payment_method": "pm_77a2…",
"quantity": 1
}{
"id": "sub_5c1e…",
"object": "subscription",
"status": "active",
"plan": "plan_3911…",
"quantity": 1,
"current_period_start": 1786998600,
"current_period_end": 1789590600,
"trial_end": null,
"cancel_at_period_end": false,
"cancellation_details": null,
"pause": null,
"dunning_attempt": 0,
"latest_payment": { "id": "pay_a348…", "object": "payment", "status": "succeeded", "amount": 12900, "currency": "AMD", "failure_code": null, "failure_message": null, "…": "the full payment object" }
}/v1/subscriptionsscope: subscriptions:readList subscriptions — supports ?status= and ?customer=
/v1/subscriptions/:idscope: subscriptions:readRetrieve a subscription
/v1/subscriptions/:id/change_planscope: subscriptions:writeChange plan with proration. An upgrade charges the difference now; a downgrade credits the customer.
{ "plan": "plan_bigger…", "prorate": true }{
"id": "sub_5c1e…",
"status": "active",
"plan": "plan_bigger…",
"proration": { "charged": 19677, "credited": 0, "currency": "AMD", "payment": "pay_aa31…" }
}/v1/subscriptions/:id/cancelscope: subscriptions:writeCancel now, or at period end with { "at_period_end": true }. Optionally record why: reason is one of too_expensive, not_using, missing_feature, switching, temporary, other, plus a free-text comment. They come back in cancellation_details, with canceled_by: merchant, customer (from the portal) or payment_failed.
{ "at_period_end": true, "reason": "switching", "comment": "Moving to annual invoicing" }/v1/subscriptions/:id/pausescope: subscriptions:writePause billing without canceling
/v1/subscriptions/:id/resumescope: subscriptions:writeResume where it stood — a trial keeps its end, a paid period keeps its end; one that ran out while paused, or was paused owing money, is charged now
/v1/subscriptions/:idscope: subscriptions:writeUpdate quantity, metadata, the card it is charged to (payment_method — a past-due subscription is retried on it now), or withdraw a scheduled cancel ({ "cancel_at_period_end": false }). A quantity change is prorated like a plan change.
{ "quantity": 3, "payment_method": "pm_77a2…", "metadata": { "seat_plan": "team" } }/v1/subscriptions/:id/simulate_renewalscope: subscriptions:writeTest mode only: run the next renewal now — the trial ends, or the next period or retry is charged — through the same path as the real schedule, with the same emails and webhooks. Refused with a live key.
/v1/subscriptions/:id/retryscope: subscriptions:writePast due: try the payment now instead of at next_attempt — after the customer fixed their card in your app. A decline counts as one of the retries. Up to three a day.
Every charge, one-off and recurring.
/v1/paymentsscope: payments:writeCharge a saved card off-session — the same call the recurring engine makes
{
"amount": 45000,
"currency": "AMD",
"customer": "cus_1b4c…",
"description": "September retainer"
}{
"id": "pay_a348cb5b0664660d4c29d890",
"object": "payment",
"amount": 45000,
"currency": "AMD",
"status": "succeeded",
"type": "one_off",
"card": { "brand": "visa", "last4": "4242", "exp_month": 12, "exp_year": 2030 },
"attempt": 1,
"is_recovery": false,
"created": 1786998900
}/v1/paymentsscope: payments:readList payments — supports ?status= and ?customer=
/v1/payments/:idscope: payments:readRetrieve a payment
/v1/payments/:id/refundscope: refunds:writeRefund in whole or part. The platform fee on the refunded amount is reversed.
{ "amount": 20000, "reason": "duplicate" }{
"id": "re_66b1…",
"object": "refund",
"payment": "pay_a348…",
"amount": 20000,
"status": "succeeded"
}/v1/refundsscope: payments:readList refunds
/v1/refunds/:idscope: payments:readRetrieve a refund
The only way a card enters the system. Works with a publishable key.
/v1/checkout/sessionsscope: publishable or payments:writeOpen a hosted checkout. type is payment, setup or subscription. The bank's order is registered as the session is created, so it comes back already processing and stays so while the customer is on the page or at the bank; it ends completed, failed, expired or canceled. (open is only ever seen if the bank could not be reached at creation.) Send the customer to url — our page, which forwards to the bank. bank_url is the bank's own card page, for an integration that must redirect there directly; prefer url, which also shows the test banner, the amount and the result.
{
"type": "payment",
"amount": 25000,
"currency": "AMD",
"description": "September membership",
"customer_email": "anna@example.am",
"save_card": true,
"success_url": "https://yourapp.am/thanks"
}{
"id": "cs_f4accee46724b73fae2ced5a",
"object": "checkout_session",
"status": "processing",
"amount": 25000,
"currency": "AMD",
"url": "https://ronda.am/checkout/cs_f4ac…",
"bank_url": "https://…bank…/payments/…",
"expires_at": 1787000363
}/v1/checkout/sessions/:idRetrieve a session and its outcome
Saved cards. Ronda holds the bank's token, brand and last four digits — never a card number.
/v1/payment_methodsscope: customers:readList saved cards — supports ?customer=
/v1/payment_methods/:idscope: customers:writeDetach a card and deactivate the binding at the bank
A shareable URL. Point one at a plan and it starts a real subscription.
/v1/payment_linksscope: links:writeCreate a payment link
{ "name": "September invoice", "amount": 45000, "currency": "AMD" }{
"id": "link_71c2…",
"object": "payment_link",
"url": "https://ronda.am/pay/pl_8f1c…",
"amount": 45000,
"currency": "AMD",
"status": "active",
"use_count": 0
}/v1/payment_linksscope: links:readList links
/v1/payment_links/:idscope: links:readRetrieve a link
/v1/payment_links/:idscope: links:writeActivate or deactivate a link
The document behind a charge — and the way to bill a company that will not hand over a card. Every subscription cycle writes one; you can also raise one directly. Sent invoices carry a due date and a hosted page the customer can pay from.
/v1/invoicesscope: payments:writeRaise an invoice and send it
{
"customer": "cus_1b4c…",
"currency": "AMD",
"collection_method": "send_invoice",
"days_until_due": 14,
"memo": "Thank you",
"lines": [
{ "description": "Consulting, March", "quantity": 2, "unit_amount": 150000 }
]
}{
"id": "inv_9d02…",
"object": "invoice",
"number": "2026-0042",
"status": "open",
"collection_method": "send_invoice",
"subtotal": 300000,
"discount": 0,
"total": 300000,
"due": 1788208563,
"hosted_url": "https://ronda.am/invoice/ivt_…",
"created": 1786998563
}/v1/invoicesscope: payments:readList invoices, filterable by status and customer
/v1/invoices/:idscope: payments:readRetrieve an invoice with its line items
/v1/invoices/:id/voidscope: payments:writeVoid an invoice. It keeps its number — the sequence stays gapless — and stops being payable.
A reusable discount rule. Attaching one to a subscription creates a discount with its own clock, so archiving the coupon never re-prices someone already on it. Discounts do not stack.
/v1/couponsscope: plans:writeCreate a coupon — a percentage or a fixed amount, never both. A fixed amount_off needs its currency and applies only to prices in it.
{
"code": "SUMMER25",
"percent_off": 25,
"duration": "repeating",
"duration_in_months": 3,
"max_redemptions": 100
}{
"id": "cpn_74b1…",
"object": "coupon",
"code": "SUMMER25",
"percent_off": 25,
"duration": "repeating",
"duration_in_months": 3,
"max_redemptions": 100,
"times_redeemed": 0,
"valid": true,
"created": 1786998563
}/v1/couponsscope: plans:readList coupons
/v1/coupons/:idscope: plans:readRetrieve a coupon by id or by code
/v1/coupons/:idscope: plans:writeArchive a coupon
/v1/subscriptions/:id/discountscope: subscriptions:writeApply a coupon to a subscription. It takes effect from the next renewal.
{ "coupon": "SUMMER25" }/v1/subscriptions/:id/discountscope: subscriptions:writeRemove the discount; full price from the next renewal
Everything else you need to reconcile.
/v1/webhook_endpointsscope: webhooks:writeRegister an endpoint. The signing secret is returned once.
{ "url": "https://yourapp.am/ronda/webhook", "enabled_events": ["payment.succeeded"] }/v1/webhook_endpointsscope: webhooks:readList endpoints
/v1/webhook_endpoints/:idscope: webhooks:readRetrieve an endpoint
/v1/webhook_endpoints/:idscope: webhooks:writeUpdate url, description or enabled_events, or disable/enable it with { "disabled": true|false }. Enabling resets its failure count.
{ "disabled": false }/v1/webhook_endpoints/:id/testscope: webhooks:writeSend a signed webhook.test event now. The response is the delivery, with your server's HTTP status. One attempt, never retried, never counted toward auto-disable.
/v1/webhook_endpoints/:id/roll_secretscope: webhooks:writeReplace the signing secret. The new secret is in the response, once; the old one stops verifying immediately.
/v1/webhook_endpoints/:idscope: webhooks:writeDelete an endpoint
/v1/eventsscope: events:readList events — supports ?type=
/v1/events/:idscope: events:readRetrieve an event
/v1/disputesscope: payments:readList chargebacks
/v1/disputes/:idscope: payments:readRetrieve a chargeback: payment, amount, currency, reason, status, evidence_due_by and opened
/v1/balancescope: payments:readDerived from the ledger. gross is everything collected; refunded and fees come off it. available (= settled) has reached your bank account; on_its_way is collected but not there yet, and pending is the part of on_its_way still clearing at the bank. Your bank pays you directly — Ronda never holds the money.
{
"object": "balance",
"currency": "AMD",
"available": 1180000,
"on_its_way": 207900,
"pending": 96000,
"gross": 1420000,
"refunded": 25000,
"fees": 7100,
"settled": 1180000,
"mode": "live"
}