Skip to content

Change a purchase order's status

Open .md

PUT/v1/api/store/{team_slug}/purchase_order/{hash_id}/status

v1Operation ID v1_public_purchase_order_change_status

Moves a purchase order to another of the team's purchase order statuses and returns the purchase order, in the same shape as Get a purchase order.

This operation is kept for YoPrint's Zapier app, which uses this path, and its answer keeps the flat line fields Zapier reads: each line in items has product (type, with id or name), quantity, price and totals as plain values. The public API has no newer purchase order operations to use instead: creating, editing and receiving purchase orders are not part of it.

Moving it to the final status (type end) marks it complete. When it is delivered to a company location that holds stock, every line except fees must be fully received first: this operation does not receive anything. Any other status clears the completion date.

{hash_id} is the purchase order's id, not its number (PO0042).

Permission

Who can update it: the team owner; a role whose Manage Purchase Order level includes update_all_po, for any of the team's purchase orders; or one with update_self_po, only for purchase orders the API key's user created or is assigned to (any other purchase order answers 404).

Business rules

  • status_id must be a purchase order status of this team (role purchase_order): a sales order, job or shipment status is refused.
  • To move to the end status, a purchase order delivered to a company location that holds stock must have every live line except fees fully received (deleted and voided lines don't count), and that location must still be current (not deleted or replaced).
  • Sending the status it already has is accepted: it saves again and sends the webhook again.

Side effects

  • Sets the status and its change date; an end status also sets status_completion_date, any other clears it.
  • Sends the purchase_order.status_changed webhook on every call, even when the status didn't change.
  • When the status really changes, adds a status change to the purchase order's history.
  • Sends no email and does not sync to QuickBooks Online.

Path parameters

  • team_slugstringrequired

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

    • Example your-team
  • hash_idstringrequired

    The purchase order's id (not its number, such as PO0042). A hash id from an earlier answer; unique keys and document numbers (such as PO0042) don't work here.

    • Example EDhVUaC6jbLbed

Request body

application/json, required.

  • status_idstringrequired

    The id of one of the team's purchase order statuses, from List purchase order statuses.

Response

200Successful response.

  • dataobjectrequired
    Child fields (39)
    • calc_subtotalinteger | stringrequired

      The purchase order's subtotal. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

    • calc_taxinteger | stringrequired

      Its tax. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

    • calc_totalinteger | stringrequired

      Its total. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

    • idstringrequired

      The purchase order's id: use it in the path.

    • itemsarray of objectsrequired

      Every line of the purchase order, including deleted and voided ones: the rows don't say which.

      Fields of each item (11)
      • calc_subtotalinteger | stringrequired

        The line's subtotal as YoPrint stores it: usually price times the quantity ordered; on some older lines, times the quantity still to receive. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

      • calc_taxinteger | stringrequired

        The line's tax. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

      • calc_totalinteger | stringrequired

        calc_subtotal plus calc_tax. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

      • idstringrequired

        The line's id.

      • non_inventorybooleanrequired

        true for a line that doesn't track stock.

      • priceinteger | stringrequired

        The unit price. Thousandths, an older encoding: 10800 is 10.80. A whole number of thousandths comes back as a JSON integer; an amount finer than a thousandth comes back as a decimal string, such as "12656.3", whatever headers you send. Parse it as a decimal. See Money and quantities.

      • productobjectrequired

        What the line buys, flat. id is a catalog item id such as smr-10001 for db_catalog, or the hash id of your product or variant for db_simple, user_simple and db_variant; name is the line's own name for custom, fee, fees and customer_provide_product. Older lines can have cart_item or order_item, with that record's id. size and color appear only when the line has them.

        Child fields (5)
        • typestringrequired

          The product kind, such as db_catalog, user_simple, db_variant, custom or fee.

        • colorstring
        • idstring
        • namestring | null
        • sizestring
      • quantityinteger | stringrequired

        The quantity still to receive (ordered minus received), not the quantity ordered. A whole number is a JSON integer; a fraction is a decimal string, such as "1.25".

      • received_totalinteger | stringrequired

        The quantity received so far. A whole number is a JSON integer; a fraction is a decimal string, such as "1.25".

      • tax_totalinteger | stringrequired

        The line's own tax rate, used when tax_mode is line_level, as a percentage ×1000: 8000 is 8% (0 when the line has none). A rate that is not a whole number comes back as a decimal string.

      • positioninteger | string | null

        The line's place on the purchase order, or null. A whole number is a JSON integer; a fraction is a decimal string, such as "1.25".

    • scoped_idstringrequired

      The purchase order number people see, such as PO0042. Not an id.

    • status_idstring | nullrequired
    • trashedbooleanrequired
    • billing_addressobject | null

      The billing address.

      Child fields (33)
      • address1string | nullrequired
      • idstringrequired
      • is_current_sourcebooleanrequired

        False for deleted, replaced, Shopify or redacted addresses. Only current addresses can be picked for new documents or edited.

      • is_primarybooleanrequired
      • labelstring | nullrequired
      • revision_numberintegerrequired

        Goes up by one on every saved change. Send it back as base_revision_number when updating the address to protect against concurrent edits.

      • rolestringrequired

        billing or shipping for customer addresses.

      • trashedbooleanrequired
      • address2string | null
      • address_family_idstring | null

        Shared by an address and the copies made when it was edited after use.

      • citystring | null
      • countrystring | null
      • country_codestring | null
      • Customer addresses only: the customer's id.

      • external_typestring | null

        shopify for an address synced from Shopify.

      • hold_stockboolean

        Company locations only; false for customer addresses.

      • Company locations only; false for customer addresses.

      • True for an address synced from Shopify; such addresses are read-only.

      • nexusboolean

        Company locations only; false for customer addresses.

      • notestring | null
      • owner_idstring | null

        The owner's id: for a customer address, the customer's id (the same as customer_id).

      • customer for customer addresses.

        • One of: "customer", "team", "unknown"
      • True once YoPrint has checked the address with its address validator. postal_can_validate says whether it could be checked and postal_is_valid gives the result. Any edit resets it to false.

      • postcodestring | null
      • sourcestring

        customer for customer addresses.

        • One of: "customer", "company_location", "custom", "unknown"
      • statestring | null
      • state_codestring | null
      • superseded_atstring (date-time) | null
      • Set on an old copy: the address that replaced it.

      • True when a brand profile uses it as Ship From. Sent on lists, reads, updates and customer answers; not on create or set-primary.

    • billing_address_idstring | null
    • created_atstring (date-time) | null
    • created_bystring | null

      The team member who created it.

    • creatorobject | null

      The team member who created it: id, name, email, avatar_url, timezone and a few profile flags.

      Child fields (3)
    • A link that opens the purchase order in the document viewer, with the same kind of token.

    • due_datestring (date-time) | null
    • internal_notestring | null
    • true when the delivery address is not one of the team's company locations.

    • issue_datestring (date-time) | null
    • namestring | null
    • pdfarray of objects

      PDF links: the purchase order detail, its 4" x 6" label, and the team's custom purchase order templates. Each url carries a token like pdf_url.

      Fields of each item (3)
    • pdf_urlstring

      A link that downloads the purchase order PDF. Its token stops working 9,000 hours (about a year) after the answer was made, and anyone with the link can open the PDF: don't share it.

    • true when QuickBooks sync is off for this purchase order.

    • quickbook_last_error_syncstring (date-time) | null
    • quickbook_last_success_syncstring (date-time) | null
    • statusobject | null

      The purchase order's status, as List purchase order statuses returns it: id, role (purchase_order), type (start, pre_production, in_progress or end), label, customer_label, color, position and trashed.

      Child fields (4)
      • idstring
      • labelstring
      • rolestring
      • typestring
        • One of: "start", "pre_production", "in_progress", "end"
    • status_completion_datestring (date-time) | null

      When it was moved to its final (end) status; null otherwise.

    • status_last_change_datestring (date-time) | null
    • tagsarray of objects
      Fields of each item (3)
      • color_hexstring | nullrequired

        Such as #2563EB. Null for a tag saved without a color.

      • idstringrequired
      • namestringrequired
    • tax_modestring | null

      order_level: one tax_rate for the purchase order, and each line is taxable or not. line_level: each line has its own rate (tax_total).

    • tax_ratestring | null

      For order_level: the rate as a decimal string fraction with 6 decimals, "0.080000" is 8%. Null when not set.

    • teamobject

      Your team, as the shared purchase order answer carries it: id, name, slug, contact details, the public ids of its enabled payment gateways, and plan. Nothing here is specific to the purchase order.

    • updated_atstring (date-time) | null
    • vendorobject | null

      The vendor with its contacts, as Get a vendor returns it.

      Child fields (8)
    • vendor_idstring | null
    • vendor_notestring | null

      The note printed for the vendor.

    • versioninteger

      2 for purchase orders made in the current editor; 1 for older ones.

    • warehouseobject | null

      The delivery address, usually one of the team's company locations.

    • true when the delivery address is set and holds stock, so receiving adds stock there.

    • warehouse_idstring | null

      Where the goods are delivered.

  • 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
    Your role has no Manage Purchase Order permission to update. This 403 has a short body, {"message": "Insufficient Permission"}, with no success or error.
    Fix
    Ask a team owner for a Manage Purchase Order level that can update.
  • 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
    No live purchase order with this id in the team, or your role updates only purchase orders you created or are assigned to and this is not one of them. Nothing changes. error.code is null and error.message names the record type.
    Fix
    Check the id, or ask to be assigned to the purchase order.
  • 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
    status_id is missing or is not an id. error.code is validation_failed.
    Fix
    Send the id of a purchase order status.
    When
    status_id is not one of this team's purchase order statuses (error.code validation_error, "Invalid status_id for purchase order").
    Fix
    Pick a status from List purchase order statuses.
    When
    Moving to the end status while lines are still to be received ("Purchase Order cannot be completed without receiving all the items"), or while the delivery location is no longer current ("Purchase Order cannot be completed with an inactive warehouse location"). error.code is validation_error; nothing changes.
    Fix
    Receive the remaining items in YoPrint first, or pick a status that is not end.