Quote Samples
Captured /Quotation POST payloads from real Halo UI interactions or worked-out shapes the DTC Client Portal exercises. Useful for:
- Reproducing edge cases against a local stack (e.g. seeding test data via curl).
- Comparing what the portal sends vs what the Halo UI sends when investigating discrepancies.
- Runbook reference when triaging webhook payloads or unexpected Halo responses.
The canonical JSON for each sample lives in the DTC Client Portal repo under docs/halo/sample-payloads/. This page mirrors the commentary and provides a stable KB link for cross-referencing.
Sample 1 — Mixed line composition (hardware + recurring + service)
Source: Halo UI "Create Quote" dialog, captured 2026-05-06. Tenant: DTC. Client: DTC Inc. (id 19), Site: Ridgebrook (id 27), User: Nate Smith (id 48).
Why this payload is useful: three lines that exercise the cross-product of cases the portal's deferred-revenue / down-payment flow has to handle:
| Line | Item | Type | Cost | Tax |
|---|---|---|---|---|
CT2K8G4SFS824A (Memory) |
hardware | non-recurring, taxable | costprice: 28.99 (real cost) |
item_tax_code: 40 (3% MD Sales Tax) |
BDR-MSP |
recurring service | item_recurring: true, billingperiod: 2 (monthly) |
costprice: 28.36 (real cost) |
item_tax_code: -1 (item-default) |
Fixed Fee- Install |
service | non-recurring, taxable, item_contract: true |
costprice: 0 (no COGS) |
item_tax_code: 40 (3% MD Sales Tax) |
This composition is what surfaced the DP-invoice phantom-loss bug in PR #99: under SO POST _create_invoice_method=3, per-line unit_cost from the SO passes through onto the Halo deferred-revenue DP invoice. The hardware line's 28.99 × qty lands as cost on a placeholder invoice that's supposed to recognize zero COGS (work invoice carries COGS later). The recurring BDR-MSP line is filtered out of the deposit by is_recurring_line() — it bills on Halo's recurring schedule, not as part of the down payment.
Payload (JSON)
[
{
"is_quote_screen": true,
"site_delivery_override": 27,
"title": "test 2",
"lines": [
{
"item_id": 2940,
"name": " CT2K8G4SFS824A",
"sort_seq": 10,
"costprice": 28.99,
"quantity": "2",
"item_recurring": false,
"billingperiod": "0",
"markup": 42.12,
"item_taxable": true,
"taxable": true,
"assetgroup_name": "Inventory",
"item_tax_code": 40,
"baseprice": "41.2",
"price": 41.2,
"cost_converted": 28.99,
"tax": 2.4720000000000004,
"stocklocation_id": 614,
"current_quantity": "2",
"purchase_cost": 28.99,
"current_price": 41.2,
"override_tax_code": "-1",
"total_price": 82.4,
"total_costprice": 57.98,
"total_profit": 24.42,
"total_tax": 4.944,
"customfields": []
},
{
"item_id": 264,
"name": "BDR-MSP",
"sort_seq": 10,
"costprice": 28.36,
"quantity": "1",
"item_recurring": true,
"billingperiod": 2,
"markup": 605.22,
"item_taxable": true,
"taxable": true,
"assetgroup_name": "Recurring Items",
"item_tax_code": -1,
"baseprice": "200",
"price": 200,
"cost_converted": 28.36,
"tax": 12,
"stocklocation_id": 614,
"current_price": 200,
"override_tax_code": "-1",
"total_price": 200,
"total_costprice": 28.36,
"total_profit": 171.64,
"total_tax": 12,
"total_price_monthly": 200,
"total_price_annual": 2400,
"customfields": []
},
{
"item_id": 17,
"name": "Fixed Fee- Install",
"sort_seq": 20,
"costprice": 0,
"quantity": "3",
"item_recurring": false,
"item_contract": true,
"billingperiod": "0",
"markup": 20,
"item_taxable": true,
"taxable": true,
"assetgroup_name": "Service",
"item_tax_code": 40,
"baseprice": "135",
"price": 135,
"cost_converted": 0,
"tax": 8.100000000000001,
"stocklocation_id": 614,
"current_quantity": "3",
"current_price": "135",
"override_tax_code": "-1",
"total_price": 405,
"total_costprice": 0,
"total_profit": 405,
"total_tax": 24.300000000000004,
"customfields": []
}
],
"user_id": 48,
"user_name": "Nate Smith",
"client_id": 19,
"site_id": 27,
"deliver_to_us": true,
"override_delivery_address": false,
"xero_status": "DRAFT",
"status": "3",
"date": "2026-05-06T03:29:29.273Z",
"expiry_date": "2026-05-16T03:29:29.273Z",
"carriage_desc": "No Carriage Charge",
"currency_code": 2,
"automatic_sales_tax": false,
"do_not_invoice": false,
"assigned_agent": "13",
"approval_status": "0",
"internal_approval_status": "0",
"pdftemplate_id": -1,
"includegroupeditemqty": true,
"includegroupeditemprice": true,
"includegrouppriceandqty": true,
"linked_pdf_list_prepend": [],
"linked_pdf_list_append": []
}
]
The full unedited payload (with the lookupdisplay React VDOM, _temp_id correlation markers, and user/site denormalization blocks Halo's UI sends) lives in the repo at docs/halo/sample-payloads/quote.json.
Notes on the payload shape
- Top-level is an array. Halo's
/QuotationPOST is batch-shaped — even for a single quote, the body is[{...}]. status: "3"is "Sent" in the DTC tenant's quote-status enum. Adjust per tenant if reusing this fixture elsewhere.xero_status: "DRAFT"— quote-level Xero sync status. Halo expects it but the portal's flow doesn't depend on it.assigned_agent: "13"— agent id 13 is Nate's linked sales agent in the DTC tenant. String-typed, not int.currency_code: 2— DTC tenant's USD code.stocklocation_id: 614— DTC's primary stock location for inventory items (Ridgebrook).item_tax_code: 40— DTC's "3% MD Sales Tax" rule.-1on the recurring line means "use item default tax setup".override_tax_code: "-1"— string-typed, means no per-line tax-code override (defaults to client/site/item rule resolution)._temp_idand_cf_temp_id— UI-internal correlation markers Halo uses while assembling the quote. Halo accepts them on POST and replaces with real ids on the response. Optional.lookupdisplayunderuserandsiteis React VDOM hydration noise (the_owner: null,props.childrenrecursive shape is the rendered dropdown option). Halo's API ignores it on POST. Preserved in the repo fixture for fidelity to what the UI actually sends; omit when constructing payloads from scratch.
Posting against Halo (test seeding)
OAuth client_credentials flow, derived from HALO_BASE_URL (replaces /api with /auth/token — same shape as HaloClient::request_access_token in the portal):
# from the client-portal repo root, with .env in scope
set -a; source .env; set +a
AUTH_URL="${HALO_BASE_URL/\/api/\/auth\/token}"
TOKEN=$(curl -s -X POST "$AUTH_URL" \
-d "grant_type=client_credentials" \
-d "client_id=${HALO_CLIENT_ID}" \
-d "client_secret=${HALO_CLIENT_SECRET}" \
-d "scope=all" \
-d "tenant=${HALO_TENANT}" | jq -r .access_token)
curl -s -X POST "${HALO_BASE_URL}/Quotation" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data @docs/halo/sample-payloads/quote.json
The portal's HaloClient (api/src/services/halo/client.rs) is the canonical write path in production code — this fixture is for ad-hoc seeding and reproduction.
Related
- Quote Endpoints —
/Quotationendpoint reference. - Quote Schema — field-by-field schema.
- Invoice Endpoints —
/Invoicereference, including_create_invoice_methodsemantics. - DTC Client Portal repo —
docs/halo/sample-payloads/for the live JSON. - DTC Client Portal PR #98 — method=3 SO POST + non-recurring filter on DP invoice (where this payload's mix surfaced the design constraints).
- DTC Client Portal PR #99 — DP invoice + credit-note cost-strip (the phantom-loss fix this payload reproduces).