Orders API

List, fetch, create, and cancel fulfillment orders.

Last updated May 8, 2026

Read, create, and cancel fulfillment orders. Orders are always created against a campaign, so a campaignId is required on create.

#Endpoints

  • GET /v1/orders/list — list fulfillment orders on the account.
  • GET /v1/orders/warehouses — list warehouses you can route to.
  • GET /v1/orders/{orderId} — get one order by id.
  • POST /v1/orders/create — create a fulfillment order from a campaign.
  • POST /v1/orders/cancel — cancel a fulfillment order.

#Authentication

Standard Bearer auth — see Authentication and API keys.

#List orders

GET /v1/orders/list

Query parameters:

  • limit (integer, default 20) — page size.
  • offset (integer, default 0) — number of records to skip.
  • campaignId (string, optional) — filter to orders for a single campaign.
  • orderStatus (string, optional) — AWAITING_SHIPMENT, SHIPPED, CANCELLED, or RETURNED.

Returns an array of order objects. Each element has the shape documented under Get one order below.

curl -X GET 'https://api.merch.com/v1/orders/list?limit=20&offset=0' \
  -H 'Authorization: Bearer <your_api_key>'

#Get one order

GET /v1/orders/{orderId}

Path parameter:

  • orderId (string, required) — the order's id.

Returns 404 { "message": "Order not found" } if no order exists for the id.

Response shape:

{
  "id": "<order_id>",
  "orderNumber": "ORD-12345",
  "sourceOrderNumber": null,
  "status": "AWAITING_SHIPMENT",
  "paymentStatus": "PAID",
  "allocationStatus": "ALLOCATED",
  "orderSource": "MANUAL_ORDER",
  "orderDate": "2026-05-01T14:22:00.000Z",
  "shipDate": null,
  "deliveredAt": null,
  "estimatedDelivery": null,
  "lastTrackingUpdate": null,
  "deliveryLocation": null,
  "deliveryDescription": null,
  "trackingNumber": null,
  "carrierCode": null,
  "campaignId": "<campaign_id>",
  "warehouse": "<warehouse_alias>",
  "recipient": {
    "firstName": "Ada",
    "lastName": "Lovelace",
    "email": "[email protected]",
    "phone": null,
    "street1": "1 Infinite Loop",
    "city": "Cupertino",
    "state": "CA",
    "postalCode": "95014",
    "country": "US"
  },
  "companyName": null,
  "notes": null,
  "products": [
    { "sku": "TEE-BLK-M", "title": "Logo Tee", "quantity": 1 }
  ],
  "addressVerificationStatus": "VERIFIED"
}

warehouse is the warehouse alias, not its id.

curl -X GET 'https://api.merch.com/v1/orders/<order_id>' \
  -H 'Authorization: Bearer <your_api_key>'

#Create an order

POST /v1/orders/create

Creates a fulfillment order against a campaign and a recipient.

Body:

{
  "campaignId": "<campaign_id>",
  "shipTo": {
    "firstName": "Ada",
    "lastName": "Lovelace",
    "email": "[email protected]",
    "phone": "+1-555-0100",
    "street1": "1 Infinite Loop",
    "street2": null,
    "city": "Cupertino",
    "state": "CA",
    "zip": "95014"
  },
  "products": [
    { "sku": "TEE-BLK-M", "quantity": 1 }
  ],
  "warehouseId": "<warehouse_id>",
  "createContactRecord": false
}

Field rules (validated server-side):

  • campaignId — required.
  • shipTo.firstName, shipTo.lastName — required, 1-100 chars.
  • shipTo.email — required, valid email, max 254 chars.
  • shipTo.phone — optional, max 30 chars.
  • shipTo.street1 — required, 1-200 chars.
  • shipTo.street2 — optional, max 200 chars.
  • shipTo.city, shipTo.state — required, 1-100 chars.
  • shipTo.zip — required, 1-20 chars.
  • products — array of at least one { sku, quantity }. The sku must match a SKU returned by GET /v1/products/list.
  • warehouseId — optional. Use one of the ids returned by GET /v1/orders/warehouses. If omitted, routing is decided server-side.
  • createContactRecord — optional, default false. Set true to also create a contact on the campaign for this recipient.

Success returns 201:

{
  "orderId": "<order_id>",
  "status": "AWAITING_SHIPMENT"
}

400 Bad Request if validation fails. The body includes the list of failing fields:

{
  "message": "Invalid request body",
  "errors": ["Required", "Invalid email"]
}
curl -X POST 'https://api.merch.com/v1/orders/create' \
  -H 'Authorization: Bearer <your_api_key>' \
  -H 'Content-Type: application/json' \
  -d '{
    "campaignId": "<campaign_id>",
    "shipTo": {
      "firstName": "Ada",
      "lastName": "Lovelace",
      "email": "[email protected]",
      "street1": "1 Infinite Loop",
      "city": "Cupertino",
      "state": "CA",
      "zip": "95014"
    },
    "products": [{ "sku": "TEE-BLK-M", "quantity": 1 }]
  }'

#Cancel an order

POST /v1/orders/cancel

Body:

{ "orderId": "<order_id>" }

Returns 201 on success (yes, 201, not 200):

{ "message": "Order cancelled successfully" }

400 Bad Request if the order is already cancelled, shipped, or delivered.

curl -X POST 'https://api.merch.com/v1/orders/cancel' \
  -H 'Authorization: Bearer <your_api_key>' \
  -H 'Content-Type: application/json' \
  -d '{ "orderId": "<order_id>" }'

#List warehouses

GET /v1/orders/warehouses

No parameters. Returns the warehouses your account can route to. Use id from this response as the warehouseId on POST /v1/orders/create.

[
  { "id": "<warehouse_id>", "name": "US East", "alias": "us-east" }
]
curl -X GET 'https://api.merch.com/v1/orders/warehouses' \
  -H 'Authorization: Bearer <your_api_key>'

#Status enums

The following enum values appear in order responses. Document them as-is — they are returned verbatim by the API.

#status — order lifecycle

| Value | Meaning | | --- | --- | | AWAITING_SHIPMENT | Order accepted, not yet handed to a carrier. | | SHIPPED | Order has left the warehouse. | | DELIVERED | Carrier has confirmed delivery. | | CANCELLED | Order was cancelled before shipment. | | RETURNED | Carrier reported the package as returned. |

#orderSource — how the order was placed

| Value | Meaning | | --- | --- | | REDEEM_PAGE | Recipient redeemed an invite. | | CSV_IMPORT | Bulk uploaded from a CSV. | | LANDING_PAGE | Submitted through a campaign landing page. | | MANUAL_ORDER | Created by hand in the customer portal. | | STANDALONE_ORDER | One-off order outside a normal campaign flow. | | SHOPIFY_STORE | Came from a connected Shopify store. | | EXTERNAL | Created via this API. |

#addressVerificationStatus — recipient address check

VERIFIED | CORRECTED | OVERRIDDEN | NEEDS_REVIEW | INVALID | UNVERIFIED | null

null means the order has not been through address verification yet.

#paymentStatus — billing state

UNPAID | PAID | null

null means the order is not subject to a separate payment record (for example, when billing rolls up to a parent invoice).

#allocationStatus — whether stock has been reserved for the shipment

UNALLOCATED | ALLOCATED | RESTOCKED | null

ALLOCATED means inventory has been reserved against the order. RESTOCKED means a previously-allocated shipment has been returned to stock.

#Errors

  • 400 Bad Request — validation failure on create (Invalid request body with an errors array) or attempting to cancel an order that is already cancelled, shipped, or delivered.
  • 401 Unauthorized — missing, malformed, or invalid bearer token. See Authentication and API keys.
  • 404 Not FoundGET /v1/orders/{orderId} only. Returned when the order does not exist or does not belong to your account.
  • 500 Internal Server Error — unexpected error. Body is a { "message": "..." } string. Retry after a short delay; if the failure persists, contact support.

Ready to elevate your merch?

Custom design, production, campaigns, and global fulfillment — one partner, zero platform fees. Your custom proposal in 24 hours.