Skip to content

Add a line item to a sales order or quote

Open .md

POST/v2/api/store/{team_slug}/v2/sales_order/{order_unique_key}/order_item

v2Operation ID v2_public_order_item_store

Adds one line to a sales order or quote and recalculates the order's totals. It works on drafts and on published orders (Live Edit). Sending the same request again adds the line again, so read the order back before you retry after a timeout.

What you send depends on what you add, chosen by product.type, which also fixes pricing.type:

You add product.type pricing.type You send
Catalog product db_catalog catalog_product_pricing the catalog item id and its supplier cost
Custom simple product user_simple product_cost_service your product's id
Custom variant product db_variant product_cost_service the id of one size and color
Custom line item custom custom_product a name and a price
Fee line item fee fee a name and an amount

Every line also needs quantity (type: "unit"), job (linked with a job id of this order, or standalone) and position. weight is optional.

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.

How the price is worked out. YoPrint determines the product price in this order:

  1. Price override: if pricing.product.override is true, it uses pricing.product.total.
  2. Customer-supplied: if the item is customer-supplied, the product price is 0.
  3. Cost and markup: otherwise, YoPrint starts from the cost (the catalog cost, your product_cost, or the product's price in Products) and applies the order's pricing group markup or a matching pricing rule.

The unit price adds the job's decoration price per unit (or pricing.service.total when service.override is true). The subtotal is the unit price multiplied by the quantity.

To add several lines at once, or a whole size run, use the bulk operation: it saves them together or not at all.

{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 is data.item, the saved line with its computed unit_price and subtotal, plus action_performed: "CREATED". Read the order to get its new totals.

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_id names it)
  • Simple product deleted: 422 product_deleted (error.product_id names it)
  • Size or color phased out: 422 variant_phased_out (error.variant_id names it)
  • Size or color deleted: 422 variant_deleted (error.variant_id names 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.

Permission

Needs permission to edit this sales order or quote:

  • The team owner
  • A role with update_all_order
  • A role with update_self_order, when the order was created by or is assigned to the API key's user
  • The person who created a draft, with create_order

Quotes use the same sales order permissions.

Business rules

  • product.type picks the kind of line; send the pricing.type that matches it: db_catalog takes catalog_product_pricing; user_simple and db_variant take product_cost_service; custom takes custom_product; fee takes fee. YoPrint refuses a mismatch with 422 validation_failed (error.fields names pricing.type).
  • product.properties.customer_supplied is required for every kind except fees.
  • A new catalog line must carry its catalog cost in pricing.catalog (provider, selected, date and total, all four required). Without it the line is refused with 422 validation_failed and error.fields pricing.catalog: "Enter the catalog cost for this line." The only exception is a line the customer supplies (product.properties.customer_supplied true, 1, "1" or "true"): it needs neither pricing.catalog nor pricing.product.
  • A line linked to a job must use a job of the same order. A line with job.type standalone has no decoration price.
  • A custom line needs pricing.product.total; a fee needs pricing.product.total of 0 or more.
  • A phased-out or deleted product, size or color can't be added.
  • position is a whole number. weight.total takes its value and dp as strings.
  • Lines that an integration brought in can't be created through the API (is_external is refused).

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.

Path parameters

  • team_slugstringrequired

    Your team slug, shown as Team ID next to your API key in Profile.

    • Example your-team
  • order_unique_keystringrequired

    The sales order's or quote's id (a hash id), or its unique_key (ord_…). The order number (scoped_id) does not work.

    • Example V4keXwwxMQyXw7

Request body

application/json, required.

What are you adding?

Send one of these 5 bodies. Picked by product.type.

db_catalog
Catalog product

Catalog product

Add a product from a supplier catalog (one size and color).

  • productobjectrequired

    What the line is. type picks the kind of line and can't change later.

    Child fields (2)
    • typestringrequired
      • Always "db_catalog"
    • propertiesobjectrequired
      Child fields (3)
      • customer_suppliedbooleanrequired

        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.

      • idstringrequired

        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.

      • Extra text shown under the line, for example a note about the color.

  • pricingobjectrequired

    How the line is priced. YoPrint determines the product price in this order:

    1. Price override: if product.override is true, YoPrint uses product.total.
    2. Customer-supplied: if customer_supplied is true (product.properties.customer_supplied), the product price is 0.
    3. Marked-up cost: otherwise, YoPrint takes the supplier cost in catalog and applies the order's pricing group markup or a matching pricing rule.

    A new catalog line must carry catalog unless customer_supplied is true (without it, the line is refused with 422: "Enter the catalog cost for this line.").

    Child fields (4)
    • typestringrequired
      • Always "catalog_product_pricing"
    • catalogobject

      The supplier price the line starts from. When you send catalog, all four fields are required.

      Child fields (4)
      • datestring (date)required

        When the price was looked up, an ISO 8601 date such as 2026-11-03 (a date-time is accepted too).

      • providerstringrequired

        The supplier code, such as smr or ssa: the code the catalog item id starts with (smr for smr-10001), and the provider of that item in its product's attr_data. YoPrint stores it as sent and doesn't check it against your suppliers.

      • selectedstringrequired

        Which supplier price total represents:

        • piece: standard piece price
        • dozen: dozen price tier
        • case: case price tier
        • account: your account's negotiated price (your_price in catalog lookups)
        • sales: the supplier's sale price (sales_price in catalog lookups)
        • custom: a custom cost you entered manually
        • legacy: lines migrated from the old editor
        • One of: "piece", "dozen", "case", "account", "sales", "custom", "legacy"
      • totaldecimal pairrequired

        The supplier's cost for one unit.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
    • productobject

      Set your own product price for one unit with override: true and total. It replaces the marked-up catalog cost.

      Child fields (2)
      • overridebooleanrequired

        true to use total as given; false to let YoPrint work it out.

      • totaldecimal pair

        The amount for one unit, as a { value, dp } pair. Up to 6 decimal places are kept.

    • serviceobject

      The decoration price added to each unit. Leave it out, or send override: false, to use the job's decoration price per unit. Send override: true with total to set your own. Ignored when the line has no job (job.type standalone).

      Child fields (2)
      • overridebooleanrequired

        true to use total instead of the job's decoration price.

      • totaldecimal pair

        The decoration price for one unit. Required when override is true. Up to 6 decimal places.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
  • quantityobjectrequired

    How many units. type is always unit.

    Child fields (2)
    • typestringrequired
      • Always "unit"
    • totaldecimal pairrequired

      The quantity as a { value, dp } pair: 24 is { "value": 24, "dp": 0 }. Up to 8 decimal places.

  • jobobjectrequired

    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 joblinked

    The line belongs to one of this order's jobs and takes its decoration price.

    • typestringrequired
      • Always "linked"
    • idstringrequired

      The job's id, from the order's jobs. It must be a job of this same order.

    No jobstandalone

    The line has no job, so no decoration price.

    • typestringrequired
      • Always "standalone"
  • positionintegerrequired

    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.

  • weightobject

    Optional, used for shipping. Leave it out to use the product's weight.

    One of, picked by type:

    Use the product's weightuse_system

    Take the weight from the product (in lb).

    • typestringrequired
      • Always "use_system"
    Set the weightmass

    Your own weight for one unit.

    • typestringrequired
      • Always "mass"
    • totaldecimal pairrequired

      The weight as a { value, dp } pair whose two parts are strings: 1.5 is { "value": "15", "dp": "1" }.

    • unitstringrequired
      • One of: "lb", "kg"

Example request

curl
curl -X POST 'https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/order_item' \  -H 'Authorization: Bearer YOUR_API_KEY' \  -H 'Accept: application/json' \  -H 'X-Yoprint-Decimal-Format: exact-v1' \  -H 'Content-Type: application/json' \  -d '{    "job": {      "id": "K6iF8n29iwOZnj",      "type": "linked"    },    "position": 100000,    "pricing": {      "catalog": {        "date": "2026-11-03",        "provider": "smr",        "selected": "piece",        "total": {          "dp": 2,          "value": 450        }      },      "product": {        "override": false      },      "service": {        "override": false      },      "type": "catalog_product_pricing"    },    "product": {      "properties": {        "customer_supplied": false,        "id": "smr-10001"      },      "type": "db_catalog"    },    "quantity": {      "total": {        "dp": 0,        "value": 24      },      "type": "unit"    }  }'

Custom simple product

Add one of your own products that has no sizes or colors.

  • productobjectrequired

    What the line is. type picks the kind of line and can't change later.

    Child fields (2)
    • typestringrequired
      • Always "user_simple"
    • propertiesobjectrequired
      Child fields (3)
      • customer_suppliedbooleanrequired

        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.

      • idstringrequired

        The product's id from Products.

      • Extra text shown under the line, for example a note about the color.

  • pricingobjectrequired

    How the line is priced. YoPrint determines the product price in this order:

    1. Price override: if product.override is true, YoPrint uses product.total.
    2. Customer-supplied: if customer_supplied is true (product.properties.customer_supplied), the product price is 0.
    3. 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)
    • typestringrequired
      • Always "product_cost_service"
    • productobject

      Set your own product price for one unit with override: true and total.

      Child fields (2)
      • overridebooleanrequired

        true to use total as given; false to let YoPrint work it out.

      • totaldecimal pair

        The amount for one unit, as a { value, dp } pair. Up to 6 decimal places are kept.

    • Your 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)
      • overridebooleanrequired

        true when you set the cost yourself.

      • totaldecimal pairrequired

        The cost for one unit. 0 means "use the product's price".

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
    • serviceobject

      The decoration price added to each unit. Leave it out, or send override: false, to use the job's decoration price per unit. Send override: true with total to set your own. Ignored when the line has no job (job.type standalone).

      Child fields (2)
      • overridebooleanrequired

        true to use total instead of the job's decoration price.

      • totaldecimal pair

        The decoration price for one unit. Required when override is true. Up to 6 decimal places.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
  • quantityobjectrequired

    How many units. type is always unit.

    Child fields (2)
    • typestringrequired
      • Always "unit"
    • totaldecimal pairrequired

      The quantity as a { value, dp } pair: 24 is { "value": 24, "dp": 0 }. Up to 8 decimal places.

  • jobobjectrequired

    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 joblinked

    The line belongs to one of this order's jobs and takes its decoration price.

    • typestringrequired
      • Always "linked"
    • idstringrequired

      The job's id, from the order's jobs. It must be a job of this same order.

    No jobstandalone

    The line has no job, so no decoration price.

    • typestringrequired
      • Always "standalone"
  • positionintegerrequired

    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.

  • weightobject

    Optional, used for shipping. Leave it out to use the product's weight.

    One of, picked by type:

    Use the product's weightuse_system

    Take the weight from the product (in lb).

    • typestringrequired
      • Always "use_system"
    Set the weightmass

    Your own weight for one unit.

    • typestringrequired
      • Always "mass"
    • totaldecimal pairrequired

      The weight as a { value, dp } pair whose two parts are strings: 1.5 is { "value": "15", "dp": "1" }.

    • unitstringrequired
      • One of: "lb", "kg"

Example request

curl
curl -X POST 'https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/order_item' \  -H 'Authorization: Bearer YOUR_API_KEY' \  -H 'Accept: application/json' \  -H 'X-Yoprint-Decimal-Format: exact-v1' \  -H 'Content-Type: application/json' \  -d '{    "job": {      "id": "K6iF8n29iwOZnj",      "type": "linked"    },    "position": 200000,    "pricing": {      "product": {        "override": true,        "total": {          "dp": 2,          "value": 1250        }      },      "service": {        "override": false      },      "type": "product_cost_service"    },    "product": {      "properties": {        "customer_supplied": false,        "id": "nqSB3HG1O2u5Jg"      },      "type": "user_simple"    },    "quantity": {      "total": {        "dp": 0,        "value": 10      },      "type": "unit"    }  }'

Custom variant product

Add one size and color of your own product.

  • productobjectrequired

    What the line is. type picks the kind of line and can't change later.

    Child fields (2)
    • typestringrequired
      • Always "db_variant"
    • propertiesobjectrequired
      Child fields (3)
      • customer_suppliedbooleanrequired

        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.

      • idstringrequired

        The id of one size and color (a variant) of your product, not the product's own id. Each size or color is its own line.

      • Extra text shown under the line, for example a note about the color.

  • pricingobjectrequired

    How the line is priced. YoPrint determines the product price in this order:

    1. Price override: if product.override is true, YoPrint uses product.total.
    2. Customer-supplied: if customer_supplied is true (product.properties.customer_supplied), the product price is 0.
    3. 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)
    • typestringrequired
      • Always "product_cost_service"
    • productobject

      Set your own product price for one unit with override: true and total.

      Child fields (2)
      • overridebooleanrequired

        true to use total as given; false to let YoPrint work it out.

      • totaldecimal pair

        The amount for one unit, as a { value, dp } pair. Up to 6 decimal places are kept.

    • Your 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)
      • overridebooleanrequired

        true when you set the cost yourself.

      • totaldecimal pairrequired

        The cost for one unit. 0 means "use the product's price".

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
    • serviceobject

      The decoration price added to each unit. Leave it out, or send override: false, to use the job's decoration price per unit. Send override: true with total to set your own. Ignored when the line has no job (job.type standalone).

      Child fields (2)
      • overridebooleanrequired

        true to use total instead of the job's decoration price.

      • totaldecimal pair

        The decoration price for one unit. Required when override is true. Up to 6 decimal places.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
  • quantityobjectrequired

    How many units. type is always unit.

    Child fields (2)
    • typestringrequired
      • Always "unit"
    • totaldecimal pairrequired

      The quantity as a { value, dp } pair: 24 is { "value": 24, "dp": 0 }. Up to 8 decimal places.

  • jobobjectrequired

    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 joblinked

    The line belongs to one of this order's jobs and takes its decoration price.

    • typestringrequired
      • Always "linked"
    • idstringrequired

      The job's id, from the order's jobs. It must be a job of this same order.

    No jobstandalone

    The line has no job, so no decoration price.

    • typestringrequired
      • Always "standalone"
  • positionintegerrequired

    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.

  • weightobject

    Optional, used for shipping. Leave it out to use the product's weight.

    One of, picked by type:

    Use the product's weightuse_system

    Take the weight from the product (in lb).

    • typestringrequired
      • Always "use_system"
    Set the weightmass

    Your own weight for one unit.

    • typestringrequired
      • Always "mass"
    • totaldecimal pairrequired

      The weight as a { value, dp } pair whose two parts are strings: 1.5 is { "value": "15", "dp": "1" }.

    • unitstringrequired
      • One of: "lb", "kg"

Example request

curl
curl -X POST 'https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/order_item' \  -H 'Authorization: Bearer YOUR_API_KEY' \  -H 'Accept: application/json' \  -H 'X-Yoprint-Decimal-Format: exact-v1' \  -H 'Content-Type: application/json' \  -d '{    "job": {      "id": "K6iF8n29iwOZnj",      "type": "linked"    },    "position": 300000,    "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"    }  }'

Custom line item

Add a one-off line with a name and a price, not linked to a product.

  • productobjectrequired

    What the line is. type picks the kind of line and can't change later.

    Child fields (2)
    • typestringrequired
      • Always "custom"
    • propertiesobjectrequired
      Child fields (3)
      • customer_suppliedbooleanrequired

        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.

      • namestringrequired

        The line's name, as the customer sees it.

      • Extra text shown under the line, for example a note about the color.

  • pricingobjectrequired

    How the line is priced. Send the unit price in product.total with override: true.

    Child fields (4)
    • typestringrequired
      • Always "custom_product"
    • productobjectrequired

      The product price for one unit. With override: true (what the web app sends) the line uses total. With override false or left out, YoPrint starts from product_cost.total (or total when no cost is set) and applies any matching pricing rule.

      Child fields (2)
      • totaldecimal pairrequired

        The price for one unit. Up to 6 decimal places are kept.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
      • overrideboolean

        true to use total as the price.

    • Optional: your cost for one unit, used for profit and margin.

      Child fields (1)
      • totaldecimal pairrequired

        Your cost for one unit.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
    • serviceobject

      The decoration price added to each unit. Leave it out, or send override: false, to use the job's decoration price per unit. Send override: true with total to set your own. Ignored when the line has no job (job.type standalone).

      Child fields (2)
      • overridebooleanrequired

        true to use total instead of the job's decoration price.

      • totaldecimal pair

        The decoration price for one unit. Required when override is true. Up to 6 decimal places.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
  • quantityobjectrequired

    How many units. type is always unit.

    Child fields (2)
    • typestringrequired
      • Always "unit"
    • totaldecimal pairrequired

      The quantity as a { value, dp } pair: 24 is { "value": 24, "dp": 0 }. Up to 8 decimal places.

  • jobobjectrequired

    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 joblinked

    The line belongs to one of this order's jobs and takes its decoration price.

    • typestringrequired
      • Always "linked"
    • idstringrequired

      The job's id, from the order's jobs. It must be a job of this same order.

    No jobstandalone

    The line has no job, so no decoration price.

    • typestringrequired
      • Always "standalone"
  • positionintegerrequired

    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.

  • weightobject

    Optional, used for shipping. Leave it out for 0 lb.

    Child fields (3)
    • typestringrequired
      • Always "mass"
    • totaldecimal pairrequired

      The weight as a { value, dp } pair whose two parts are strings: 1.5 is { "value": "15", "dp": "1" }.

    • unitstringrequired
      • One of: "lb", "kg"

Example request

curl
curl -X POST 'https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/order_item' \  -H 'Authorization: Bearer YOUR_API_KEY' \  -H 'Accept: application/json' \  -H 'X-Yoprint-Decimal-Format: exact-v1' \  -H 'Content-Type: application/json' \  -d '{    "job": {      "id": "K6iF8n29iwOZnj",      "type": "linked"    },    "position": 400000,    "pricing": {      "product": {        "override": true,        "total": {          "dp": 2,          "value": 300        }      },      "product_cost": {        "total": {          "dp": 2,          "value": 120        }      },      "service": {        "override": false      },      "type": "custom_product"    },    "product": {      "properties": {        "customer_supplied": false,        "description": "Navy border",        "name": "Embroidered patch"      },      "type": "custom"    },    "quantity": {      "total": {        "dp": 0,        "value": 50      },      "type": "unit"    }  }'

Fee line item

Add a fee, such as a rush or setup fee.

  • productobjectrequired

    What the line is. type picks the kind of line and can't change later.

    Child fields (2)
    • typestringrequired
      • Always "fee"
    • propertiesobjectrequired
      Child fields (2)
      • namestringrequired

        The fee's name, for example "Rush fee".

      • Extra text shown under the fee, for example what it covers.

  • pricingobjectrequired

    The fee amount for one unit. Fees never take a decoration price.

    Child fields (2)
    • typestringrequired
      • Always "fee"
    • productobjectrequired
      Child fields (1)
      • totaldecimal pairrequired

        The fee for one unit, 0 or more.

        • { "value": 1250, "dp": 2 } is 12.50: value holds the digits, dp the decimal places. See Money and quantities.
  • quantityobjectrequired

    How many units. type is always unit.

    Child fields (2)
    • typestringrequired
      • Always "unit"
    • totaldecimal pairrequired

      The quantity as a { value, dp } pair: 24 is { "value": 24, "dp": 0 }. Up to 8 decimal places.

  • jobobjectrequired

    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 joblinked

    The line belongs to one of this order's jobs and takes its decoration price.

    • typestringrequired
      • Always "linked"
    • idstringrequired

      The job's id, from the order's jobs. It must be a job of this same order.

    No jobstandalone

    The line has no job, so no decoration price.

    • typestringrequired
      • Always "standalone"
  • positionintegerrequired

    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.

  • weightobject

    Optional, used for shipping. Leave it out for no weight.

    Child fields (3)
    • typestringrequired
      • Always "mass"
    • totaldecimal pairrequired

      The weight as a { value, dp } pair whose two parts are strings: 1.5 is { "value": "15", "dp": "1" }.

    • unitstringrequired
      • One of: "lb", "kg"

Example request

curl
curl -X POST 'https://secure.yoprint.com/v2/api/store/your-team/v2/sales_order/V4keXwwxMQyXw7/order_item' \  -H 'Authorization: Bearer YOUR_API_KEY' \  -H 'Accept: application/json' \  -H 'X-Yoprint-Decimal-Format: exact-v1' \  -H 'Content-Type: application/json' \  -d '{    "job": {      "type": "standalone"    },    "position": 500000,    "pricing": {      "product": {        "total": {          "dp": 2,          "value": 2500        }      },      "type": "fee"    },    "product": {      "properties": {        "name": "Rush fee"      },      "type": "fee"    },    "quantity": {      "total": {        "dp": 0,        "value": 1      },      "type": "unit"    }  }'

Response

200Successful response.

  • dataobjectrequired
    Child fields (5)
      • Always "order_item"
    • NONE when nothing changed.

      • One of: "CREATED", "UPDATED", "DELETED", "NONE"
    • itemobject

      One 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 as pricing.catalog.cost with its date as a date-time, and a linked job also has its unique_key and scoped_id (JOB-1001). Each group's _meta.editable_fields_on_update lists the request paths an update accepts for that group (pricing.type is listed, but it must stay the line's own).

      Child fields (16)
      • _metaobject

        The line's own values again (id, type, order_id, unit_price, subtotal and so on). Always an object.

      • idstring
      • inventory_statusstring | null

        Stock status of the line.

      • jobobject
      • lock_versioninteger | null

        The line's own lock version (a microsecond timestamp).

      • order_idstring
      • The order's unique_key. The line's own unique_key is not in the answer: use id.

      • positioninteger
      • pricingobject
      • The 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)
        • afterstring

          Full summary only: the price after the rule, as a decimal string.

        • after_totaldecimal pair

          The 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). Read dp every time: it can differ between fields and records.

        • basestring

          Full summary only: that starting price, as a decimal string with at least 2 decimal places.

        • base_typestring

          Full 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"
        • normal_pricestring | null

          Full 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 pair

          The 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). Read dp every time: it can differ between fields and records.

        • pricing_group_idstring | null

          The pricing group whose rule applied.

        • pricing_group_namestring | null

          Full summary only: the group's name now.

        • pricing_group_removedboolean | null

          Full summary only: true when the group was removed since. The line keeps its price.

        • pricing_rule_idstring | null

          The rule that applied.

        • ruleobject | null

          Full 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.

          Child fields (3)
        • typestring

          product on a line.

      • productobject
      • quantityobject

        The quantity, trailing zeros dropped: 10 is { "value": 10, "dp": 0 }.

      • subtotaldecimal pair

        unit_price times the quantity. 4 decimal places: 125.00 is { "value": 1250000, "dp": 4 }. A decimal pair: the amount is value ÷ 10^dp ({ "value": 1250, "dp": 2 } is 12.50). Read dp every time: it can differ between fields and records.

      • trashedboolean

        true when the line was deleted.

      • typestring

        The kind of line: db_catalog, user_simple, db_variant, custom or fee.

      • unit_pricedecimal pair

        The 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 is value ÷ 10^dp ({ "value": 1250, "dp": 2 } is 12.50). Read dp every time: it can differ between fields and records.

    • The 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)
  • statusintegerrequired
  • successbooleanrequired

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, with unauthorized or user_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.code is null and error.message says "No query results for …".
    Fix
    Check the id.
  • 422The request was refused and changed nothing. validation_failed lists what to fix in error.fields; other codes name a business rule, explained in error.message. A few checks answer with only {"message": "..."}. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer connect_timeout ("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.

    When
    A new catalog line (db_catalog) has no pricing.catalog and is not customer-supplied: validation_failed, with "Enter the catalog cost for this line." on pricing.catalog in error.fields. Nothing is saved.
    Fix
    Look up the supplier cost with the catalog pricing lookup and send it in pricing.catalog, or send customer_supplied: true when the customer provides the item.
    When
    A required field is missing, a type value is unknown, or a { value, dp } pair is malformed (for example sending {"value": 12.5, "dp": 1} instead of {"value": 125, "dp": 1}: value must be an integer).
    Fix
    Read error.fields; send whole numbers in value and the decimal places in dp (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-10001 repeats the catalog id).
    Fix
    Use an id from Products, or a catalog item id.
    When
    job.id is 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, with error.fields.job.id, and error.context.reason job_service_repair_required with error.context.job_id and job_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

  • Prices keep up to 6 decimal places and quantities up to 8. The product price is then rounded to 2 decimal places (3 when you give 3 or more).
  • A variant product has one line per size and color: send each variant's own id. Put a product's sizes on one job so quantity breaks apply.
  • Get a catalog item's current supplier cost from the catalog pricing lookup before adding it.
  • The order number (SO1001) is not an id here: use the order's id or unique_key.