QBO ↔ Scoro Quote-to-Cash

Print version →

End-to-end deposit walk — project → quote → 50% prepayment → clickable pay-link → customer pays → receipt back → reconciled. For the ProMount by Vancomm (V2) entity.

What this covers

This is the validation and reference runbook for the QBO ↔ Scoro bridge (spec 004-qbo-payments, Worker at scoro-qbo-bridge.vancomm.workers.dev). It walks one complete order from project creation through paid in full, for the 50%-deposit path: the customer pays a deposit upfront (Scoro prepayment invoice) and the balance on completion.

Entity check. All Scoro steps run in the ProMount by Vancomm (new / promount) entity. If the Scoro invoice list shows 4-digit invoice numbers (2914…) you’re on the wrong entity — switch via vancomm.scoro.com/?mode=switchCompany.

Status — proven live both ways (2026-05-26)

The deposit loop (steps 1–7: prepayment → QBO deposit invoice → clickable pay-link → customer pays → receipt back to Scoro) was walked live against the fixtures named here and confirmed end-to-end across both systems. Every mechanism listed is real and verified, not projected.

The final-invoice loop (steps 8–10) uses native connector mechanisms proven earlier the same session: a QBO payment auto-marked Scoro invoice 2346 paid via Receipts = To Scoro. A full order-fixture walk is pending.

Automated vs. manual — at a glance

Step Who does it Status
Project / Company / Quote / Prepayment creation Michael (Scoro UI) ✓ Proven
Prepayment → QBO deposit invoice + clickable pay-link writeback Worker (Path A) ✓ Live (this walk)
Deposit payment → Scoro prepayment receipt Worker (Path B, QBO webhook) ✓ Live (this walk)
Final invoice → QBO sync → paid in full Native connector (Path C) ● Built + doc-verified; final-invoice live walk pending an order fixture
Mark delivered (Shipped/Picked Up) Michael (Scoro UI) ✓ Trivial

How the automation works — three paths

Path A

Prepayment → QBO deposit + pay-link

Scoro fires a prepayment-created webhook. The Worker reads the prepayment (amount, percent), creates a QBO deposit invoice (Customer Deposit item → liability #15) for the advance amount, fetches the Intuit InvoiceLink, and writes <a href="…">Pay online</a> back into c_qbo_invoice_link on the Scoro prepayment.

✓ Live

Path B

QBO payment → Scoro receipt

When the customer pays the QBO deposit invoice, Intuit fires a payment webhook. The Worker posts a receipt against the matching Scoro prepayment (by prepayment_id, is_prepayment:1), taking it off Outstanding and reconciling the deposit.

✓ Live

Path C

Order complete → final invoice → QBO balance

Michael creates the final (balance) invoice in Scoro. The native Invoices = From Scoro connector syncs it to QBO. Customer pays; Receipts = To Scoro auto-marks the Scoro invoice paid in full. No Worker needed for this loop.

● Built + doc-verified; final-invoice live walk pending an order fixture

One-time prerequisites (already done)

WhatWhere / value
QBO Customer Deposits liability account QBO chart of accounts — Id 15 (scripts/qbo-create-account.mjs)
QBO Customer Deposit service item → maps to #15 QBO products/services — Id 4 (scripts/qbo-create-item.mjs)
Custom field c_qbo_invoice_link, "Can add text in HTML format" = ON Scoro → Settings → Custom fields — field_id 27; scoped to invoices + prepayments. The HTML-format flag makes the stored <a href> render as a clickable link.
Connector Invoices = From Scoro Scoro ↔ QBO connector settings — ON
Connector Receipts = To Scoro Scoro ↔ QBO connector settings — ON (auto-marks Scoro invoices paid from QBO payments)
PDF templates: Quote 48, Prepayment 51, Invoice 49 Scoro → Settings → PDF templates — carry [a]c_qbo_invoice_link[/a] in the Payment Instructions block

The full quote-to-cash walk

Fixtures created for this walk. Reuse — don’t recreate:

ObjectFixture IDNotes
Project3031“QBO TEST Project”
Company / Person565 / 566“QBO Test Customer LLC” / “QBO Test Buyer”
Product4409ZTEST-PLT-6X6-14-G, $1.00, group V2_Raw Materials
Quote3290 (No. 5)product 4409, 5% quote-level discount → Total $0.95
Prepayment invoice128 (No. 2)50% deposit on quote 3290 → advance $0.50
1Create the project Michael — Scoro UI

Open Scoro in the ProMount by Vancomm entity. Create a new Project (fixture: #3031 “QBO TEST Project”) and link it to the company (fixture: #565 QBO Test Customer LLC). Ensure there’s a contact person (fixture: #566 QBO Test Buyer).

Make sure the product exists in the catalog (fixture: #4409 ZTEST-PLT-6X6-14-G, $1.00, group V2_Raw Materials, named per the product-naming convention).

2Create the quote with a 5% discount Michael — Scoro UI

From inside the project, click New Quote. Add product #4409 ($1.00). Apply the quote-level discount: triple-click the Discount field, type 5, Tab. Scoro auto-calculates the discount line on the PDF — it hides when 0%.

Result (fixture: Quote 3290, No. 5): Subtotal $1.00 — Discount (5%) −$0.05 — Total (USD) $0.95.

Quote 3290 PDF showing $1.00 subtotal, 5% discount −$0.05, total $0.95.

Quote 3290 PDF. The discount line is auto-rendered because the 5% field is non-zero. “This quote requires a 50% deposit at order confirmation.”

3Create the prepayment (50% deposit) invoice Michael — Scoro UI

From the quote/order: Invoices → New prepayment invoice, set the advance to 50%. Scoro creates a prepayment for $0.50 (50% of $0.95, rounded to the configured precision).

Prepayments cannot be created via the API — they’re UI-only to mint. But they’re fully readable and writable via the REST API afterward (including invoices/prepayments/modify).

Fixture: Prepayment 128, No. 2.

4Worker: prepayment → QBO deposit invoice + clickable pay-link Worker (Path A)

This is the core of the bridge. In production the Scoro prepayment-created webhook triggers the Worker automatically. For this walk it was driven manually:

cd workers/scoro-qbo-bridge
npx esbuild src/index.ts --bundle --format=esm --platform=node \
  --outfile=dist-node/index.mjs
doppler run -p vancomm -c dev_vancomm -- node test/drive.mjs \
  POST /process/prepayment/128 \
  '{"customerId":"9","billEmail":"worker-test@example.com"}'

What the Worker does (src/routes/process.tslib/qbo.ts + lib/scoro.ts):

  1. Calls invoices/prepayments/view/128 → reads sum=1.00, prepayment_percent=50.
  2. Computes deposit amount: sum × prepayment_percent = $0.50 (the advance, not the full sum).
  3. Creates a QBO deposit invoice (Customer Deposit item #4 → liability #15) for $0.50, online payment enabled.
  4. GET invoice/{id}?include=invoiceLink&minorversion=75 → pulls the Intuit InvoiceLink.
  5. Calls invoices/prepayments/modify → writes <a href="…">Pay online</a> into c_qbo_invoice_link. The Worker echoes back prepayment_percent + custom_fields so the 50% advance isn’t reset to 100%.

Verified response (2026-05-25):

{
  "ok": true,
  "scoroPrepaymentId": 128,
  "fullSum": 1,
  "prepaymentPercent": 50,
  "depositAmount": 0.5,
  "qboInvoiceId": "26",
  "payLink": "https://connect.intuit.com/portal/app/CommerceNetwork/view/scs-v1-…",
  "wroteAnchorTo": "c_qbo_invoice_link"
}

The Scoro prepayment record now shows the live pay-link in the c_qbo_invoice_link custom field:

Scoro prepayment 128 record showing Pay online link in the c_qbo_invoice_link field.

Scoro prepayment 128 record after the Worker ran. The “Pay online” anchor is live in the c_qbo_invoice_link custom field — rendered as a clickable link because the HTML-format flag is ON.

And the same link renders on the customer-facing prepayment (deposit) PDF:

Prepayment 128 deposit invoice PDF showing 'To be paid in advance (50%): 0.50' and clickable Pay online link.

Prepayment 128 PDF. Math reconciles: “To be paid in advance (50%): 0.50” matches the Worker’s computed deposit amount. The Pay online link in PAYMENT INSTRUCTIONS is the live Intuit hosted invoice link.

Customer mapping note. The Scoro→QBO customer mapping (Scoro company 565 → QBO customer 9) is passed in the request body for this walk. In production it resolves from a stored map (or the connector’s Contacts sync) — that’s the T-031 seam.
5Customer pays the deposit → receipt back to Scoro Worker (Path B)

In production the customer clicks Pay online and QBO records the payment; the Worker (on a QBO payment webhook) posts the receipt back to Scoro. For this walk both steps were driven manually:

# (a) Simulate the customer paying the QBO deposit invoice
doppler run -p vancomm -c dev_vancomm -- node test/drive.mjs \
  POST /process/qbo-payment \
  '{"customerId":"9","invoiceId":"26","amount":0.50}'
# → { "ok": true, "qboPaymentId": "27" }

# (b) Post the receipt against the Scoro prepayment
doppler run -p vancomm -c dev_vancomm -- node test/drive.mjs \
  POST /process/receipt \
  '{"prepaymentId":128,"contactId":565,"sum":0.50}'
# → { "ok": true, "reconciledPrepaymentId": 128 }

Receipts reference the prepayment by prepayment_id (is_prepayment:1, invoice_id:0). After this, prepayment 128 is reconciled (off Outstanding) — the deposit is received.

From the customer’s perspective, clicking Pay online opens the Intuit-hosted invoice page:

QBO hosted invoice page showing Mhondoro Capital Partners, $0.50, Paid / $0.00 balance due.

The Intuit-hosted pay-link page after QBO payment 27 was recorded. Mhondoro Capital Partners, LLC — amount $0.50 — Paid / $0.00 balance due. End-to-end confirmed live across both systems on 2026-05-25.

6–7Project work → ready to invoice Michael — Scoro UI

Move the order through the pipeline: In Process → Completed / Ready to Invoice. No QBO interaction at this stage — this is pure production work and internal pipeline management.

8–10Final invoice → paid in full → delivered Native connector (Path C)

Status: built and doc-verified; final-invoice live walk pending an order fixture.

  1. Create the final (balance) invoice in Scoro from the quote/order. Scoro credits the received prepayment, leaving the remaining balance. The Invoice V2 template (49) carries the same c_qbo_invoice_link field, so the regular-invoice pay-link applies here too.
  2. Connector syncs to QBO (Invoices = From Scoro). Customer pays via the pay-link.
  3. Receipts = To Scoro auto-marks the Scoro invoice paid in full — no Worker needed for this loop. Then set the order to Shipped/Picked Up (pipeline stage 10) = delivered.

The native connector mechanism is confirmed: a $1 QBO payment auto-marked Scoro invoice 2346 paid via Receipts = To Scoro earlier the same session. Path C requires no Worker code for the regular-invoice loop.

Production activation checklist

Before the Worker handles live traffic, three things must be wired in production:

Deposit loop proven live 2026-05-26

Prepayment 128 → QBO deposit invoice 26 → $0.50 paid → receipt back to Scoro → reconciled. End-to-end. Both systems.

Path C (final invoice via native connector) is built and verified against invoice 2346. The full order walk will confirm it against a real order fixture.

Need the printable version?

The print page has a condensed one-sheet of the walk: the step sequence, automation paths, and production checklist — designed to fit on letter paper.

Open print version →