Pay this invoice online

A Pay button that opens a hosted checkout for the balance and confirms the payment on return, with the button hidden entirely when the builder has no provider connected.

What it is

A checkout session created from the invoice's balance, returning a hosted payment URL. The button only appears when a payment provider is connected and the invoice is in a payable state with a positive balance. Returning from checkout confirms server-side and then re-polls so the status and balance catch up.

Also called: take a card payment · pay online · stripe checkout · customer pays the deposit

See it
Pay this invoice online
Prepared for
Delia Yoder
1140 Ridge Line Rd · Fair Play
Shell package$27,206
Concrete & site$7,898
Doors & windows$5,266
Trim & finish$3,510
Total
$43,880
Signature
The invoice action bar with a 'Pay $12,400.00' button, then the paid-in-full confirmation line. src/app/invoice/[token]/page.tsx. Sample data — no customer information appears here.
How it works
  1. 1POST /api/client-portal/invoice/pay authorises on the invoice's portal token and creates a session
  2. 2Return redirects are built from the host the customer is actually on, so sub-account domains land back correctly
  3. 3On return with a session id, a confirm call verifies the session server-side, then the page re-polls four times
  4. 4Inside the dashboard modal the checkout opens in a new tab, because checkout refuses to load framed
  5. 5Coming back to the dashboard tab refetches so the modal updates in place
Why we built it

Getting paid meant waiting on a cheque or talking a customer through bank details over the phone, for a bill they were already looking at. Customers pay by card from the invoice itself. Payment is confirmed server-side as the primary path so it works in every environment, with a webhook and a reconcile pass as backups that cannot double-count, and a customer on a builder's own subdomain lands back on that builder's portal rather than the platform's. The checkout is never framed, because the payment provider refuses to be embedded and the customer would otherwise be staring at a blank box where the card form should be.

The problem
  • Payment friction on a document the customer already has open
  • A pay button that fails on press for builders with no provider
  • Payments that do not reflect until a webhook lands
Sound familiar?
What you get
Deposits and draws can be paid the moment the invoice is read
The invoice updates itself on return without a refresh
Sub-account customers stay on their builder's own domain

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →