Sales orders
A sales order records products or services that a customer has ordered and tracks how much has been invoiced, packed, and shipped. API v3 can create open sales orders, invoice or pack selected remaining quantities, mark packing fulfillments as shipped, update or delete eligible orders, and read visible sales orders with their current line items and fulfillment history.
The sales order object
| Field | Type | Description |
|---|---|---|
id | string | SalesBinder UUID for the sales order. |
object | string | Always sales_order. |
sales_order_number | integer | Account-local SalesBinder sales-order number. |
name | string or null | Optional sales-order name or reference. |
customer_id | string | UUID of the customer. |
customer_name | string or null | Customer name stored with the sales order. |
salesperson_id | string | UUID of the assigned SalesBinder user. |
location_id | string or null | UUID of the assigned inventory location. |
status_id | integer | Current SalesBinder sales-order status ID. |
status | string or null | Current status name. |
issue_date | string or null | Issue date in YYYY-MM-DD format. |
expiry_date | string or null | Expiry date in YYYY-MM-DD format. |
purchase_order_number | string or null | Customer-provided purchase-order number. |
attention | string or null | Attention or recipient information. |
shipping_address | string or null | Shipping address stored on the sales order. |
drop_shipped | boolean | Whether the sales order is drop-shipped. |
drop_ship_customer_id | string or null | UUID of the drop-ship customer when applicable. |
drop_ship_address | string or null | Drop-ship address when applicable. |
public_note | string or null | Customer-visible note. |
packing_list_note | string or null | Note intended for packing-list workflows. |
payment_terms | string or null | Payment terms stored on the sales order. |
subtotal | string | Subtotal excluding shipping and taxes, with four decimal places. |
shipping | string | Customer shipping charge, with four decimal places. |
tax | string | First tax total, with four decimal places. |
tax_2 | string | Second tax total, with four decimal places. |
total | string | Sales-order total including taxes, with four decimal places. |
amount_paid | string | Applied payment total, with four decimal places. |
amount_due | string | Remaining balance, with four decimal places. |
invoiced_percent | number or null | Percentage of the sales order invoiced. |
paid_percent | number or null | Percentage of the sales order paid. |
packed_percent | number or null | Percentage of the sales order packed. |
shipped_percent | number or null | Percentage of the sales order shipped. |
invoice_count | integer | Number of invoices currently associated with the sales order. |
created_at | string or null | Creation timestamp in ISO 8601 format. |
updated_at | string or null | Last-modified timestamp in ISO 8601 format. |
lines | array | Current line items. Included only when retrieving one sales order. |
Sales-order and line-item unit costs are not included in API v3 responses.
The sales order line object
| Field | Type | Description |
|---|---|---|
id | string | UUID of the sales-order line. |
object | string | Always sales_order_line. |
item_id | string or null | Inventory item UUID, or null for a service line. |
item_variation_location_id | integer or null | Selected variation-location identifier when applicable. |
name | string or null | Line-item name. |
description | string or null | Line-item description. |
quantity | number | Quantity ordered. |
quantity_invoiced | number | Quantity already invoiced. |
quantity_packed | number | Quantity already packed. |
quantity_shipped | number | Quantity already shipped. |
unit_id | integer or null | SalesBinder unit ID. |
unit_price | string | Unit selling price, with four decimal places. |
discount_percent | string | Line discount rate, with three decimal places. |
discounted_unit_price | string or null | Discounted unit price when one is stored. |
tax_rate | string | First tax rate, with three decimal places. |
tax_2_rate | string | Second tax rate, with three decimal places. |
subtotal | string | Line quantity multiplied by its effective unit price, with four decimal places. |
The fulfillment object
| Field | Type | Description |
|---|---|---|
id | string | UUID of the packing-list fulfillment. |
object | string | Always fulfillment. |
sales_order_id | string | UUID of the related sales order. |
packing_list_number | integer | Account-local packing-list number. |
status | string | packed until a shipped date is recorded, then shipped. |
units_packed | number | Total quantity represented by the packing snapshot. |
shipped_date | string or null | Shipment date in YYYY-MM-DD format. |
carrier | string or null | Manual or provider shipping carrier. |
tracking_number | string or null | Carrier tracking number. |
tracking_url | string or null | Public shipment-tracking URL. |
tracking_status | string or null | Latest stored provider tracking status. |
tracking_status_details | string or null | Latest stored provider tracking detail. |
estimated_delivery_date | string or null | Estimated delivery in YYYY-MM-DD format. |
tracking_updated_at | string or null | ISO 8601 timestamp of the latest tracking update. |
lines | array | Historical packed-line snapshot. |
lines[].sales_order_line_id | string | UUID of the sales-order line that was packed. |
lines[].quantity | number | Quantity packed for the line in this fulfillment. |
created_at | string or null | Creation timestamp in ISO 8601 format. |
updated_at | string or null | Last-modified timestamp in ISO 8601 format. |
Create a sales order
POST/api/v3/sales-orders
Required scope: sales_orders:write
Creates an open sales order assigned to the API key's current user. SalesBinder assigns the sales-order number and derives status, costs, totals, fulfillment quantities, and customer information server-side.
| Field | Type | Required | Description |
|---|---|---|---|
customer_id | string | Yes | UUID of an active customer in the current account. |
location_id | string | No | Inventory-location UUID. It must follow the user's location restriction, when one exists. |
name | string | No | Sales-order name or reference. |
issue_date | string | No | YYYY-MM-DD; defaults to the user's current local date. |
expiry_date | string | No | YYYY-MM-DD; cannot be before issue_date. |
purchase_order_number | string | No | Customer purchase-order reference. |
attention | string | No | Attention or recipient information. |
shipping_address | string | No | Shipping address for the order. |
public_note | string | No | Customer-visible note. |
packing_list_note | string | No | Note for packing-list workflows. |
payment_terms | string | No | Payment terms. Account defaults apply when omitted. |
shipping | number | No | Non-negative customer shipping charge. Defaults to 0. |
discount_percent | number | No | Order-wide discount from 0 through 100. |
lines | array | Yes | From 1 through 100 inventory or service lines. |
Inventory lines use item_id, optional item_variation_location_id, quantity, optional description, and optional tax rates. SalesBinder supplies the item's current selling price unless unit_price is provided and the user currently has permission to modify selling prices. Service lines omit item_id and require name and unit_price.
curl https://yourbusiness.salesbinder.com/api/v3/sales-orders \
-X POST \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: warehouse-order-2026-07-19-001" \
-d '{
"customer_id": "06be9b09-bb9c-4555-aa95-0629285ee050",
"location_id": "2e665b38-3a31-451f-a61e-e7da20e09b29",
"issue_date": "2026-07-19",
"shipping": 5,
"lines": [
{"item_id": "3f7cdc78-64e4-4897-b465-e9de6c14cdea", "quantity": 2},
{"name": "Setup", "quantity": 1, "unit_price": 50}
]
}'The response is the newly created sales order object with lines and HTTP status 201. Repeating the same request with the same short-lived Idempotency-Key returns the original response instead of creating a quick duplicate.
List sales orders
GET/api/v3/sales-orders
Required scope: sales_orders:read
Returns a page of visible sales orders ordered by sales-order number, newest first. Line items are omitted from list responses.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number. Defaults to 1. |
limit | integer | No | Records per page from 1 to 100. Defaults to 20. |
q | string | No | Searches customer name, customer purchase-order number, sales-order name, or an exact numeric sales-order number. |
customer_id | string | No | Returns sales orders for this customer UUID. |
status_id | integer | No | Returns sales orders with this status ID. |
location_id | string | No | Returns sales orders assigned to this inventory-location UUID. |
assigned_user_id | string | No | Returns sales orders assigned to this user UUID. This filter cannot expand the key user's visibility. |
issue_date_from | string | No | Includes sales orders issued on or after this YYYY-MM-DD date. |
issue_date_to | string | No | Includes sales orders issued on or before this YYYY-MM-DD date. |
expiry_date_from | string | No | Includes sales orders expiring on or after this YYYY-MM-DD date. |
expiry_date_to | string | No | Includes sales orders expiring on or before this YYYY-MM-DD date. |
curl "https://yourbusiness.salesbinder.com/api/v3/sales-orders?customer_id=06be9b09-bb9c-4555-aa95-0629285ee050&status_id=29&limit=20" \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Accept: application/json"{
"object": "list",
"url": "/api/v3/sales-orders",
"has_more": false,
"data": [
{
"id": "95000000-0000-4000-8000-000000000101",
"object": "sales_order",
"sales_order_number": 7002,
"name": "Warehouse restock",
"customer_id": "06be9b09-bb9c-4555-aa95-0629285ee050",
"customer_name": "Acme Customer",
"salesperson_id": "10f36523-23ef-442d-8d68-4aa206d93160",
"location_id": "2e665b38-3a31-451f-a61e-e7da20e09b29",
"status_id": 29,
"status": "Open",
"issue_date": "2026-07-01",
"expiry_date": "2026-08-01",
"purchase_order_number": "CUSTOMER-PO-7002",
"attention": "Receiving",
"shipping_address": "123 Customer Road",
"drop_shipped": false,
"drop_ship_customer_id": null,
"drop_ship_address": "",
"public_note": "Sales-order terms.",
"packing_list_note": "Pack carefully.",
"payment_terms": "Net 30",
"subtotal": "100.0000",
"shipping": "10.0000",
"tax": "5.5000",
"tax_2": "2.2000",
"total": "117.7000",
"amount_paid": "25.0000",
"amount_due": "92.7000",
"invoiced_percent": 50,
"paid_percent": 25,
"packed_percent": 50,
"shipped_percent": 25,
"invoice_count": 1,
"created_at": "2026-07-01T12:00:00+00:00",
"updated_at": "2026-07-02T12:00:00+00:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total_pages": 1,
"total_records": 1
}
}Retrieve a sales order
GET/api/v3/sales-orders/{sales_order_id}
Required scope: sales_orders:read
Returns one visible sales order and its current line items.
curl "https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101" \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Accept: application/json"The response uses the sales order object above and adds lines:
{
"id": "95000000-0000-4000-8000-000000000101",
"object": "sales_order",
"sales_order_number": 7002,
"customer_id": "06be9b09-bb9c-4555-aa95-0629285ee050",
"customer_name": "Acme Customer",
"status_id": 29,
"status": "Open",
"total": "117.7000",
"invoiced_percent": 50,
"packed_percent": 50,
"shipped_percent": 25,
"lines": [
{
"id": "95000000-0000-4000-8000-000000000201",
"object": "sales_order_line",
"item_id": "95000000-0000-4000-8000-000000000601",
"item_variation_location_id": null,
"name": "Warehouse supplies",
"description": "Sales-order line",
"quantity": 2,
"quantity_invoiced": 1,
"quantity_packed": 1,
"quantity_shipped": 0.5,
"unit_id": 1,
"unit_price": "50.0000",
"discount_percent": "10.000",
"discounted_unit_price": "45.0000",
"tax_rate": "5.000",
"tax_2_rate": "2.000",
"subtotal": "90.0000"
}
]
}A sales order outside the key user's account or assigned-user visibility is returned as a missing resource rather than revealing that the record exists.
List fulfillments for a sales order
GET/api/v3/sales-orders/{sales_order_id}/fulfillments
Required scope: sales_orders:read
Returns the sales order's packing lists with their historical packed-line quantities and current shipping or tracking state. Packing lists are ordered by number with the newest first and use the standard page-based list envelope.
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number. Defaults to 1. |
limit | integer | No | Records per page from 1 through 100. Defaults to 20. |
curl "https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/fulfillments?limit=20" \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Accept: application/json"{
"object": "list",
"url": "/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/fulfillments",
"has_more": false,
"data": [
{
"id": "95000000-0000-4000-8000-000000000401",
"object": "fulfillment",
"sales_order_id": "95000000-0000-4000-8000-000000000101",
"packing_list_number": 2,
"status": "shipped",
"units_packed": 1.5,
"shipped_date": "2026-07-20",
"carrier": "Canada Post",
"tracking_number": "TRACK-7002-2",
"tracking_url": "https://tracking.example/7002-2",
"tracking_status": "in_transit",
"tracking_status_details": "Package is moving",
"estimated_delivery_date": "2026-07-24",
"tracking_updated_at": "2026-07-20T14:30:00+00:00",
"lines": [
{
"sales_order_line_id": "95000000-0000-4000-8000-000000000201",
"quantity": 1.5
}
],
"created_at": "2026-07-20T12:00:00+00:00",
"updated_at": "2026-07-20T14:30:00+00:00"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total_pages": 1,
"total_records": 1
}
}The fulfillment object is the public representation of SalesBinder's packing-list record. status is packed until a shipped date is recorded and shipped afterward. Manual shipping details and provider-backed label or tracking updates converge on the same public carrier and tracking fields.
The lines array preserves what was packed, even if the current sales-order line later changes. The response includes only the fulfillment fields documented above.
The endpoint applies the same current account, live sales-order permission, and assigned-user visibility boundary as retrieving the sales order. An inaccessible sales order returns 404 resource_missing.
Create a packing fulfillment
POST/api/v3/sales-orders/{sales_order_id}/fulfillments
Required scope: sales_orders:pack
Creates one packing list from explicit remaining sales-order quantities and returns the new fulfillment object with 201 Created.
curl "https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/fulfillments" \
--request POST \
--header "Authorization: Bearer sb_live_your_api_key" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: pack-order-7002-1" \
--data '{
"lines": [
{
"id": "95000000-0000-4000-8000-000000000201",
"quantity": 1.5
}
]
}'lines must be a non-empty array of at most 100 entries. Each entry accepts only:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | UUID of one line on the sales order. Each line can appear once. |
quantity | number | Yes | Positive incremental quantity to pack. It cannot exceed the line's current unpacked quantity. |
Inventory lines are packable. Service lines are packable only when the account's packing-list service-item setting is enabled. Discount lines cannot be packed.
The account must have packing lists enabled, the sales order must remain open and visible, and the user must retain sales-order-modify permission and access to the order's inventory location. A closed or concurrently fully packed order returns 409 sales_order_pack_not_allowed; a line already fully packed at initial validation returns 409 sales_order_line_already_packed.
SalesBinder rechecks all submitted quantities and prevents concurrent requests from overpacking. The packing list, line quantities, and packed percentage are saved together or not at all. Packing does not change on-hand inventory quantity.
Use an optional Idempotency-Key when retrying the same logical packing operation. An identical retry within the short idempotency window returns the original 201 response without packing twice; reusing the key with different request data returns 409 idempotency_key_reused.
Shipping is intentionally separate. This endpoint does not accept a carrier, tracking number, shipped date, label, rate, or provider payload.
Mark a fulfillment as shipped
POST/api/v3/sales-orders/{sales_order_id}/fulfillments/{fulfillment_id}/ship
Required scope: sales_orders:ship
Marks one existing packing fulfillment as manually shipped and returns the updated fulfillment object with 200 OK. This endpoint records an existing shipment; it does not quote rates or purchase a shipping label.
curl "https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/fulfillments/95000000-0000-4000-8000-000000000401/ship" \
--request POST \
--header "Authorization: Bearer sb_live_your_api_key" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: ship-order-7002-pl-2" \
--data '{
"shipped_date": "2026-07-21",
"carrier": "Canada Post",
"tracking_number": "TRACK-7002-2",
"tracking_url": "https://tracking.example/7002-2",
"estimated_delivery_date": "2026-07-24"
}'| Field | Type | Required | Description |
|---|---|---|---|
shipped_date | string | No | Shipment date in YYYY-MM-DD format. Defaults to the API user's current local date. |
carrier | string | No | Shipping carrier, up to 60 characters. Omission preserves an existing value. |
tracking_number | string | No | Carrier tracking number, up to 60 characters. Omission preserves an existing value. |
tracking_url | string | No | HTTP or HTTPS tracking URL, up to 250 characters. Omission preserves an existing value. |
estimated_delivery_date | string | No | Estimated delivery in YYYY-MM-DD format. It cannot be before shipped_date. |
The account must have packing lists enabled, and the user must retain sales-order-modify permission, current sales-order visibility, and access to the order's inventory location. The fulfillment must belong to that sales order and account and must not already have a shipped date. Missing or inaccessible parents and fulfillments return 404 resource_missing; an already shipped fulfillment returns 409 sales_order_ship_not_allowed.
SalesBinder rechecks the fulfillment state and saves the shipped date, shipment fields, line-level shipped quantities, and order progress together. When automatic shipping notifications are enabled, SalesBinder sends the customer notification after the shipment is saved. Shipping activity is recorded automatically.
Carrier, tracking number, or tracking URL values already stored by a manual or provider workflow do not mark a fulfillment as shipped by themselves. Only shipped_date performs that transition. Omitted optional fields preserve those existing values.
Use an optional Idempotency-Key for safe retries. An identical retry during the short idempotency window returns the original 200 response even though the fulfillment is now shipped. Reusing the key with different request data returns 409 idempotency_key_reused.
List invoices for a sales order
GET/api/v3/sales-orders/{sales_order_id}/invoices
Required scopes: sales_orders:read and invoices:read
Returns invoices linked to one visible sales order, ordered by invoice number with the newest first. The endpoint uses the same page-based pagination as other API v3 collections.
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number. Defaults to 1. |
limit | integer | No | Records per page from 1 through 100. Defaults to 20. |
curl "https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/invoices?limit=20" \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Accept: application/json"{
"object": "list",
"url": "/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/invoices",
"has_more": false,
"data": [
{
"id": "95000000-0000-4000-8000-000000000701",
"object": "invoice",
"invoice_number": 1042,
"customer_id": "06be9b09-bb9c-4555-aa95-0629285ee050",
"status_id": 9,
"status": "Unpaid",
"total": "52.5000",
"amount_paid": "0.0000",
"amount_due": "52.5000"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total_pages": 1,
"total_records": 1
}
}The data array uses the compact invoice object without lines. Retrieve an invoice through GET/api/v3/invoices/{invoice_id} when its current lines are needed.
Both visibility boundaries apply independently. The sales order must be visible through the user's current sales-order permissions, and each returned invoice must be visible through the user's current invoice permissions. An inaccessible sales order returns 404 resource_missing; inaccessible linked invoices are omitted from the collection.
Create an invoice from a sales order
POST/api/v3/sales-orders/{sales_order_id}/invoice
Required scope: sales_orders:invoice
Creates an unpaid invoice from an open sales order. Send an empty JSON object to invoice every remaining quantity:
curl https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/invoice \
-X POST \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-order-7002-remaining" \
-d '{}'To create a partial invoice, provide one or more sales-order line IDs and the positive quantity to invoice now:
curl https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101/invoice \
-X POST \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: invoice-order-7002-partial-1" \
-d '{
"lines": [
{
"id": "95000000-0000-4000-8000-000000000201",
"quantity": 0.5
}
]
}'| Field | Type | Required | Description |
|---|---|---|---|
lines | array | No | Omit to invoice all remaining quantities. When supplied, include from 1 through 100 unique sales-order lines. |
lines[].id | string | Yes | ID of a non-discount line belonging to this sales order. |
lines[].quantity | number | Yes | Positive quantity to invoice now. It cannot exceed the line's remaining uninvoiced quantity. |
The response is the newly created invoice object with lines and HTTP status 201. SalesBinder copies the selected sales-order line details, shipping, customer, notes, payment terms, and applicable order-level discount into the invoice. The sales order's invoiced quantities, percentage, and invoice count are refreshed from its linked invoices.
This action requires the API scope above plus the user's current sales-order-modify and invoice-modify permissions. Account and assigned-user visibility still apply, and creating the invoice follows the account's current record limit.
Use a unique Idempotency-Key for each intended invoice. During the short replay window, an identical retry returns the original 201 response with Idempotent-Replayed: true. Reusing the key with a different body returns 409 Conflict.
The endpoint returns 409 sales_order_invoice_not_allowed for a closed sales order, 409 sales_order_already_invoiced when no invoiceable quantity remains, and 409 sales_order_line_already_invoiced when a selected line has no remaining quantity. Invalid, duplicate, discount, or excessive line quantities return 422 invalid_sales_order_invoice.
Update a sales order
PATCH/api/v3/sales-orders/{sales_order_id}
Required scope: sales_orders:write
Updates supported fields on an open sales order. Omitted fields retain their current values. Header fields remain editable after fulfillment begins; financial and line fields require a completely untouched order.
| Field | Type | Description |
|---|---|---|
name | string | Sales-order name or reference. |
issue_date | string | Non-empty date in YYYY-MM-DD format. |
expiry_date | string or null | Date in YYYY-MM-DD format. Send an empty string or null to clear it. |
purchase_order_number | string | Customer purchase-order reference. |
attention | string | Attention or recipient information. |
shipping_address | string | Shipping address for the order. |
public_note | string | Customer-visible note. |
packing_list_note | string | Note for packing-list workflows. |
payment_terms | string | Payment terms. |
shipping | number | Non-negative customer shipping charge. Only available before payment or fulfillment begins. |
discount_percent | number | Order-wide discount from 0 through 100. Only available before payment or fulfillment begins. |
lines | array | Complete replacement of 1 through 100 active lines. Only available before payment or fulfillment begins. |
When lines is supplied, each existing non-discount line may include its id to retain that line identifier. Omitted lines are permanently removed, and new lines omit id. Every supplied line must include the complete inventory or service-line data needed to rebuild it. Discount lines are server-managed and must be changed with discount_percent rather than included in lines.
curl https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101 \
-X PATCH \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: warehouse-order-header-2026-07-19-001" \
-d '{
"purchase_order_number": "CUSTOMER-PO-UPDATED",
"shipping": 12,
"discount_percent": 10,
"lines": [
{
"id": "95000000-0000-4000-8000-000000000201",
"item_id": "3f7cdc78-64e4-4897-b465-e9de6c14cdea",
"quantity": 3
},
{"name": "Updated setup", "quantity": 1, "unit_price": 75}
]
}'The response is the updated sales order object with lines. All updates preserve the sales-order number, status, customer, salesperson, location, fulfillment quantities, and document associations. Costs, taxes, discounts, weights, and totals are calculated server-side.
Line replacement and total recalculation are completed together. If any line fails to save, the order, its previous lines, and its previous totals remain unchanged. Reserved quantities may update shortly after a successful response; on-hand quantity does not change.
Repeating the same request with the same short-lived Idempotency-Key returns the original response without applying the update twice.
Delete a sales order
DELETE/api/v3/sales-orders/{sales_order_id}
Required scope: sales_orders:delete
Permanently deletes an open sales order and its lines when no related processing has begun.
curl https://yourbusiness.salesbinder.com/api/v3/sales-orders/95000000-0000-4000-8000-000000000101 \
-X DELETE \
-H "Authorization: Bearer sb_live_your_api_key" \
-H "Accept: application/json"{
"id": "95000000-0000-4000-8000-000000000101",
"object": "sales_order",
"deleted": true
}The endpoint returns 409 Conflict when the sales order is closed or has payments, invoices, purchase orders, packing lists, shipments, drop-shipping activity, or invoiced, packed, or shipped quantities. Deleting a sales order never deletes those related records. Delete access also follows the user's current SalesBinder delete permission and assigned-user visibility.
The sales order and its lines are deleted together. Reserved quantities may update shortly after the response; on-hand inventory quantity does not change.
Unsupported operations
API v3 does not allow changing a sales order's customer, salesperson, location, status, or document associations directly. Financial and line updates are unavailable after related processing begins. Deleting is limited to untouched open sales orders. Packing and manual shipping use dedicated fulfillment endpoints. API v3 does not support closing, reopening, provider-backed label purchases, shipment reversal, or crediting previously invoiced quantities. Unsupported fields and actions are rejected.
Sales orders can also be created from eligible estimates through POST/api/v3/estimates/{estimate_id}/convert-to-sales-order. That dedicated action preserves the source relationship and closes the estimate as part of the same operation.
Sales-order reads and header-only updates do not change reserved inventory or recalculate fulfillment percentages. After creation, estimate conversion, line replacement, or invoicing, related reserved-inventory values may update shortly after the response.