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

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger50Items per page (max 100)
statusstringFilter by status: pending, shipped, cancelled, or all
storeIdstringFilter by store ID
warehouseIdstringFilter by warehouse ID
searchstringSearch by order number, customer name, or email
dateFromstringOrders on or after this date (ISO 8601)
dateTostringOrders 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

FieldTypeRequiredDescription
storeIdstringyesThe store this order belongs to
orderNumberstringyesDisplay order number (e.g. "1042")
customerNamestringyesCustomer's full name
shippingAddressobjectyesShipping address — see below
customerEmailstringnoCustomer's email address
lineItemsarraynoOrder line items — see below
orderDatestringnoISO 8601 date (defaults to now)
notesstringnoInternal notes
tagsstring[]noTags for filtering
warehouseIdstringnoWarehouse to ship from
totalWeightnumbernoTotal weight in ounces
totalValuenumbernoTotal order value
weightOverrideOznumbernoOverride weight (oz) for rate calculation
lengthOverridenumbernoOverride length (inches)
widthOverridenumbernoOverride width (inches)
heightOverridenumbernoOverride height (inches)
externalIdstringnoUnique external ID (for idempotency)

Shipping Address Object:

FieldTypeRequired
namestringno
street1stringno
street2stringno
citystringno
statestringno
zipstringno
countrystringno (defaults to US)
phonestringno

The API validates that shippingAddress is present. Specific address fields are validated later when requesting rates or buying labels.

Line Item Object:

FieldTypeRequired
namestringyes
skustringno
quantityintegerno (defaults to 1)
weightnumberno
pricenumberno
imageUrlstringno

Idempotency

You can ensure requests are idempotent in two ways:

  1. externalId field — if an order with this ID already exists for the store, the existing order is returned.
  2. Idempotency-Key header — functions the same as externalId.

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

StatusCodeCause
400VALIDATION_ERRORMissing required fields or invalid data
404NOT_FOUNDStore or warehouse not found
409CONFLICTDuplicate 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

StatusCodeCause
403FORBIDDENOrder exists but belongs to another user
404NOT_FOUNDOrder does not exist

Update Order

PUT /api/v1/orders/:id

Updates an existing order. Only the provided fields are modified.

Updatable Fields

FieldTypeDescription
statusstringOrder status
notesstring | nullInternal notes
tagsstring[] | nullTags for filtering
shipByDatestring | nullShip-by date (ISO 8601)
shippingAddressobjectFull shipping address object
warehouseIdstring | nullWarehouse ID
weightOverrideOznumber | nullWeight override (oz)
lengthOverridenumber | nullLength override (in)
widthOverridenumber | nullWidth override (in)
heightOverridenumber | nullHeight 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

StatusCodeCause
400VALIDATION_ERRORInvalid request body or invalid shipByDate format
403FORBIDDENOrder exists but belongs to another user
404NOT_FOUNDOrder 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

StatusCodeCause
403FORBIDDENOrder exists but belongs to another user
404NOT_FOUNDOrder not found
409CONFLICTOrder has active (non-voided) shipments