Skip to content

Bridge Methods

All read methods are available to both standalone and quoting_extension tool types.

Returns the current user and tenant context.

const ctx = await window.pipeline.context.get();
// Returns:
// {
// userName: "Jane Smith",
// userEmail: "jane@example.com",
// userRole: "H_Admin",
// tenantName: "Acme Corp",
// tenantId: "abc-123",
// cultureCode: "en-NZ"
// }

Returns a paginated list of customers.

const result = await window.pipeline.customers.list({ page: 1, pageSize: 50 });
// Returns:
// {
// items: [{ id: "...", name: "John Doe", email: "john@example.com", phone: "021..." }],
// totalCount: 150,
// page: 1,
// pageSize: 50
// }

Returns a paginated list of products/services. The sku field is the human-readable product code from Stock_SKU.SKU - use this for stable cross-environment product references (GUIDs can vary between environments).

const result = await window.pipeline.products.list({ page: 1, pageSize: 50 });
// Returns:
// {
// items: [
// { id: "a1b2c3d4-...", sku: "WGT-001", name: "Widget A", price: 29.99, unit: "T_ITEM" }
// ],
// totalCount: 42,
// page: 1,
// pageSize: 50
// }

Response item fields: id (GUID), sku (human-readable code), name, price (retail sell price), unit (UOM token).

Returns task templates from G_Task_Templates, filtered to active rows in the current tenant. Use this to resolve a task template’s code (e.g. T_DEFAULT_INSTALLATION_TASK) to its GUID so the GUID can be passed as linkedItemId on a lineType: "task" line in quotes.addLines.

When codes is provided, page/pageSize are ignored and all matching rows are returned. When codes is omitted, results paginate the full active task-template list.

const result = await window.pipeline.taskTemplates.list({
codes: ["T_DEFAULT_INSTALLATION_TASK", "T_DEFAULT_REMOVAL_TASK"]
});
// Returns:
// {
// items: [
// { id: "8a9d034f-...", code: "T_DEFAULT_INSTALLATION_TASK", name: "T_DEFAULT_INSTALLATION_TASK" }
// ],
// totalCount: 2,
// page: 1,
// pageSize: 50
// }

Request fields: codes (string[], optional), page (number, optional), pageSize (number, optional).

Response item fields: id (GUID), code (stable token), name.

Returns cost-of-business items from COB_Items, filtered to active rows in the current tenant. Use this to resolve a COB item’s code (e.g. COS-TRAVEL-TIME, COS-SITE-VISIT) to its GUID for use as linkedItemId on a lineType: "cost" line.

const result = await window.pipeline.costItems.list({
codes: ["COS-TRAVEL-TIME", "COS-SITE-VISIT", "COS-SHIPPING", "COS-DISPOSAL"]
});
// Returns:
// {
// items: [
// { id: "95abe0dc-...", code: "COS-TRAVEL-TIME", name: "Travel time", type: "T_TRAVEL" }
// ],
// totalCount: 4,
// page: 1,
// pageSize: 50
// }

Request fields: codes (string[], optional), page (number, optional), pageSize (number, optional).

Response item fields: id (GUID), code (stable token), name, type (COB_Items.T_Type token, e.g. "T_FINANCIAL", "T_TRAVEL").

Returns job-cost templates from JobCostTemplate, filtered to active rows in the current tenant and ordered by CostCode. This is the modern replacement for costItems.list: use it to resolve a template’s code (e.g. SHIPPING, DISPOSAL, TRAVEL, CHECK-MEASURE) to its GUID for use as linkedItemId on a lineType: "jobcost" line.

When the resolved GUID is passed back as linkedItemId, the host routes the line’s GL via the template’s cost code; the extension-supplied unitPrice / costPrice always win (the template contributes classification and GL routing only, not pricing).

When codes is provided, page/pageSize are ignored and all matching rows are returned. When codes is omitted, results paginate the full active job-cost-template list.

const result = await window.pipeline.jobCostTemplates.list({
codes: ["SHIPPING", "DISPOSAL", "TRAVEL", "CHECK-MEASURE"]
});
// Returns:
// {
// items: [
// { id: "95abe0dc-...", code: "SHIPPING", name: "Shipping", type: "T_PURCHASED_ITEM" }
// ],
// totalCount: 4,
// page: 1,
// pageSize: 50
// }

Request fields: codes (string[], optional), page (number, optional), pageSize (number, optional).

Response item fields: id (GUID), code (JobCostTemplate.CostCode), name (CostName), type (T_CostType token: "T_ADHOC" | "T_PURCHASED_ITEM" | "T_THIRD_PARTY_COST" | "T_EXPENSE").

Returns a paginated list of active jobs for the tenant. Available to all tool types.

const result = await window.pipeline.jobs.list({ page: 1, pageSize: 50 });
// Returns:
// {
// items: [
// {
// id: "e5f6a7b8-...",
// ref: "JOB-0042",
// customerName: "Acme Corp",
// customerIdGuid: "c1d2e3f4-...",
// status: "InProgress"
// }
// ],
// totalCount: 12,
// page: 1,
// pageSize: 50
// }

Response item fields: id (GUID), ref (human-readable job reference), customerName, customerIdGuid (GUID), status.

Returns a paginated list of quotes.

const result = await window.pipeline.quotes.list({ page: 1, pageSize: 50 });
// Returns:
// {
// items: [{ id: "...", ref: "QR-001", customerName: "John Doe", total: 115.00, status: "Draft", date: "2026-04-16T00:00:00" }],
// totalCount: 25,
// page: 1,
// pageSize: 50
// }

Creates a new quote in Vera. Available to all tool types.

Marketplace tools do NOT need API keys or inbound tokens - the bridge handles all authentication through the current user’s Vera session.

const result = await window.pipeline.quotes.create({
customerName: "John Doe",
customerEmail: "john@example.com",
customerPhone: "021 123 4567",
upsertByEmail: true,
title: "Quick Quote",
quoteRef: "",
lines: [
{
description: "Widget A",
productCode: "WGT-001",
qty: 2,
unitPrice: 29.99,
taxRate: 0.15
}
]
});
// Returns:
// {
// id: "abc-123-...",
// ref: "QR-042",
// total: 68.98
// }

Request fields:

Field Type Required Description
customerName string No Customer display name
customerEmail string Conditional Required when upsertByEmail is true
customerPhone string No Customer phone number
upsertByEmail boolean No If true, creates or matches customer by email
title string No Quote title
quoteRef string No Custom quote reference
lines array Yes At least one line item required

Line item fields:

Field Type Required Description
description string No Line item description
productCode string No Product code reference
qty number Yes Quantity (1-10000)
unitPrice number Yes Unit price (0-1000000)
taxRate number Yes Tax rate as decimal (e.g. 0.15 for 15%)

Validation rules:

  • Lines array must not be empty
  • Maximum 200 line items per quote
  • Quantity must be > 0 and <= 10,000
  • Unit price must be >= 0 and <= 1,000,000

Available to quoting_extension tools only.

Appends one or more lines to the currently-open quote. No server round-trip - the host merges the lines into its in-memory quote and the user saves normally. Calling this method from a standalone tool will return an error.

await window.pipeline.quotes.addLines([
// Product line (default lineType): generic SKU, with section grouping
{
description: "Roller blind - Main Lounge",
productCode: "BLIND",
qty: 1,
unitPrice: 480.00,
costPrice: 290.00,
taxRate: 15,
location: "Main Lounge",
specification: "Linesque Fleece, 1200×1500, Inside fit",
unit: "T_ITEM",
groupKey: "blind-1",
lineType: "product",
linkedItemId: "a1b2c3d4-...", // Stock_SKU.IdGuid - replaces productId
supplierRef: "WINDOWARE", // resolved against G_Suppliers (drives PO on quote-to-job)
discountPercent: 10, // RRP unitPrice, nets back to the real selling price
section: "Blinds"
},
// Task line: explicit installation task
{
description: "Installation",
qty: 1,
unitPrice: 95.00,
costPrice: 95.00,
taxRate: 15,
unit: "T_ITEM",
lineType: "task",
linkedItemId: "8a9d034f-...", // G_Task_Templates.IdGuid
section: "Installation"
},
// Job-cost line: shipping pass-through (template-linked)
{
description: "Shipping (standard)",
qty: 1,
unitPrice: 20.00,
costPrice: 20.00,
taxRate: 15,
unit: "T_ITEM",
lineType: "jobcost",
linkedItemId: "eaaebd29-...", // JobCostTemplate.IdGuid (from jobCostTemplates.list)
section: "Extras"
}
]);

BridgeAddLineDto fields:

Field Type Required Description
description string optional Free-text line description. Displayed as the line name in the quote.
productCode string optional Human-readable SKU/code. Stored as WorkObjectCode on the quote line.
qty number required Line quantity. Must be > 0.
unitPrice number required Retail/sell price per unit. Markup must already be applied - the host does not re-mark up.
costPrice number optional Buy/cost price per unit. When provided: BUY column = costPrice, SELL column = unitPrice (real margin visible in COB panel). When omitted: both BUY and SELL use unitPrice.
taxRate number required Tax rate. Accepted as percentage (e.g. 15) or decimal fraction (e.g. 0.15) - the host normalises.
location string optional Location or zone label. Maps to QuoteLine.FreeTextField2. Use for room, area, or zone labels (e.g. "Patio", "Living Room").
specification string optional Configuration or specification detail. Maps to QuoteLine.FreeTextField. Use for dimensions, colours, or model info.
unit string optional Unit of measure token. Valid values: "T_ITEM" (default), "T_SQUARE_METRE" (m²), "T_LINEAR_METRE" (lm).
groupKey string optional Arbitrary stable string identifier. Lines sharing the same groupKey receive the same QuoteLine.GroupId on the host, keeping related lines visually grouped within their section. Lines without a groupKey are ungrouped (GroupId = 0).
lineType string optional One of "product" | "task" | "cost" | "jobcost". Defaults to "product". Selects which Vera table linkedItemId resolves into - see “Four line kinds” below.
linkedItemId string (GUID) optional GUID into Stock_SKU / G_Task_Templates / COB_Items / JobCostTemplate based on lineType. Replaces productId for new tools. For product / task / cost the whole addLines batch is rejected if the GUID does not resolve to an active row in the indicated table. For jobcost, linkedItemId is optional (null = ad-hoc job cost, materialised on quote-to-job conversion).
section string optional Categorical section label (e.g. "Blinds", "Motorisation", "Installation", "Extras", "Removal"). The host quote UI groups lines visually by section. Max 100 chars; trimmed; null/empty renders under “Ungrouped”. Section identity is the pair (section, summaryOnly).
summaryOnly boolean optional Default false. When true, the section this line belongs to renders on customer-facing output as a single name + total row, with its individual lines suppressed. Lines are unaffected everywhere else - editor, job costing, grand total. Lines sharing a section but differing on summaryOnly resolve to two separate sections, so set it identically across a section’s lines.
sectionNotes string optional Customer-facing note for this line’s section, printed under the section heading on the quote (including when the section is summaryOnly). Plain text; line breaks are kept; max 2000 chars. Not part of section identity - the first non-empty value among a section’s lines wins, so later lines need not repeat it.
discountPercent number optional Per-line discount percentage (0-100). When set, the host stores it on QuoteLine.DiscountPercent and computes LineNett = sell × qty × (1 − discountPercent/100). Lets a tool pass an inflated RRP unitPrice with a discount that nets back to the real selling price. Null = 0 (no discount).
supplierRef string optional Supplier identifier. Resolved host-side case-insensitively against G_Suppliers.SupplierRef, then G_Suppliers.Name (active suppliers only). Null or unresolved falls back to the Self supplier (T_SELF). A resolved supplier drives purchase-order and supplier-invoice creation after quote-to-job conversion.
freeTextField3 string optional Free-text slot persisted onto QuoteLine.FreeTextField3 (fields 1 and 2 are populated from specification / location). Use to stash source-system metadata with nowhere else to go. On quote-to-job conversion, the four free-text fields map 1:1 to JobCost.FreeTextLine1-4.
freeTextField4 string optional Free-text slot persisted onto QuoteLine.FreeTextField4. See freeTextField3.
productId string (GUID) deprecated Use linkedItemId with lineType="product" instead. Retained for back-compat with Ziptrak v2.1.2 and earlier. When set without linkedItemId, behaves as linkedItemId with lineType="product" - triggers task-sequence auto-injection if the SKU has one configured.

Four line kinds (lineType → linkedItemId target table):

lineType Target table Behaviour
"product" (default) Stock_SKU.IdGuid If the linked SKU has a task sequence configured, the host auto-injects its task template lines (e.g. installation tasks).
"task" G_Task_Templates.IdGuid The line is the task. No auto-injection. Use taskTemplates.list to resolve codes to GUIDs.
"cost" (deprecated) COB_Items.IdGuid Legacy cost-of-business line. No auto-injection. Superseded by "jobcost" - prefer that for new tools. Use costItems.list to resolve codes to GUIDs.
"jobcost" JobCostTemplate.IdGuid (optional) Cost category (shipping, disposal, travel, check-measure) or an ad-hoc import line. No auto-injection. Template-linked when linkedItemId is set - GL routed via the template’s cost code, extension-supplied price wins. Ad-hoc when linkedItemId is null - the job-cost record is materialised on quote-to-job conversion (use for imports whose products don’t map to the catalogue). Use jobCostTemplates.list to resolve codes to GUIDs.

Validation: the host rejects the entire addLines batch if any line has an unknown lineType or a non-null linkedItemId that does not resolve to an active row in the indicated table. A jobcost line with a null linkedItemId is valid (ad-hoc). summaryOnly is never a validation failure - it defaults to false when absent or non-boolean. A section longer than 100 chars is truncated, not rejected. Failures surface to the extension as an exception from addLines.

A section usually comes into existence because a line names it. To add a section that has no lines of its own - an “Optional Extras” section whose content is a list of add-ons, for example - pass it in options.sections, or call quotes.addSections(sections), which is the same call with no lines.

await window.pipeline.quotes.addLines(lines, {
sections: [
{
name: "Optional Extras",
notes: "Motorisation - add $180 per blind\nBlockout lining - add $45 per blind"
}
]
});
// Or on its own:
await window.pipeline.quotes.addSections([
{ name: "Optional Extras", notes: "Motorisation - add $180 per blind" }
]);
Field Type Required Description
name string required Section label. Max 100 chars; longer names are truncated.
summaryOnly boolean optional Default false. Part of section identity, exactly as on a line.
notes string optional Printed under the section heading. Plain text; line breaks are kept; max 2000 chars.

Declared sections are applied after the lines, so a new one lands after every section the lines created - which is where “Optional Extras” belongs. A declared section whose (name, summaryOnly) matches one the lines already created is not duplicated; its notes fill in the existing section only if that section has none yet.

On the customer’s quote, a section with notes but no lines prints its name and notes, with no subtotal or total. A section with neither lines nor notes is not printed.

A declared section with a blank name rejects the whole batch, lines included.