Skip to content
Coritan Docs

Organization API: Customer Portal: Invoices

The 18 Organization API operations for invoices.

View as Markdown

Part of Customer Portal.

Method Path Summary
GET /api/v1/orgs/{org_slug}/portal/invoices Newest first, ties by id
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id} One of the customer's invoices, with what was paid against it
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/apply-credit Apply the customer's credit balance toward an unpaid invoice
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/charge Pay an invoice with a saved payment method
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/checkout Canonical hosted checkout for an org-customer invoice (alias of /pay)
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/checkout-session Resume an in-flight checkout after a new tab, login, or API restart
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/confirm-payment Record a card payment the customer finished in the page, and answer how it settled
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/delivery How far each store item and server on an invoice has got
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/gateways Gateway accounts that can checkout this invoice's pay currency
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pay Hosted checkout for an invoice (legacy path; prefer /checkout)
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pay-intent Create a Stripe PaymentIntent to pay an invoice in the page
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pay-quote The card account and amount for paying an invoice in the page
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/paypal-capture Capture paypal order
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/paypal-stash Persist a PayPal order id so a redirect or reboot can still capture it
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pdf The invoice as a document to keep
GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/refund-eligibility My invoice refund eligibility
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/refund-request Ask for the money paid on one of your invoices back
POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/square-pay Pay an invoice with a Square card token, in one request

GET /api/v1/orgs/{org_slug}/portal/invoices

Newest first, ties by id. with_total wraps the page as {items, total, limit, offset, counts}; counts are per status for the same search, whatever the status filter.

Name In Type Required Description
org_slug path string yes
status_filter query string no
q query string no
limit query integer no Default: 50.
offset query integer no Default: 0.
with_total query boolean no Default: False.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

One of the customer's invoices, with what was paid against it

Section titled One of the customer's invoices, with what was paid against it

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}

One of the customer's invoices, with what was paid against it.

Every amount is in the invoice's currency. credit_covers is what the customer's wallet (kept in USD) would pay of amount_remaining if applied now, converted as POST .../apply-credit converts it; it equals amount_remaining when the wallet covers the invoice, and is 0 when the invoice is closed, the wallet is empty or the currency has no rate.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Apply the customer's credit balance toward an unpaid invoice

Section titled Apply the customer's credit balance toward an unpaid invoice

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/apply-credit

Apply the customer's credit balance toward an unpaid invoice.

amount_applied and amount_remaining are in the invoice's currency; credit_balance is what is left in the wallet, in credit_currency (USD). The wallet pays the applied amount's USD value.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Pay an invoice with a saved payment method

Section titled Pay an invoice with a saved payment method

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/charge

Pay an invoice with a saved payment method.

Send payment_method_id, or leave it out to use the customer's default method. We charge the invoice's remaining amount in currency at the exchange rate GET .../storefront/currencies shows. Answers 404 for an invoice that is not this customer's or is already paid, 400 for a currency the customer cannot pay in and for an invoice with nothing left to pay, and 402 when the charge is declined. When currency is sent and the payment account that holds the card does not take it (a Square card takes US dollars only), we answer 400 with This card cannot pay in <code>. Choose another card or pay with a new card., write nothing and charge nothing. A saved bank method pays in one currency: a SEPA debit method pays in euros, a US bank account in dollars, a Bacs method in pounds. Whichever currency the charge is in, we answer 400 with This payment method cannot pay in <code>. Choose another method. for a method that cannot take it, and 400 with Your bank ended the permission to charge this account. Choose another payment method. for a method whose mandate the bank ended. A bank debit answers pending and settles days later, and the invoice updates when the bank confirms.

A payment the customer already made for this invoice in the page is used first, so the card is not charged twice: one that went through settles the invoice and answers succeeded with its gateway_reference, and one the bank is still confirming answers pending.

Name In Type Required Description
invoice_id path integer yes
org_slug path string yes
payment_method_id query integer no
currency query string no The currency to charge in: the code your page showed the customer. Without it we use the payment method's own currency, then the customer's preferred pay currency.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Canonical hosted checkout for an org-customer invoice (alias of /pay)

Section titled Canonical hosted checkout for an org-customer invoice (alias of /pay)

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/checkout

Canonical hosted checkout for an org-customer invoice (alias of /pay).

Name In Type Required
invoice_id path integer yes
org_slug path string yes
return_url query string no
cancel_url query string no
currency query string no
gateway_name query string no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Resume an in-flight checkout after a new tab, login, or API restart

Section titled Resume an in-flight checkout after a new tab, login, or API restart

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/checkout-session

Resume an in-flight checkout after a new tab, login, or API restart.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Record a card payment the customer finished in the page, and answer how it settled

Section titled Record a card payment the customer finished in the page, and answer how it settled

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/confirm-payment

Record a card payment the customer finished in the page, and answer how it settled.

Send payment_intent_id, the gateway_reference that POST /orgs/{org_slug}/portal/invoices/{invoice_id}/pay-intent answered, and the gateway_name it was made on. We read the payment from the card processor and book what it took in its own currency, priced against the invoice's, at the US dollar amount and exchange rate the payment was made for. Answers requires_action with a client_secret while the customer must still authenticate, pending while the processor has not finished, and succeeded once the invoice is credited. Sending a payment we already booked to this invoice answers succeeded again and books nothing more.

We write nothing and refuse a payment this customer did not make for this invoice. Answers 400 for a payment made for another invoice, another organization or to add credit, 403 for a payment another customer made, 409 This payment has already been applied for a payment that already settled something else, 409 Your payment is being processed when the payment does not name this invoice yet (the invoice updates by itself once the processor confirms it), and 402 when the payment did not complete.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
gateway_name query string yes
payment_intent_id query string yes
currency query string no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

How far each store item and server on an invoice has got

Section titled How far each store item and server on an invoice has got

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/delivery

How far each store item and server on an invoice has got.

Lists the invoice's store items and servers, one for each bought. A store item (kind item) is pending_payment until the invoice is paid, then waiting until one of your game servers reports it, then delivered or failed, with the game server's note in detail.

A server (kind server) is pending_payment until the invoice is paid, then setting_up until the server exists and has finished installing, then ready. It is failed when we could not set it up, with a sentence in detail. Its name is the name the customer gave it, plan the plan it runs on and address where players join: the server's own address once it has one, and the name the customer chose before that. server_uuid is the ID that /portal/servers/{uuid} takes, once the server exists. Poll this until no line is pending_payment or setting_up. Answers 404 for an invoice that is not the customer's.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Fields of a 200 response:

Field Type Description
invoice_id integer
invoice_number string or null The number printed on the invoice, such as INV-000123. Analytics tags use it as the order id.
currency string or null The invoice's three letter currency code, such as USD.
status string The invoice's status, such as unpaid or paid.
items array of DeliveryItem The invoice's store items and servers, in the order of the invoice.
items[].service_id integer
items[].kind string, one of item, server item for a store item that a game server grants, server for a server we set up.
items[].name string The store item's name, or for a server the name the customer gave it.
items[].plan string or null For a server, the plan it runs on. null for a store item.
items[].quantity integer Always 1: an item bought several times is listed once for each.
items[].player DeliveryPlayer or null The player the item was bought for, or null.
items[].gift_from string or null The sender's name the buyer gave for a gift, or null.
items[].address string or null For a server, the address players join, such as play-hub.example.gg. It is the server's own once it exists and the name the customer chose before that. null for a store item.
items[].server_uuid string or null For a server, its ID in /portal/servers/{uuid} once we have created it. null before that and for a store item.
items[].status string, one of pending_payment, waiting, setting_up, ready, delivered, failed A store item is pending_payment until the invoice is paid, then waiting until a game server reports it, then delivered or failed. A server is pending_payment until the invoice is paid, then setting_up until it exists and has finished installing, then ready, or failed when we could not set it up.
items[].delivered_at string or null When a game server granted the item, in UTC.
items[].detail string or null The game server's note about a store item, or our note about a server that failed. null otherwise.

Gateway accounts that can checkout this invoice's pay currency

Section titled Gateway accounts that can checkout this invoice's pay currency

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/gateways

Warning

Deprecated. It still answers, but new code should not use it.

Gateway accounts that can checkout this invoice's pay currency.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
currency query string no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Hosted checkout for an invoice (legacy path; prefer /checkout)

Section titled Hosted checkout for an invoice (legacy path; prefer /checkout)

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pay

Warning

Deprecated. It still answers, but new code should not use it.

Hosted checkout for an invoice (legacy path; prefer /checkout). Creates a hosted checkout session and returns an approval URL.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
return_url query string no
cancel_url query string no
currency query string no
gateway_name query string no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Create a Stripe PaymentIntent to pay an invoice in the page

Section titled Create a Stripe PaymentIntent to pay an invoice in the page

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pay-intent

Create a Stripe PaymentIntent to pay an invoice in the page.

Complete it with Stripe.js confirmPayment and the client_secret, then call POST /orgs/{org_slug}/portal/invoices/{invoice_id}/confirm-payment. Without gateway_name we pick the Stripe account for the currency and the customer's country, as GET /orgs/{org_slug}/portal/invoices/{invoice_id}/pay-quote does.

Send expected_amount (the quote's charge_amount) from a wallet button. When the amount to pay has changed since the quote, we answer 412 with detail.code amount_changed and a new quote in detail.quote, and create nothing. Answers 404 for an invoice that is not this customer's or is already paid, and 400 for an invoice with nothing left to pay.

The answer's status is requires_payment_method (mount the Payment Element with client_secret), succeeded (the payment already went through), or pending: a payment of this invoice is processing at the bank (SEPA, ACH or Bacs take days). A pending answer has no client_secret and holds a message to show. We make no second intent for it, so the customer cannot pay the invoice twice, and the invoice updates when the bank confirms.

Methods that cannot be saved (Klarna, P24, TWINT, Swish and the like) stay on the page for an invoice that renews: only a method that can be saved asks to be saved. The statement line shows the account's name for any method that is not a card.

Name In Type Required Description
invoice_id path integer yes
org_slug path string yes
currency query string or null no Currency to charge in. Defaults to the customer's preferred pay currency.
country query string or null no Two-letter billing country. Defaults to the customer's country.
gateway_name query string or null no Stripe account to charge through. Leave it out and we pick the account the pay intent picks.
save_method query boolean or null no Keep the payment method for renewals. Leave it out and we decide from the invoice: one that renews a service keeps it. A Square payment keeps the card only while the account offers saved cards.
expected_amount query integer or null no The charge_amount from the invoice's pay quote, in minor units. When the amount to pay has changed since, we answer 412 with a new quote and create nothing.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

The card account and amount for paying an invoice in the page

Section titled The card account and amount for paying an invoice in the page

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pay-quote

The card account and amount for paying an invoice in the page.

Ask for it before you draw the payment form. adapter says which form to draw, and public holds that account's non-secret settings.

For adapter stripe, create Stripe's Express Checkout Element with publishable_key, charge_amount, currency, save_method and payment_method_configuration, put label on the wallet sheet's line and business_name (your store's name) at its top, and when renewal is set, pass it to Apple Pay as the recurring payment. Once the customer approves, create the payment with POST /orgs/{org_slug}/portal/invoices/{invoice_id}/pay-intent with the same currency, country, gateway_name and save_method, and the charge_amount as expected_amount.

For adapter square, draw Square's card form with public.application_id and public.location_id (the location of your store's brand), tokenize the card, and send the token to POST /orgs/{org_slug}/portal/invoices/{invoice_id}/square-pay with the charge_amount as expected_amount. Square takes US dollars only and does not keep the card unless the account offers saved cards: save_method is then true when the card will be kept, and renewal is always null.

Send card_adapters (for example stripe,square) to say which card forms your frontend can draw. Without it we pick among Stripe accounts only.

local_methods lists the payment methods made for the customer's country (iDEAL for the Netherlands, BLIK for Poland, TWINT for Switzerland) that the quote's account can show in currency, as method tokens such as ideal. Without gateway_name we prefer a Stripe account that can show one, unless your routing profile names its accounts. The list is empty when the customer has none, when the account shows none, and until we have read the account's payment method settings, which a quote never waits for, so ask again to see it. The payment form still shows whatever Stripe offers. The detail.quote of a 412 does not carry it.

A quote creates nothing and does not contact the card processor. Answers 404 for an invoice that is not this customer's or is already paid, 400 for an invoice with nothing left to pay and for a currency that is not enabled or that the account does not take, and 503 when no account takes the currency.

Name In Type Required Description
invoice_id path integer yes
org_slug path string yes
currency query string or null no Currency to charge in. Defaults to the customer's preferred pay currency.
country query string or null no Two-letter billing country. Defaults to the customer's country.
gateway_name query string or null no Card account to charge through. Leave it out and we pick the account your routing rules choose among the card_adapters you can draw.
save_method query boolean or null no Keep the payment method for renewals. Leave it out and we decide from the invoice: one that renews a service keeps it. A Square payment keeps the card only while the account offers saved cards.
card_adapters query string or null no The card forms your frontend can draw, as a comma list of stripe and square. Defaults to stripe, so a frontend with no Square form keeps getting Stripe accounts. Send stripe,square once it can draw Square's card form: the quote then names whichever account your routing rules choose, and its adapter says which form to draw.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/paypal-capture

Finalize an embedded PayPal Buttons one-off payment: capture the buyer-approved order server-side and apply it to the org invoice (USD ledger). Idempotent via the gateway_reference uniqueness in settle_org_invoice_payment.

A cancelled or refunded invoice answers 409 before anything is captured. What PayPal took is booked in its own currency and priced against the invoice's (settle_org_invoice_charge). No transaction is open while PayPal answers.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
order_id query string yes
gateway_name query string yes
currency query string no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Persist a PayPal order id so a redirect or reboot can still capture it

Section titled Persist a PayPal order id so a redirect or reboot can still capture it

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/paypal-stash

Persist a PayPal order id so a redirect or reboot can still capture it.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
order_id query string yes
gateway_name query string yes
currency query string no
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

The invoice as a document to keep

Section titled The invoice as a document to keep

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/pdf

The invoice as a document to keep. Statements are staff-facing; this is the copy a customer files with their own accounts. It is made out to the customer's billing details (GET /portal/billing-details): the name, the company, the address with the country's name under it, then the email. Without an address, the country's code follows the email.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

GET /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/refund-eligibility

What the Refund Policy says about this invoice, so the page can offer the request, or say plainly why it cannot, before the customer types.

eligible says whether a request would be accepted, blocker_messages why not, flag_messages what the policy leaves to staff, and reason_codes the reasons a request takes. self_serve is false when the organization takes refund requests in a billing ticket instead: the request form is then closed, whatever eligible says.

Name In Type Required
invoice_id path integer yes
org_slug path string yes
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Ask for the money paid on one of your invoices back

Section titled Ask for the money paid on one of your invoices back

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/refund-request

Ask for the money paid on one of your invoices back.

Send reason_code, one of the eligibility answer's reason_codes, and reason_text, what happened. The answer is the request, pending until staff decide it, and we email you that it arrived. 400 with the reason when the Refund Policy refuses it or a request on the invoice is already pending. 403 when the organization takes refund requests in a billing support ticket instead (the eligibility answer's self_serve is false): nothing is created.

Name In Type Required
invoice_id path integer yes
org_slug path string yes

application/json (required)

Type: Body.

Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.

Pay an invoice with a Square card token, in one request

Section titled Pay an invoice with a Square card token, in one request

POST /api/v1/orgs/{org_slug}/portal/invoices/{invoice_id}/square-pay

Pay an invoice with a Square card token, in one request.

Square has no intent. Draw Square's card form with the public settings of GET /orgs/{org_slug}/portal/invoices/{invoice_id}/pay-quote?card_adapters=stripe,square (when its adapter is square), tokenize the card in the browser, and send the token as source_id. We charge it in this request and settle the invoice when Square takes the payment.

Send the quote's charge_amount as expected_amount. When the amount to pay has changed since, we answer 412 with detail.code amount_changed and a new quote in detail.quote, and charge nothing. Send save_method true to keep the card for renewals. We honor it only while the account offers saved cards (public.can_save_cards in the quote) and ignore it otherwise. When a save was asked for and the payment succeeds, the answer holds saved_method: true when we saved the card, false with a plain message when we could not. A card that fails to save never changes the payment, which stays succeeded. Only a card can be saved: a payment made with Apple Pay, Google Pay, Cash App Pay, Afterpay or a bank account (ACH) answers saved_method false. Square takes US dollars only, so a currency other than USD answers 400. amount_usd is ignored: an invoice is paid in full.

Send source_kind (card, apple_pay, google_pay, ach, cash_app or afterpay) to say which Web Payments SDK method made the token, and leave it out for a card. We answer 400 and charge nothing when the account has not switched that method on (public in the quote) or the token is not that kind of token. The answer holds method ({kind, label, brand, source_type}). An ach payment answers pending and holds the invoice for up to 7 days while the bank confirms it (2 to 3 business days), so no other payment is taken for the invoice meanwhile.

The answer is status succeeded, pending or failed, with gateway_reference, charge_amount, currency and, when there is something to say, a plain message. A declined card is HTTP 200 with status failed and nothing is booked: show message and let the customer try another card. pending means Square has not finished, or that we could not read its answer. The payment may have gone through, so do not charge again until the invoice updates. attempt_id is always null here.

A token works once, so sending the same token twice is one payment. While a first request for the invoice is still running we answer 409 with a Retry-After header. Answers 404 for an invoice that is not this customer's or is already paid, and 400 for another currency, for an account that is not Square, and for an invoice with nothing left to pay.

Name In Type Required
invoice_id path integer yes
org_slug path string yes

application/json (required)

Field Type Required Description
gateway_name string or null no The Square account to charge through. Leave it out and we pick the account the pay quote picks.
source_id string yes The payment token the Web Payments SDK returned from tokenize().
source_kind string, one of card, apple_pay, google_pay, ach, cash_app, afterpay or null no The way of paying the token came from: card, apple_pay, google_pay, ach (a US bank account), cash_app or afterpay. Leave it out for a card. We refuse a way the account has not switched on, and a token that is not that kind of token, before we charge anything. Only a card can be saved: a save_method sent with any other kind is refused with saved_method false. An ach payment answers pending and settles 2 to 3 business days later.
expected_amount integer or null no The quote's charge_amount in the smallest currency unit. When the amount due has moved since, we answer 412 and create nothing.
save_method boolean no Keep the card for renewals. Honored only while the account offers saved cards (public.can_save_cards).
verification_token string or null no The buyer verification token tokenize() returned, when it returned one.
buyer_email string or null no Where Square sends its receipt, when you want one.
billing SquareBilling or null no
billing.given_name string or null no
billing.family_name string or null no
billing.email string or null no
billing.phone string or null no
billing.address_lines array of string or null no
billing.city string or null no
billing.state string or null no
billing.postal_code string or null no
billing.country_code string or null no
currency string or null no The currency of the quote. Defaults to the account's pay currency.
amount_usd number or string or null no US dollars to pay now, for part of an invoice. Defaults to everything still owed.
Status Meaning
200 Success.
422 The request is not valid. detail lists each problem.