Developers / Guides / Records
Invoices and the pay page
Bill a customer with an itemized invoice and send them a link they can pay from directly — no login, no app, nothing for them to install.
Create an invoice
/Merchants → your merchant → Invoices → New, or POST /api/merchant-accounts/{ref}/invoices
Itemized line items (description, quantity, unit price, whether each is taxable, and an optional
productId), a tax rate (taxRateId or a typed taxRatePercent —
see Customers, products & tax rates), a due date, and a
gateway that supports hosted checkout. Optionally restrict which payment method type(s) the
customer may use on the pay page — card only, bank account (ACH) only, or both (the default) —
via allowedPaymentMethods. BankAccountOnly/Both is only
valid on a gateway that supports ACH (see "ACH / eCheck bank-account payments" below); set once
here and not editable afterward, same as every other invoice field. Two more choices are made once
at creation: whether the customer may pay in parts (see
Partial payments & deposits) and authorizeOnly.
Send it
Emails the customer a unique, unguessable pay-page link (if Mailgun is configured — see below) and always returns/display it either way, so you can share it yourself if you'd rather.
Customer pays
They open the link, enter their card (or use a saved method), and pay — right there, no PayMidWare account needed. The invoice flips to Paid automatically.
Endpoints
| Endpoint | Purpose |
|---|---|
| POST /api/merchant-accounts/{ref}/invoices | Create an invoice. |
| GET .../invoices | List a merchant's invoices, optionally by customer. |
| GET .../invoices/{invoiceNumber} | Read one invoice — status, lines, tax, amount paid and due, and each payment recorded against it. The way to confirm an invoice is really paid. |
| POST .../invoices/{invoiceNumber}/send | Email the pay link and mark the invoice Sent. |
| POST .../invoices/{invoiceNumber}/embed | Get the iframe snippet that shows the pay page on your own website (see below). |
| POST .../invoices/{invoiceNumber}/void | Void an invoice (blocked once it's Paid). |
Invoice numbers default to INV-000123
(a platform-wide sequence). A merchant can choose its own format, such as {YYYY}-{####}, and starting number on its
account page under Invoice numbers; the API returns whatever number the invoice was given in invoiceNumber.
Numbers are up to 20 characters of letters, digits, -, _ and ..
Partial payments & deposits
By default an invoice is paid in one charge for the full total. Set
partialPaymentMode when you create the invoice to change that (it cannot be changed
afterward):
| Mode | What the customer can do on the pay page |
|---|---|
| Disabled | The default. One "Pay the full amount" button. |
| CustomerChoice | Type any amount up to what is still due, and come back to pay again until the balance is zero. |
| FixedDeposit | The first payment must be exactly requiredDepositAmount (more than zero and less than the total) or the full balance — nothing in between. |
The invoice shows amountPaid, amountDue and a list of payments, and is
marked Paid only when nothing is due. authorizeOnly: true reserves the
money on the customer's card instead of taking it, so the merchant can capture it later from the
Portal's Transactions page; it is allowed only with Disabled and only on a gateway that
supports authorize-only (otherwise 400).
Add billToAddress and/or shipToAddress (line1, line2,
city, state, postalCode, country) to print them on the pay page, the
receipt and its PDF. Both are optional. Without billToAddress the customer's billing address is used if it has one;
shipToAddress is only what you send. They are copied onto the invoice when it is created and do not change if the
customer is edited later. Over-long fields (lines 200, city, state and country 100, postal code 20) are rejected with 400.
Invoices pulled in from BigCommerce, WooCommerce and QuickBooks bring the order's or invoice's own addresses, filled only where the
invoice has none; an invoice you push to QuickBooks carries its addresses.
Embedding the pay page in your own website
Instead of sending the customer to PayMidWare's pay site, show the pay page inside an
<iframe> on your page. It is the same page and the same payment code, in a flat
layout meant to sit inside another page.
List your website addresses
/Merchants → your merchant → Website embedding
One address per line, https:// only (no path or wildcards), up to 10. Only these
sites may frame the pay page; anything else is refused by the browser.
Ask for the snippet
POST /api/merchant-accounts/store-001/invoices/INV-000123/embed
X-Api-Key: <your key>
The response has embedUrl, a ready-made iframeHtml tag, an optional
resizeScriptHtml that keeps the frame the right height, and the
allowedOrigins. The call changes nothing and can be repeated. You get
409 if the invoice is still a Draft (send it first) or Void, or if no website has been
allowed yet.
Listen for messages
The page posts messages to your page shaped
{ source: "paymidware", type, invoiceNumber, status, ... }, where
type is loaded, resize (with height),
paid (with amountPaid and amountDue; a partial payment is
also paid, with an amount still due) or failed (with
message). Check event.origin before trusting one.
paid message is a convenience, not proof. Confirm the payment from
your server with GET .../invoices/{invoiceNumber} before you release goods or services.
Card forms that open a pop-up or redirect (3-D Secure, some wallet buttons) can behave differently
inside a frame, so test your merchant's gateway in the frame first.