Invoices and Payments

Create durable V2 invoices, review email or SMS delivery, and collect or refund the ledger-derived balance.

BeginnerownermanageradminUpdated 2026-10-07

Invoices and Payments

Use the compact invoice list

The record list keeps invoice status, sales representative, issue and due dates, totals, paid amounts, balances, and permitted reminder actions. On wider laptop screens, the four Summary metrics fit on one row. Open More filters for office, issue-date, customer-tag, and sales-rep criteria; active search and filter results remain visible with Clear filters. The labeled, focusable table region scrolls internally on narrower laptop screens. Invoice amounts, creation, sending, and payment behavior use the existing workflows.

The Clean Estimate V2 invoice workspace creates real accounting documents without weakening estimate deposits or payment history. An invoice has its own itemized total, due date, customer link, PDF, and invoice-payment ledger. A settled payment collected as an estimate deposit remains attached to the estimate acceptance and is never copied or relabeled as an invoice payment. When the invoice is linked to that estimate or its job, an auditable allocation carries the deposit's remaining value forward as a separate credit and reduces only the balance still due. Until that allocation exists, the accepted deposit remains reversible from the lead's Deposit & Payments card. After allocation, the invoice credit is the source-linked reversal surface; the lead card disables reversal for that payment. A pending or failed accepted provider reversal also blocks allocation until the command is settled or recovered, including the interval while the provider request is in flight.

Open Business > Invoices in the web app. This V2 workspace is for office roles. The mobile invoice experience and the remaining V1 billing tools remain parity work described under V1 parity still to port. The complete retained procedures are available in Invoices and Payments (V1).

Owners, admins, office teammates, and sales reps retain the V1 invoice-management permission by default. An owner can revoke that individual permission to leave a web-capable teammate's workspace read-only: invoice history remains visible, but create, edit, send, resend, and void controls are unavailable. Sales and crew roles remain on the approved mobile surfaces and do not gain the web billing workspace through this flag; no mobile invoice UI is added or changed by this release.

Office payment collection, including hosted card Checkout, and refunds use a stricter authorization in addition to invoice access. The service locks and revalidates the current active member with both manage_invoices and issue_refunds plus current all-office or same-office access before accepting money work. A teammate who can prepare or deliver an invoice does not automatically gain authority to attest offline money or reverse a settled payment. Deactivation, permission removal, or reassignment away from the invoice office that wins the race blocks stale collection, Checkout, refund, and refund-retry work.

Invoice list

The responsive list loads 25 records at a time and returns an authoritative matching total. Newest, oldest, nearest-due, and highest-total each use their own stable indexed keyset with invoice ID as the tie-breaker, so simultaneous inserts and same-value rows do not cause offset skips or duplicates. A cursor is bound to its exact tenant, access scope, filters, and sort and fails closed if reused against a different list. A single-office view seeks through location-leading indexes, so invoices in sibling offices do not expand the page scan. The first page uses the same typed query shape before a cursor exists, so empty or filtered invoice sets load normally. The Due soonest cursor also retains its date type after paging reaches invoices with no due date. It includes:

  • search by invoice number, customer, or service address;
  • status filters for Draft, Sent, Viewed, Partially paid,

Overdue, Paid, and Void;

  • office location and issue-date filters;
  • a match-any Customer tags filter using the shared CRM labels;
  • a Sales rep filter for one teammate or Unassigned invoices;
  • newest, oldest, nearest-due, and highest-total sorting; and
  • totals for matching invoices plus outstanding, overdue, and collected

invoice money under the same search, status, office, date, and customer-tag filters.

Invoice rows and mobile web cards show the first linked customer tags for context. Selecting more than one tag returns invoices whose customer has any selected label. Customer tags are organization-scoped and do not change the invoice's frozen bill-to snapshot or accounting history.

Rows and mobile web cards also show the assigned sales representative. Sales-rep filtering is applied by the server to the rows, matching count, and money summary, and the selected assignment is part of the cursor scope. Changing the rep filter therefore starts a fresh first page instead of reusing a cursor from another teammate's results. Changing the office clears the selected rep and replaces the rep menu with only the latest office-scoped response, so a slower prior request cannot bring back teammates from another office. A deactivated, role-changed, or office-moved teammate who still owns a visible historical invoice remains in this filter with an Unavailable label, so retained sales attribution and totals can still be reviewed instead of disappearing from reporting. If an older teammate record has no usable mirrored name or email, the invoice shows Team member rather than incorrectly presenting that assigned invoice as Unassigned.

Paid and partially paid states are derived from settled invoice collections plus carried-forward deposit credits, less refunds. They are not editable status labels. Due-date comparisons use the valid service-location timezone retained on that invoice, so a later office edit or a multi-location server clock cannot move a previously issued document's due-day boundary. A partially paid invoice whose remaining balance passes that boundary appears as Overdue and contributes only its remaining balance to overdue totals; Partially paid describes a partial balance that is not yet overdue. Invoice creation and send fail closed when the selected office has an invalid timezone instead of saving ambiguous dates. The builder shows a blocking office-timezone message rather than crashing while it tries to calculate local default dates.

Export and bulk actions

Checking one or more rows on the loaded page of the invoice list opens a selection toolbar with Export CSV and, for a teammate who can manage invoices, Archive to void.

Export CSV downloads exactly the checked rows on the current page, not a fresh query over the full filtered result, so page through or widen filters first if you need more than what's loaded. The file uses V1's exact seven columns: Invoice #, Customer, Estimate #, Status, Total, Balance Due, Due Date. V2 has no separate human-facing estimate number, so the linked estimate's own ID fills that column, left blank when the invoice has no linked estimate.

Archive to void asks for confirmation, then voids each selected invoice one at a time. One failure does not stop the rest: the toolbar reports how many succeeded and, for any that failed, the reason. A teammate without manage invoices does not see this button, since voiding is gated the same way it already is everywhere else in this workspace.

V1's other two bulk statuses are not offered. Mark overdue has no V2 equivalent to flip: overdue is derived from the due date and is never a stored status. Mark sent is refused by the database itself; a sent invoice must carry a real delivery (email or SMS, with its own recipient and token), so marking a batch of invoices sent without actually delivering them is not a safe bulk action.

Create a draft

Select New invoice, then choose an active work-owning customer and service property. Company portfolio parents are rollups and cannot own invoices; open the child service site that owns the work.

Clean Estimate rechecks that customer, property, and any linked source when the draft is first sent, so a draft cannot bypass the rule if its service account is archived or converted into a portfolio after creation. A linked job and estimate must also name each other exactly; omitting the job's estimate does not weaken that lineage check. An already-sent retained invoice can still be resent for billing follow-up.

The single-screen builder includes:

  • issue and due dates;
  • up to 100 itemized descriptions;
  • quantities stored to three decimal places;
  • unit prices, an optional discount, and a 0–100% tax rate entered to two

decimal places and converted exactly to integer basis points;

  • an optional customer note and payment terms; and
  • a live preview of the amount, with the server recalculating every line and

total before saving.

Focusing the unit-price field selects its current 0.00 text for easier replacement. Review & Send shows the customer preview and explains that its secure link is added when sent. Draft PDF previews use the invoice's pinned brand when available, and short payment terms stay on the first page when space permits. The invoice and linked job screens use Open client for the customer link. These are display and draft-review corrections; they do not repair historical issued issuer names, enable draft cash/check collection, or send a draft.

For a new draft, the issue date defaults to today in the selected service property's office timezone and the untouched due date follows 15 calendar days later. The due date cannot be earlier than the issue date. Creating the invoice saves a private draft only. It does not send a message or charge the customer. The save atomically allocates the organization's invoice number; a workspace without an invoice-specific numbering row starts with INV-0001 and advances independently from lead numbers.

You can also select New invoice from a service client's profile. The customer is preselected only when the URL contains a valid client ID, and the same property and portfolio guards still run on the server.

From an eligible service job, select Create invoice to open the same single-screen builder with the job, its customer, service property, and linked estimate lineage already selected. The server revalidates those relationships; the shortcut cannot invoice a different customer, a portfolio parent, an archived property, or a job outside the current workspace.

For a one-time job created from the web New job dialog, the job's immutable direct property is the invoice scope even when the job has no estimate. Any non-null estimate, plan, or repeat-work property attached to that job must agree; conflicting lineage fails closed instead of retargeting the bill.

Generate invoices for several jobs

On the Jobs list, members who can manage invoices see a checkbox on each scheduled, in-progress, or complete job that can be invoiced. Pick the jobs, then click Generate invoices and confirm. CE Pro creates one draft invoice per job, each on its own, so a job that cannot be invoiced never stops the others. The draft's total is always the job's accepted price, with the same 15-day terms a new invoice gets. When the job came from an accepted estimate option whose taxable amount and tax rate reproduce that price to the cent, the draft keeps that breakdown (a pretax line and the rate), so the office never adds tax a second time; otherwise the draft has one line for the whole accepted price with tax left at zero for the office to set, as with a new invoice. An estimate's job is named after the accepted option on the line.

A job is skipped, with the reason shown, when it already has an active invoice, is cancelled or not scheduled yet, is a visit of a plan billed monthly by subscription, was prepaid through a retention offer, or has no customer, service property, or price on file. A job's status is checked again the moment its draft is made, so a job cancelled after the selection is skipped too. The result lists every job that was skipped or failed so the office knows which ones to fix, and the new drafts wait under Invoices to be reviewed and sent. Up to 25 jobs go in one batch, and the selection starts over when the page or filters change.

Sales attribution

A source-linked invoice inherits the assigned sales representative from its estimate, including when the estimate is reached through a linked job. Invoices created without a source estimate begin unassigned. This carries the V1 sales owner into billing without making attribution part of the customer-facing document.

An authorized billing teammate can open invoice detail, choose Change sales rep, and assign an active owner, admin, or sales rep who can work in that invoice's service office. Choose Unassigned to clear attribution. A historical assignee remains visible even if the teammate is later deactivated or changes roles, but that teammate cannot be newly selected again unless eligible.

Sales attribution has its own concurrency version and audit event. If two open invoice tabs try to change it, the stale save is rejected and must be refreshed. Every accepted change also appends a permanent attribution-history row containing the old rep, new rep, actor, service office, and assignment version. That history is not removed with the short-lived event-delivery queue. The row retains the office where the assignment changed without preventing or being rewritten by a later valid draft office move. If a draft is moved to another office, its current rep is revalidated against the new office in the same save; choose an eligible rep or Unassigned before moving a draft whose current rep cannot work there. Changing the rep does not alter itemized content, money, delivery history, customer links, PDFs, payment sessions, or the invoice-payment ledger.

Review and edit

Open an invoice number to see its status, issue and due dates, itemized charges, customer and service-property snapshot, saved note and terms, settled payment history, any separate Deposit carried forward credit, paid amount, and current balance.

Drafts can be edited. Each save uses an optimistic content version, so an old browser tab cannot overwrite a newer edit. Draft detail and PDF previews use the current customer, billing contact, and property address, matching the party details the send action will freeze. Once an invoice is sent, its billed party and itemized content are frozen. If sent content is wrong, void the unpaid invoice and create a replacement rather than rewriting the immutable issued document.

The issued document and its delivery reading are intentionally different. Send and resend never edit the frozen accounting snapshot, but they can add new, auditable email or SMS attempts. Each attempt combines the handoff record with later provider facts: provider acceptance alone is Accepted, not Delivered, and only confirmed arrival is green. A text remains Accepted because CE Pro receives no handset-delivery receipt; an email can later become Delivered, Did not arrive, Marked as spam, or Records disagree. Failures and other outcomes that require intervention are presented as Action needed. Send, resend, and void compare a monotonic delivery version loaded by the office. Two tabs cannot both rotate the customer link; the later stale action is asked to refresh instead of returning a link another action already invalidated. The separate first-send timestamp stays immutable so signed-in customer-history cursors do not move when a delivery is retried.

If a draft already carries an estimate or job source, its customer and service property stay fixed to that source while the draft's charges, dates, note, and terms remain editable. This avoids silently detaching a bill from its work record. If that retained property is later archived, the disabled selector keeps showing the real property with an Archived label instead of jumping to another address. Reactivate or correct the source work record before sending; the invoice cannot silently substitute a different property.

An unpaid draft or sent invoice can be voided. Voiding invalidates its customer link and safely expires an open Stripe Checkout session. Void compares both the content and delivery version loaded by the office, so an older tab cannot void an invoice after another user edits or resends it without first refreshing. An unsent draft freezes the current customer, billing contact, and service address as it becomes a retained void document; it does not fall back to party details from an older draft save. An invoice that was already sent keeps its issued party snapshot when it is voided. An invoice with settled money cannot be voided, even after that payment is fully refunded; the retained payment/refund history must not disappear behind a Void label.

V1 destructive invoice deletion and editing of an already-issued document are intentional safety exceptions in V2, not silently missing controls. Drafts remain editable, but sending freezes the customer and accounting snapshot; retained voiding replaces destructive deletion so delivery, payment, refund, and audit history cannot disappear.

Email pause: Outgoing email delivery remains paused. The invoice send flow still requires an eligible delivery channel; SMS requires the configured workspace sender and customer consent. Copy link is available after invoice issuance, and the email steps below describe resumed delivery.

Send and resend

Send invoice opens Review & Send before any send attempt is queued. Choose the saved recipient and an eligible delivery channel; SMS requires the configured workspace sender and customer consent while outgoing email delivery is paused. Review or edit the email subject and body plus the SMS copy, and use Preview to inspect the issued invoice. The office can copy the secure invoice link after issuance, but the current send flow does not offer a copy-only issue path. Each selected channel requires the matching active contact method and consent; a phone number is never guessed from an unrelated contact when SMS is selected.

The first confirmed send performs one atomic transition:

  1. freezes the current customer, billing contact, service address, office, timezone, and itemized invoice snapshot;
  2. mints a high-entropy customer link while storing only its digest;
  3. marks the accounting document sent; and
  4. commits a durable delivery attempt for each selected channel beside the invoice change.

Email and SMS workers use the reviewed copy through the existing consent, provider, lease, and idempotency pipeline. A delayed attempt rechecks the invoice status, delivery version, token digest, exact selected method, and its active contact immediately before provider handoff. The method and contact stay locked through provider acceptance, so a recipient edit or archive cannot slip between the final check and the send.

Invoice detail keeps one durable reading for every channel and attempt: Queued is waiting to send; Not sent is a failed handoff; Accepted means the provider took the message but arrival is not confirmed; Delivered requires an arrival receipt; and Marked as spam, Did not arrive, or Records disagree name later evidence that needs care. Each row explains the provider fact that decided its reading. The page headline uses the newest attempt per channel and puts a complaint or delivery problem ahead of a success on another channel. A customer view remains useful evidence, but it never hides a bounce, complaint, or contradictory record. Terminal provider, consent, configuration, or recipient-change failures and other actionable outcomes are retained as Action needed instead of being presented as sent or retried forever. Resend invoice opens Review & Send again with current eligible recipients and creates new attempts without deleting or rewriting the earlier failure. That retry changes delivery state, not the immutable issued invoice.

Resending rotates the customer link; a delayed attempt from the earlier send is a safe no-op instead of sending a revoked link. A resend keeps the invoice's prior qualified-view timestamp because it is the same accounting document. Paid invoices retain Resend invoice; when the settled ledger shows the invoice paid in full, reviewed copy invites the customer to view the paid invoice instead of inaccurately asking them to pay it. Before a resend rotates the link, it expires any registered open Stripe Checkout created from the previous link. If Stripe reports that payment already completed but its webhook has not yet landed, resend stops and asks the office to refresh rather than racing real money or leaving a stale payable tab alive.

Delivery requires an explicit HTTPS NEXT_PUBLIC_APP_URL (localhost HTTP is accepted only for local development). The worker fails closed when that value is missing or unsafe instead of emailing a link for the wrong environment.

Reminders

Send reminder appears on an open invoice row on the list, sent, viewed, partially paid, or overdue, for a teammate who can manage invoices, and is hidden once the invoice is paid or void. It sends immediately, under its own reminder subject, body, and delivery template, separate from the first Send/Resend path: a reminder never re-triggers Invoice is sent automations or resets the invoice's qualified-view history.

Like a resend, sending a reminder mints a fresh customer link and expires any Stripe Checkout session opened from the previous link. To avoid pulling a customer's live payment screen out from under them, CE Pro refuses to send a reminder while a payment for that invoice has been pending in the last 15 minutes, asking the office to try again shortly instead.

CE Pro also raises reminders on its own. A daily sweep raises one Invoice is overdue automation event per invoice the first time it crosses its due date with a balance still owed, so an owner-configured workflow can message the customer without office involvement. The sweep never raises that event twice for the same invoice unless the due date later changes, and only looks within 30 days of the due date, so turning reminder automation on does not backfill notices for an organization's existing overdue book, only for invoices that become newly overdue afterward. See Automation Triggers to build a workflow on it.

Customer invoice and PDF

The secure /i/... link is authorization for one invoice only. It shows the provider, customer, service address, issue and due dates, itemized charges, discount and tax, settled payments/refunds, current balance, note, and terms. Draft and void invoices return the same unavailable response as an unknown link. Customer responses are private and no-store. The bearer-link page is also marked noindex and uses a no-referrer policy so the token-bearing URL is not offered to crawlers or forwarded as navigation context.

The downloadable PDF uses the same allow-listed projection. It includes no provider payload, internal note, full payment instrument, estimate approval, or signature block. Calendar dates remain calendar dates, and payment event dates use the invoice's service-location timezone. The public invoice also renders issue and due dates as saved calendar dates in every browser timezone, rather than letting a customer's device shift them by a day. Paid and voided PDFs label their zero balance Paid in full or No balance, never Balance due $0.00.

The signed-in customer account also has an Invoices destination with stable 25-record cursor pagination. Customers can open every sent invoice in their verified customer scope, including a sent invoice that was later voided, download its PDF, and see its current paid amount, collectible balance, and settled payment/refund history. A later-voided record has no balance due or pay action, while a draft voided before send remains private. Customer headings and history rows say Paid in full or Voided instead of describing a zero balance as money still due. The same invoice payment appears in signed-in Payments history only after Stripe reports a settled or refunded state.

Opening a sent invoice records customer engagement only after the interactive browser explicitly acknowledges that the customer invoice rendered. A raw server request, security scanner, email-link preview, crawler, office preview, or Checkout-return poll cannot mark the invoice viewed. Qualified opens through the /i/... link and signed-in Invoices pages count toward view totals once per hour per subject and can raise configured staff alerts; refreshing within the same hour does not repeat the invoice.viewed event. A direct signed-in customer PDF open records the view too.

Pay online

A sent invoice with a positive balance can open Stripe Checkout for exactly the current ledger-derived balance after settled deposit credit. The server:

  • requires the provider's connected Stripe account to be ready;
  • locks the invoice while choosing or creating a session;
  • reuses only a registered, still-unexpired pending session for the same

balance, content version, and exact success/cancel return boundary, so a resent public link or a signed-in portal visit cannot inherit a stale return URL from the other surface;

  • expires a stale session before replacing it, and refuses replacement if

Stripe still reports that session open or already completed;

  • uses direct charges and the saved platform-fee configuration; and
  • registers the pending session, including the exact connected Stripe account

that owns it, before returning its URL.

Before Pay, the customer can add a tip from the workspace's three choices under Payment Collection or pick No tip. The Pay button shows the balance plus the tip, Checkout carries the tip as its own line, and the tip is charged on top of the balance: it never reduces what is owed, so the invoice shows paid the same either way. The tip is kept with the payment, printed on the receipt as its own line, and shown in payment history. The server works the tip out from the saved choice, so a page opened before the choices changed cannot charge a tip the workspace no longer offers: the page sends the tip it showed, and if the choices changed in the meantime the customer is asked to pick again. A session minted for one tip is never reused for another.

A refund from the office can include the payment's remaining tip. The refund reduces remaining invoice principal first, then the remaining tip; a tip-only remainder can be refunded. The invoice balance continues to include principal only. A refund made in the Stripe dashboard is recorded invoice-first: it reduces the invoice amount until that is fully refunded, and only what goes beyond it comes out of the tip. Reports count tips as cash collected (and a refunded tip as refunded); invoice balances never include them.

Safe invoice payment transitions

Before a manual invoice payment is recorded, Clean Estimate asks Stripe to expire any open Checkout session for that invoice. Cash can still be recorded when there is no prior Checkout. Manual collection stops if Stripe reports that the existing Checkout completed or cannot confirm its status, to avoid collecting twice.

If a valid Stripe charge settles after the invoice changes, becomes unpayable, or has less remaining balance than the charge, Clean Estimate records it once and surfaces a conflict for office reconciliation instead of silently overpaying. It does not discard evidence of money received.

The public-link checkout transaction is bound to the exact token digest that authorized it. If a resend rotates the link during a request, the old request cannot mint a fresh payable session. A signed-in customer uses customer-session identity instead of the bearer link. That signed-in action revalidates the service-only portal session, current customer scope, invoice ownership, and invoice balance in one service transaction; staff database permissions are not expanded to expose customer session records.

Stripe Checkout accepts at most eight digits for a USD charge amount, so a sent invoice whose balance exceeds $999,999.99 cannot be paid online. Both the public invoice page and the signed-in portal hide Pay there and ask the customer to contact the office to arrange payment, and the checkout API rejects such attempts server-side (invoice-above-maximum) before contacting Stripe.

Stripe webhooks validate the connected account, organization, invoice, location, currency, amount shape, and invoice metadata before attaching real money. They also require the session ID, amount, currency, document version, application fee, and connected-account snapshot to match the exact local Checkout registry row created while the invoice was locked. Provider replay identity includes the Clean Estimate organization, provider, connected-account snapshot, and provider object ID. The same provider object text on a different connected account is therefore a separate namespace, while an account reused by another organization fails closed instead of choosing a ledger. A later change to the organization's Stripe connection does not orphan the earlier session: expiry, settlement, delayed-payment failure, and refund handling continue to use that saved account boundary. A separately created Stripe session cannot impersonate an invoice payment merely by copying invoice metadata. A replay updates the same provider payment row. If money arrives after the invoice changed or was voided, CE Pro records the real money first and creates a payment-conflict event rather than discarding evidence of the charge.

Only settled invoice payments and available carried-forward deposits reduce the displayed balance. Pending and failed attempts do not appear as collected money. Refunds reduce paid-to-date by the actual refunded cents, including reducing a linked deposit credit when its source deposit is refunded. On return from Checkout, both the secure public invoice and the signed-in customer account say the payment is still processing and briefly refresh the ledger-backed invoice until its balance reaches zero; only then do they show a paid confirmation. The return URL alone is never treated as proof of payment.

When an invoice is linked to an estimate assigned to a salesperson, its settled collections and refunds also flow through that estimate into the rep's earnings and commission history. The invoice payment remains a separate accounting target; Clean Estimate does not duplicate it onto the estimate payment ledger.

Saved cards (signed-in portal)

The signed-in Payments page begins with Payment methods: the cards the customer keeps on file with your company's connected Stripe account. The list is read live from Stripe — the portal never stores card numbers, brands, or expiry dates — and shows each card's brand, last four digits, expiry, and which card is the default.

Add card opens Stripe's hosted secure page, exactly like paying an invoice: card details are entered on Stripe, never on the portal, and the customer returns to the Payments page when the card is saved. A newly saved card can take a moment to appear while the provider confirms it. Each card can be removed (with confirmation) or made the default; both actions are recorded for the office with the acting customer session, and a customer can only ever see or change cards on their own verified account.

Saving a card never authorizes a charge on its own — and paying is where the wallet pays off: when a signed-in customer selects Pay on an invoice, Stripe's hosted checkout recognizes their account and offers their saved cards, so paying is one click instead of retyping the number. The same page lets the customer choose to save the card they use for next time. Payment from the emailed invoice link without signing in is unchanged, and a Suds Club membership keeps billing the payment method from its own signup.

Office saved-method administration

The client profile's Payments tab shows the same wallet as its own office-scoped card list: brand, last four digits, and expiry only, never a full card number. Any teammate who can manage invoices can view it; removing a saved card needs Issue refunds as well. The list and the remove action are scoped to the signed-in office member's organization, so a card cannot be viewed or removed across organizations.

Office keyed-card collection does not add a second, in-app card-entry form. It reuses the same hosted Stripe Checkout the Collect payment panel already opens for card, staying a guest session for the invoice's exact outstanding balance. The session is never resolved or attached to the client's saved-card wallet, even though its URL doubles as a copyable link handed to the office: a wallet-bound link would let anyone holding it see or charge the client's saved cards without ever signing in as the client. A card only reaches a client's wallet through the client's own action on the signed-in customer portal above, never through office keyed entry.

Optional payment offers (signed-in portal)

When the office enables Customer payment offers in Settings, selecting Pay on an eligible open invoice in the signed-in portal can first show a short optional offer sequence in a fixed order: Suds Club, get the next service on the calendar, then prepay the next service. The offers never prevent, delay, or change paying the invoice:

  • Every offer screen keeps a full-size **Continue to invoice payment

([balance])** button, and declining or closing the sequence lands on the existing secure checkout with the exact current balance. The issued invoice document and balance are never changed by an offer.

  • The server decides eligibility for the whole sequence and revalidates the

live portal session, customer scope, invoice state, and Stripe readiness when the sequence opens and again on any accept. If eligibility cannot be loaded quickly or safely — or the offer system fails for any reason — the Pay button goes straight to checkout. An offer problem is never a payment outage.

  • An offer whose requirements are not met is skipped without an empty screen:

the Suds Club step appears only for customers whose membership can be priced honestly (see below), the calendar step offers the guarded request-a-time service request (a real lead the office confirms — nothing extra is charged, and the customer picks a preferred day rather than typing a time), and the prepay step stays hidden until a priced, bookable next service exists. No offer invents a price, discount, or calendar capacity.

  • Each attempt is recorded durably — which offers were shown or suppressed

and why, and what the customer decided — and a sequence the customer just finished does not replay on an immediate second Pay click.

  • Enabling the flow and each individual offer are independent switches under

Settings, default off, restricted to teammates with Manage invoices, and every toggle change is recorded with the acting teammate in an append-only audit trail.

Public bearer-link invoice payment and the office collection flows are unchanged; the offers exist only for signed-in portal customers.

Choosing which Suds Club plans can be offered

The Suds Club offer prices from the workspace's own Suds Club configuration: the Suds Club section of the stored pricing configuration when a complete one exists, otherwise the built-in Suds Club template. Under Settings → Customer payment offers, teammates with Manage invoices see a server-computed preview of every plan exactly as the offer step will present it — the amount due today, the monthly payment schedule, the yearly total plus tax, the included services, and only genuine configured savings — and can untick individual plans to keep them out of the offer. Plan-selection changes are recorded in the same append-only audit trail as the offer switches.

One safety rule applies to all of it: if the stored Suds Club configuration is incomplete or invalid, no plan is offered or previewed until it validates — Clean Estimate never fills gaps with guessed prices.

How the customer joins Suds Club at payment time

When the Suds Club offer is enabled and configured, the step shows the ONE plan the customer's own home resolves to. The tier comes from the house-wash square footage on the customer's real estimate history — the estimate behind the invoice being paid first — priced from the workspace's Suds Club configuration plus the service property's tax basis. The card presents the included services with their visits per year and seasons, only genuine configured savings, the amount due today, the monthly payment schedule that follows, the tax-inclusive year total, and the plan terms. Nothing is computed in the browser.

The offer is residential-only. The invoice must resolve to an authoritative completed source job, and that job must resolve to a linked estimate whose saved vertical is residential. The organization, service location, customer, and property must remain coherent across that lineage. Commercial, generic, Holiday Lights, missing, mismatched, and ambiguous sources suppress the Suds Club offer; Clean Estimate does not guess from a customer label or use an unrelated historical estimate as a substitute.

Joining opens a separate, secure membership checkout for the signup amount — today's invoice is a separate accounting target and its document and balance never change. The membership plan and its seasonal visits are created immediately but stay payment-pending until Stripe confirms the signup payment settled; only then are the visits released for scheduling and the remaining monthly installments created as the same Stripe subscription schedule estimate-accepted memberships use. After the signup checkout the customer returns to the invoice page to finish the invoice payment, and accepting the membership ends the offer sequence — the rebook and prepay offers are not shown after a membership that covers the next service.

The step suppresses itself, with the reason recorded on the attempt, when the membership cannot be sold honestly: the customer already has an active or paused plan (or an unfinished membership signup), no measured estimate exists to anchor a tier, the home falls in the custom-quote band, the admin's plan selection excludes the resolved tier, or the amount cannot be charged. A signup the customer abandons is reclaimed automatically after its checkout session expires — the never-paid plan and its visits are cancelled and the customer can be offered a membership again later. If a signup payment arrives for a membership the office has since cancelled, the payment is recorded and the office is alerted to refund or keep it deliberately; the cancelled membership is never silently revived.

Rebook the completed work after payment

An eligible completed job can present the same protected next-service card from the invoice experience and, when the app URL is configured, the Work link in the post-job review follow-up. The card uses the issued invoice's immutable scope and total. It never rebuilds the job from a live price book or accepts a customer-entered amount.

A new Rebook this exact work request requires an explicit payment choice:

  • Pay after the next service creates a retry-safe office request and no charge.
  • Prepay this exact work opens Stripe-hosted Checkout for the exact frozen total. It appears only when Let customers prepay when rebooking the exact completed work is enabled under Settings > Customer payment offers, the connected account can charge, and the amount is provider-valid.

An unfinished repeat-work command saved by an older browser before this payment choice existed keeps its original notes and decision/request keys. CE Pro unlocks the choices and waits for an explicit selection, then upgrades that same saved command with pay later or prepay. It does not silently default the old attempt to pay later. When server state shows a resumable prepayment, that immutable choice takes precedence and only prepay is available to continue. If secure prepayment is definitively unavailable before that first acceptance, CE Pro discards the uncommitted browser command, refreshes server truth, and reopens the payment choices, including pay later. No accepted server order or payment is changed; an accepted, open, or processing prepayment remains prepay-only.

Neither choice schedules an appointment. Ready pay-later requests and verified prepayments enter the location-scoped repeat-work queue. A teammate with Manage calendar reviews the frozen customer, property, invoice, line items, amount, and payment state, then creates one unscheduled job for office scheduling. A row marked Refund attention cannot be turned into work until the payment is resolved. If Stripe reports a partial refund on the applied prepayment, that row stays in Refund attention with the remaining refundable balance. CE Pro blocks initial job creation and any linked job's scheduling, rescheduling, start, or completion until the remaining refund is resolved; a scheduled job can still be pulled back to Unscheduled for safe review. If the applied prepayment was partially refunded, the customer sees Prepayment needs office review and has no pay-later, Checkout, or second-payment action while the office resolves the remaining balance.

Checkout return and cancel URLs are navigation only. The account shows awaiting payment, asynchronous processing, settled, or attention state from the registered Stripe payment. An abandoned open Checkout remains resumable and cannot be changed back to pay later. A verified late success from a replaced session always remains in the payment ledger: when it is the first applied payment it settles the order and expires any still-payable replacement session; otherwise it remains an unapplied duplicate and records a conflict for operational handling. Any additional attempt that remains pending or succeeds holds fulfillment for payment or refund review, and database guards block job creation and later job progression until every extra attempt is failed, cancelled, or fully refunded. A Refund attention row lists each exact refundable payment. A teammate needs Manage calendar to see the queue; the refund buttons appear only when that teammate also has Manage invoices and Issue refunds. The dialog requires a 1–1,000 character reason and refunds the payment's full remaining balance. CE Pro re-derives that amount and the original connected account and PaymentIntent on the server instead of trusting browser-supplied financial details.

The refund uses a durable command. If Stripe does not confirm the exact refund, the office sees The refund could not be confirmed and can safely retry that saved command after reviewing the payment record. Ambiguous transport errors and pending provider states reuse the same Stripe attempt and key. After an exact Stripe failed or canceled result, the next authorized retry advances the same command to a fresh durable provider-attempt key. The original command reason is shown read-only to teammates who have both financial permissions, and another currently authorized teammate can retry without rewriting the original actor, amount, reason, provider account, PaymentIntent, or command idempotency. Calendar-only users can see that financial attention blocks the work but do not receive the command ID, command state, or reason. CE Pro shows the refunded amount and refreshes the queue only after Stripe reports a successful refund with the expected amount and PaymentIntent, or exact registered provider truth proves the exact scoped payment is fully refunded while the matching command remains unresolved. In that external-completion case, the next authorized retry supersedes the command locally and does not send Stripe another refund request. The original command remains auditable.

An applied prepayment can start a governed refund after materialization only while its exact linked job is Unscheduled, Scheduled, or In progress; a Complete or Cancelled job cannot start it. The provider refund runs first. A provider failure leaves the linked job active and blocked from moving forward while the same command remains available for retry. After provider success, CE Pro finalizes the ledger and cancels that exact linked job in the same local transaction with the refund reason and normal job-status audit. A full applied refund made outside CE Pro is recorded as provider truth but stays in Refund attention until the office reconciles any matching saved command and closes the linked active job; when no matching unresolved command exists, the office still reviews and cancels that job explicitly. A partial applied refund made outside CE Pro also returns active or unmaterialized repeat work to Refund attention and blocks dispatch without rewriting the order's settled-payment history.

A refund never creates a job. Refunding only an extra duplicate can return the valid settled request to office review after every other attempt is resolved; it never cancels the valid linked job. A late duplicate that arrives after the valid job exists stays in the queue as financial attention with a link to that job and cannot materialize a second one. Pending or failed refund commands also block initial job attachment and later transitions to scheduled, in-progress, or complete until the command is resolved.

Creating the unscheduled job also reconciles the linked intake lead through the pipeline's audited Won transition. If a custom pipeline has no single active Won stage, CE Pro leaves the lead unchanged and records a durable reconciliation event instead of guessing. That event is not, by itself, a delivered office notification.

When the office later creates, edits, or first sends an invoice for that repeat-work job, CE Pro binds the invoice work scope to the retention offer's frozen property. Another active property for the same customer and office cannot be substituted by stale or changed editor input. A standalone office job uses its immutable direct property, and every other non-null lineage source must agree before the invoice can be created, edited, or sent.

An exact repeat-work job with an applied prepayment cannot create, retarget or edit a draft, or first-send a second invoice for the same work. This protection remains in place after a partial or full provider refund: the original provider payment history remains the financial record, while the governed refund and linked-job cancellation workflow handles reversals without reopening a second customer balance. A repeat-work job booked with Pay later remains invoiceable through the normal workflow, with its frozen property still enforced.

Collect and refund in the office

An authorized admin can open Collect payment on a sent invoice and record a partial tender; additional tender entries can complete a split payment. Cash, check, ACH/bank transfer, and an external terminal or processor are always available, and the other ways to pay turned on under Payment Collection (Zelle, Venmo, Cash App, PayPal, financing) join the method list; each is recorded as an office collection against the exact invoice, with an optional reference and note. The server checks the workspace's saved list again when the payment is recorded. The panel's Customer tip row offers the workspace's three tip choices plus No tip; one choice feeds both the recorded payment and the card checkout, and the tip is charged on top of the amount without touching the balance. Changing the tip drops a checkout link already made for the old one, and a tip the panel showed that no longer matches the saved choices is refused so the invoice can be reloaded. Card collection opens hosted Stripe on the connected account and settles only from its registered provider payment; Clean Estimate never accepts raw card details. The combined settled amount cannot exceed the invoice's current ledger-derived balance.

For card, the Collect panel asks the server to create or safely reuse Checkout for that exact organization, connected account, invoice, remaining amount, and return surface. It then shows Open secure card checkout and a copy link. Opening Checkout on the staff device can return to the authenticated office invoice. The copied customer link instead uses a customer-safe public invoice/confirmation return; it never redirects the customer to admin sign-in. Opening or copying either link does not record money: the payment becomes settled only after the connected-account Stripe webhook verifies the registered session. Reopening the panel reuses only that exact compatible Checkout instead of creating an independently payable duplicate.

Every tender remains a separate append-only ledger entry with its amount, method, office actor, time, workspace, and provider or manual reference where applicable. A repeated submission reuses its idempotent operation instead of adding the same money twice. Concurrent customer Checkout, office collection, deposit allocation, and refund actions serialize on the invoice/payment rows, so two surfaces cannot both consume the same remaining balance.

Each successful direct invoice payment also receives an immutable Clean Estimate receipt. The receipt freezes the invoice number, amount, currency, payment method, safe manual reference, paid time, customer, service address, and business name from the settled payment and issued invoice. It never includes Stripe payloads, card details, provider credentials, internal notes, or processing fees.

Customers can download a receipt from Portal > Payments. A receipt email also includes a customer-safe signed download link that works without office or portal sign-in for 30 days. The link is bound to the exact receipt, customer, delivery attempt, and still-active Billing or Primary email; it stops working when it expires or that customer email is deactivated or changed. An authorized office teammate can use Receipt in invoice payment history to download the same customer-safe PDF or Email receipt to send another copy to an active billing or primary email. The app rechecks that recipient when sending and shows any address or eligibility change inside the recipient chooser without sending to the retired address. Each newly settled direct invoice payment queues one automatic email when the issued invoice's billing email is still an active customer contact. Each intentional office resend creates one new delivery record; a retry or background replay of that same command reuses its durable idempotency record instead of creating a duplicate. Existing successful direct invoice payments receive downloadable receipts during the migration, while automatic receipt email begins with payments settled after this release.

The receipt records the original payment. A later refund or adjustment does not rewrite that receipt; the PDF says this explicitly and directs the customer to the current invoice or payment history for the latest net amount.

Payment rows, refund-command state, and delivery outcomes are controlled service records. Raw or direct application-role inserts and outcome updates fail closed, preventing a client or ad hoc write from manufacturing settled money, completing a refund command, or claiming provider delivery.

A freeform staff payment reference or note is office-only audit context. Bearer invoice links, signed-in customer history, customer payment history, and PDFs never receive it. Those customer surfaces show only an allowlisted payment method label and safe accounting facts such as amount, date, refund, and net effect; they do not serialize the staff-entered text or raw provider payload.

For an eligible settled payment, an authorized admin can select Refund and enter a partial or remaining refundable amount. A Stripe-backed refund remains bound to the connected account and exact provider payment that collected it; an offline or external refund remains attached to its original office collection. Pending, succeeded, and failed refund attempts are retained rather than rewriting the original payment or disappearing after an error. The invoice, customer account, client payment history, list totals, earnings, and balance all derive paid and refunded cents from that same ledger projection.

The first transition to a zero collectible balance publishes exactly one invoice.paid business event. Provider retries, concurrent final tenders, later refunds, and a later recollection do not publish a second first-paid event. A refund can reopen a balance without erasing the original collection, refund, delivery, or paid-event history.

Collect and refund actions finish the money mutation before reloading invoice detail. If that follow-up read fails, the office receives a separate refresh notice rather than a false “payment failed” or “refund failed” result. The original idempotency identity is retained, so retrying after an uncertain browser response replays the terminal outcome instead of collecting or refunding twice.

A pending or failed provider refund is recovered only by the service worker. Before retry, it validates the exact tenant, invoice, original payment, refund command, actor, amount, reason, idempotency key, provider account, and provider payment identity. Staff and ordinary application roles cannot invoke a raw command-state transition or attach the provider result to a different ledger.

The refund panel also lists any deposit carried forward from an accepted estimate as its own refundable item, labeled Deposit carried forward. Selecting it refunds the original estimate deposit payment through the rail that collected it, Stripe or a recorded manual refund, up to the unrefunded credit, partial amounts included.

This only works when the deposit is fully applied to this invoice. When it is only partly applied, the panel says to refund it from the estimate deposit instead. A deposit shared across more than one invoice is refused the same way, since crediting the wrong invoice could leave a balance that does not add up.

A failed deposit-credit refund is retried the same way as a failed invoice-payment refund: from the same panel, without rewriting the original actor, amount, or reason.

Void a payment

A Void action sits next to Refund in a payment's history row. It covers only a settled, non-adjustment, unrefunded, positive direct invoice payment that has never already been voided, and a note explaining the void is required.

A Stripe card payment can be voided only within 24 hours of settling and only while its PaymentIntent has not yet captured. Once Stripe reports the PaymentIntent captured, which V2's always-auto-capture design makes the normal case, the void is refused with V1's own message: "This payment has settled, use Refund instead." A void never falls back to a refund on its own; the office chooses Refund separately when that happens.

Voiding raises the invoice balance by exactly the voided cents. It reuses the same payment row's refunded-cents field rather than adding a separate negative row, so the balance calculation already nets to zero once the voided amount matches the payment amount. A tipped payment's tip is voided along with it, the same way a refund on a tipped payment covers the tip.

Void uses the same durable, append-only command pattern as refunds: a failed or interrupted void can be retried without rewriting the original actor, amount, or reason, and a stranded void is picked up by the same recovery job that sweeps stranded refunds.

Attachments

Every invoice has an Attachments section at the bottom of its office page for jobsite photos, signed approvals or change orders, purchase orders, permits, and supporting PDFs and office files. Anyone who can open the invoice can see the list and open a file; Upload file and Delete need the manage invoices permission. Customers never see these files.

Images, PDFs, text and CSV files, and Word, Excel, and PowerPoint files are accepted, one at a time, up to 20 MB each and 50 per invoice. CE Pro reads the file's real type from its contents before saving it; a file whose contents do not match its type is refused with a plain message instead of being stored. Deleting a file marks it removed right away; it stays recoverable for 30 days, then a daily job permanently purges the file and its record. See Storage and Attachments for usage totals.

Client history

The client profile has a paginated Invoices tab and includes invoice payments in its settled payment history. A company portfolio rolls up invoices from visible child service sites; the parent still cannot own a new invoice. This keeps client billing history reachable beyond the first 25 records without mixing inaccessible offices or retained work on the portfolio parent.

V1 parity still to port

V1 remains the product baseline. The current safe V2 invoice workspace deliberately does not replace the following features with placeholders or silent removals:

The delivery, collection, and refund additions above do not constitute full V1 invoice parity. Every item below remains future work until its actual V2 UI, authorization, data, and audit contracts ship.

Keep the complete V1 invoice workflow alongside this backlog when training or supporting teams that still use those controls.

  • the bulk-schedule entry point (drafts for several jobs come from the jobs list instead);
  • a reminder's own delivery/open activity inside Inbox: sending a reminder

raises its own comms event, but Inbox's shared timeline query has no column yet to tell that attempt apart from an ordinary send;

  • a true embedded, in-app card-entry form and mobile keyed-card entry or

saved-method administration; same-day payment void, office keyed-card collection through hosted Checkout, and office saved-method administration are live, described above;

  • credits and write-offs beyond controlled refunds;
  • tasks/activity and internal notes beyond the single office note field; V1's

own "Tasks & activity" panel is not an invoice-native feature either, it is a reused CRM activity/task list anchored on the invoice's underlying deal, lead, or client;

  • recurring invoices and mobile invoice workflows;
  • QuickBooks/accounting sync, not merely unbuilt but explicitly excluded by

this repo's own build charter (docs/BUILD_PROMPT.md); building it needs an owner decision to lift that exclusion first, not just V1 parity work;

  • generic portal lookup by invoice number or customer email; current V2 uses

the secure invoice email link or authenticated customer Invoices page; and

  • create-from-estimate and other bulk/source shortcuts beyond the current

client and job entry points into the source-linked single-screen draft.

Troubleshooting

Review & Send says a contact method is required

For email, add an active email to an eligible Billing or Primary contact on the service client. For SMS, choose an eligible active phone method with the required consent. Do not add the method only to a company portfolio parent; the service site owns the invoice and recipient.

If a prior attempt says Action needed, open its channel detail before resending. Correct the recipient, consent, or provider setup named there, then open Resend invoice and review the current recipient and copy. Resend adds a new attempt; it does not erase the failed one or change the issued invoice.

Online payment is unavailable

Confirm the organization's connected Stripe account has charges enabled. The invoice remains viewable and downloadable when payment setup is incomplete, but Checkout is not created.

Also check the balance amount itself. Stripe Checkout accepts at most eight digits, so a sent invoice with a balance above $999,999.99 deliberately hides Pay on both the public invoice page and the signed-in portal and asks the customer to contact the office; the checkout API rejects such attempts server-side before contacting Stripe. That ceiling is intentional and is not a Stripe configuration problem, so no amount of settings review will restore the pay action.

A draft appears past its due date

A draft always remains Draft. Overdue is derived only after sending, when its due date is before today's date at that invoice's service location and a balance remains.

An estimate deposit is missing from the invoice

A settled deposit carries forward only when the invoice is linked to the same estimate or a job from that estimate, in the same organization and service office. It appears separately as Deposit carried forward, not as a new invoice payment. Pending or failed deposits do not qualify, another invoice may already have allocated the available amount, and a refund reduces the credit. Confirm the source link and review the estimate's payment history if the credit is lower than expected.

Allocation is serialized on the source payment, and the database also binds the allocation's organization and service office to both the payment and invoice. Concurrent drafts therefore cannot consume the same deposit cents or carry money across offices.

A refund or office payment did not change the balance

Confirm the tender or refund reached its settled or succeeded state. Pending and failed Stripe operations do not count as collected or refunded money. Also confirm the refund was created from the exact original payment and did not exceed its remaining refundable amount. Refresh the invoice to reload the same ledger projection used by customer history, client payments, and list totals; do not add a compensating fake payment or edit an earlier ledger row.

Was this article helpful?

Still need help? Contact support