customerId | string | no | The customer's unique id, as returned by the Customers API. Exactly one of customerId or companyName must be set; in this version only customerId is accepted. |
companyName | string | no | The customer's company name. Not yet supported: a request that sets companyName instead of customerId is rejected with HTTP 501 (not_implemented). Resolve the name with ListCustomers and send customerId. |
lines | SalesLine[] | no | The quote's line items. Each line is one of the supported line types (on-the-fly, catalogue, labour, notes, flashing, or product kit). |
lines.onTheFly | OnTheFlyLine | no | A free-form line not tied to a catalogue product. Set exactly one of the six line-type fields. |
lines.onTheFly.productName | string | yes | Name of the item. Required. |
lines.onTheFly.productDescription | string | no | Optional longer description of the item. |
lines.onTheFly.colour | string | no | Optional colour for the item. |
lines.onTheFly.pricing | LinePricing | no | Pricing for this line. Unit price is required; the line total is required until server-side derivation is enabled for your account (see totalPrice on LinePricing), except on custom-formula lines, where it is always required. Pricing for a single priced line: quantity, prices, discount, cost, markup, margin, and pricing strategy. On priced lines the server validates — or, once derivation is enabled for your account, derives — the line total from the quantity, unit price, and discount; see totalPrice for the exact formula, the rounding rule, and what happens if it does not match. |
lines.onTheFly.pricing.quantity | string | no | Quantity for this line, as a decimal string (e.g. "2" or "2.5"). Supports up to 4 decimal places. It is the first factor of the line-total formula documented on totalPrice — EXCEPT on measurement-priced (lineal/square) lines, where the measured length or area alone sets the priced amount and this factor is treated as 1 whenever the server derives or checks the total. Do not multiply a measurement-priced total by quantity. (Only on free-text lines on accounts WITHOUT server-side derivation does the legacy formula still multiply by it — see totalPrice). |
lines.onTheFly.pricing.unitPrice | Money | no | Per-unit price. Required on priced lines — except on catalogue lines with server-side derivation enabled for your account, where you may omit it and supply cost plus markup instead: the server computes it as cost x (1 + markup/100) (or cost + markup for a fixed markup). If you can send the price directly, do; the derivation exists for callers whose source system stores only cost and markup. The server rounds this to 4 decimal places (half up) before pricing, so unit-price precision finer than that (micro amounts that are not a multiple of 100) is not preserved and can shift the computed line total. |
lines.onTheFly.pricing.totalPrice | Money | no | The line total, as a Money amount in micros. Server-side derivation is rolling out account by account. Once it is enabled for your account, this field is optional on most priced lines — omit it (leave the whole Money object out; an empty Money is a supplied $0.00) and the server computes it. Until then it is required on priced lines, exactly as before. The formula is: quantity * unitPrice * (1 - discount / 100) rounded to the nearest cent — 2 decimal places, half up (0.005 rounds up). For lineal or square measurement pricing the result is then multiplied by the measured length or area the server derives from the line's measurement details before rounding — and on measurement-priced lines the quantity factor is pinned to 1 once derivation is enabled for your account, whether the server derives the total or checks one you send: the measurements alone set the priced amount. (Without derivation, free-text lines still multiply by quantity — match it when computing such a total yourself.) Deriving needs a non-zero quantity or measurement set (deriving with a zero quantity or an empty measurement set is rejected rather than stored as $0.00; a zero unit price — a free line — still derives). On a product kit priced as a standard kit, an omitted parent total is derived as the sum of its components and sub-kits (omitted sub-kit totals are likewise derived from their components) — priced component totals must accompany the request; a missing one is rejected rather than summed as zero. A supplied kit total, at any tier, is stored as sent. If you DO send a value on a catalogue (once derivation is enabled for your account), on-the-fly, or labour line, it is checked against the formula and a mismatch is rejected with HTTP 400. Send the amount as a whole number of cents (amountMicros a multiple of 10000); a sub-cent amount is rounded to the nearest cent before the check. Exceptions, where the total is never derived — send a correct value, because these lines are stored as sent: |
lines.onTheFly.pricing.discount | string | no | Discount applied to the line, as a decimal percentage string (e.g. "10.00" means 10%). Supports up to 2 decimal places. In the line-total formula on totalPrice it enters as the factor (1 - discount / 100). |
lines.onTheFly.pricing.cost | Money | no | Unit cost for this line, used to compute margin — and, with derivation enabled, the base the server recomputes markup (and an omitted unitPrice) from. Rounded to 4 decimal places (half up) before use, so sub-4dp cost precision is not preserved. |
lines.onTheFly.pricing.markup | string | no | Markup applied to the line, as a decimal string — either a money amount or a percentage, depending on markupIsPercentage. With server-side derivation enabled for your account: whenever cost is non-zero, the value you send here is DISCARDED and recomputed from cost and the unit price (as a percentage — markupIsPercentage reads back true), so the stored markup always agrees with the stored prices. Do not expect to read back the value you sent. With a zero or absent cost your value is kept as sent. |
lines.onTheFly.pricing.markupIsPercentage | boolean | no | Whether markup is a percentage (true) or a fixed amount (false). Omit it to use the default, true; send false only for a fixed-amount markup. Always present on reads, and reads back true whenever the server recomputed the markup (see markup). |
lines.onTheFly.pricing.margin | Money | no | Margin for the line. When supplied, it is validated against cost and quantity — and with derivation enabled it is recomputed alongside the total whenever cost is present, so (like markup) the stored value may differ from what you sent. Simplest: omit it and let the server compute. |
lines.onTheFly.pricing.pricingStrategy | PricingStrategy | no | How this line is priced (per-unit quantity, lineal, or square measurement). Defaults to per-unit quantity pricing. How a quantity is interpreted for pricing — whether it means a count of each, a length, or an area. On a catalogue product this is the product's pricing basis. On an order or quote line, measurement-based strategies (lineal or square metres/feet) require the line's measurement details to be supplied. - PRICING_STRATEGY_UNSPECIFIED: Unset, or a legacy product with no pricing strategy recorded. - PRICING_STRATEGY_BASIC_QUANTITIES: Quantity is a simple per-each count. - PRICING_STRATEGY_LINEAL_METRES: Quantity is a length in lineal metres. - PRICING_STRATEGY_CUSTOM_FORMULA: Quantity is priced by a custom formula. - PRICING_STRATEGY_SQUARE_METRES: Quantity is an area in square metres. - PRICING_STRATEGY_LINEAL_FEET: Quantity is a length in lineal feet. - PRICING_STRATEGY_SQUARE_FEET: Quantity is an area in square feet. One of: PRICING_STRATEGY_UNSPECIFIED, PRICING_STRATEGY_BASIC_QUANTITIES, PRICING_STRATEGY_LINEAL_METRES, PRICING_STRATEGY_CUSTOM_FORMULA, PRICING_STRATEGY_SQUARE_METRES, PRICING_STRATEGY_LINEAL_FEET, PRICING_STRATEGY_SQUARE_FEET. |
lines.onTheFly.pricing.priceLevel | string | no | Optional named price level applied to this line. |
lines.onTheFly.pricing.isTaxFree | boolean | no | Whether this line is exempt from tax. |
lines.onTheFly.pricing.tax | TaxDetail | no | The tax applied to this line: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable lines; this object reserves the shape for richer per-line tax later. |
lines.onTheFly.pricing.measurements | MeasurementEntry[] | no | The measurements that price this line, for the lineal and square pricing strategies. Units follow the strategy: metres for *_METRES, feet for *_FEET (see MeasurementEntry). Requires an explicit, measurement-priced pricingStrategy on this same object. On these strategies the measured amount is the priced quantity — quantity is NOT a factor (on accounts without server-side derivation, free-text lines are the one legacy exception; see quantity); the server sums these pieces (applying your account's minimum-length setting on lineal strategies) to derive the amount that scales the line total. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.onTheFly.pricing.measurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.onTheFly.pricing.measurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.onTheFly.pricing.measurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.onTheFly.pricing.asBuiltMeasurements | MeasurementEntry[] | no | As-built measurements — what production actually cut, in the same shape and units as measurements. These drive cost, margin, and stock consumption, never the line price. Optional: whenever omitted (create and update alike) they default to measurements. Send them only when your as-built figures differ from what was quoted. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.onTheFly.pricing.asBuiltMeasurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.onTheFly.pricing.asBuiltMeasurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.onTheFly.pricing.asBuiltMeasurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.onTheFly.attributes | object[] | no | Additional named attributes for the line, as a JSON array of {name, value} entries (for example {name: "Size", value: "76x38mm"}). An entry may also carry flags that hide it from specific documents or views, such as the invoice PDF or the customer view. |
lines.catalogue | CatalogueLine | no | A line for a product from your catalogue. Set exactly one of the six line-type fields. |
lines.catalogue.productId | string | yes | The id of the catalogue product for this line. Required, and must match an existing catalogue product; an unknown id rejects the whole request. |
lines.catalogue.productRowId | string | no | Optional id of a specific row within the catalogue product. If set, it must resolve. |
lines.catalogue.rowPriceId | string | no | Optional id selecting the row's price at one of your price levels — the rowPriceId returned by the catalogue (not the price level's own id). If set, it must resolve. |
lines.catalogue.productName | string | no | Display name for the line. |
lines.catalogue.productDescription | string | no | Longer description for the line. |
lines.catalogue.categoryName | string | no | Category name for the line. |
lines.catalogue.priceName | string | no | Price name shown for the line. |
lines.catalogue.params | object[] | no | Product parameters as a JSON array of {name, value} entries (for example [{"name": "Colour", "value": "Monument"}]). The colour is taken from the "Colour" parameter and validated against the product's available colours. |
lines.catalogue.attributes | object[] | no | Additional named attributes for the line, as a JSON array of {name, value} entries (for example {name: "Size", value: "76x38mm"}). An entry may also carry flags that hide it from specific documents or views, such as the invoice PDF or the customer view. |
lines.catalogue.pricing | LinePricing | no | Pricing for this line. The catalogue does not price the line; you supply it. Pricing for a single priced line: quantity, prices, discount, cost, markup, margin, and pricing strategy. On priced lines the server validates — or, once derivation is enabled for your account, derives — the line total from the quantity, unit price, and discount; see totalPrice for the exact formula, the rounding rule, and what happens if it does not match. |
lines.catalogue.pricing.quantity | string | no | Quantity for this line, as a decimal string (e.g. "2" or "2.5"). Supports up to 4 decimal places. It is the first factor of the line-total formula documented on totalPrice — EXCEPT on measurement-priced (lineal/square) lines, where the measured length or area alone sets the priced amount and this factor is treated as 1 whenever the server derives or checks the total. Do not multiply a measurement-priced total by quantity. (Only on free-text lines on accounts WITHOUT server-side derivation does the legacy formula still multiply by it — see totalPrice). |
lines.catalogue.pricing.unitPrice | Money | no | Per-unit price. Required on priced lines — except on catalogue lines with server-side derivation enabled for your account, where you may omit it and supply cost plus markup instead: the server computes it as cost x (1 + markup/100) (or cost + markup for a fixed markup). If you can send the price directly, do; the derivation exists for callers whose source system stores only cost and markup. The server rounds this to 4 decimal places (half up) before pricing, so unit-price precision finer than that (micro amounts that are not a multiple of 100) is not preserved and can shift the computed line total. |
lines.catalogue.pricing.totalPrice | Money | no | The line total, as a Money amount in micros. Server-side derivation is rolling out account by account. Once it is enabled for your account, this field is optional on most priced lines — omit it (leave the whole Money object out; an empty Money is a supplied $0.00) and the server computes it. Until then it is required on priced lines, exactly as before. The formula is: quantity * unitPrice * (1 - discount / 100) rounded to the nearest cent — 2 decimal places, half up (0.005 rounds up). For lineal or square measurement pricing the result is then multiplied by the measured length or area the server derives from the line's measurement details before rounding — and on measurement-priced lines the quantity factor is pinned to 1 once derivation is enabled for your account, whether the server derives the total or checks one you send: the measurements alone set the priced amount. (Without derivation, free-text lines still multiply by quantity — match it when computing such a total yourself.) Deriving needs a non-zero quantity or measurement set (deriving with a zero quantity or an empty measurement set is rejected rather than stored as $0.00; a zero unit price — a free line — still derives). On a product kit priced as a standard kit, an omitted parent total is derived as the sum of its components and sub-kits (omitted sub-kit totals are likewise derived from their components) — priced component totals must accompany the request; a missing one is rejected rather than summed as zero. A supplied kit total, at any tier, is stored as sent. If you DO send a value on a catalogue (once derivation is enabled for your account), on-the-fly, or labour line, it is checked against the formula and a mismatch is rejected with HTTP 400. Send the amount as a whole number of cents (amountMicros a multiple of 10000); a sub-cent amount is rounded to the nearest cent before the check. Exceptions, where the total is never derived — send a correct value, because these lines are stored as sent: |
lines.catalogue.pricing.discount | string | no | Discount applied to the line, as a decimal percentage string (e.g. "10.00" means 10%). Supports up to 2 decimal places. In the line-total formula on totalPrice it enters as the factor (1 - discount / 100). |
lines.catalogue.pricing.cost | Money | no | Unit cost for this line, used to compute margin — and, with derivation enabled, the base the server recomputes markup (and an omitted unitPrice) from. Rounded to 4 decimal places (half up) before use, so sub-4dp cost precision is not preserved. |
lines.catalogue.pricing.markup | string | no | Markup applied to the line, as a decimal string — either a money amount or a percentage, depending on markupIsPercentage. With server-side derivation enabled for your account: whenever cost is non-zero, the value you send here is DISCARDED and recomputed from cost and the unit price (as a percentage — markupIsPercentage reads back true), so the stored markup always agrees with the stored prices. Do not expect to read back the value you sent. With a zero or absent cost your value is kept as sent. |
lines.catalogue.pricing.markupIsPercentage | boolean | no | Whether markup is a percentage (true) or a fixed amount (false). Omit it to use the default, true; send false only for a fixed-amount markup. Always present on reads, and reads back true whenever the server recomputed the markup (see markup). |
lines.catalogue.pricing.margin | Money | no | Margin for the line. When supplied, it is validated against cost and quantity — and with derivation enabled it is recomputed alongside the total whenever cost is present, so (like markup) the stored value may differ from what you sent. Simplest: omit it and let the server compute. |
lines.catalogue.pricing.pricingStrategy | PricingStrategy | no | How this line is priced (per-unit quantity, lineal, or square measurement). Defaults to per-unit quantity pricing. How a quantity is interpreted for pricing — whether it means a count of each, a length, or an area. On a catalogue product this is the product's pricing basis. On an order or quote line, measurement-based strategies (lineal or square metres/feet) require the line's measurement details to be supplied. - PRICING_STRATEGY_UNSPECIFIED: Unset, or a legacy product with no pricing strategy recorded. - PRICING_STRATEGY_BASIC_QUANTITIES: Quantity is a simple per-each count. - PRICING_STRATEGY_LINEAL_METRES: Quantity is a length in lineal metres. - PRICING_STRATEGY_CUSTOM_FORMULA: Quantity is priced by a custom formula. - PRICING_STRATEGY_SQUARE_METRES: Quantity is an area in square metres. - PRICING_STRATEGY_LINEAL_FEET: Quantity is a length in lineal feet. - PRICING_STRATEGY_SQUARE_FEET: Quantity is an area in square feet. One of: PRICING_STRATEGY_UNSPECIFIED, PRICING_STRATEGY_BASIC_QUANTITIES, PRICING_STRATEGY_LINEAL_METRES, PRICING_STRATEGY_CUSTOM_FORMULA, PRICING_STRATEGY_SQUARE_METRES, PRICING_STRATEGY_LINEAL_FEET, PRICING_STRATEGY_SQUARE_FEET. |
lines.catalogue.pricing.priceLevel | string | no | Optional named price level applied to this line. |
lines.catalogue.pricing.isTaxFree | boolean | no | Whether this line is exempt from tax. |
lines.catalogue.pricing.tax | TaxDetail | no | The tax applied to this line: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable lines; this object reserves the shape for richer per-line tax later. |
lines.catalogue.pricing.measurements | MeasurementEntry[] | no | The measurements that price this line, for the lineal and square pricing strategies. Units follow the strategy: metres for *_METRES, feet for *_FEET (see MeasurementEntry). Requires an explicit, measurement-priced pricingStrategy on this same object. On these strategies the measured amount is the priced quantity — quantity is NOT a factor (on accounts without server-side derivation, free-text lines are the one legacy exception; see quantity); the server sums these pieces (applying your account's minimum-length setting on lineal strategies) to derive the amount that scales the line total. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.catalogue.pricing.measurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.catalogue.pricing.measurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.catalogue.pricing.measurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.catalogue.pricing.asBuiltMeasurements | MeasurementEntry[] | no | As-built measurements — what production actually cut, in the same shape and units as measurements. These drive cost, margin, and stock consumption, never the line price. Optional: whenever omitted (create and update alike) they default to measurements. Send them only when your as-built figures differ from what was quoted. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.catalogue.pricing.asBuiltMeasurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.catalogue.pricing.asBuiltMeasurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.catalogue.pricing.asBuiltMeasurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.labour | LabourLine | no | A line charging for labour. Set exactly one of the six line-type fields. |
lines.labour.labourUserId | string | yes | The id of the worker who performed the labour. Required, and must be an active user in the company that owns the order or quote. |
lines.labour.productName | string | no | A short name for the labour. |
lines.labour.productDescription | string | no | A longer description of the labour. |
lines.labour.pricing | LinePricing | no | Quantity and pricing for this line: the hours in quantity, the charge rate in unitPrice and the cost rate in cost. There are no rate overrides elsewhere on the line, and the worker's own rates are not applied: an omitted cost is stored as zero, not taken from the user's hourlyRateCost. Pricing for a single priced line: quantity, prices, discount, cost, markup, margin, and pricing strategy. On priced lines the server validates — or, once derivation is enabled for your account, derives — the line total from the quantity, unit price, and discount; see totalPrice for the exact formula, the rounding rule, and what happens if it does not match. |
lines.labour.pricing.quantity | string | no | Quantity for this line, as a decimal string (e.g. "2" or "2.5"). Supports up to 4 decimal places. It is the first factor of the line-total formula documented on totalPrice — EXCEPT on measurement-priced (lineal/square) lines, where the measured length or area alone sets the priced amount and this factor is treated as 1 whenever the server derives or checks the total. Do not multiply a measurement-priced total by quantity. (Only on free-text lines on accounts WITHOUT server-side derivation does the legacy formula still multiply by it — see totalPrice). |
lines.labour.pricing.unitPrice | Money | no | Per-unit price. Required on priced lines — except on catalogue lines with server-side derivation enabled for your account, where you may omit it and supply cost plus markup instead: the server computes it as cost x (1 + markup/100) (or cost + markup for a fixed markup). If you can send the price directly, do; the derivation exists for callers whose source system stores only cost and markup. The server rounds this to 4 decimal places (half up) before pricing, so unit-price precision finer than that (micro amounts that are not a multiple of 100) is not preserved and can shift the computed line total. |
lines.labour.pricing.totalPrice | Money | no | The line total, as a Money amount in micros. Server-side derivation is rolling out account by account. Once it is enabled for your account, this field is optional on most priced lines — omit it (leave the whole Money object out; an empty Money is a supplied $0.00) and the server computes it. Until then it is required on priced lines, exactly as before. The formula is: quantity * unitPrice * (1 - discount / 100) rounded to the nearest cent — 2 decimal places, half up (0.005 rounds up). For lineal or square measurement pricing the result is then multiplied by the measured length or area the server derives from the line's measurement details before rounding — and on measurement-priced lines the quantity factor is pinned to 1 once derivation is enabled for your account, whether the server derives the total or checks one you send: the measurements alone set the priced amount. (Without derivation, free-text lines still multiply by quantity — match it when computing such a total yourself.) Deriving needs a non-zero quantity or measurement set (deriving with a zero quantity or an empty measurement set is rejected rather than stored as $0.00; a zero unit price — a free line — still derives). On a product kit priced as a standard kit, an omitted parent total is derived as the sum of its components and sub-kits (omitted sub-kit totals are likewise derived from their components) — priced component totals must accompany the request; a missing one is rejected rather than summed as zero. A supplied kit total, at any tier, is stored as sent. If you DO send a value on a catalogue (once derivation is enabled for your account), on-the-fly, or labour line, it is checked against the formula and a mismatch is rejected with HTTP 400. Send the amount as a whole number of cents (amountMicros a multiple of 10000); a sub-cent amount is rounded to the nearest cent before the check. Exceptions, where the total is never derived — send a correct value, because these lines are stored as sent: |
lines.labour.pricing.discount | string | no | Discount applied to the line, as a decimal percentage string (e.g. "10.00" means 10%). Supports up to 2 decimal places. In the line-total formula on totalPrice it enters as the factor (1 - discount / 100). |
lines.labour.pricing.cost | Money | no | Unit cost for this line, used to compute margin — and, with derivation enabled, the base the server recomputes markup (and an omitted unitPrice) from. Rounded to 4 decimal places (half up) before use, so sub-4dp cost precision is not preserved. |
lines.labour.pricing.markup | string | no | Markup applied to the line, as a decimal string — either a money amount or a percentage, depending on markupIsPercentage. With server-side derivation enabled for your account: whenever cost is non-zero, the value you send here is DISCARDED and recomputed from cost and the unit price (as a percentage — markupIsPercentage reads back true), so the stored markup always agrees with the stored prices. Do not expect to read back the value you sent. With a zero or absent cost your value is kept as sent. |
lines.labour.pricing.markupIsPercentage | boolean | no | Whether markup is a percentage (true) or a fixed amount (false). Omit it to use the default, true; send false only for a fixed-amount markup. Always present on reads, and reads back true whenever the server recomputed the markup (see markup). |
lines.labour.pricing.margin | Money | no | Margin for the line. When supplied, it is validated against cost and quantity — and with derivation enabled it is recomputed alongside the total whenever cost is present, so (like markup) the stored value may differ from what you sent. Simplest: omit it and let the server compute. |
lines.labour.pricing.pricingStrategy | PricingStrategy | no | How this line is priced (per-unit quantity, lineal, or square measurement). Defaults to per-unit quantity pricing. How a quantity is interpreted for pricing — whether it means a count of each, a length, or an area. On a catalogue product this is the product's pricing basis. On an order or quote line, measurement-based strategies (lineal or square metres/feet) require the line's measurement details to be supplied. - PRICING_STRATEGY_UNSPECIFIED: Unset, or a legacy product with no pricing strategy recorded. - PRICING_STRATEGY_BASIC_QUANTITIES: Quantity is a simple per-each count. - PRICING_STRATEGY_LINEAL_METRES: Quantity is a length in lineal metres. - PRICING_STRATEGY_CUSTOM_FORMULA: Quantity is priced by a custom formula. - PRICING_STRATEGY_SQUARE_METRES: Quantity is an area in square metres. - PRICING_STRATEGY_LINEAL_FEET: Quantity is a length in lineal feet. - PRICING_STRATEGY_SQUARE_FEET: Quantity is an area in square feet. One of: PRICING_STRATEGY_UNSPECIFIED, PRICING_STRATEGY_BASIC_QUANTITIES, PRICING_STRATEGY_LINEAL_METRES, PRICING_STRATEGY_CUSTOM_FORMULA, PRICING_STRATEGY_SQUARE_METRES, PRICING_STRATEGY_LINEAL_FEET, PRICING_STRATEGY_SQUARE_FEET. |
lines.labour.pricing.priceLevel | string | no | Optional named price level applied to this line. |
lines.labour.pricing.isTaxFree | boolean | no | Whether this line is exempt from tax. |
lines.labour.pricing.tax | TaxDetail | no | The tax applied to this line: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable lines; this object reserves the shape for richer per-line tax later. |
lines.labour.pricing.measurements | MeasurementEntry[] | no | The measurements that price this line, for the lineal and square pricing strategies. Units follow the strategy: metres for *_METRES, feet for *_FEET (see MeasurementEntry). Requires an explicit, measurement-priced pricingStrategy on this same object. On these strategies the measured amount is the priced quantity — quantity is NOT a factor (on accounts without server-side derivation, free-text lines are the one legacy exception; see quantity); the server sums these pieces (applying your account's minimum-length setting on lineal strategies) to derive the amount that scales the line total. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.labour.pricing.measurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.labour.pricing.measurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.labour.pricing.measurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.labour.pricing.asBuiltMeasurements | MeasurementEntry[] | no | As-built measurements — what production actually cut, in the same shape and units as measurements. These drive cost, margin, and stock consumption, never the line price. Optional: whenever omitted (create and update alike) they default to measurements. Send them only when your as-built figures differ from what was quoted. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.labour.pricing.asBuiltMeasurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.labour.pricing.asBuiltMeasurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.labour.pricing.asBuiltMeasurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.notes | NotesLine | no | A note line, with no pricing. Set exactly one of the six line-type fields. |
lines.notes.notesType | NotesType | yes | The kind of note. Required. Whether a notes line is internal-only or visible to the customer. - NOTES_TYPE_UNSPECIFIED: Default, unset value. Not a valid choice for a notes line. - NOTES_TYPE_INTERNAL: An internal note, not shown to the customer. - NOTES_TYPE_EXTERNAL: An external note, visible to the customer. One of: NOTES_TYPE_UNSPECIFIED, NOTES_TYPE_INTERNAL, NOTES_TYPE_EXTERNAL. |
lines.notes.notes | string | no | The note text. |
lines.notes.productName | string | no | A short name for the note line. |
lines.notes.productDescription | string | no | A longer description for the note line. |
lines.flashing | FlashingLine | no | A flashing line, with its drawing and geometry. Set exactly one of the six line-type fields. A sheet-metal flashing line item: the flashing material, its specification, pricing, and its drawings. A flashing line is created with its document (CreateQuote, CreateOrder) or added whole to a quote (AddQuoteLineItem); it cannot yet be added to an existing order, updated, or removed individually — those calls answer HTTP 501 (not_implemented). Its specification (bends, totalGirth, totalLength, subitems) and its prices are stored exactly as you send them: the API never derives, prices, or cross-checks a flashing, so compute them yourself from the drawing and cut list as described on each field. Lengths and girths are always millimetres (metres for totalLength), whatever the account's measurement system. |
lines.flashing.templateId | string | no | The id of the flashing material or template. Required when the order or quote is submitted. |
lines.flashing.productName | string | no | The display name of the flashing material. |
lines.flashing.priceLevel | string | no | The name of the price level applied to this line (for example "A"), not a price level id. Required when the order or quote is submitted; an empty value is stored as "A". |
lines.flashing.colour | string | no | The flashing colour. Required when the order or quote is submitted, and validated against the colours available for the template when templateId is set; without a template it is stored unchecked. |
lines.flashing.thickness | string | no | The material thickness, as a decimal string in millimetres (for example "0.55"). Required when the order or quote is submitted. Send the thickness of the selected template (templateId) — each thickness is a distinct template. It is stored as sent and not compared with the template, so a mismatch is saved silently. |
lines.flashing.bends | string | no | The number of bends in the flashing, as a decimal string. Count one bend for each point that joins two edges, plus the bends each finish adds (crush fold 2, open hook 2, feather 1, drip edge 1; the account's crushFoldBendCount setting, when set, replaces the crush-fold count). With otherSides, take the count from the side with the largest girth. Required when the order or quote is submitted, and must then be greater than zero. Stored as sent; not checked against the drawing. |
lines.flashing.totalGirth | string | no | The total girth of the flashing in millimetres, as a decimal string: the sum of every edge size in the drawing's lines.values (hidden edges excluded) plus the size of every finish. Edges of 110, 320 and 10 with a 10 mm crush fold give "450". With otherSides, use the side with the largest girth. Required when the order or quote is submitted, and must then be greater than zero. Stored as sent; not checked against the drawing. |
lines.flashing.totalLength | string | no | The total length of the flashing in metres, as a decimal string: the sum over subitems of amount × length ÷ 1000. Three pieces at 1200 plus two at 925 give "5.45". Stored as sent; not checked against subitems. |
lines.flashing.unitPrice | Money | no | The price per metre of the flashing. Required when the order or quote is submitted. |
lines.flashing.totalPrice | Money | no | The total price for this line. Stored as sent and never derived or checked. Factory prices a flashing as unitPrice × the priced length, where each piece shorter than the account's minimumFlashingLengthMm is charged at that minimum, rounded to the cent. |
lines.flashing.customPrice | Money | no | A custom total price for the line. When set, the document's subtotal uses it in place of totalPrice; unitPrice and customPricePerLength never enter the subtotal directly. |
lines.flashing.customPricePerLength | Money | no | A custom price per metre. Factory uses it in place of unitPrice when computing totalPrice; send the resulting totalPrice yourself, as the API does not recompute it. |
lines.flashing.subitems | object[] | no | The cut list: one entry per piece length, each an object with amount (the number of pieces) and length (the piece length in millimetres), both JSON numbers — for example [{"amount": 3, "length": 1200}, {"amount": 2, "length": 925}]. Stored as sent and not validated; a flashing with no lengths cannot be completed in Factory. Unlike measurements on other line kinds, lengths here are millimetre numbers, not metre strings. |
lines.flashing.isTaxFree | boolean | no | Whether this line is exempt from tax. |
lines.flashing.drawing | FlashingDrawing | yes | The main drawing for the flashing: the folded profile whose edge sizes give totalGirth and bends. Required — a flashing line without a drawing is rejected with HTTP 400 (validation_failure). Its side defaults to the far side. A flashing drawing: its identity, metadata, geometry, and the URL of its rendered SVG image. Carried only by flashing lines (drawing / otherSides on FlashingLine) — drawings describe a flashing's folded profile and are not a general-purpose image or attachment type. Geometry is sent in the same shape the drawing tool holds it: points are the vertices, joined by the edges listed in each point's vectors and connect; lines.values gives each edge's real size in millimetres; angles.values gives the angle at each vertex. Point coordinates only lay out the sketch — the sizes in lines are the dimensions. A drawing whose points, lines or angles exceeds about 15,000 characters of JSON is rejected with HTTP 400 (validation_failure). |
lines.flashing.drawing.drawingId | string | no | Server-assigned unique id of the drawing. Read-only output. |
lines.flashing.drawing.tempId | string | no | A client-assigned correlation id supplied when creating the drawing. The write that creates the drawing returns it paired with the assigned drawingId in the response's drawings mapping (CreateQuote, CreateOrder, AddQuoteLineItem) — use that to address UploadDrawingSvg. It must be unique across every drawing in the request, other sides included; a repeated id is rejected with HTTP 400 (validation_failure). Omit it and the server assigns unique ids for you. It is not stored, so reads do not return it. |
lines.flashing.drawing.drawingNumber | integer | no | The drawing's display number within the order or quote. Not assigned by the server: it is stored as sent (0 when omitted), and reads and printed documents order drawings by it, so number them 0, 1, 2… in line order. |
lines.flashing.drawing.side | DrawingSide | no | Which face of the flashing this drawing represents. When not specified, a line's main drawing is the far side and each of its otherSides is the near side. Which face of the flashing a drawing represents. When not specified, a flashing line's main drawing is the far side and each of its otherSides is the near side. - DRAWING_SIDE_UNSPECIFIED: Default, unset value. - DRAWING_SIDE_FAR: The far side of the flashing. - DRAWING_SIDE_NEAR: The near side of the flashing. One of: DRAWING_SIDE_UNSPECIFIED, DRAWING_SIDE_FAR, DRAWING_SIDE_NEAR. |
lines.flashing.drawing.isFreeDrawing | boolean | no | Whether the edge sizes in lines.values are the drawing's dimensions. Send true: when false, Factory measures each edge from the points' canvas coordinates instead, so girth, bends and the displayed sizes come from the sketch rather than from the sizes you supplied. |
lines.flashing.drawing.isLargeBoxSize | boolean | no | Whether the drawing uses the large box size. |
lines.flashing.drawing.isDeleted | boolean | no | Whether the drawing has been deleted. |
lines.flashing.drawing.points | map<Point> | no | The vertices of the drawing, keyed by point id. Record each edge at both ends: p1.vectors lists p2 exactly when p2.connect lists p1. Required when the order or quote is submitted. A vertex in the drawing. Points are connected by edges to form the flashing profile. |
lines.flashing.drawing.points.*.id | string | no | The unique id of this point within the drawing. |
lines.flashing.drawing.points.*.x | number | no | The x coordinate of the point, in canvas space. |
lines.flashing.drawing.points.*.y | number | no | The y coordinate of the point, in canvas space. |
lines.flashing.drawing.points.*.vectors | string[] | no | The ids of points reached by edges leaving this point. Every edge must also appear in the target point's connect. |
lines.flashing.drawing.points.*.connect | string[] | no | The ids of points connected to this point by incoming edges. Every edge must also appear in the source point's vectors. |
lines.flashing.drawing.points.*.finish | Finish | no | Optional end treatment at this point. An end treatment applied to a point on a flashing edge (for example a hook or fold). Optional on a point. |
lines.flashing.drawing.points.*.finish.type | FinishType | no | The kind of end treatment. The end-treatment applied to a flashing edge. Each type has a short code used in the finish's label, adds its size to the flashing's total girth, and counts a fixed number of bends. - FINISH_TYPE_UNSPECIFIED: Unspecified end treatment. - FINISH_TYPE_CRUSH_FOLD: A crush fold. Code "cf"; counts 2 bends (or the account's crushFoldBendCount when set). - FINISH_TYPE_OPEN_HOOK: An open hook. Code "oh"; counts 2 bends. - FINISH_TYPE_FEATHER: A feathered edge. Code "fe"; counts 1 bend. - FINISH_TYPE_DRIP_EDGE: A drip edge. Code "de"; counts 1 bend. One of: FINISH_TYPE_UNSPECIFIED, FINISH_TYPE_CRUSH_FOLD, FINISH_TYPE_OPEN_HOOK, FINISH_TYPE_FEATHER, FINISH_TYPE_DRIP_EDGE. |
lines.flashing.drawing.points.*.finish.size | number | no | The size of the end treatment in millimetres. It counts toward the flashing's totalGirth. |
lines.flashing.drawing.points.*.finish.label | string | no | The display label for this finish: the type's code followed by the size, e.g. "cf10" for a 10 mm crush fold or "oh25" for a 25 mm open hook. |
lines.flashing.drawing.points.*.finish.flip | boolean | no | Which side of the edge the finish folds to. Looking from the finished end along its edge (screen coordinates, y pointing down), false puts the fold on the right-hand side and true on the left. A feathered edge is drawn mirrored relative to the other types. |
lines.flashing.drawing.points.*.finish.position | LabelPosition | no | Optional bounding box for this finish's label. A label's bounding box in canvas (SVG) coordinate space. Used for line labels, angle labels, and finish labels. |
lines.flashing.drawing.points.*.finish.position.x | number | no | The x coordinate of the label box, in canvas space. |
lines.flashing.drawing.points.*.finish.position.y | number | no | The y coordinate of the label box, in canvas space. |
lines.flashing.drawing.points.*.finish.position.width | number | no | The width of the label box, in canvas space. |
lines.flashing.drawing.points.*.finish.position.height | number | no | The height of the label box, in canvas space. |
lines.flashing.drawing.lines | LineSet | no | The edge sizes between points in millimetres, with their optional label positions. Give every edge a size — Factory counts the girth of a drawing with a missing size as 0. When omitted, the drawing is stored with an empty set and reads return lines with empty values and positions. The collection of edge lengths and their label positions for a drawing. |
lines.flashing.drawing.lines.values | map<LineCell> | no | The size entry for each edge, keyed by the ids of the two points it connects joined with a hyphen, source first: the edge from p1 to p2 is "p1-p2". The length entry for a single edge between two points. |
lines.flashing.drawing.lines.values.*.size | number | no | The size of the edge in millimetres. Omitted when a size has not yet been entered — but give every edge a size, or Factory counts the girth as 0. |
lines.flashing.drawing.lines.values.*.hidden | boolean | no | Whether this edge's length label is hidden. |
lines.flashing.drawing.lines.positions | map<LabelPosition> | no | The label box for each edge's size label, keyed like values. Optional: Factory places any label without a box itself. A label's bounding box in canvas (SVG) coordinate space. Used for line labels, angle labels, and finish labels. |
lines.flashing.drawing.lines.positions.*.x | number | no | The x coordinate of the label box, in canvas space. |
lines.flashing.drawing.lines.positions.*.y | number | no | The y coordinate of the label box, in canvas space. |
lines.flashing.drawing.lines.positions.*.width | number | no | The width of the label box, in canvas space. |
lines.flashing.drawing.lines.positions.*.height | number | no | The height of the label box, in canvas space. |
lines.flashing.drawing.angles | AngleSet | no | The vertex angles in degrees, with their optional label positions. When omitted, the drawing is stored with an empty set and reads return angles with empty values and positions. The collection of vertex angles and their label positions for a drawing. |
lines.flashing.drawing.angles.values | map<AngleCell> | no | The angle entry for each vertex, keyed by point id. The angle entry for a single point (vertex) in the drawing. |
lines.flashing.drawing.angles.values.*.angle | number | no | The angle at this vertex, in degrees. Omitted when no angle is set. |
lines.flashing.drawing.angles.values.*.hidden | boolean | no | Whether this vertex's angle label is hidden. Omitted when not set. |
lines.flashing.drawing.angles.positions | map<LabelPosition> | no | The label box for each vertex's angle label, keyed by point id. Optional: Factory places any label without a box itself. A label's bounding box in canvas (SVG) coordinate space. Used for line labels, angle labels, and finish labels. |
lines.flashing.drawing.angles.positions.*.x | number | no | The x coordinate of the label box, in canvas space. |
lines.flashing.drawing.angles.positions.*.y | number | no | The y coordinate of the label box, in canvas space. |
lines.flashing.drawing.angles.positions.*.width | number | no | The width of the label box, in canvas space. |
lines.flashing.drawing.angles.positions.*.height | number | no | The height of the label box, in canvas space. |
lines.flashing.drawing.annotations | map<TextBox> | no | Free-text annotations on the drawing, keyed by annotation id. A free-text annotation placed on the drawing. |
lines.flashing.drawing.annotations.*.x | number | no | The x coordinate of the annotation, in canvas space. Omitted until placed. |
lines.flashing.drawing.annotations.*.y | number | no | The y coordinate of the annotation, in canvas space. Omitted until placed. |
lines.flashing.drawing.annotations.*.width | number | no | The width of the annotation box, in canvas space. |
lines.flashing.drawing.annotations.*.height | number | no | The height of the annotation box, in canvas space. |
lines.flashing.drawing.annotations.*.value | string | no | The annotation text as a flat string. May be present alongside the structured text form. |
lines.flashing.drawing.annotations.*.text | TextRow[] | no | The annotation text in structured rows. May be present alongside value. One row of text within a text annotation. |
lines.flashing.drawing.annotations.*.text.id | integer | no | The 0-based index of this row within the text annotation. |
lines.flashing.drawing.annotations.*.text.indent | integer | no | The indentation level of this row. |
lines.flashing.drawing.annotations.*.text.value | string[] | no | The text segments that make up this row, in order. |
lines.flashing.drawing.annotations.*.rotateDeg | number | no | Optional rotation of the annotation, in degrees. |
lines.flashing.drawing.frontArrow | Arrow | no | The arrow marking the front face of the flashing. Optional. The arrow that indicates the front-facing direction of the flashing. |
lines.flashing.drawing.frontArrow.x | number | no | The x coordinate of the arrow, in canvas space. Omitted until placed. |
lines.flashing.drawing.frontArrow.y | number | no | The y coordinate of the arrow, in canvas space. Omitted until placed. |
lines.flashing.drawing.frontArrow.angle | number | no | The direction the arrow points, in degrees, turning clockwise on screen from 0 = left: 90 points up, 180 right, 270 down. |
lines.flashing.drawing.squareAngle | SquareAngle | no | The right-angle (90°) marker placed on the drawing. |
lines.flashing.drawing.squareAngle.x | number | no | The x coordinate of the marker, in canvas space. Omitted until placed. |
lines.flashing.drawing.squareAngle.y | number | no | The y coordinate of the marker, in canvas space. Omitted until placed. |
lines.flashing.drawing.svgUrl | string | no | A presigned URL to the rendered SVG image of the drawing. Read-only output; populated after the SVG is uploaded via UploadDrawingSvg on OrderService or QuoteService. |
lines.flashing.otherSides | FlashingDrawing[] | no | Additional side drawings of the same flashing, used when the profile tapers: Factory compares each side's edge sizes with the main drawing's, edge by edge, and counts every differing edge as a taper. Their side defaults to the near side. When present, totalGirth and bends come from whichever side has the largest girth. A flashing drawing: its identity, metadata, geometry, and the URL of its rendered SVG image. Carried only by flashing lines (drawing / otherSides on FlashingLine) — drawings describe a flashing's folded profile and are not a general-purpose image or attachment type. Geometry is sent in the same shape the drawing tool holds it: points are the vertices, joined by the edges listed in each point's vectors and connect; lines.values gives each edge's real size in millimetres; angles.values gives the angle at each vertex. Point coordinates only lay out the sketch — the sizes in lines are the dimensions. A drawing whose points, lines or angles exceeds about 15,000 characters of JSON is rejected with HTTP 400 (validation_failure). |
lines.flashing.otherSides.drawingId | string | no | Server-assigned unique id of the drawing. Read-only output. |
lines.flashing.otherSides.tempId | string | no | A client-assigned correlation id supplied when creating the drawing. The write that creates the drawing returns it paired with the assigned drawingId in the response's drawings mapping (CreateQuote, CreateOrder, AddQuoteLineItem) — use that to address UploadDrawingSvg. It must be unique across every drawing in the request, other sides included; a repeated id is rejected with HTTP 400 (validation_failure). Omit it and the server assigns unique ids for you. It is not stored, so reads do not return it. |
lines.flashing.otherSides.drawingNumber | integer | no | The drawing's display number within the order or quote. Not assigned by the server: it is stored as sent (0 when omitted), and reads and printed documents order drawings by it, so number them 0, 1, 2… in line order. |
lines.flashing.otherSides.side | DrawingSide | no | Which face of the flashing this drawing represents. When not specified, a line's main drawing is the far side and each of its otherSides is the near side. Which face of the flashing a drawing represents. When not specified, a flashing line's main drawing is the far side and each of its otherSides is the near side. - DRAWING_SIDE_UNSPECIFIED: Default, unset value. - DRAWING_SIDE_FAR: The far side of the flashing. - DRAWING_SIDE_NEAR: The near side of the flashing. One of: DRAWING_SIDE_UNSPECIFIED, DRAWING_SIDE_FAR, DRAWING_SIDE_NEAR. |
lines.flashing.otherSides.isFreeDrawing | boolean | no | Whether the edge sizes in lines.values are the drawing's dimensions. Send true: when false, Factory measures each edge from the points' canvas coordinates instead, so girth, bends and the displayed sizes come from the sketch rather than from the sizes you supplied. |
lines.flashing.otherSides.isLargeBoxSize | boolean | no | Whether the drawing uses the large box size. |
lines.flashing.otherSides.isDeleted | boolean | no | Whether the drawing has been deleted. |
lines.flashing.otherSides.points | map<Point> | no | The vertices of the drawing, keyed by point id. Record each edge at both ends: p1.vectors lists p2 exactly when p2.connect lists p1. Required when the order or quote is submitted. A vertex in the drawing. Points are connected by edges to form the flashing profile. |
lines.flashing.otherSides.points.*.id | string | no | The unique id of this point within the drawing. |
lines.flashing.otherSides.points.*.x | number | no | The x coordinate of the point, in canvas space. |
lines.flashing.otherSides.points.*.y | number | no | The y coordinate of the point, in canvas space. |
lines.flashing.otherSides.points.*.vectors | string[] | no | The ids of points reached by edges leaving this point. Every edge must also appear in the target point's connect. |
lines.flashing.otherSides.points.*.connect | string[] | no | The ids of points connected to this point by incoming edges. Every edge must also appear in the source point's vectors. |
lines.flashing.otherSides.points.*.finish | Finish | no | Optional end treatment at this point. An end treatment applied to a point on a flashing edge (for example a hook or fold). Optional on a point. |
lines.flashing.otherSides.points.*.finish.type | FinishType | no | The kind of end treatment. The end-treatment applied to a flashing edge. Each type has a short code used in the finish's label, adds its size to the flashing's total girth, and counts a fixed number of bends. - FINISH_TYPE_UNSPECIFIED: Unspecified end treatment. - FINISH_TYPE_CRUSH_FOLD: A crush fold. Code "cf"; counts 2 bends (or the account's crushFoldBendCount when set). - FINISH_TYPE_OPEN_HOOK: An open hook. Code "oh"; counts 2 bends. - FINISH_TYPE_FEATHER: A feathered edge. Code "fe"; counts 1 bend. - FINISH_TYPE_DRIP_EDGE: A drip edge. Code "de"; counts 1 bend. One of: FINISH_TYPE_UNSPECIFIED, FINISH_TYPE_CRUSH_FOLD, FINISH_TYPE_OPEN_HOOK, FINISH_TYPE_FEATHER, FINISH_TYPE_DRIP_EDGE. |
lines.flashing.otherSides.points.*.finish.size | number | no | The size of the end treatment in millimetres. It counts toward the flashing's totalGirth. |
lines.flashing.otherSides.points.*.finish.label | string | no | The display label for this finish: the type's code followed by the size, e.g. "cf10" for a 10 mm crush fold or "oh25" for a 25 mm open hook. |
lines.flashing.otherSides.points.*.finish.flip | boolean | no | Which side of the edge the finish folds to. Looking from the finished end along its edge (screen coordinates, y pointing down), false puts the fold on the right-hand side and true on the left. A feathered edge is drawn mirrored relative to the other types. |
lines.flashing.otherSides.points.*.finish.position | LabelPosition | no | Optional bounding box for this finish's label. A label's bounding box in canvas (SVG) coordinate space. Used for line labels, angle labels, and finish labels. |
lines.flashing.otherSides.points.*.finish.position.x | number | no | The x coordinate of the label box, in canvas space. |
lines.flashing.otherSides.points.*.finish.position.y | number | no | The y coordinate of the label box, in canvas space. |
lines.flashing.otherSides.points.*.finish.position.width | number | no | The width of the label box, in canvas space. |
lines.flashing.otherSides.points.*.finish.position.height | number | no | The height of the label box, in canvas space. |
lines.flashing.otherSides.lines | LineSet | no | The edge sizes between points in millimetres, with their optional label positions. Give every edge a size — Factory counts the girth of a drawing with a missing size as 0. When omitted, the drawing is stored with an empty set and reads return lines with empty values and positions. The collection of edge lengths and their label positions for a drawing. |
lines.flashing.otherSides.lines.values | map<LineCell> | no | The size entry for each edge, keyed by the ids of the two points it connects joined with a hyphen, source first: the edge from p1 to p2 is "p1-p2". The length entry for a single edge between two points. |
lines.flashing.otherSides.lines.values.*.size | number | no | The size of the edge in millimetres. Omitted when a size has not yet been entered — but give every edge a size, or Factory counts the girth as 0. |
lines.flashing.otherSides.lines.values.*.hidden | boolean | no | Whether this edge's length label is hidden. |
lines.flashing.otherSides.lines.positions | map<LabelPosition> | no | The label box for each edge's size label, keyed like values. Optional: Factory places any label without a box itself. A label's bounding box in canvas (SVG) coordinate space. Used for line labels, angle labels, and finish labels. |
lines.flashing.otherSides.lines.positions.*.x | number | no | The x coordinate of the label box, in canvas space. |
lines.flashing.otherSides.lines.positions.*.y | number | no | The y coordinate of the label box, in canvas space. |
lines.flashing.otherSides.lines.positions.*.width | number | no | The width of the label box, in canvas space. |
lines.flashing.otherSides.lines.positions.*.height | number | no | The height of the label box, in canvas space. |
lines.flashing.otherSides.angles | AngleSet | no | The vertex angles in degrees, with their optional label positions. When omitted, the drawing is stored with an empty set and reads return angles with empty values and positions. The collection of vertex angles and their label positions for a drawing. |
lines.flashing.otherSides.angles.values | map<AngleCell> | no | The angle entry for each vertex, keyed by point id. The angle entry for a single point (vertex) in the drawing. |
lines.flashing.otherSides.angles.values.*.angle | number | no | The angle at this vertex, in degrees. Omitted when no angle is set. |
lines.flashing.otherSides.angles.values.*.hidden | boolean | no | Whether this vertex's angle label is hidden. Omitted when not set. |
lines.flashing.otherSides.angles.positions | map<LabelPosition> | no | The label box for each vertex's angle label, keyed by point id. Optional: Factory places any label without a box itself. A label's bounding box in canvas (SVG) coordinate space. Used for line labels, angle labels, and finish labels. |
lines.flashing.otherSides.angles.positions.*.x | number | no | The x coordinate of the label box, in canvas space. |
lines.flashing.otherSides.angles.positions.*.y | number | no | The y coordinate of the label box, in canvas space. |
lines.flashing.otherSides.angles.positions.*.width | number | no | The width of the label box, in canvas space. |
lines.flashing.otherSides.angles.positions.*.height | number | no | The height of the label box, in canvas space. |
lines.flashing.otherSides.annotations | map<TextBox> | no | Free-text annotations on the drawing, keyed by annotation id. A free-text annotation placed on the drawing. |
lines.flashing.otherSides.annotations.*.x | number | no | The x coordinate of the annotation, in canvas space. Omitted until placed. |
lines.flashing.otherSides.annotations.*.y | number | no | The y coordinate of the annotation, in canvas space. Omitted until placed. |
lines.flashing.otherSides.annotations.*.width | number | no | The width of the annotation box, in canvas space. |
lines.flashing.otherSides.annotations.*.height | number | no | The height of the annotation box, in canvas space. |
lines.flashing.otherSides.annotations.*.value | string | no | The annotation text as a flat string. May be present alongside the structured text form. |
lines.flashing.otherSides.annotations.*.text | TextRow[] | no | The annotation text in structured rows. May be present alongside value. One row of text within a text annotation. |
lines.flashing.otherSides.annotations.*.text.id | integer | no | The 0-based index of this row within the text annotation. |
lines.flashing.otherSides.annotations.*.text.indent | integer | no | The indentation level of this row. |
lines.flashing.otherSides.annotations.*.text.value | string[] | no | The text segments that make up this row, in order. |
lines.flashing.otherSides.annotations.*.rotateDeg | number | no | Optional rotation of the annotation, in degrees. |
lines.flashing.otherSides.frontArrow | Arrow | no | The arrow marking the front face of the flashing. Optional. The arrow that indicates the front-facing direction of the flashing. |
lines.flashing.otherSides.frontArrow.x | number | no | The x coordinate of the arrow, in canvas space. Omitted until placed. |
lines.flashing.otherSides.frontArrow.y | number | no | The y coordinate of the arrow, in canvas space. Omitted until placed. |
lines.flashing.otherSides.frontArrow.angle | number | no | The direction the arrow points, in degrees, turning clockwise on screen from 0 = left: 90 points up, 180 right, 270 down. |
lines.flashing.otherSides.squareAngle | SquareAngle | no | The right-angle (90°) marker placed on the drawing. |
lines.flashing.otherSides.squareAngle.x | number | no | The x coordinate of the marker, in canvas space. Omitted until placed. |
lines.flashing.otherSides.squareAngle.y | number | no | The y coordinate of the marker, in canvas space. Omitted until placed. |
lines.flashing.otherSides.svgUrl | string | no | A presigned URL to the rendered SVG image of the drawing. Read-only output; populated after the SVG is uploaded via UploadDrawingSvg on OrderService or QuoteService. |
lines.flashing.tax | TaxDetail | no | The tax applied to this line: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable lines; this object reserves the shape for richer per-line tax later. |
lines.productKit | ProductKitLine | no | A line for a predefined product kit. Set exactly one of the six line-type fields. |
lines.productKit.kitId | string | no | The kit's id (kitId on Kit, from the catalogue read surface). Optional: omit it to define an on-the-fly kit not linked to any catalogue kit — the kit is described entirely by this line's name, pricing, components, and sub-kits. |
lines.productKit.kitRowId | string | no | The selected kit row/variant id. Optional. |
lines.productKit.productName | string | no | Display name of the kit. |
lines.productKit.customPricing | boolean | no | Whether the kit is custom-priced (true) rather than computed from its components (false). |
lines.productKit.description | string | no | Free-text description of the kit. |
lines.productKit.displayKitItems | object[] | no | Which documents and views the kit's components are shown on, as a JSON array of display-target keys — for example "displayOnWorkOrderPdf", "displayOnInvoicePdf", or "displayOnAllViews". Optional. |
lines.productKit.displaySubKits | object[] | no | Which documents and views the kit's sub-kits are shown on, as a JSON array of display-target keys, using the same values as displayKitItems. Optional. |
lines.productKit.pricing | LinePricing | no | Overall pricing for the kit line. Pricing for a single priced line: quantity, prices, discount, cost, markup, margin, and pricing strategy. On priced lines the server validates — or, once derivation is enabled for your account, derives — the line total from the quantity, unit price, and discount; see totalPrice for the exact formula, the rounding rule, and what happens if it does not match. |
lines.productKit.pricing.quantity | string | no | Quantity for this line, as a decimal string (e.g. "2" or "2.5"). Supports up to 4 decimal places. It is the first factor of the line-total formula documented on totalPrice — EXCEPT on measurement-priced (lineal/square) lines, where the measured length or area alone sets the priced amount and this factor is treated as 1 whenever the server derives or checks the total. Do not multiply a measurement-priced total by quantity. (Only on free-text lines on accounts WITHOUT server-side derivation does the legacy formula still multiply by it — see totalPrice). |
lines.productKit.pricing.unitPrice | Money | no | Per-unit price. Required on priced lines — except on catalogue lines with server-side derivation enabled for your account, where you may omit it and supply cost plus markup instead: the server computes it as cost x (1 + markup/100) (or cost + markup for a fixed markup). If you can send the price directly, do; the derivation exists for callers whose source system stores only cost and markup. The server rounds this to 4 decimal places (half up) before pricing, so unit-price precision finer than that (micro amounts that are not a multiple of 100) is not preserved and can shift the computed line total. |
lines.productKit.pricing.totalPrice | Money | no | The line total, as a Money amount in micros. Server-side derivation is rolling out account by account. Once it is enabled for your account, this field is optional on most priced lines — omit it (leave the whole Money object out; an empty Money is a supplied $0.00) and the server computes it. Until then it is required on priced lines, exactly as before. The formula is: quantity * unitPrice * (1 - discount / 100) rounded to the nearest cent — 2 decimal places, half up (0.005 rounds up). For lineal or square measurement pricing the result is then multiplied by the measured length or area the server derives from the line's measurement details before rounding — and on measurement-priced lines the quantity factor is pinned to 1 once derivation is enabled for your account, whether the server derives the total or checks one you send: the measurements alone set the priced amount. (Without derivation, free-text lines still multiply by quantity — match it when computing such a total yourself.) Deriving needs a non-zero quantity or measurement set (deriving with a zero quantity or an empty measurement set is rejected rather than stored as $0.00; a zero unit price — a free line — still derives). On a product kit priced as a standard kit, an omitted parent total is derived as the sum of its components and sub-kits (omitted sub-kit totals are likewise derived from their components) — priced component totals must accompany the request; a missing one is rejected rather than summed as zero. A supplied kit total, at any tier, is stored as sent. If you DO send a value on a catalogue (once derivation is enabled for your account), on-the-fly, or labour line, it is checked against the formula and a mismatch is rejected with HTTP 400. Send the amount as a whole number of cents (amountMicros a multiple of 10000); a sub-cent amount is rounded to the nearest cent before the check. Exceptions, where the total is never derived — send a correct value, because these lines are stored as sent: |
lines.productKit.pricing.discount | string | no | Discount applied to the line, as a decimal percentage string (e.g. "10.00" means 10%). Supports up to 2 decimal places. In the line-total formula on totalPrice it enters as the factor (1 - discount / 100). |
lines.productKit.pricing.cost | Money | no | Unit cost for this line, used to compute margin — and, with derivation enabled, the base the server recomputes markup (and an omitted unitPrice) from. Rounded to 4 decimal places (half up) before use, so sub-4dp cost precision is not preserved. |
lines.productKit.pricing.markup | string | no | Markup applied to the line, as a decimal string — either a money amount or a percentage, depending on markupIsPercentage. With server-side derivation enabled for your account: whenever cost is non-zero, the value you send here is DISCARDED and recomputed from cost and the unit price (as a percentage — markupIsPercentage reads back true), so the stored markup always agrees with the stored prices. Do not expect to read back the value you sent. With a zero or absent cost your value is kept as sent. |
lines.productKit.pricing.markupIsPercentage | boolean | no | Whether markup is a percentage (true) or a fixed amount (false). Omit it to use the default, true; send false only for a fixed-amount markup. Always present on reads, and reads back true whenever the server recomputed the markup (see markup). |
lines.productKit.pricing.margin | Money | no | Margin for the line. When supplied, it is validated against cost and quantity — and with derivation enabled it is recomputed alongside the total whenever cost is present, so (like markup) the stored value may differ from what you sent. Simplest: omit it and let the server compute. |
lines.productKit.pricing.pricingStrategy | PricingStrategy | no | How this line is priced (per-unit quantity, lineal, or square measurement). Defaults to per-unit quantity pricing. How a quantity is interpreted for pricing — whether it means a count of each, a length, or an area. On a catalogue product this is the product's pricing basis. On an order or quote line, measurement-based strategies (lineal or square metres/feet) require the line's measurement details to be supplied. - PRICING_STRATEGY_UNSPECIFIED: Unset, or a legacy product with no pricing strategy recorded. - PRICING_STRATEGY_BASIC_QUANTITIES: Quantity is a simple per-each count. - PRICING_STRATEGY_LINEAL_METRES: Quantity is a length in lineal metres. - PRICING_STRATEGY_CUSTOM_FORMULA: Quantity is priced by a custom formula. - PRICING_STRATEGY_SQUARE_METRES: Quantity is an area in square metres. - PRICING_STRATEGY_LINEAL_FEET: Quantity is a length in lineal feet. - PRICING_STRATEGY_SQUARE_FEET: Quantity is an area in square feet. One of: PRICING_STRATEGY_UNSPECIFIED, PRICING_STRATEGY_BASIC_QUANTITIES, PRICING_STRATEGY_LINEAL_METRES, PRICING_STRATEGY_CUSTOM_FORMULA, PRICING_STRATEGY_SQUARE_METRES, PRICING_STRATEGY_LINEAL_FEET, PRICING_STRATEGY_SQUARE_FEET. |
lines.productKit.pricing.priceLevel | string | no | Optional named price level applied to this line. |
lines.productKit.pricing.isTaxFree | boolean | no | Whether this line is exempt from tax. |
lines.productKit.pricing.tax | TaxDetail | no | The tax applied to this line: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable lines; this object reserves the shape for richer per-line tax later. |
lines.productKit.pricing.measurements | MeasurementEntry[] | no | The measurements that price this line, for the lineal and square pricing strategies. Units follow the strategy: metres for *_METRES, feet for *_FEET (see MeasurementEntry). Requires an explicit, measurement-priced pricingStrategy on this same object. On these strategies the measured amount is the priced quantity — quantity is NOT a factor (on accounts without server-side derivation, free-text lines are the one legacy exception; see quantity); the server sums these pieces (applying your account's minimum-length setting on lineal strategies) to derive the amount that scales the line total. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.productKit.pricing.measurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.productKit.pricing.measurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.productKit.pricing.measurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.productKit.pricing.asBuiltMeasurements | MeasurementEntry[] | no | As-built measurements — what production actually cut, in the same shape and units as measurements. These drive cost, margin, and stock consumption, never the line price. Optional: whenever omitted (create and update alike) they default to measurements. Send them only when your as-built figures differ from what was quoted. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.productKit.pricing.asBuiltMeasurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.productKit.pricing.asBuiltMeasurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.productKit.pricing.asBuiltMeasurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.productKit.attributes | object[] | no | Additional named attributes for the kit line, as a JSON array of {name, value} entries; for measurement-priced kits they describe the measurement entries. |
lines.productKit.components | KitComponent[] | no | The kit's direct components. One component line inside a kit or sub-kit. A component is itself typed — it may be a catalogue-product, on-the-fly, notes, labour, or kit-product line — and carries its own pricing and measurement details. |
lines.productKit.components.productType | KitComponentType | no | The component's kind: catalogue product, on-the-fly, labour, or notes. Required — it determines which of the fields below apply. The kind of a component within a product kit. - KIT_COMPONENT_TYPE_UNSPECIFIED: Default, unset value. Not a valid choice for a kit component. - KIT_COMPONENT_TYPE_CATALOGUE_PRODUCT: A component that is a product from your catalogue. - KIT_COMPONENT_TYPE_ON_THE_FLY_PRODUCT: A free-form component not tied to a catalogue product. Occurs on order and quote kits only — it is not a catalogue-template component kind. - KIT_COMPONENT_TYPE_NOTES: A note component: carries text rather than a priced product. - KIT_COMPONENT_TYPE_LABOUR: A labour component. One of: KIT_COMPONENT_TYPE_UNSPECIFIED, KIT_COMPONENT_TYPE_CATALOGUE_PRODUCT, KIT_COMPONENT_TYPE_ON_THE_FLY_PRODUCT, KIT_COMPONENT_TYPE_NOTES, KIT_COMPONENT_TYPE_LABOUR. |
lines.productKit.components.productId | string | no | The catalogue product id for this component. Optional. |
lines.productKit.components.productRowId | string | no | The catalogue product table-row (variant) id. Optional. |
lines.productKit.components.kitProductId | string | no | The catalogue kit-product-component id this component was instantiated from. Optional. |
lines.productKit.components.productName | string | no | Display name of the component. Set it on every write: component names are stored verbatim and are NEVER derived from productId or productRowId — a component created without a name is stored nameless and every read of the document returns it with an empty name. When building this line from a catalogue kit template, echo the template component's productName (returned by GetKit) into this field. |
lines.productKit.components.productDescription | string | no | Free-text description of the component. |
lines.productKit.components.quantity | string | no | Quantity for this component, as a decimal string. |
lines.productKit.components.baseQuantity | string | no | Base quantity before any per-unit multipliers, as a decimal string. |
lines.productKit.components.unitPrice | Money | no | Price per unit. |
lines.productKit.components.totalPrice | Money | no | Total price for this component. With derived pricing enabled every priced component must carry it — a missing one is rejected rather than summed as zero — and it is checked against the component's own figures: unit price x quantity x (1 - discount / 100), with the measured amount replacing quantity on measurement-priced components (quantity is not a factor there — see measurements). |
lines.productKit.components.customPrice | Money | no | A manual override of the component's TOTAL price — not a unit price. When set, tax and margin are computed from this value in place of totalPrice, so a disagreeing pair stores an incoherent document. Send it only to deliberately override the component's total, and never echo unitPrice into it. With derived pricing enabled, a customPrice that disagrees with totalPrice is rejected (400). |
lines.productKit.components.customPricePerLength | Money | no | A manual override of the price per unit of measured length (for example, per lineal metre), applied instead of the unit price on measurement-priced components. Send it only to deliberately override — omit it otherwise: an explicit $0.00 is stored as an override of $0.00, not ignored. |
lines.productKit.components.discount | string | no | Discount applied to this component, as a decimal string. |
lines.productKit.components.cost | Money | no | Cost of the component. |
lines.productKit.components.markup | string | no | Markup applied to the component, as a decimal string. Interpreted as a percentage when markupIsPercentage is true. |
lines.productKit.components.markupIsPercentage | boolean | no | Whether markup is a percentage (true) or an absolute amount (false). Omit it to use the default, true; send false only for a fixed-amount markup. Always present on reads. |
lines.productKit.components.margin | Money | no | Margin earned on the component. |
lines.productKit.components.pricingStrategy | PricingStrategy | no | How the component is priced. How a quantity is interpreted for pricing — whether it means a count of each, a length, or an area. On a catalogue product this is the product's pricing basis. On an order or quote line, measurement-based strategies (lineal or square metres/feet) require the line's measurement details to be supplied. - PRICING_STRATEGY_UNSPECIFIED: Unset, or a legacy product with no pricing strategy recorded. - PRICING_STRATEGY_BASIC_QUANTITIES: Quantity is a simple per-each count. - PRICING_STRATEGY_LINEAL_METRES: Quantity is a length in lineal metres. - PRICING_STRATEGY_CUSTOM_FORMULA: Quantity is priced by a custom formula. - PRICING_STRATEGY_SQUARE_METRES: Quantity is an area in square metres. - PRICING_STRATEGY_LINEAL_FEET: Quantity is a length in lineal feet. - PRICING_STRATEGY_SQUARE_FEET: Quantity is an area in square feet. One of: PRICING_STRATEGY_UNSPECIFIED, PRICING_STRATEGY_BASIC_QUANTITIES, PRICING_STRATEGY_LINEAL_METRES, PRICING_STRATEGY_CUSTOM_FORMULA, PRICING_STRATEGY_SQUARE_METRES, PRICING_STRATEGY_LINEAL_FEET, PRICING_STRATEGY_SQUARE_FEET. |
lines.productKit.components.isTaxFree | boolean | no | Whether this component is exempt from tax. |
lines.productKit.components.attributes | object[] | no | Additional named attributes for the component, as a JSON array of {name, value} entries; for measurement-priced components they describe the measurement entries. |
lines.productKit.components.notes | string | no | Free-text notes — used when the component is a notes line. |
lines.productKit.components.notesType | NotesType | no | The kind of notes line, when this is a notes component. Whether a notes line is internal-only or visible to the customer. - NOTES_TYPE_UNSPECIFIED: Default, unset value. Not a valid choice for a notes line. - NOTES_TYPE_INTERNAL: An internal note, not shown to the customer. - NOTES_TYPE_EXTERNAL: An external note, visible to the customer. One of: NOTES_TYPE_UNSPECIFIED, NOTES_TYPE_INTERNAL, NOTES_TYPE_EXTERNAL. |
lines.productKit.components.labourUserId | string | no | The company user assigned, when this is a labour component. |
lines.productKit.components.colour | string | no | Colour of the component, populated for catalogue components from the product row. |
lines.productKit.components.material | string | no | Material of the component, populated for catalogue components from the product row. |
lines.productKit.components.colourOptions | object[] | no | The selectable options for this component's variant attribute — most often colour, but also other attributes such as size — as a JSON array of {label, value} entries, echoed from the catalogue. Display and read only. |
lines.productKit.components.tax | TaxDetail | no | The tax applied to this component: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable components; this object reserves the shape for richer tax later. |
lines.productKit.components.measurements | MeasurementEntry[] | no | The measurements that price this component, for the lineal and square pricing strategies. Units follow the strategy: metres for *_METRES, feet for *_FEET (see MeasurementEntry). Requires an explicit, measurement-priced pricingStrategy on this component. The measured amount is the priced quantity — quantity is NOT a factor. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.productKit.components.measurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.productKit.components.measurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.productKit.components.measurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.productKit.components.asBuiltMeasurements | MeasurementEntry[] | no | As-built measurements — what production actually cut, in the same shape and units as measurements. These drive cost, margin, and stock consumption, never the component price. Optional: whenever omitted (create and update alike) they default to measurements. Send them only when your as-built figures differ from what was quoted. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.productKit.components.asBuiltMeasurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.productKit.components.asBuiltMeasurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.productKit.components.asBuiltMeasurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.productKit.subKits | SubKit[] | no | The kit's sub-assemblies, each with its own components. A sub-assembly within a kit. A sub-kit groups a set of components under its own title and quantity, letting a kit be organized into named sub-assemblies. |
lines.productKit.subKits.title | string | no | Display title of the sub-assembly. |
lines.productKit.subKits.quantity | string | no | Quantity of this sub-assembly, as a decimal string. |
lines.productKit.subKits.actualQuantity | string | no | Actual measured quantity, as a decimal string. |
lines.productKit.subKits.unitPrice | Money | no | Price per unit of the sub-assembly. |
lines.productKit.subKits.totalPrice | Money | no | Total price of the sub-assembly. |
lines.productKit.subKits.components | KitComponent[] | no | The components that make up this sub-assembly. One component line inside a kit or sub-kit. A component is itself typed — it may be a catalogue-product, on-the-fly, notes, labour, or kit-product line — and carries its own pricing and measurement details. |
lines.productKit.subKits.components.productType | KitComponentType | no | The component's kind: catalogue product, on-the-fly, labour, or notes. Required — it determines which of the fields below apply. The kind of a component within a product kit. - KIT_COMPONENT_TYPE_UNSPECIFIED: Default, unset value. Not a valid choice for a kit component. - KIT_COMPONENT_TYPE_CATALOGUE_PRODUCT: A component that is a product from your catalogue. - KIT_COMPONENT_TYPE_ON_THE_FLY_PRODUCT: A free-form component not tied to a catalogue product. Occurs on order and quote kits only — it is not a catalogue-template component kind. - KIT_COMPONENT_TYPE_NOTES: A note component: carries text rather than a priced product. - KIT_COMPONENT_TYPE_LABOUR: A labour component. One of: KIT_COMPONENT_TYPE_UNSPECIFIED, KIT_COMPONENT_TYPE_CATALOGUE_PRODUCT, KIT_COMPONENT_TYPE_ON_THE_FLY_PRODUCT, KIT_COMPONENT_TYPE_NOTES, KIT_COMPONENT_TYPE_LABOUR. |
lines.productKit.subKits.components.productId | string | no | The catalogue product id for this component. Optional. |
lines.productKit.subKits.components.productRowId | string | no | The catalogue product table-row (variant) id. Optional. |
lines.productKit.subKits.components.kitProductId | string | no | The catalogue kit-product-component id this component was instantiated from. Optional. |
lines.productKit.subKits.components.productName | string | no | Display name of the component. Set it on every write: component names are stored verbatim and are NEVER derived from productId or productRowId — a component created without a name is stored nameless and every read of the document returns it with an empty name. When building this line from a catalogue kit template, echo the template component's productName (returned by GetKit) into this field. |
lines.productKit.subKits.components.productDescription | string | no | Free-text description of the component. |
lines.productKit.subKits.components.quantity | string | no | Quantity for this component, as a decimal string. |
lines.productKit.subKits.components.baseQuantity | string | no | Base quantity before any per-unit multipliers, as a decimal string. |
lines.productKit.subKits.components.unitPrice | Money | no | Price per unit. |
lines.productKit.subKits.components.totalPrice | Money | no | Total price for this component. With derived pricing enabled every priced component must carry it — a missing one is rejected rather than summed as zero — and it is checked against the component's own figures: unit price x quantity x (1 - discount / 100), with the measured amount replacing quantity on measurement-priced components (quantity is not a factor there — see measurements). |
lines.productKit.subKits.components.customPrice | Money | no | A manual override of the component's TOTAL price — not a unit price. When set, tax and margin are computed from this value in place of totalPrice, so a disagreeing pair stores an incoherent document. Send it only to deliberately override the component's total, and never echo unitPrice into it. With derived pricing enabled, a customPrice that disagrees with totalPrice is rejected (400). |
lines.productKit.subKits.components.customPricePerLength | Money | no | A manual override of the price per unit of measured length (for example, per lineal metre), applied instead of the unit price on measurement-priced components. Send it only to deliberately override — omit it otherwise: an explicit $0.00 is stored as an override of $0.00, not ignored. |
lines.productKit.subKits.components.discount | string | no | Discount applied to this component, as a decimal string. |
lines.productKit.subKits.components.cost | Money | no | Cost of the component. |
lines.productKit.subKits.components.markup | string | no | Markup applied to the component, as a decimal string. Interpreted as a percentage when markupIsPercentage is true. |
lines.productKit.subKits.components.markupIsPercentage | boolean | no | Whether markup is a percentage (true) or an absolute amount (false). Omit it to use the default, true; send false only for a fixed-amount markup. Always present on reads. |
lines.productKit.subKits.components.margin | Money | no | Margin earned on the component. |
lines.productKit.subKits.components.pricingStrategy | PricingStrategy | no | How the component is priced. How a quantity is interpreted for pricing — whether it means a count of each, a length, or an area. On a catalogue product this is the product's pricing basis. On an order or quote line, measurement-based strategies (lineal or square metres/feet) require the line's measurement details to be supplied. - PRICING_STRATEGY_UNSPECIFIED: Unset, or a legacy product with no pricing strategy recorded. - PRICING_STRATEGY_BASIC_QUANTITIES: Quantity is a simple per-each count. - PRICING_STRATEGY_LINEAL_METRES: Quantity is a length in lineal metres. - PRICING_STRATEGY_CUSTOM_FORMULA: Quantity is priced by a custom formula. - PRICING_STRATEGY_SQUARE_METRES: Quantity is an area in square metres. - PRICING_STRATEGY_LINEAL_FEET: Quantity is a length in lineal feet. - PRICING_STRATEGY_SQUARE_FEET: Quantity is an area in square feet. One of: PRICING_STRATEGY_UNSPECIFIED, PRICING_STRATEGY_BASIC_QUANTITIES, PRICING_STRATEGY_LINEAL_METRES, PRICING_STRATEGY_CUSTOM_FORMULA, PRICING_STRATEGY_SQUARE_METRES, PRICING_STRATEGY_LINEAL_FEET, PRICING_STRATEGY_SQUARE_FEET. |
lines.productKit.subKits.components.isTaxFree | boolean | no | Whether this component is exempt from tax. |
lines.productKit.subKits.components.attributes | object[] | no | Additional named attributes for the component, as a JSON array of {name, value} entries; for measurement-priced components they describe the measurement entries. |
lines.productKit.subKits.components.notes | string | no | Free-text notes — used when the component is a notes line. |
lines.productKit.subKits.components.notesType | NotesType | no | The kind of notes line, when this is a notes component. Whether a notes line is internal-only or visible to the customer. - NOTES_TYPE_UNSPECIFIED: Default, unset value. Not a valid choice for a notes line. - NOTES_TYPE_INTERNAL: An internal note, not shown to the customer. - NOTES_TYPE_EXTERNAL: An external note, visible to the customer. One of: NOTES_TYPE_UNSPECIFIED, NOTES_TYPE_INTERNAL, NOTES_TYPE_EXTERNAL. |
lines.productKit.subKits.components.labourUserId | string | no | The company user assigned, when this is a labour component. |
lines.productKit.subKits.components.colour | string | no | Colour of the component, populated for catalogue components from the product row. |
lines.productKit.subKits.components.material | string | no | Material of the component, populated for catalogue components from the product row. |
lines.productKit.subKits.components.colourOptions | object[] | no | The selectable options for this component's variant attribute — most often colour, but also other attributes such as size — as a JSON array of {label, value} entries, echoed from the catalogue. Display and read only. |
lines.productKit.subKits.components.tax | TaxDetail | no | The tax applied to this component: rate, code, and jurisdiction. Complements the isTaxFree flag. In v1 the server applies your account's tax settings to taxable components; this object reserves the shape for richer tax later. |
lines.productKit.subKits.components.measurements | MeasurementEntry[] | no | The measurements that price this component, for the lineal and square pricing strategies. Units follow the strategy: metres for *_METRES, feet for *_FEET (see MeasurementEntry). Requires an explicit, measurement-priced pricingStrategy on this component. The measured amount is the priced quantity — quantity is NOT a factor. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.productKit.subKits.components.measurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.productKit.subKits.components.measurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.productKit.subKits.components.measurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.productKit.subKits.components.asBuiltMeasurements | MeasurementEntry[] | no | As-built measurements — what production actually cut, in the same shape and units as measurements. These drive cost, margin, and stock consumption, never the component price. Optional: whenever omitted (create and update alike) they default to measurements. Send them only when your as-built figures differ from what was quoted. One measured piece (or panel) in a measurement-priced line or kit component. Values are decimal strings in the line's strategy-native unit: metres for the *_METRES pricing strategies, feet for *_FEET. |
lines.productKit.subKits.components.asBuiltMeasurements.length | string | no | Length of this piece, as a decimal string in the strategy's unit (e.g. "2.4" metres, or "8" feet). |
lines.productKit.subKits.components.asBuiltMeasurements.width | string | no | Width of this piece, as a decimal string in the strategy's unit. Square strategies only — a width on a lineal entry is rejected, and a square entry without one is rejected. |
lines.productKit.subKits.components.asBuiltMeasurements.amount | string | no | How many pieces of this size, as a decimal string. Defaults to 1. |
lines.id | string | no | The server-assigned id of this line — unique and stable for the life of the line. Returned when a quote is read; pass it to update or remove the line. Not set when creating a line (the server assigns it). This id has a different form from the quote id. |
adjustments | Adjustment[] | no | Quote-level fees, discounts, and markups applied across the whole quote. |
adjustments.type | AdjustmentType | yes | The kind of adjustment: a fee, discount, or markup. Required. The kind of order- or quote-level adjustment: a fee, a discount, or a markup. Only fees and discounts change the document's totals. - ADJUSTMENT_TYPE_UNSPECIFIED: Default, unset value. Not a valid choice when setting an adjustment. - ADJUSTMENT_TYPE_FEE: A fee added to the order or quote after any discounts, and taxed at the account's rate. It must be a fixed amount, not a percent, and at most one fee is allowed per order or quote. - ADJUSTMENT_TYPE_DISCOUNT: A discount subtracted from the lines' subtotal before tax and before any fee. A percent discount is taken of the lines' subtotal as it stands when the discount is applied; with several discounts, each applies to the subtotal left by the earlier ones, in the order they were added. - ADJUSTMENT_TYPE_MARKUP: A markup recorded against the order or quote. It is stored and returned on reads but changes no total: to mark up a document, raise its line prices. Any number of markups may be recorded. One of: ADJUSTMENT_TYPE_UNSPECIFIED, ADJUSTMENT_TYPE_FEE, ADJUSTMENT_TYPE_DISCOUNT, ADJUSTMENT_TYPE_MARKUP. |
adjustments.title | string | no | A label describing the adjustment. |
adjustments.amount | Money | no | The adjustment as a fixed money amount. Exactly one of amount or percent must be set. A fee must use this form. |
adjustments.amount.amountMicros | string | no | Amount in micros — millionths of the currency's major unit. 1.00 = 1_000_000 micros, so 2.34 is 12_340_000 — sent and returned over JSON as the string "12340000" (64-bit integers serialize as JSON strings). A whole number of cents (or pence, etc.) is a multiple of 10_000 micros. |
adjustments.amount.currency | string | no | ISO 4217 currency code (3 letters, e.g. "AUD"). |
adjustments.percent | string | no | The adjustment as a percentage (for example, "10.00"). Exactly one of amount or percent must be set. For a discount, the percentage is taken of the lines' subtotal (see AdjustmentType); a fee given as a percent is rejected with HTTP 400 (validation_failure). |
isSubmitted | boolean | no | Finalise and send the quote immediately (true) or save it as a draft (false). |
fulfilmentMethod | FulfilmentMethod | no | How the customer would receive the order if the quote is accepted: pickup, delivery, or installation. Determines which address below applies. How the customer receives the goods on an order or quote. Determines which address is used: delivery uses the delivery address, installation uses the install address. - FULFILMENT_METHOD_UNSPECIFIED: Default, unset value. - FULFILMENT_METHOD_PICKUP: The customer collects the goods themselves. - FULFILMENT_METHOD_DELIVERY: The goods are delivered to the delivery address. - FULFILMENT_METHOD_INSTALL: The goods are installed at the install address. One of: FULFILMENT_METHOD_UNSPECIFIED, FULFILMENT_METHOD_PICKUP, FULFILMENT_METHOD_DELIVERY, FULFILMENT_METHOD_INSTALL. |
billingAddress | Address | no | Billing address for the quote. |
billingAddress.address1 | string | no | First address line (street number and name). |
billingAddress.address2 | string | no | Second address line (unit, suite, or similar). |
billingAddress.city | string | no | City or suburb. |
billingAddress.state | string | no | State, province, or region. |
billingAddress.postalCode | string | no | Postal code (ZIP code, postcode). |
billingAddress.countryCode | string | no | Country, as an uppercase ISO 3166-1 alpha-2 code (e.g. "AU"). Optional; when supplied, any other form is rejected. |
deliveryAddress | Address | no | Delivery address. Used only when fulfilmentMethod is DELIVERY. |
deliveryAddress.address1 | string | no | First address line (street number and name). |
deliveryAddress.address2 | string | no | Second address line (unit, suite, or similar). |
deliveryAddress.city | string | no | City or suburb. |
deliveryAddress.state | string | no | State, province, or region. |
deliveryAddress.postalCode | string | no | Postal code (ZIP code, postcode). |
deliveryAddress.countryCode | string | no | Country, as an uppercase ISO 3166-1 alpha-2 code (e.g. "AU"). Optional; when supplied, any other form is rejected. |
installAddress | Address | no | Installation address. Used only when fulfilmentMethod is INSTALL. |
installAddress.address1 | string | no | First address line (street number and name). |
installAddress.address2 | string | no | Second address line (unit, suite, or similar). |
installAddress.city | string | no | City or suburb. |
installAddress.state | string | no | State, province, or region. |
installAddress.postalCode | string | no | Postal code (ZIP code, postcode). |
installAddress.countryCode | string | no | Country, as an uppercase ISO 3166-1 alpha-2 code (e.g. "AU"). Optional; when supplied, any other form is rejected. |
reference | string | no | Free-text external reference for this quote — e.g. the quote id or purchase order (PO) number from your own system. Shown as "PO #" in the Factory app and as "PO" on the quote and order documents. Stored for lookup and audit; distinct from requestId (the retry key) and from the read-only orderNumber (Factory's own number for the quote). |
customFields | object | no | Values for your account's custom-defined sales-document fields, keyed by each field's configured key. Unknown keys, keys of other modules, and values that don't match the field's type are rejected. Send number and currency values as numbers or decimal strings, checkboxes as booleans, multi-selects as arrays of strings, and everything else as strings. Select and multi-select values must be option keys from the field's definition, never display labels; discover your account's field keys and options with GET /v1/company/custom-fields. Formula fields are computed and cannot be written. |
requiredAt | string | no | The date the customer needs the order by, if the quote is accepted. |
contact | Contact | no | The point-of-contact person for this quote, distinct from the customer. |
contact.name | string | no | The contact person's name. |
contact.email | string | no | The contact's email address. Optional; when provided, it must be a valid email address. |
contact.phone | string | no | The contact's landline phone number. |
contact.mobile | string | no | The contact's mobile number, normalized to E.164 format (e.g. +61400000000). |
notes | string | no | Free-text notes about the quote. |
quotedAt | string | no | The date the quote was issued. If omitted, the server sets it. |
tax | TaxDetail | no | The tax to apply, as a rate/code/jurisdiction descriptor. Optional and advisory in this version: the server applies your account's configured tax settings and echoes the values actually applied (tax and taxAmount on the Quote) — compare them to detect an override. |
tax.rate | string | no | The tax rate applied, as a decimal fraction (e.g. "0.10" means 10%). |
tax.code | string | no | The tax code, e.g. "GST", "VAT", or "SALES_TAX". Open-ended — not a fixed set. |
tax.jurisdiction | string | no | The tax jurisdiction, e.g. "AU", "GB", or "US-CA-LOS_ANGELES". Open-ended. |
requestId | string | no | Optional idempotency key for this request: an opaque, client-generated UUID, scoped to the API key that sends it. Requests carrying the same key are executed at most once, so a retry can never create a second copy. Any repeat is rejected with HTTP 409: if the original request completed, the body's resourceId carries the id it created; if its outcome is still unknown, or the key is reused with a materially different body, verify with a read before retrying with a fresh key. Keys are retained for at least 24 hours. If the idempotency store is unavailable, requests carrying a key are rejected with HTTP 503 (requests without a key are unaffected). Omit the key for no idempotency guarantee. |
labelIds | string[] | no | Labels to attach to the quote as part of creating it, by id. Every id must exist in your company's label set (discover them with GET /v1/company/labels): an unknown id fails the whole call with HTTP 404 before the quote is created. Labelling happens with the create but not atomically inside it — in the rare case the quote is created and labelling then fails, the error names the created quote id and the quote exists WITHOUT labels; attach them with SetQuoteLabels. The created quote echoes the attached labels. Duplicate ids are rejected. |
fields | string | no | Comma-separated response fields to include, using camelCase JSON names (e.g. orderId,total.amountMicros). Dot paths reach into nested objects and map transparently across arrays. Paths are relative to the resource, not the response envelope; envelope keys are always preserved. Only 2xx JSON responses are filtered; error bodies pass through unmodified. Unknown names are silently ignored. Takes precedence over excludeFields when both are provided. |
excludeFields | string | no | Comma-separated response fields to exclude, using camelCase JSON names. Dot paths and array-transparency work the same as fields. Paths are relative to the resource, not the response envelope. Only 2xx JSON responses are filtered; error bodies pass through unmodified. Ignored when fields is also provided. |