Pay an invoice
Find your unpaid invoices, pay one with credit, a saved method or a new one, and read an invoice's lines and status.
In the dashboard
Coritan raises an invoice for every order, every renewal and every plan upgrade. Invoices are in US dollars. Pay one to start a new service, to keep a service running past its renewal date, or to lift a suspension. Every invoice downloads as a PDF for your records.
Before you begin
Section titled Before you begin- Sign in to the dashboard.
- To pay with credit, have credit on your balance. Add credit to your balance explains how.
- To pay with a saved method, such as a card, a bank account or a PayPal account, save it first on the Payment methods tab (Manage payment methods). You can also enter a new card, use another method open to you, or use PayPal while you pay. Ways to pay lists every method and says which currencies and countries each one takes.
- To pay with Apple Pay or Google Pay, have a card in that wallet. On a computer, Apple Pay asks you to scan a QR code with an iPhone on iOS 18 or later.
Find an invoice
Section titled Find an invoice- In the sidebar, select Billing, then the Invoices tab.
- Choose a filter:
- Unpaid lists every invoice you still owe on: unpaid and overdue ones, however old.
- Paid lists the invoices you have paid.
- All lists everything, newest first.
- Select View beside an invoice, or the row itself, to open it as a page (Read an invoice).
The table shows each invoice's number, Status, Total, the date it was Issued and the date it is Due. Choose how many rows a page shows at the bottom of the table, and move between pages with Previous and Next.
Pay an invoice
Section titled Pay an invoiceSelect Pay beside the invoice. When only one invoice is unpaid, the Overview tab of Billing has the same button under Due now, and an invoice's own page has a pay button too. The page Pay invoice and the invoice's number opens, at
/dashboard/billing/invoices/<id>/pay. What you are paying shows the Amount due: the invoice total less anything already paid. When your account's currency is not US dollars, it shows what we charge in your currency, with the invoice's amount in US dollars under it, for example€12.10over≈ $12.99 USD. The invoice itself stays in US dollars. The Your payment card beside it lists the invoice's lines and Due now.Under Currency, check the currency we charge. Choose another one if you want to pay in it, and the Amount due changes at once. The choice is your account's currency, the same one as in Settings.
Choose how to pay:
- Account credit takes the amount from your balance. It is greyed out when your balance is empty.
- A saved card or PayPal account pays with that method. Your default method is marked
Default. - Card opens the payment form, where you choose from the methods open to you. It is also how you pay with a new method when you already have a saved one.
- PayPal shows PayPal's buttons on the page. Approve the payment in the PayPal window that opens; you stay on the page.
- Crypto shows where to send cryptocurrency for an invoice in US dollars. It is offered wherever Add credit offers it. The transfer pays the invoice when it lands, as Pay with cryptocurrency describes for credit.
- Any other provider opens that provider's checkout page, then brings you back to this page.
An Apple Pay or Google Pay button above these choices pays in one step instead, as Pay with Apple Pay or Google Pay describes.
Select the button in the Your payment card (on a phone, the button at the foot of the page). It says what happens next:
- Pay with credit when your credit covers the whole amount. Credit is in US dollars whatever currency you pay in.
- Apply credit when it covers part. The rest stays due, and you pay it the same way.
Pay $12.99(with the amount due) for a saved method or a new card. In another currency it shows the charge in that currency, for examplePay €12.10. For a saved method it readsPay about €12.10, because we price that charge when it is made.Continue toand the provider's name for a checkout page.
If a payment form opens in place of the choices (Payment details, or Confirm with your bank when your bank asks for a check), complete it and select the button under it, which reads
Payand the amount. Choose another way goes back to the choices. You enter your details in a secure form; Coritan does not store them. The form lists the methods open to you for the Currency and billing country you have. When one of your country's own methods is open, a line under the form names it, for exampleiDEAL is available for your payment.A method that takes you to another page returns you to the pay page afterwards (When a payment is still processing).
While a payment is running, Cancel and the button are held. If you select a link or a sidebar entry meanwhile, the page asks Leave while paying?. Select Stay to wait for the answer, or Leave if you must; leaving does not cancel the payment, so check Invoices before you pay again. A page you opened from a list, an email or an order's Order placed page returns you there when the payment is done.
When you choose Card, a Keep this payment method for renewals box sits under the choices and is ticked. Ticked, the method is saved to your account when it can be kept again, and we charge it when your services renew. Clear it to pay this invoice only. A kept method appears on the Payment methods tab, where you can remove it (Manage payment methods).
Pay in another currency
Section titled Pay in another currencyYou can pay an invoice in any currency the Currency list offers. We convert the invoice's dollar amount at the exchange rate we publish for that currency and charge the result, so a card statement shows the amount in your currency. The amount we charge is the one on the page. When the rate moves while the page is open, the page shows the new amount and asks you to check it before you pay again.
A saved card pays in the currency you chose only when its account takes that currency. When it does not, the page stays as it is and says This card cannot pay in EUR. Choose another card or pay with a new card. A payment we cannot take in your currency at all shows the reason and Pay in US dollars, which changes your account's currency to US dollars.
Pay every unpaid invoice at once
Section titled Pay every unpaid invoice at onceWhen two or more invoices are unpaid, Pay all appears on the Invoices tab and under Due now on the Overview tab. It opens the page Pay all invoices, at /dashboard/billing/invoices/pay-all. The Invoices card lists every open invoice, overdue ones first, and Your payment shows the number of invoices and the total in Amount due. Account credit takes US dollars, so the total is in dollars. When your account's currency is not US dollars and you choose a saved card or PayPal account, Amount due shows what we charge in your currency with the dollar total under it, for example €26.06 over ≈ $27.98 USD. The Currency list on the page changes it.
- Under How to pay, choose Account credit or a saved card or PayPal account. A new card, a wallet and PayPal pay one invoice at a time. With no saved method and no credit, the page says so and offers Add a payment method.
- Select the button in Your payment, which reads Pay with credit or
Payand the total. For a saved method in another currency it readsPay about €26.06, because we price each charge when it is made. - Watch the list. We charge the invoices in turn, and each shows Paid, Submitted, Needs your bank, Credit ran out, Declined or Not tried.
- Select Done. You return to the page you came from.
If an invoice is declined, or your credit runs out, we stop there and the rest read Not tried. When a card cannot pay in your currency, we stop at the first invoice with This card cannot pay in EUR. Choose another card or pay with a new card. The page then shows We cannot charge this card in your currency and Pay in US dollars, which changes your account's currency to US dollars and brings back the choices for the invoices that are still due. Submitted means your bank is still settling the payment, so do not pay that invoice again. For Needs your bank, open the invoice from Invoices and confirm the payment there. The page ends with how many invoices were paid, and the unpaid ones stay under Unpaid.
Pay with Apple Pay or Google Pay
Section titled Pay with Apple Pay or Google PayWhen your phone or browser can pay with Apple Pay or Google Pay, the pay page shows that wallet's button above the other ways to pay. It appears once you first touch or click the page. The button stays when your credit covers the whole amount due. Paying with it charges the wallet's card for the full amount and leaves your credit on your account. While another payment is in progress, such as a saved card or PayPal, the button is greyed out and does nothing.
- Select Pay beside the invoice.
- Select the Apple Pay or Google Pay button at the top of How to pay.
- Check the amount on the payment sheet that opens. It is the Amount due, and it is what we charge.
- Approve the payment on the sheet.
The page says Confirming your payment… while we confirm the payment, then returns you to the invoice. Until then, the other ways to pay wait. Like any card you pay with in the dashboard, the card then appears on the Payment methods tab, named after its wallet: for example Apple Pay (Visa ending in 4242) (Manage payment methods).
When a payment is still processing
Section titled When a payment is still processingA bank debit, a bank transfer and a voucher confirm days later (How long a bank payment takes). After you pay, a message says Payment submitted. The invoice updates once your bank settles it. or Your payment is being processed. The invoice updates when it is done. The pay page stays and shows Your payment is still settling with See the invoice. The invoice stays unpaid until the money arrives, and then moves to Paid. In Pay all, the invoice reads Submitted.
Do not pay again while it processes. Coritan holds the invoice: a second payment on it waits, and renewal retries do not charge it again. The page reads the invoice again for a short time after you pay, and leaves for the invoice when it is paid. When it is still unpaid, open the invoice later.
A method that opens another page (iDEAL, Bancontact, EPS, Przelewy24, Klarna, Alipay, or your bank's own check) returns you to the pay page, and Coritan reads the result:
- You paid: a message says
Invoice paid.and you return to the page you came from. - You cancelled: a message says
Payment cancelled. The invoice is still due and you paid nothing. - The payment failed: a message says
The payment did not go through, so you paid nothing. Try again or choose another way to pay. - Your bank wants one more step: a message says
Your bank still needs to confirm this payment. Open the payment again to finish it.Open the pay page again and finish the check. - It is still clearing: a message says
Your payment is still being processed. The invoice shows paid when it clears. Do not pay again.
Result
Section titled ResultA message confirms the payment, for example Invoice INV-20260925-48213 paid. The page ends on the page you opened it from, or on the invoice. After a saved method in another currency it adds what we charged, for example Invoice INV-20260925-48213 paid. We charged €12.10. The invoice moves to the Paid filter and Coritan emails you a receipt. Paying in full also does what the invoice was for:
- A new service starts setting up.
- A renewal moves the service's next renewal date on by one billing period.
- An upgrade applies the new plan (Change a service's plan).
- A service suspended over this invoice is resumed.
When a payment is accepted but not yet settled, you see Payment submitted. The invoice updates once your bank settles it. The invoice stays unpaid until the payment clears (When a payment is still processing). Every payment also appears on the Transactions tab (Transactions and payment attempts).
Read an invoice
Section titled Read an invoiceSelect View, or the invoice's row, to open it. The page Invoice and its number, at /dashboard/billing/invoices/<id>, shows the status next to the heading, and a back link, All invoices, to the list with its filter. It has three cards:
- Items: one line per charge, with the Item, Qty, Unit price and Amount. An invoice with use billed by the hour adds Usage detail, with Download rows (CSV) and a help button on each row that asks about that charge (See your usage).
- Details: Issued, Due and Paid (the date and time it was paid, or
Not yet). Refund appears while a refund request for it is open, with its status and amount, and Notes when the invoice has any. - Totals: the Subtotal, Tax and Total. When part of the invoice is paid, Already paid and Left to pay follow. Under them are Download PDF and, for an unpaid invoice, a pay button. A paid invoice has Ask for a refund instead, unless a request for it is open already (Ask for a refund).
An older link that ends in ?invoice= opens this page, and one that ends in ?pay= opens the pay page.
Download an invoice as a PDF
Section titled Download an invoice as a PDFOn the Invoices tab, select the download button at the end of the invoice's row, or open the invoice and select Download PDF under Totals. The PDF holds the invoice's lines and totals, and the payments and refunds made on it. It names the Coritan company that issued the invoice, and who the invoice is made out to:
- With a billing address saved, its Legal name, its postal address with the country, your email address and its VAT ID. When Legal name is empty, your name and company stand in for it.
- Without one, your name, company, email address and country code from your profile.
The PDF shows the billing address as it is when you download it, and that includes older invoices. Keep the PDF you downloaded at the time if you need a record of what an invoice showed.
Each invoice has one of these statuses:
| Status | Meaning |
|---|---|
unpaid |
Issued and waiting for payment. |
overdue |
Its due date has passed and it is still unpaid. The services on it are suspended soon after; Failed payments and suspended services has the timeline. |
paid |
Paid in full. |
cancelled |
Voided. You owe nothing on it. Coritan cancels an invoice when you cancel its service, or when a newer upgrade replaces an unpaid one. |
refunded |
Paid, then refunded. |
draft |
Not issued yet. |
Troubleshooting
Section titled Troubleshooting- No way to pay is available right now
- Nothing is set up to take a payment for this invoice. Contact support.
- Could not load the ways to pay
- The page could not read the payment options. Select Try again.
- Could not take the payment
- We could not take the payment from a saved method, Apple Pay or Google Pay. The message under it gives the reason, for example
Payment method 812 not found or inactivewhen the saved method has been removed, orYour card was declined.from the wallet's card. Try again, or choose another way to pay. The card was declined. Try another card.- The card form shows the reason in a sentence, for example
Your card was declined. Try another card.orThe security code did not match. Check it and try again.Nothing was charged. Enter the card again, or choose another way to pay. The payment is processing. The invoice updates once it settles.- The card processor has accepted the payment but not finished it, as with a bank debit. The invoice stays unpaid until it settles.
We have not heard back from the card processor yet. Do not pay again until your invoice updates. If the payment went through, it updates within a few minutes.- The card processor did not answer in time, so we cannot say whether it took the payment. Wait for the invoice to update, then check the Unpaid filter before you pay again. If the invoice stays unpaid, contact support with the date and amount.
- Could not start the payment
- The card form, the provider's checkout page or the Apple Pay or Google Pay payment could not be created. The message under it gives the reason. Try again, or choose another way to pay.
- The Apple Pay or Google Pay button is missing
- The button appears only where your browser and device can pay with that wallet, and only while the invoice has something left to pay. Choose another way to pay.
- The Apple Pay or Google Pay button is greyed out
- Another payment for the invoice is in progress, such as a saved card or PayPal. Wait for it to finish.
- We cannot take this payment in your currency
- The message under it gives the reason, for example
Payment currency EUR is not enabled. Select Pay in US dollars to pay in US dollars, or choose another way to pay. The amount changed to $214.20. Check it and pay again.- The amount due changed after the page opened, and we charged nothing. The page now shows the new Amount due. Check it, then select the Apple Pay or Google Pay button again.
The amount changed while the payment sheet was open. Check it and pay again.- The amount due changed while the Apple Pay or Google Pay sheet was open, so we charged nothing. Check the Amount due, then select the button again.
Another payment started while the payment sheet was open, so we did not take this one.- You paid the invoice another way while the Apple Pay or Google Pay sheet was open. We charged the wallet nothing. Check the invoice before you pay again.
We received your payment and are confirming it. You do not need to pay again.- The wallet took the payment, and we are still recording it. The invoice changes to Paid once we have, without you doing anything. Until you reload the page, it does not offer Apple Pay or Google Pay for this invoice again. If the invoice stays unpaid, contact support with the date and amount.
- Could not confirm the payment
- You approved the payment, but the invoice did not update. Your bank may already have taken the money, so check the invoice under the Unpaid filter, and your balance, before you pay again. If the invoice is still unpaid, contact support with the date and amount.
The payment was declined.- Your bank or PayPal refused the charge. The message may give the bank's reason instead. Pay another way, or see Failed payments and suspended services.
The payment did not go through, so you paid nothing. Try again or choose another way to pay.- You came back from another page (a bank, iDEAL or Klarna, for example) and the payment was not made. Try again, or pay another way.
Payment cancelled. The invoice is still due and you paid nothing.- You left the other page before paying. Nothing was charged.
Your bank still needs to confirm this payment. Open the payment again to finish it.- Your bank asked for a check that is not finished. Open the pay page again and finish it.
Your payment is still being processed. The invoice shows paid when it clears. Do not pay again.- The payment is clearing. Wait for the invoice to change to Paid.
Back from checkout. The invoice updates once the payment clears.- You came back from a checkout page before the provider confirmed the payment. Check the invoice again later; do not pay twice.
- Your payment is still settling
- The bank has not confirmed the payment yet. Select See the invoice and check it again later. Do not pay again.
- Nothing is due on this invoice
- You opened the pay page of an invoice that is already paid or cancelled. Select See the invoice.
- We could not find this invoice
- The address names an invoice that is not on your account. Select All invoices.
- Could not open PayPal
- PayPal did not load on the page. Select Try again. If the message says
PayPal is not available in this browser. Choose another way to pay., use a card or another method. - Could not open the card form
- The card form did not load. Select Try again.
- Could not apply your credit
- The message gives the reason, for example
No credit balance available. - The Pay button is missing
- Only unpaid and overdue invoices can be paid. The invoice is already paid, cancelled or refunded.
Could not download INV-20260925-48213- The PDF did not download. The message under it gives the reason. Try again, and contact support if it keeps failing.
Related
Section titled Related- Ways to pay
- Add credit to your balance
- Manage payment methods
- Failed payments and suspended services
- Ask for a refund
- Currencies and countries
With the API
Section titled With the APIList your invoices
Section titled List your invoicesGET /billing/invoices lists your invoices, newest first. It takes:
status_filteropen(unpaid or overdue, what the Unpaid filter shows), or one status:draft,unpaid,paid,cancelled,refundedoroverdue. Leave it out for every invoice.pageandlimit- The page to return (from
1) and how many invoices a page holds (default50, at most200). with_totaltruewraps the page in an object with the total and the count per status. Without it, the answer is a bare array of invoices.
curl "https://api.coritan.com/api/v1/billing/invoices?status_filter=open&with_total=true" \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"items": [
{
"id": 5011,
"invoice_number": "INV-20260925-48213",
"user_id": 4821,
"subtotal": 12.99,
"tax": 0.0,
"total": 12.99,
"amount_paid": 0.0,
"currency": "USD",
"status": "unpaid",
"due_date": "2026-09-28T00:00:00",
"paid_at": null,
"notes": null,
"items": [
{
"id": 9120,
"service_id": 311,
"description": "Service renewal - survival-smp",
"item_type": "recurring",
"quantity": 1.0,
"unit_price": 12.99,
"total": 12.99
}
],
"created_at": "2026-09-25T02:00:00"
}
],
"total": 1,
"page": 1,
"limit": 50,
"counts": {"all": 14, "open": 1, "draft": 0, "unpaid": 1, "paid": 13, "cancelled": 0, "refunded": 0, "overdue": 0}
}
total counts the invoices that match the filter. counts holds every status whatever the filter, with all and open added.
In each invoice:
idandinvoice_number- The number the API uses in paths, and the number printed on the invoice.
subtotal,taxandtotal- The amounts in US dollars.
amount_paid- What credit and earlier payments have covered. What is left to pay is
totalminusamount_paid. currencyUSD.status- One of the statuses in the table above.
due_date,paid_atandcreated_at- When the invoice falls due, when it was paid (or
null) and when it was issued. items- The lines.
service_idis the service a line bills, anditem_typeisrecurring,one_time,proration,addon,discountormanual.
GET /billing/invoices/{invoice_id} returns one invoice in the same shape. It answers 404 with Invoice not found, or 403 with Access denied for an invoice on another account.
Download a PDF
Section titled Download a PDFGET /billing/invoices/{invoice_id}/pdf returns the invoice as a PDF file, named after its number:
curl https://api.coritan.com/api/v1/billing/invoices/5011/pdf \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-o INV-20260925-48213.pdf
An invoice that is not on your account answers 404 with Invoice not found. The PDF is made out to the billing address saved when you send the request, as GET /auth/me/billing-profile returns it, or to your profile when none is saved.
Pay with credit
Section titled Pay with creditPOST /billing/invoices/{invoice_id}/apply-credit takes as much of the amount due as your balance covers:
curl -X POST https://api.coritan.com/api/v1/billing/invoices/5011/apply-credit \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"invoice_id": 5011,
"applied": "12.99",
"fully_paid": true,
"credit_balance": "12.01",
"message": "Invoice paid with credit"
}
When credit covers only part, fully_paid is false and message is Partial credit applied. When nothing can be applied, the answer is 400 with the reason, such as No credit balance available.
Pay with a saved method
Section titled Pay with a saved methodPOST /payments/invoices/{invoice_id}/charge charges a saved method. Find its id with GET /payments/methods (Manage payment methods).
curl -X POST https://api.coritan.com/api/v1/payments/invoices/5011/charge \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pay-inv-5011-1" \
-d '{"payment_method_id": 812}'
The body takes:
payment_method_id- The saved method to charge. Required.
amount_usd- Pay part of the invoice: this many US dollars, at most what is left. Leave it out to pay the rest in full.
currency- The currency to charge the method in. Leave it out to use your account's currency (Currencies and countries).
Send an Idempotency-Key header so that retrying a request whose answer you did not receive does not charge twice (Idempotency).
The answer is the payment attempt:
{
"id": 7730,
"invoice_id": 5011,
"user_id": 4821,
"user_email": "alex@example.com",
"gateway_name": "stripe",
"gateway_config_id": 3,
"payment_method_id": 812,
"amount": 1299,
"currency": "USD",
"base_amount": "12.99",
"fx_rate": "1",
"status": "succeeded",
"gateway_reference": "pi_3Qexample",
"error_message": null,
"decline_type": null,
"decline_code": null,
"is_auto_charge": false,
"charge_schedule_id": null,
"idempotency_key": "pay-inv-5011-1",
"refunded_amount": null,
"created_at": "2026-09-25T09:12:40",
"completed_at": "2026-09-25T09:12:42",
"gateway_response": {"id": "pi_3Qexample", "status": "succeeded"},
"client_secret": null
}
amount is in the charged currency's smallest unit (cents here). base_amount is the US dollar amount it pays and fx_rate the exchange rate used, both as decimal strings. gateway_reference is the provider's id for the payment, and gateway_response holds the provider's own answer. status is one of:
succeeded- Paid.
processing- Accepted but not settled. The invoice updates when it settles.
requires_action- The bank wants the cardholder to confirm.
client_secretlets a browser page finish it with Stripe.js; then callconfirm-paymentas below. A script alone cannot complete this step. failed- Declined.
error_messagegives the reason, anddecline_typesays whether retrying can work (soft) or not (hard).
POST /payments/invoices/{invoice_id}/pay is the older path for the same charge, with the same body and answer.
Pay with a new card, PayPal or a checkout page
Section titled Pay with a new card, PayPal or a checkout pageThese flows need a browser for the cardholder's part; the API creates and finishes each payment.
- List what can take this invoice with
GET /payments/invoices/{invoice_id}/gateways. Each entry has anameto send asgateway_name, andadaptersays what it is (stripefor cards,paypal, or another provider). - For a card, create a payment with
POST /payments/invoices/{invoice_id}/pay-intent. The answer'sclient_secretis for Stripe.js in the browser. Asking again for the same invoice and amount returns the same payment. After the card is confirmed, callPOST /payments/invoices/{invoice_id}/confirm-paymentwith the query parametersgateway_nameandpayment_intent_id. It credits the invoice with the amount that payment was made for, never more than the invoice still owes, and only once. It answerssucceeded,pendingorrequires_action, or402withPayment not completed. It writes nothing and answers400for a payment made for another invoice or to add credit,403for a payment another account made, and409for a payment that already settled something else or that does not name this invoice yet. In that last case the invoice updates by itself once the card processor confirms the payment. - For PayPal or another provider, call
POST /payments/invoices/{invoice_id}/checkoutwithgateway_name,return_urlandcancel_url. Both must be absolutehttporhttpsURLs on a real host: the API answers400for a placeholder host such asexample.comorlocalhost. Send the payer tocheckout_url. For PayPal,session_idis the PayPal order; once the payer approves it, callPOST /payments/invoices/{invoice_id}/paypal-capturewith the query parametersorder_idandgateway_name.
curl -X POST https://api.coritan.com/api/v1/payments/invoices/5011/checkout \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"gateway_name": "paypal", "return_url": "https://www.coritan.com/dashboard/billing/invoices", "cancel_url": "https://www.coritan.com/dashboard/billing/invoices"}'
A checkout that is still open for the invoice is returned again instead of a new one, with reused set to true. The checkout answers 400 when the invoice is already paid or cancelled.
Show Apple Pay and Google Pay buttons
Section titled Show Apple Pay and Google Pay buttonsApple Pay and Google Pay buttons pay with a card kept in the payer's phone or browser, through Stripe's Express Checkout Element. The payment sheet shows the amount before the payment exists, so ask for a quote before you show the buttons, and create the payment only once the payer approves.
Ask for the quote with
GET /payments/invoices/{invoice_id}/pay-quotebefore you show the buttons, and again whenever the amount or the currency changes. It takescurrency(default: your account's currency),country,gateway_name,amount_usdandsave_method, aspay-intenttakes them;countryis thecountry_codeyou send topay-intent. It also takescard_adapters, which Pay with a Square card explains: leave it out and the quote is always for Stripe. A quote creates nothing and does not contact the card processor.Shellcurl "https://api.coritan.com/api/v1/payments/invoices/5011/pay-quote?currency=USD" \ -H "Authorization: Bearer $CORITAN_TOKEN"JSON{ "gateway_name": "stripe", "adapter": "stripe", "public": {"adapter": "stripe", "account": "stripe", "publishable_key": "pk_live_...", "payment_method_configuration": "pmc_..."}, "publishable_key": "pk_live_...", "payment_method_configuration": "pmc_...", "currency": "USD", "charge_amount": 1299, "base_amount": "12.9900", "fx_rate": "1", "save_method": true, "business_name": "Coritan", "save_types": ["card", "link", "sepa_debit", "us_bank_account", "bacs_debit", "au_becs_debit", "cashapp", "amazon_pay", "revolut_pay", "ideal", "bancontact"], "label": "Invoice INV-20260925-48213", "renewal": { "amount": 1299, "label": "Monthly renewal", "interval_unit": "month", "interval_count": 1 }, "local_methods": [] }gateway_nameis the account we charge through,adaptersays which processor it is (stripeorsquare) andpublicholds the account's keys for its card form. For Stripe,publishable_keyandpayment_method_configurationare that account's. The configuration can benull.charge_amountis what the payer pays, in the smallest unit ofcurrency, such as cents.base_amountis the US dollars it pays andfx_ratethe rate we converted at.save_methodsays whether we keep the method for renewals. Without it, we keep the method for an invoice that renews a service.save_typeslists the method types the payment saves for later charges whensave_methodistrue, and is empty otherwise. A method that cannot be charged again is paid once and never listed (What a renewal can use). ACSS debit is not listed either: Stripe.js refuses it inpaymentMethodOptionsand the wallet buttons then fail to load. The buttons pay by card, so leaving it out changes nothing they charge.local_methodslists the methods made for the payer's billing country that the account can show incurrency, such asidealfor a payer in the Netherlands paying inEUR. It is empty when there are none, and it can be empty on the first quote after a change.labelis the line for the payment sheet, andbusiness_namethe name at its top.renewalis what the next renewal charges, when we keep the card and every service on the invoice renews on the same billing cycle. Otherwise it isnull.
Load Stripe.js with
publishable_key. Create the elements withmode: "payment",amount: charge_amount,currencyin lower case,paymentMethodConfiguration: payment_method_configuration, andsetupFutureUsage: "off_session"whensave_methodistrue. Whensave_methodistrue, also set the saving option of each type insave_typestooff_sessioninpaymentMethodOptions, so Stripe accepts the payment we create. Mount anexpressCheckoutelement withbusiness: {name: business_name}andpaymentMethodsset to{applePay: "always", googlePay: "always", link: "never", paypal: "never", amazonPay: "never", klarna: "never"}.alwaysshows Apple Pay as a QR code outside Safari. The other four never show in this row. Show the row only once Stripe reports a wallet it can offer.In the element's
clickhandler, resolve with one line item:labelforcharge_amount. With Apple Pay and arenewal, also sendapplePay.recurringPaymentRequest:renewal.labelas itspaymentDescriptionandregularBilling.label,renewal.amountasregularBilling.amount,interval_unitandinterval_countasrecurringPaymentIntervalUnitandrecurringPaymentIntervalCount, andhttps://www.coritan.com/dashboard/billing/methods, where you manage saved methods, asmanagementURL.In the
confirmhandler, callelements.submit(). Then create the payment withPOST /payments/invoices/{invoice_id}/pay-intent, sending the quote'sgateway_name,currencyandsave_method, and itscharge_amountasexpected_amount:Shellcurl -X POST https://api.coritan.com/api/v1/payments/invoices/5011/pay-intent \ -H "Authorization: Bearer $CORITAN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"gateway_name": "stripe", "currency": "USD", "save_method": true, "expected_amount": 1299}'Pass the answer's
client_secrettostripe.confirmPaymentwith the same elements, then callconfirm-paymentas for a card form above.
Charge the quote the sheet opened with. Keep a copy of the quote in the click handler and send that copy's values in step 4. A quote you ask for while the sheet is open waits until the sheet closes (cancel) or its payment ends. When that quote names another amount, or the payer started another payment meanwhile, call event.paymentFailed({reason: "fail"}) in confirm instead of creating the payment, then update the elements to the new quote and let the payer approve again.
When the amount changed after the quote, pay-intent answers 412 and creates nothing. detail.code is amount_changed, detail.message is The amount to pay changed. Check the new amount and pay again., and detail.quote is a new quote in the shape above. Call event.paymentFailed({reason: "fail"}), update the elements to the new charge_amount and currency, and let the payer approve again. Do not retry a 412 with the old amount.
The quote answers 400 for an invoice that is paid, cancelled or has nothing left to pay, and for a currency we do not take, such as Payment currency TRY is not enabled. It answers 503 with No Stripe gateway available when no Stripe account takes the currency. With card_adapters set, the 503 says No card gateway available when no card account takes it.
Pay with a Square card
Section titled Pay with a Square cardWe no longer take payments with Square. No Square account is open, so a quote never names one, and square-pay refuses every payment and charges nothing. Draw the Stripe form. The rest of this section describes the route while it remains.
Square is a second card processor. A page that can draw Square's card form lists it in card_adapters, a comma list of the processors the page can show: stripe, square or stripe,square. The default is stripe, so a page that does not send it keeps getting Stripe. With square listed, the quote is for Square when the payment rules prefer it for this payment, and for Stripe otherwise. A payment that must keep the card for renewals (an invoice that renews a service, or a quote with save_method true) goes to Stripe while Square cannot keep cards, even when the rules prefer Square. A payment in a currency other than US dollars always goes to Stripe, because Square takes US dollars only.
Ask for the quote with
card_adapters=stripe,square. Whenadapterissquare,publicholds the account'sapplication_id, thelocation_idof the storefront andcan_save_cards, which isfalseuntil we switch saved Square cards on.save_methodisfalsewhilecan_save_cardsisfalse, andrenewalis alwaysnull.Shellcurl "https://api.coritan.com/api/v1/payments/invoices/5011/pay-quote?currency=USD&card_adapters=stripe,square" \ -H "Authorization: Bearer $CORITAN_TOKEN"JSON{ "gateway_name": "square-coritan-americas", "adapter": "square", "public": { "adapter": "square", "account": "square-coritan-americas", "application_id": "sq0idp-example", "location_id": "LEXAMPLE0001", "sandbox": false, "can_save_cards": false, "google_pay": false, "apple_pay": false, "ach": false, "cash_app_pay": false, "afterpay": false }, "publishable_key": null, "payment_method_configuration": null, "currency": "USD", "charge_amount": 1299, "base_amount": "12.9900", "fx_rate": "1", "save_method": false, "business_name": "Coritan", "label": "Invoice INV-20260925-48213", "renewal": null }Load Square's Web Payments SDK in the browser, create the card form with
public.application_idandpublic.location_id, and calltokenize()when the payer approves. The call returns a one-usetoken, and sometimes a verification token.Send the token to
POST /payments/invoices/{invoice_id}/square-pay. We charge it in that request, so there is no second step:Shellcurl -X POST https://api.coritan.com/api/v1/payments/invoices/5011/square-pay \ -H "Authorization: Bearer $CORITAN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"source_id": "cnon:example-token", "gateway_name": "square-coritan-americas", "expected_amount": 1299}'JSON{ "status": "succeeded", "attempt_id": 7731, "gateway_reference": "OW0aoXS9VTEpMqKlTTYg7OsWY09YY", "charge_amount": 1299, "currency": "USD", "save_method": false, "base_amount": "12.99", "invoice_number": "INV-20260925-48213" }
The body takes:
source_id- The token from
tokenize(). Required. It works once. expected_amount- The quote's
charge_amount. Send it so that a payment for a changed amount is refused. gateway_name- The Square account from the quote. Leave it out and we pick the one the quote picks.
verification_token,buyer_emailandbilling- What Square's buyer verification and receipt use, when you have them.
source_kind- Which method made the token:
card(the default),apple_pay,google_pay,ach,cash_apporafterpay. The quote'spublicsays which ofgoogle_pay,apple_pay,ach,cash_app_payandafterpaythe account has switched on. We answer400and charge nothing for a method the account has not switched on, or when the token is not that kind of token. A payment made withachanswerspending, and the invoice updates when the bank confirms it, 2 to 3 business days later. Only a card can be kept for renewals: with any other kind,save_methodanswerssaved_methodfalsewith amessage. currencyandamount_usd- As for
pay-intent.currencydefaults toUSDand must beUSD.amount_usdpays part of the invoice. save_methodtrueto keep the card for renewals. We honor it only whilepublic.can_save_cardsistrueand ignore it otherwise. When a save was asked for and Square took the payment, the answer also holdssaved_method:truewhen the card is saved, andfalsewith amessagewhen it could not be saved. The payment issucceededeither way.
status says what happened:
succeeded- Square took the payment and the invoice is updated. A later webhook from Square changes nothing.
pending- Square has not finished (a bank debit, or a payment it approved and has not captured), or the card processor did not answer in time.
messagesays which. The invoice is unchanged. Do not send the payer to pay again: when the answer hasunknownset totrue, the card may already be charged, and Square tells us the result. failed- Square declined the card. The answer is still
200.messageis a sentence to show the payer. Ask for a new token withtokenize()and send it: a token that was used cannot be used again.
Send the same token twice and we charge once: the second request answers what the first did, with reused set to true. A new token for an invoice that has a payment still in progress answers 409 with a Retry-After header and A payment for this invoice is still being processed. Wait for the invoice to update before you pay again., and no charge, as does a second request while the first still waits for Square. Two different cards sent together never both charge: the second answers 409. When the amount changed after the quote, square-pay answers 412 and charges nothing, exactly as pay-intent does: detail.quote is a new quote to show. Square charges whole cents, so amount_usd is rounded to cents. It answers 400 for a currency other than USD (This way of paying takes US dollars only. Choose another way to pay., with or without gateway_name), for an invoice that is paid, cancelled or refunded or has nothing left to pay, and for an account that is not Square's (send Stripe payments to pay-intent), 404 for an unknown invoice, 403 for another account's, and 429 after 20 tries in 10 minutes for your account or 60 for your address. When Square took the money and our booking then failed, the answer is pending and the invoice updates when we finish the booking. When the card processor never answered (unknown is true), we look the payment up again within a few minutes: if it exists the invoice is paid, and if there is none after 30 minutes the try is closed and you can pay again. pay-intent called with a Square account answers 400 with Use square-pay to pay by Square.
API operations on this page
| Method | Path | What it does |
|---|---|---|
GET | /api/v1/billing/invoices | Newest first, ties by id so a page boundary never repeats or skips a row |
GET | /api/v1/billing/invoices/{invoice_id} | Get invoice |
GET | /api/v1/billing/invoices/{invoice_id}/pdf | The invoice as a PDF to keep, for the account it belongs to |
POST | /api/v1/billing/invoices/{invoice_id}/apply-credit | Apply account credit to an unpaid invoice (unlocks provision / plan change when paid) |
GET | /api/v1/payments/invoices/{invoice_id}/gateways | The payment accounts that can take this invoice, in routing order |
POST | /api/v1/payments/invoices/{invoice_id}/charge | Canonical saved-method charge for an invoice (alias of /pay) |
POST | /api/v1/payments/invoices/{invoice_id}/pay | Charge a saved payment method for an invoice (legacy path; prefer /charge) |
POST | /api/v1/payments/invoices/{invoice_id}/checkout | Create invoice checkout |
GET | /api/v1/payments/invoices/{invoice_id}/pay-quote | What a card payment for an invoice charges, and which card form to draw |
POST | /api/v1/payments/invoices/{invoice_id}/pay-intent | Create a Stripe PaymentIntent to pay an invoice in the page |
POST | /api/v1/payments/invoices/{invoice_id}/square-pay | Pay an invoice with a Square card token |
POST | /api/v1/payments/invoices/{invoice_id}/confirm-payment | Record a card payment the customer finished in the page, and answer how it settled |
POST | /api/v1/payments/invoices/{invoice_id}/paypal-capture | Capture an approved PayPal order for an invoice and apply it |