# Update Purchase Orders Update existing purchase orders to modify product quantities, change delivery dates, or add tracking information. ShipStation provides three endpoints for updates: - **PUT** `/v2/purchase_orders/{purchase_order_id}` - Update all order details (only available in **draft** status) - **POST** `/v2/purchase_orders/{purchase_order_id}/shipping_details` - Update shipping-related details (only available in **open** status) - **POST** `/v2/purchase_orders/{purchase_order_id}/status` - Update only the status ## Update Purchase Order Details (Draft Status Only) Use the PUT method to update all details of a purchase order that is in `draft` status. This includes modifying products, dates, tracking, and all other information. Once a purchase order moves to **open** status or beyond, you cannot use this endpoint. For purchase orders in **open** status, use the POST endpoint described below to update shipping-related details only. ### Path Parameters | Parameter | Type | Description | | --- | --- | --- | | `purchase_order_id` | *string* | The unique identifier of the purchase order to update | ### Request Body Properties All fields can be updated when the purchase order is in **draft** status. | Property | Type | Required | Description | | --- | --- | --- | --- | | `supplier_id` | *string* | **Required** | Identifier for the supplier providing the products | | `warehouse_id` | *string* | **Required** | Identifier for the warehouse where products will be received | | `products` | *array* | **Required** | Array of products to order (must contain at least one product) | | `order_date` | *string* (date-time) | Optional | Date when the order was placed | | `expected_delivery_date` | *string* (date-time) | Optional | Expected delivery date | | `payment_terms` | *enumerated string* | Optional | Payment terms: `none`, `cash_on_delivery`, `payment_on_receipt`, `payment_in_advance`, `net_7`, `net_15`, `net_30`, `net_45`, `net_60` | | `payment_status` | *enumerated string* | Optional | Payment status: `none`, `unpaid`, `partially_paid`, `paid`, `refunded`, `credit_issued`, `other` | | `currency_code` | *string* | Optional | ISO 4217 currency code | | `shipping_carrier` | *string* | Optional | Shipping carrier name | | `tracking_number` | *string* | Optional | Tracking number from supplier | | `reference_number` | *string* | Optional | Your custom reference number | | `note_to_supplier` | *string* | Optional | Notes or special instructions | ### Product Properties Each product in the `products` array must include: | Property | Type | Required | Description | | --- | --- | --- | --- | | `sku` | *string* | **Required** | Stock Keeping Unit identifier | | `quantity` | *integer* | **Required** | Quantity to order (minimum: 1) | | `supplier_sku` | *string* | Optional | Supplier's SKU for this product | | `cost` | *number* | Optional | Unit cost of the product (minimum: 0) | ### Example Request & Response **PUT /v2/purchase_orders/{purchase_order_id}** ## Update Shipping Details (Open Status Only) Use the POST `/v2/purchase_orders/{purchase_order_id}/shipping_details` method to update shipping-related details for a purchase order in `open` status. This allows you to modify delivery dates, tracking information, and other shipping details after the order has been sent to the supplier. Once a purchase order moves to receiving, received, cancelled, or closed status, updating is no longer allowed. ### Path Parameters | Parameter | Type | Description | | --- | --- | --- | | `purchase_order_id` | *string* | The unique identifier of the purchase order to update | ### Request Body Properties Only the following shipping-related fields can be updated when the purchase order is in **open** status: | Property | Type | Required | Description | | --- | --- | --- | --- | | `expected_delivery_date` | *string* (date-time) | Optional | Expected delivery date | | `payment_terms` | *enumerated string* | Optional | Payment terms: `none`, `cash_on_delivery`, `payment_on_receipt`, `payment_in_advance`, `net_7`, `net_15`, `net_30`, `net_45`, `net_60` | | `payment_status` | *enumerated string* | Optional | Payment status: `none`, `unpaid`, `partially_paid`, `paid`, `refunded`, `credit_issued`, `other` | | `currency_code` | *string* | Optional | ISO 4217 currency code | | `shipping_carrier` | *string* | Optional | Shipping carrier name | | `tracking_number` | *string* | Optional | Tracking number from supplier | | `reference_number` | *string* | Optional | Your custom reference number | | `order_date` | *string* (date-time) | Optional | The date the order was placed | | `note_to_supplier` | *string* | Optional | A note or message to the supplier | ### Example Request & Response **POST /v2/purchase_orders/{purchase_order_id}/shipping_details** ## Update Purchase Order Status Use the POST method to update only the status of a purchase order. This is useful for workflow management without modifying other details. ### Path Parameters | Parameter | Type | Description | | --- | --- | --- | | `purchase_order_id` | *string* | The unique identifier of the purchase order | ### Request Body | Property | Type | Description | | --- | --- | --- | | `status` | *enumerated string* | New status: `open`, `receiving`, `received`, `cancelled`, `closed` | ### Valid Status Transitions Purchase orders follow specific status transition rules: | From Status | Can Transition To | Use Case | | --- | --- | --- | | `draft` | `open`, `cancelled` | Send order to supplier or cancel before ordering | | `open` | `receiving`, `cancelled` | Begin receiving products or cancel the order | | `receiving` | `received`, `cancelled` | Complete receiving or cancel partial shipment | | `received` | `closed` | Terminal state - all products received | | `closed` | *(none)* | Terminal state - order completed | | `cancelled` | *(none)* | Terminal state - order cancelled | ### Example Request & Response **POST /v2/purchase_orders/{purchase_order_id}/status** ## Error Handling Common errors when updating purchase orders: - **400 Bad Request**: Missing required fields or invalid data format - Invalid status transition (e.g., trying to go from `received` to `open`) - Invalid enum values - **404 Not Found**: Purchase order ID doesn't exist ### Invalid Status Transitions If you attempt an invalid status transition, you'll receive a 422 error. For example: ```json { "request_id": "aa3d8e8e-462b-4476-9618-72db7f7b7009", "errors": [ { "error_source": "Shipengine", "error_type": "validation", "error_code": "invalid_status", "message": "Cannot transition from 'received' to 'open'" } ] } ``` Always check the current status before attempting to update it, and follow the valid transition rules listed above.