Add, change and delete line items in one save
AI agents: read /llms.txt; add .md to any page URL. This page as Markdown: /reference/sales-order-line-items/v2-order-item-bulk.md. Index of every page and the rules for every call: /llms.txt. Guides and concepts in one file: /llms-full.txt. OpenAPI: /openapi.json.
POST/
Runs several line operations on one sales order or quote as one save: all of them are written, or none. Sending the same batch again adds the lines again, so read the order back before you retry after a timeout.
The body is a JSON array of operations. Each has your own bid, an action and, depending on the action:
create:payloadis the body of Add a line item;update:cart_item_id(the line's id) andpayload, the body of Update a line item (send only what changes);delete:cart_item_idonly.
Whatever the order in the array, deletes run first, then creates, then updates. Prices, job decoration pricing, shipments, invoices and totals are recalculated once, at the end.
The optional header X-Yoprint-Order-Item-Save-Intent says what the save is for. The web app sends save.
save: when nothing in the batch changes anything, nothing is written andhas_changesis false;recalculate: always recalculates, even when only a description or position changed;- left out (or any other value): the older behavior, where
has_changesis always true.
Amounts and quantities are sent as { value, dp } pairs: value is the number without its decimal point and dp is how many of its digits come after the decimal point. 12.50 is { "value": 1250, "dp": 2 }; 24 is { "value": 24, "dp": 0 }. value is a whole number (a JSON integer or a string of digits); dp is 0 to 30.
{order_unique_key} is the sales order or quote id (for example V4keXwwxMQyXw7) or its unique_key (it starts with ord_). The order number people see, such as SO1001, is not accepted here.
The answer, in data, lists every line of the order after the save, by position, each as { object_type, action_performed, has_changes, lock_version, item, bid }. A line created by this request carries its operation's bid; other lines have bid: null. Ignore action_performed and has_changes on individual rows: action_performed is always CREATED and has_changes is always true. The has_changes next to data tells whether anything changed.
A new line is refused with HTTP 422 if the product or variant cannot be sold:
- Simple product phased out: 422
product_phased_out(error.product_idnames it) - Simple product deleted: 422
product_deleted(error.product_idnames it) - Size or color phased out: 422
variant_phased_out(error.variant_idnames it) - Size or color deleted: 422
variant_deleted(error.variant_idnames it)
This holds for quotes, published orders (Live Edit), and the public API alike. Resume the product, or its size or color, in Products to sell it again. Existing lines keep working. A refused batch writes none of its lines and names the refused line in error.bid.
Business rules
- The body is an array. Each operation needs
bidandaction(create,updateordelete).createandupdateneedpayload;updateanddeleteneedcart_item_id. - Deletes run first, then creates, then updates, whatever their order in the array.
- One refused operation refuses the whole batch: nothing is saved. Most refusals name the operation in
error.bid; a product that is not found (no envelope), aproduct.typechange, a storage range error (error.context.item_bid) and malformed operation fields (validation_failed,error.fieldslike0.bid) do not. - Every create and update follows the same rules as the single Add and Update operations. In particular a new catalog line needs its catalog cost in
pricing.catalogunless it is customer-supplied; without it the whole batch is refused withbulk_validation_payload_failed, naming the operation'sbidand "Enter the catalog cost for this line." onpricing.cataloginerror.fields. cart_item_idmust be a line of this order: otherwise "Order item not found".- Lines an integration brought in can't be created or deleted here.
Side effects
- Recalculates the line's price, every job's decoration pricing (quantity breaks count all lines on a job), the order totals, profit, margin and deposit.
- Updates stock tracking for the line (inventory status and stock workflow), and, on a published sales order, reserves or releases stock as quantities change.
- Updates this line on the order's invoices (new price, excess quantity removed); when the order keeps its invoice up to date automatically, rebuilds that invoice. Rebalances payments across the invoices.
- On a published sales order with QuickBooks Online connected, queues the order's QuickBooks sync.
- Refreshes the order for people who have it open in the web app. No email is sent.
- Recalculates everything once, after all operations.
Path parameters
Your team slug, shown as Team ID next to your API key in Profile.
- Example
your-team
- Example
The sales order's or quote's
id(a hash id), or itsunique_key(ord_…). The order number (scoped_id) does not work.- Example
V4keXwwxMQyXw7
- Example
Headers
save(what the web app sends): a batch that changes nothing writes nothing and answershas_changes: false(next todata).recalculate: always recalculate. Left out: the older behavior,has_changesalways true.- One of:
"save","recalculate" - Example
save
- One of:
Request body
application/json, required.
The body is an array of objects.
Each item is one of these 3 kinds, picked by action:
Add a linecreate
Adds a line. payload is the same body as Add a line item.
- Always
"create"
- Always
Your own id for this operation, unique in the request. The new line comes back with this
bid, and an error names it.Pick the branch by
product.type.One of, picked by
product.type:Catalog product
db_catalogAdd a product from a supplier catalog (one size and color).
What the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"db_catalog"
- Always
Child fields (3)
true when the customer provides the item and you only decorate it. The product price is then 0; the line still carries the decoration price. Only then may a new catalog line leave out
pricing.catalog. true, 1, "1" and "true" count as true.The catalog item: one size and color of a supplier style. It is the supplier code, a dash and the supplier's number, for example
smr-10001.descriptionstringExtra text shown under the line, for example a note about the color.
How the line is priced. YoPrint determines the product price in this order:
- Price override: if
product.overrideis true, YoPrint usesproduct.total. - Customer-supplied: if
customer_suppliedis true (product.properties.customer_supplied), the product price is 0. - Marked-up cost: otherwise, YoPrint takes the supplier cost in
catalogand applies the order's pricing group markup or a matching pricing rule.
A new catalog line must carry
catalogunlesscustomer_suppliedis true (without it, the line is refused with 422: "Enter the catalog cost for this line.").Child fields (4)
- Always
"catalog_product_pricing"
- Always
catalogobjectThe supplier price the line starts from. When you send
catalog, all four fields are required.Child fields (4)
When the price was looked up, an ISO 8601 date such as 2026-11-03 (a date-time is accepted too).
The supplier code, such as
smrorssa: the code the catalog item id starts with (smrforsmr-10001), and theproviderof that item in its product'sattr_data. YoPrint stores it as sent and doesn't check it against your suppliers.Which supplier price
totalrepresents:piece: standard piece pricedozen: dozen price tiercase: case price tieraccount: your account's negotiated price (your_pricein catalog lookups)sales: the supplier's sale price (sales_pricein catalog lookups)custom: a custom cost you entered manuallylegacy: lines migrated from the old editor
- One of:
"piece","dozen","case","account","sales","custom","legacy"
The supplier's cost for one unit.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
productobjectSet your own product price for one unit with
override: trueandtotal. It replaces the marked-up catalog cost.Child fields (2)
true to use
totalas given; false to let YoPrint work it out.totaldecimal pairThe amount for one unit, as a
{ value, dp }pair. Up to 6 decimal places are kept.- See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
- Price override: if
How many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
The quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
Which job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
Where the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.weightobjectOptional, used for shipping. Leave it out to use the product's weight.
One of, picked by
type:Use the product's weight
use_systemTake the weight from the product (in lb).
- Always
"use_system"
- Always
Set the weight
massYour own weight for one unit.
- Always
"mass"
- Always
The weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
- One of:
"lb","kg"
- One of:
Custom simple product
user_simpleAdd one of your own products that has no sizes or colors.
What the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"user_simple"
- Always
Child fields (3)
true when the customer provides the item and you only decorate it. The product price is then 0; the line still carries the decoration price.
The product's
idfrom Products.descriptionstringExtra text shown under the line, for example a note about the color.
How the line is priced. YoPrint determines the product price in this order:
- Price override: if
product.overrideis true, YoPrint usesproduct.total. - Customer-supplied: if
customer_suppliedis true (product.properties.customer_supplied), the product price is 0. - Product pricing: otherwise, YoPrint starts from
product_cost.total(or the price from Products when omitted or 0) and applies any matching pricing rule.
Child fields (4)
- Always
"product_cost_service"
- Always
productobjectSet your own product price for one unit with
override: trueandtotal.Child fields (2)
true to use
totalas given; false to let YoPrint work it out.totaldecimal pairThe amount for one unit, as a
{ value, dp }pair. Up to 6 decimal places are kept.- See Money and quantities.
product_costobjectYour cost for one unit. Optional: leave it out, or send a total of 0, to use the product's price from Products.
Child fields (2)
true when you set the cost yourself.
The cost for one unit. 0 means "use the product's price".
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
- Price override: if
How many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
The quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
Which job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
Where the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.weightobjectOptional, used for shipping. Leave it out to use the product's weight.
One of, picked by
type:Use the product's weight
use_systemTake the weight from the product (in lb).
- Always
"use_system"
- Always
Set the weight
massYour own weight for one unit.
- Always
"mass"
- Always
The weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
- One of:
"lb","kg"
- One of:
Custom variant product
db_variantAdd one size and color of your own product.
What the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"db_variant"
- Always
Child fields (3)
true when the customer provides the item and you only decorate it. The product price is then 0; the line still carries the decoration price.
The
idof one size and color (a variant) of your product, not the product's own id. Each size or color is its own line.descriptionstringExtra text shown under the line, for example a note about the color.
How the line is priced. YoPrint determines the product price in this order:
- Price override: if
product.overrideis true, YoPrint usesproduct.total. - Customer-supplied: if
customer_suppliedis true (product.properties.customer_supplied), the product price is 0. - Product pricing: otherwise, YoPrint starts from
product_cost.total(or the price from Products when omitted or 0) and applies any matching pricing rule.
Child fields (4)
- Always
"product_cost_service"
- Always
productobjectSet your own product price for one unit with
override: trueandtotal.Child fields (2)
true to use
totalas given; false to let YoPrint work it out.totaldecimal pairThe amount for one unit, as a
{ value, dp }pair. Up to 6 decimal places are kept.- See Money and quantities.
product_costobjectYour cost for one unit. Optional: leave it out, or send a total of 0, to use the product's price from Products.
Child fields (2)
true when you set the cost yourself.
The cost for one unit. 0 means "use the product's price".
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
- Price override: if
How many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
The quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
Which job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
Where the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.weightobjectOptional, used for shipping. Leave it out to use the product's weight.
One of, picked by
type:Use the product's weight
use_systemTake the weight from the product (in lb).
- Always
"use_system"
- Always
Set the weight
massYour own weight for one unit.
- Always
"mass"
- Always
The weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
- One of:
"lb","kg"
- One of:
Custom line item
customAdd a one-off line with a name and a price, not linked to a product.
What the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"custom"
- Always
Child fields (3)
true when the customer provides the item and you only decorate it. The product price is then 0; the line still carries the decoration price.
The line's name, as the customer sees it.
descriptionstringExtra text shown under the line, for example a note about the color.
How the line is priced. Send the unit price in
product.totalwithoverride: true.Child fields (4)
- Always
"custom_product"
- Always
The product price for one unit. With
override: true(what the web app sends) the line usestotal. Withoverridefalse or left out, YoPrint starts fromproduct_cost.total(ortotalwhen no cost is set) and applies any matching pricing rule.Child fields (2)
The price for one unit. Up to 6 decimal places are kept.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
overridebooleantrue to use
totalas the price.
product_costobjectOptional: your cost for one unit, used for profit and margin.
Child fields (1)
Your cost for one unit.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
How many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
The quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
Which job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
Where the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.weightobjectOptional, used for shipping. Leave it out for 0 lb.
Child fields (3)
- Always
"mass"
- Always
The weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
- One of:
"lb","kg"
- One of:
Fee line item
feeAdd a fee, such as a rush or setup fee.
What the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"fee"
- Always
Child fields (2)
The fee's name, for example "Rush fee".
descriptionstringExtra text shown under the fee, for example what it covers.
The fee amount for one unit. Fees never take a decoration price.
Child fields (2)
- Always
"fee"
- Always
Child fields (1)
The fee for one unit, 0 or more.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
How many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
The quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
Which job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
Where the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.weightobjectOptional, used for shipping. Leave it out for no weight.
Child fields (3)
- Always
"mass"
- Always
The weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
- One of:
"lb","kg"
- One of:
Change a lineupdate
Changes a line. payload is the same body as Update a line item: send only what changes.
- Always
"update"
- Always
Your own id for this operation, unique in the request. An error names it.
The line's
id(a hash id) from the order's line items. It must be a line of this order. (Itsorditm_unique key is also accepted, but no API answer shows it.)Send only what changes. Each object you send (
product,pricing,quantity,job,weight) must carry itstype, andproduct.typeandpricing.typemust stay the line's own. Fields you leave out keep their value.Any of, picked by
product.type:Catalog product
db_catalogChange a product from a supplier catalog (one size and color).
productobjectWhat the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"db_catalog"
- Always
propertiesobjectChild fields (1)
descriptionstringExtra text shown under the line, for example a note about the color.
jobobjectWhich job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
positionintegerWhere the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.pricingobjectHow the line is priced. YoPrint determines the product price in this order:
- Price override: if
product.overrideis true, YoPrint usesproduct.total. - Customer-supplied: if
customer_suppliedis true (product.properties.customer_supplied), the product price is 0. - Marked-up cost: otherwise, YoPrint takes the supplier cost in
catalogand applies the order's pricing group markup or a matching pricing rule.
On an update,
catalogis optional; send it to change the supplier cost.Child fields (4)
- Always
"catalog_product_pricing"
- Always
catalogobjectThe supplier price the line starts from. When you send
catalog, all four fields are required.Child fields (4)
When the price was looked up, an ISO 8601 date such as 2026-11-03 (a date-time is accepted too).
The supplier code, such as
smrorssa: the code the catalog item id starts with (smrforsmr-10001), and theproviderof that item in its product'sattr_data. YoPrint stores it as sent and doesn't check it against your suppliers.Which supplier price
totalrepresents:piece: standard piece pricedozen: dozen price tiercase: case price tieraccount: your account's negotiated price (your_pricein catalog lookups)sales: the supplier's sale price (sales_pricein catalog lookups)custom: a custom cost you entered manuallylegacy: lines migrated from the old editor
- One of:
"piece","dozen","case","account","sales","custom","legacy"
The supplier's cost for one unit.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
productobjectSet your own product price for one unit with
override: trueandtotal. It replaces the marked-up catalog cost.Child fields (2)
true to use
totalas given; false to let YoPrint work it out.totaldecimal pairThe amount for one unit, as a
{ value, dp }pair. Up to 6 decimal places are kept.- See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
- Price override: if
quantityobjectHow many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
totaldecimal pairThe quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
weightobjectOptional, used for shipping. Leave it out to use the product's weight.
One of, picked by
type:Use the product's weight
use_systemTake the weight from the product (in lb).
- Always
"use_system"
- Always
Set the weight
massYour own weight for one unit.
unitis required; leavetotalout to keep the current weight.- Always
"mass"
- Always
- One of:
"lb","kg"
- One of:
totaldecimal pairThe weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
Custom simple product
user_simpleChange one of your own products that has no sizes or colors.
productobjectWhat the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"user_simple"
- Always
propertiesobjectChild fields (1)
descriptionstringExtra text shown under the line, for example a note about the color.
jobobjectWhich job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
positionintegerWhere the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.pricingobjectHow the line is priced. YoPrint determines the product price in this order:
- Price override: if
product.overrideis true, YoPrint usesproduct.total. - Customer-supplied: if
customer_suppliedis true (product.properties.customer_supplied), the product price is 0. - Product pricing: otherwise, YoPrint starts from
product_cost.total(or the price from Products when omitted or 0) and applies any matching pricing rule.
Child fields (4)
- Always
"product_cost_service"
- Always
productobjectSet your own product price for one unit with
override: trueandtotal.Child fields (2)
true to use
totalas given; false to let YoPrint work it out.totaldecimal pairThe amount for one unit, as a
{ value, dp }pair. Up to 6 decimal places are kept.- See Money and quantities.
product_costobjectYour cost for one unit. Optional: leave it out, or send a total of 0, to use the product's price from Products.
Child fields (2)
true when you set the cost yourself.
The cost for one unit. 0 means "use the product's price".
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
- Price override: if
quantityobjectHow many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
totaldecimal pairThe quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
weightobjectOptional, used for shipping. Leave it out to use the product's weight.
One of, picked by
type:Use the product's weight
use_systemTake the weight from the product (in lb).
- Always
"use_system"
- Always
Set the weight
massYour own weight for one unit.
unitis required; leavetotalout to keep the current weight.- Always
"mass"
- Always
- One of:
"lb","kg"
- One of:
totaldecimal pairThe weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
Custom variant product
db_variantChange one size and color of your own product.
productobjectWhat the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"db_variant"
- Always
propertiesobjectChild fields (1)
descriptionstringExtra text shown under the line, for example a note about the color.
jobobjectWhich job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
positionintegerWhere the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.pricingobjectHow the line is priced. YoPrint determines the product price in this order:
- Price override: if
product.overrideis true, YoPrint usesproduct.total. - Customer-supplied: if
customer_suppliedis true (product.properties.customer_supplied), the product price is 0. - Product pricing: otherwise, YoPrint starts from
product_cost.total(or the price from Products when omitted or 0) and applies any matching pricing rule.
Child fields (4)
- Always
"product_cost_service"
- Always
productobjectSet your own product price for one unit with
override: trueandtotal.Child fields (2)
true to use
totalas given; false to let YoPrint work it out.totaldecimal pairThe amount for one unit, as a
{ value, dp }pair. Up to 6 decimal places are kept.- See Money and quantities.
product_costobjectYour cost for one unit. Optional: leave it out, or send a total of 0, to use the product's price from Products.
Child fields (2)
true when you set the cost yourself.
The cost for one unit. 0 means "use the product's price".
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
- Price override: if
quantityobjectHow many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
totaldecimal pairThe quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
weightobjectOptional, used for shipping. Leave it out to use the product's weight.
One of, picked by
type:Use the product's weight
use_systemTake the weight from the product (in lb).
- Always
"use_system"
- Always
Set the weight
massYour own weight for one unit.
unitis required; leavetotalout to keep the current weight.- Always
"mass"
- Always
- One of:
"lb","kg"
- One of:
totaldecimal pairThe weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
Custom line item
customChange a one-off line with a name and a price, not linked to a product.
productobjectWhat the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"custom"
- Always
propertiesobjectChild fields (2)
descriptionstringExtra text shown under the line, for example a note about the color.
namestringThe line's name, as the customer sees it.
jobobjectWhich job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
positionintegerWhere the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.pricingobjectHow the line is priced. Send the unit price in
product.totalwithoverride: true.Child fields (4)
- Always
"custom_product"
- Always
productobjectThe product price for one unit. With
override: true(what the web app sends) the line usestotal. Withoverridefalse or left out, YoPrint starts fromproduct_cost.total(ortotalwhen no cost is set) and applies any matching pricing rule.Child fields (2)
The price for one unit. Up to 6 decimal places are kept.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
overridebooleantrue to use
totalas the price.
product_costobjectOptional: your cost for one unit, used for profit and margin.
Child fields (1)
Your cost for one unit.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
serviceobjectThe decoration price added to each unit. Leave it out, or send
override: false, to use the job's decoration price per unit. Sendoverride: truewithtotalto set your own. Ignored when the line has no job (job.typestandalone).Child fields (2)
true to use
totalinstead of the job's decoration price.totaldecimal pairThe decoration price for one unit. Required when
overrideis true. Up to 6 decimal places.{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
quantityobjectHow many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
totaldecimal pairThe quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
weightobjectOptional, used for shipping.
Child fields (3)
- Always
"mass"
- Always
- One of:
"lb","kg"
- One of:
totaldecimal pairThe weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
Fee line item
feeChange a fee, such as a rush or setup fee.
productobjectWhat the line is.
typepicks the kind of line and can't change later.Child fields (2)
- Always
"fee"
- Always
propertiesobjectChild fields (2)
descriptionstringExtra text shown under the fee, for example what it covers.
namestringThe fee's name, for example "Rush fee".
jobobjectWhich job of this order the line belongs to. Decoration prices and quantity breaks count every line on a job, so put all sizes of a product on the same job.
One of, picked by
type:Linked to a job
linkedThe line belongs to one of this order's jobs and takes its decoration price.
- Always
"linked"
- Always
The job's
id, from the order's jobs. It must be a job of this same order.
positionintegerWhere the line sits on the order: lines are shown by ascending
position. The web app spaces lines 100000 apart, which leaves room to insert between them. A value outside the allowed range is replaced by the next free position at the end.pricingobjectThe fee amount for one unit. Fees never take a decoration price.
Child fields (2)
- Always
"fee"
- Always
productobjectChild fields (1)
The fee for one unit, 0 or more.
{ "value": 1250, "dp": 2 }is 12.50:valueholds the digits,dpthe decimal places. See Money and quantities.
quantityobjectHow many units.
typeis alwaysunit.Child fields (2)
- Always
"unit"
- Always
totaldecimal pairThe quantity as a
{ value, dp }pair: 24 is{ "value": 24, "dp": 0 }. Up to 8 decimal places.- See Money and quantities.
weightobjectOptional, used for shipping. Leave it out for no weight.
Child fields (3)
- Always
"mass"
- Always
- One of:
"lb","kg"
- One of:
totaldecimal pairThe weight as a
{ value, dp }pair whose two parts are strings: 1.5 is{ "value": "15", "dp": "1" }.- See Money and quantities.
Delete a linedelete
Deletes a line. A line that is already deleted is skipped without an error.
- Always
"delete"
- Always
Your own id for this operation, unique in the request. An error names it.
The line's
id(a hash id) from the order's line items. It must be a line of this order. (Itsorditm_unique key is also accepted, but no API answer shows it.)
More examples (1)
Add two sizes of a variant product to one job
curl -X POST 'https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/order_item/bulk' \ -H 'Authorization: Bearer YOUR_API_KEY' \ -H 'Accept: application/json' \ -H 'X-Yoprint-Decimal-Format: exact-v1' \ -H 'Content-Type: application/json' \ -d '[ { "action": "create", "bid": "b1", "payload": { "job": { "id": "K6iF8n29iwOZnj", "type": "linked" }, "position": 100000, "pricing": { "product": { "override": false }, "service": { "override": false }, "type": "product_cost_service" }, "product": { "properties": { "customer_supplied": false, "id": "TGbMAohWcL31V0" }, "type": "db_variant" }, "quantity": { "total": { "dp": 0, "value": 12 }, "type": "unit" } } }, { "action": "create", "bid": "b2", "payload": { "job": { "id": "K6iF8n29iwOZnj", "type": "linked" }, "position": 200000, "pricing": { "product": { "override": false }, "service": { "override": false }, "type": "product_cost_service" }, "product": { "properties": { "customer_supplied": false, "id": "ZrdJ9i78QVmdhr" }, "type": "db_variant" }, "quantity": { "total": { "dp": 0, "value": 18 }, "type": "unit" } } } ]'Response
200Successful response.
Every line of the order after the save.
Fields of each item (6)
object_typestring- Always
"order_item"
- Always
action_performedstringIgnore this field here: always
CREATEDin this answer.bidstring | nullYour
bidfor a line this request created; null for other lines.has_changesbooleanIgnore this field here: always
trueon every row. Read the top-levelhas_changesnext todata.itemobjectOne line. It has the request's groups (
product,pricing,quantity,job,weight,position) as saved, with the prices YoPrint worked out, and the same values again in_meta. A few groups differ from the request: the catalog cost comes back aspricing.catalog.costwith its date as a date-time, and a linkedjobalso has itsunique_keyandscoped_id(JOB-1001). Each group's_meta.editable_fields_on_updatelists the request paths an update accepts for that group (pricing.typeis listed, but it must stay the line's own).Child fields (16)
_metaobjectThe line's own values again (
id,type,order_id,unit_price,subtotaland so on). Always an object.idstringinventory_statusstring | nullStock status of the line.
jobobjectlock_versioninteger | nullThe line's own lock version (a microsecond timestamp).
order_idstringorder_unique_keystringThe order's
unique_key. The line's ownunique_keyis not in the answer: useid.positionintegerpricingobjectpricing_rule_appliedobject | nullThe pricing rule that set the line's product price, or null when no rule did. List the line items, Get one line item and the bulk save answer with the full summary below. Other answers carry only
type, the two ids and the two totals.Child fields (12)
afterstringFull summary only: the price after the rule, as a decimal string.
after_totaldecimal pairThe product price per unit after the rule. 6 decimal places. A decimal pair: the amount is
value÷ 10^dp({ "value": 1250, "dp": 2 }is 12.50). Readdpevery time: it can differ between fields and records.- See Money and quantities.
basestringFull summary only: that starting price, as a decimal string with at least 2 decimal places.
base_typestringFull summary only: what the rule started from: the supplier price for catalog lines, the product's own price for other lines.
- One of:
"supplier_price","base_price"
- One of:
normal_pricestring | nullFull summary only: what the line would cost with no rule. For catalog lines the supplier price plus the group's catalog markup as it is now; otherwise the same as
base.original_totaldecimal pairThe product price per unit before the rule. 6 decimal places. A decimal pair: the amount is
value÷ 10^dp({ "value": 1250, "dp": 2 }is 12.50). Readdpevery time: it can differ between fields and records.- See Money and quantities.
pricing_group_idstring | nullThe pricing group whose rule applied.
pricing_group_namestring | nullFull summary only: the group's name now.
pricing_group_removedboolean | nullFull summary only: true when the group was removed since. The line keeps its price.
pricing_rule_idstring | nullThe rule that applied.
ruleobject | nullFull summary only: the rule as the group holds it now, with its current name and position (1 is the first rule checked). Null when the rule no longer exists.
typestringproducton a line.
productobjectquantityobjectThe quantity, trailing zeros dropped: 10 is
{ "value": 10, "dp": 0 }.subtotaldecimal pairunit_pricetimes the quantity. 4 decimal places: 125.00 is{ "value": 1250000, "dp": 4 }. A decimal pair: the amount isvalue÷ 10^dp({ "value": 1250, "dp": 2 }is 12.50). Readdpevery time: it can differ between fields and records.- See Money and quantities.
trashedbooleantrue when the line was deleted.
typestringThe kind of line: db_catalog, user_simple, db_variant, custom or fee.
unit_pricedecimal pairThe price of one unit: the product price plus the decoration price. 6 decimal places: 12.50 is
{ "value": 12500000, "dp": 6 }. A decimal pair: the amount isvalue÷ 10^dp({ "value": 1250, "dp": 2 }is 12.50). Readdpevery time: it can differ between fields and records.- See Money and quantities.
lock_versionobjectThe order's lock versions after this call. Each is a whole number (a microsecond timestamp) that changes on every save, or null.
Child fields (1)
Child fields (6)
invoice_lock_versioninteger | nulljob_lock_versioninteger | nullorder_item_lock_versioninteger | nullorder_lock_versioninteger | nullThe order's own
lock_version.payment_lock_versioninteger | nullshipment_lock_versioninteger | null
false when the batch changed nothing (with the
saveintent).
Errors
401The API key is missing or wrong (
unauthenticated).403You are not allowed to do this.
api_access_not_in_plan: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only{"message": "Insufficient Permission"}. Other refusals use the error envelope, withunauthorizedoruser_is_not_authorized.- When
- The API key's role can't edit this order (
user_is_not_authorized). - Fix
- Ask the team owner for sales order edit permission, or assign the user to the order.
404Not found.
page_not_found: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's.code: null, with a message that starts "No query results for": there is no record with that id.- When
- The order or line does not exist in this team:
error.codeis null anderror.messagesays "No query results for …". - Fix
- Check the id.
422The request was refused and changed nothing.
validation_failedlists what to fix inerror.fields;bulk_validation_payload_failednames the failing item'sbidand itsfields.- When
- One operation is invalid (
bulk_validation_payload_failed, witherror.bidanderror.fields). - Fix
- Fix the operation named by
bidand resend the whole batch. - When
cart_item_idis not a line of this order:validation_error"Order item not found".- Fix
- Use line ids from this order.
- When
- A required field is missing, a
typevalue is unknown, or a{ value, dp }pair is malformed (for example sending{"value": 12.5, "dp": 1}instead of{"value": 125, "dp": 1}:valuemust be an integer). - Fix
- Read
error.fields; send whole numbers invalueand the decimal places indp(for example{"value": 1250, "dp": 2}for 12.50). - When
- The product, variant or catalog item id is not found. This error has no envelope: the body is
{"message": "user_simple: Simple Product not found:48213"}, where the number is YoPrint's internal number for the id you sent (db_variant: Variant Product not found:…the same way;db_catalog: Catalog Product not found:smr-10001repeats the catalog id). - Fix
- Use an id from Products, or a catalog item id.
- When
job.idis not a job of this order: "This job is no longer available. Choose a job from this order and save again."- Fix
- Use a job id from this order's jobs.
- When
- The job's decoration setup needs repair: "Review this job’s services before changing quantities or adding, removing or moving items." (
validation_error, witherror.fields.job.id, anderror.context.reasonjob_service_repair_requiredwitherror.context.job_idandjob_label). - Fix
- Fix the job's services in the web app, then retry.
- When
- The product, or its size or color, is phased out or deleted (
product_phased_out,product_deleted,variant_phased_out,variant_deleted). - Fix
- Resume it in Products, or choose another product.
- When
- A price, quantity or calculated total is out of range (
amount_out_of_range). - Fix
- Check the amount and its decimal places.
Notes
- Use this to add a product's whole size run in one save, so quantity breaks are worked out once.
- Resending the same batch adds the lines again: creates are not deduplicated by
bid. - Deleting a line that is already deleted counts as no change.
Related
- POSTAdd a line item to a sales order or quote
/v2/ api/ store/ {team_slug}/ v2/ sales_order/ {order_unique_key}/ order_item - PUTUpdate a line item
/v2/ api/ store/ {team_slug}/ v2/ sales_order/ order_item/ {order_item_unique_key} - DELETEDelete a line item
/v2/ api/ store/ {team_slug}/ v2/ sales_order/ order_item/ {order_item_unique_key} - GETList the line items of a sales order or quote
/v2/ api/ store/ {team_slug}/ v2/ sales_order/ {order_unique_key}/ order_item
