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": "ada@example.com",
    "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": "ada@example.com",
    "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": "ada@example.com",
      "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 build your merch?

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

Create an account to browse, design, and request orders right away. A discovery call with your rep completes onboarding.