Orders
Create, list, update, and cancel orders. To ship an order, see Rates & Labels.
Order refund integrations must first call
GET /api/v1/orders/:id/refund-quote. For a partial merchandise refund, pass a
URL-encoded lineItems JSON array containing exact ShipWave
orderLineItemId/quantity pairs, then send the same array and
refundScope: "line_items" to POST /api/v1/orders/:id/cancel-or-refund. For a
full-order refund, send the full quantity of every listed line with
refundScope: "full_order"; incomplete full-order selections are rejected.
Omitting both retains compatibility as a full-order request. A partial scope
never cancels the order, and ShipWave stores the resolved scope in the refund
ledger before calling Shopify.
List Orders
GET /api/v1/orders
Returns a paginated list of orders for your account.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 50 | Items per page (max 100) |
status | string | — | Filter by status: pending, shipped, cancelled, or all |
storeId | string | — | Filter by store ID |
warehouseId | string | — | Filter by warehouse ID |
search | string | — | Search by order number, customer name, or email |
dateFrom | string | — | Orders on or after this date (ISO 8601) |
dateTo | string | — | Orders on or before this date (ISO 8601) |
Example
curl "https://shipwave.app/api/v1/orders?status=pending&limit=10" \
-H "Authorization: Bearer sw_live_abc123..."
const res = await fetch(
"https://shipwave.app/api/v1/orders?status=pending&limit=10",
{ headers: { Authorization: "Bearer sw_live_abc123..." } }
);
const { data, meta } = await res.json();
Response
{
"data": [
{
"id": "clx1abc2d3efg",
"storeId": "clw9store1",
"externalId": "shopify_12345",
"orderNumber": "1042",
"status": "pending",
"customerName": "Jane Smith",
"customerEmail": "jane@example.com",
"shippingAddress": {
"name": "Jane Smith",
"street1": "123 Main St",
"street2": "Apt 4B",
"city": "Austin",
"state": "TX",
"zip": "78701",
"country": "US"
},
"totalWeight": 32.5,
"weightOverrideOz": null,
"lengthOverride": null,
"widthOverride": null,
"heightOverride": null,
"totalValue": 149.99,
"requestedService": null,
"tags": ["priority"],
"notes": null,
"orderDate": "2026-02-18T14:30:00.000Z",
"shipByDate": "2026-02-20T00:00:00.000Z",
"createdAt": "2026-02-18T14:30:00.000Z",
"updatedAt": "2026-02-18T14:30:00.000Z",
"store": {
"id": "clw9store1",
"shopDomain": "myshop.myshopify.com",
"platform": "shopify"
},
"warehouse": {
"id": "clw9wh1",
"name": "Main Warehouse"
},
"lineItems": [
{
"id": "clx1item1",
"sku": "WIDGET-001",
"name": "Blue Widget",
"quantity": 2,
"weight": 16.0,
"price": 49.99,
"imageUrl": "https://cdn.shopify.com/s/files/1/image.jpg"
}
],
"shipments": []
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 47,
"totalPages": 5
}
}
Create Order
POST /api/v1/orders
Creates a new order. If an order with the same externalId already exists for the given store, the existing order is returned instead (idempotent).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
storeId | string | yes | The store this order belongs to |
orderNumber | string | yes | Display order number (e.g. "1042") |
customerName | string | yes | Customer's full name |
shippingAddress | object | yes | Shipping address — see below |
customerEmail | string | no | Customer's email address |
lineItems | array | no | Order line items — see below |
orderDate | string | no | ISO 8601 date (defaults to now) |
notes | string | no | Internal notes |
tags | string[] | no | Tags for filtering |
warehouseId | string | no | Warehouse to ship from |
totalWeight | number | no | Total weight in ounces |
totalValue | number | no | Total order value |
weightOverrideOz | number | no | Override weight (oz) for rate calculation |
lengthOverride | number | no | Override length (inches) |
widthOverride | number | no | Override width (inches) |
heightOverride | number | no | Override height (inches) |
externalId | string | no | Unique external ID (for idempotency) |
Shipping Address Object:
| Field | Type | Required |
|---|---|---|
name | string | no |
street1 | string | no |
street2 | string | no |
city | string | no |
state | string | no |
zip | string | no |
country | string | no (defaults to US) |
phone | string | no |
The API validates that shippingAddress is present. Specific address fields are validated later when requesting rates or buying labels.
Line Item Object:
| Field | Type | Required |
|---|---|---|
name | string | yes |
sku | string | no |
quantity | integer | no (defaults to 1) |
weight | number | no |
price | number | no |
imageUrl | string | no |
Idempotency
You can ensure requests are idempotent in two ways:
externalIdfield — if an order with this ID already exists for the store, the existing order is returned.Idempotency-Keyheader — functions the same asexternalId.
Example
curl -X POST https://shipwave.app/api/v1/orders \
-H "Authorization: Bearer sw_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"storeId": "clw9store1",
"orderNumber": "1043",
"customerName": "John Doe",
"customerEmail": "john@example.com",
"shippingAddress": {
"name": "John Doe",
"street1": "456 Oak Ave",
"city": "Portland",
"state": "OR",
"zip": "97201",
"country": "US"
},
"lineItems": [
{
"name": "Red Widget",
"sku": "WIDGET-002",
"quantity": 1,
"weight": 8.5,
"price": 29.99
}
],
"warehouseId": "clw9wh1",
"externalId": "my-system-order-1043"
}'
const res = await fetch("https://shipwave.app/api/v1/orders", {
method: "POST",
headers: {
Authorization: "Bearer sw_live_abc123...",
"Content-Type": "application/json",
},
body: JSON.stringify({
storeId: "clw9store1",
orderNumber: "1043",
customerName: "John Doe",
customerEmail: "john@example.com",
shippingAddress: {
name: "John Doe",
street1: "456 Oak Ave",
city: "Portland",
state: "OR",
zip: "97201",
country: "US",
},
lineItems: [
{ name: "Red Widget", sku: "WIDGET-002", quantity: 1, weight: 8.5, price: 29.99 },
],
warehouseId: "clw9wh1",
externalId: "my-system-order-1043",
}),
});
const { data } = await res.json(); // 201 Created
Response (201 Created)
Returns the full order object (same shape as the list response).
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | VALIDATION_ERROR | Missing required fields or invalid data |
| 404 | NOT_FOUND | Store or warehouse not found |
| 409 | CONFLICT | Duplicate externalId for this store |
Get Order
GET /api/v1/orders/:id
Returns a single order with full details including warehouse address, line items, and shipments.
Example
curl https://shipwave.app/api/v1/orders/clx1abc2d3efg \
-H "Authorization: Bearer sw_live_abc123..."
Errors
| Status | Code | Cause |
|---|---|---|
| 403 | FORBIDDEN | Order exists but belongs to another user |
| 404 | NOT_FOUND | Order does not exist |
Update Order
PUT /api/v1/orders/:id
Updates an existing order. Only the provided fields are modified.
Updatable Fields
| Field | Type | Description |
|---|---|---|
status | string | Order status |
notes | string | null | Internal notes |
tags | string[] | null | Tags for filtering |
shipByDate | string | null | Ship-by date (ISO 8601) |
shippingAddress | object | Full shipping address object |
warehouseId | string | null | Warehouse ID |
weightOverrideOz | number | null | Weight override (oz) |
lengthOverride | number | null | Length override (in) |
widthOverride | number | null | Width override (in) |
heightOverride | number | null | Height override (in) |
Example
curl -X PUT https://shipwave.app/api/v1/orders/clx1abc2d3efg \
-H "Authorization: Bearer sw_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"tags": ["rush", "fragile"],
"notes": "Customer requested gift wrap",
"shipByDate": "2026-02-22T00:00:00.000Z"
}'
const res = await fetch("https://shipwave.app/api/v1/orders/clx1abc2d3efg", {
method: "PUT",
headers: {
Authorization: "Bearer sw_live_abc123...",
"Content-Type": "application/json",
},
body: JSON.stringify({
tags: ["rush", "fragile"],
notes: "Customer requested gift wrap",
shipByDate: "2026-02-22T00:00:00.000Z",
}),
});
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid request body or invalid shipByDate format |
| 403 | FORBIDDEN | Order exists but belongs to another user |
| 404 | NOT_FOUND | Order or warehouse not found |
Cancel Order
DELETE /api/v1/orders/:id
Cancels an order by setting its status to cancelled.
You must void all active shipments before cancelling. If the order has non-voided shipments, the request will fail with a 409 CONFLICT.
Example
curl -X DELETE https://shipwave.app/api/v1/orders/clx1abc2d3efg \
-H "Authorization: Bearer sw_live_abc123..."
const res = await fetch("https://shipwave.app/api/v1/orders/clx1abc2d3efg", {
method: "DELETE",
headers: { Authorization: "Bearer sw_live_abc123..." },
});
const { data } = await res.json();
// { "id": "clx1abc2d3efg", "status": "cancelled" }
Response
{
"data": {
"id": "clx1abc2d3efg",
"status": "cancelled"
}
}
Errors
| Status | Code | Cause |
|---|---|---|
| 403 | FORBIDDEN | Order exists but belongs to another user |
| 404 | NOT_FOUND | Order not found |
| 409 | CONFLICT | Order has active (non-voided) shipments |