Order Intake API — Developer Guide

Updated 10/26/202610 min read

The Order Intake API lets an order platform (a checkout, CRM or call-center system) send orders to a warehouse that runs on Warehance and read status and tracking back. Your platform pushes each order to Warehance, the warehouse picks, packs and ships it, and your platform polls Warehance for the shipment and tracking number.

This guide is for developers building or maintaining that connection. It covers authentication, every endpoint, the recommended workflow, and the edge cases you need to handle.

If your platform already sends orders to a fulfillment house over an API with these paths (/stores/{store_id}/orders/new.json, /shipments.json and so on), it works with Warehance unchanged. Point it at the Warehance Base URL and use the credentials the warehouse gives you.

How It Works

  • You push orders. Warehance never pulls from your platform. Each new order is one POST to Warehance.
  • The warehouse fulfills them. The order lands in the warehouse's Warehance account like any other store order, where its usual rules, holds and routing apply.
  • You poll for tracking. Warehance doesn't call your platform back. Read shipments from Warehance on a schedule and write the tracking into your platform.
  • Edits are allowed until work starts. You can change the address, items or cancel the order while its status is unverified. Once the warehouse starts working on it, edits are refused.
StepRequestPurpose
Send an orderPOST /orders/new.jsonCreate the order in Warehance
Change itPUT /orders/{id}/update.json, item endpoints, DELETE /orders/{id}.jsonEdit or cancel while still unverified
Read itGET /orders/{id}.json, GET /orders.jsonStatus, items and shipments
Get trackingGET /shipments.json?updated_at_start=…New shipments since your last poll

Get Your Credentials

The warehouse creates the connection in Warehance and gives you four values. Each store you connect has its own set.

ValueExampleUsed as
Base URLhttps://app.warehance.com/api/v1/fulfillment-api/apiPrefix for every request
Usernameapi-1a2b3c4d5e6f7a8b@stores.warehance.comHTTP Basic username
API Key48 charactersHTTP Basic password
Store ID7f3c2a10-5b8e-4d21-9c6f-2e4a8b9d0c11{store_id} in every path

For the warehouse: set up the store

Step 1: In Warehance, go to Stores. Under Connect Store, click Connect on your platform (for example BuyGoods or HelpGrid).

Step 2: Enter a Store Name (and choose the Client, if you're a 3PL), then pick how to get credentials:

  • New connection: Warehance generates the username and store ID.
  • Moving an existing store: enter the Store ID, Username and API Key the platform already sends to its current fulfillment house. The platform then only changes its URL. The Store ID must be a UUID, and the same credentials can't be used on two Warehance stores.

Step 3: Open the store. The General settings tab shows the Base URL, Username and Store ID. For a new connection, click Generate API Key.

Step 4: Copy the key from the dialog and send all four values to the platform securely. Warehance shows the key only once. Afterwards the page shows only its last four characters.

Regenerate API Key replaces the key immediately. The old key stops working right away, so the platform can't send orders until it has the new one. The username and store ID don't change.

Authentication

Every request uses HTTP Basic authentication with the username and API key, and includes the store ID in the path:

GET https://app.warehance.com/api/v1/fulfillment-api/api/stores/{store_id}/orders.json
Authorization: Basic base64(username:api_key)
SituationResponse
Missing, unknown or wrong credentials401 with an empty body and WWW-Authenticate: Basic realm="API Authorization"
No API key generated yet401 (as above)
Store deactivated in Warehance401 (as above), until the warehouse reactivates it
Correct credentials, wrong {store_id}404 {"errors": ["Please check your store number"]}
A 401 never has a JSON body. Check the status code before parsing.

Conventions

  • Paths. Every path works with or without .json: /orders/new.json and /orders/new are the same endpoint.
  • IDs are strings. Order, shipment and item IDs are JSON strings, even when they look numeric.
  • Request bodies. You can wrap the body ({"order": {...}}, {"order_item": {...}}) or send the fields at the top level.
  • Flexible types. Text fields also accept numbers, so "order_number": 10001 works. Quantities also accept numeric strings.
  • Content type. Send Content-Type: application/json.

Create an Order

POST /stores/{store_id}/orders/new.json
{
  "order": {
    "order_number": "10001",
    "order_date": "2026-10-26T14:30:00Z",
    "requested_shipping_service": "Standard",
    "ship_name": "Jane Doe",
    "address1": "1600 SW 4th Ave",
    "address2": "Suite 300",
    "city": "Portland",
    "state": "OR",
    "postal_code": "97201",
    "country": "US",
    "phone": "555-010-0000",
    "email": "jane@example.com",
    "items": [
      {"sku": "TEA-001", "quantity": 2},
      {"sku": "MUG-RED", "quantity": 1}
    ]
  }
}
FieldRequiredNotes
order_numberYesYour order number. It's unique per store and can't be changed later.
ship_nameYesRecipient's full name.
address1Yes
cityYes
countryYesTwo-letter code (US) recommended. A country name also works.
address2, state, postal_code, phone, emailNoSend state and postal_code wherever the country uses them.
requested_shipping_serviceNoThe shipping service name your platform uses, such as Standard or Expedited. See Shipping Services below.
order_dateNo2026-10-26T14:30:00Z (RFC 3339) or 2026-10-26 14:30:00 -0700. If it's missing or can't be read, the time Warehance received the order is used.
itemsNoOne entry per line: sku (required) and quantity (1 or more). You can create an order with no items and add them later.

A new order returns 201:

{
  "order": {
    "id": "231185181863",
    "status": "unverified",
    "order_number": "10001",
    "ship_name": "Jane Doe",
    "address1": "1600 SW 4TH AVE",
    "address2": "SUITE 300",
    "city": "PORTLAND",
    "state": "OR",
    "postal_code": "97201",
    "country": "US",
    "shipments": [
      {
        "id": "pending-231185181863",
        "order_number": "10001",
        "tracking_number": null,
        "status": "pending_shipment",
        "carrier_code": null,
        "service_code": null,
        "ship_date": null,
        "orders": [{"id": "231185181863", "order_number": "10001"}],
        "ship_name": "Jane Doe",
        "address1": "1600 SW 4TH AVE",
        "address2": "SUITE 300",
        "city": "PORTLAND",
        "state": "OR",
        "postal_code": "97201",
        "country": "US"
      }
    ],
    "items": [
      {"id": "54a1e612-ab3d-45b4-aec5-abc064650bce", "sku_id": 231185181506, "quantity": 2, "sku": "TEA-001"},
      {"id": "92cc21b0-7d0e-4f8a-9b51-0c8d3e6f2a47", "sku_id": 231185181508, "quantity": 1, "sku": "MUG-RED"}
    ]
  }
}

Store the order id and each item id; you need them for edits.

  • Sending the same order twice is safe. If an order with that order_number already exists in the store, Warehance returns it with 200 and creates nothing. Retry a create after a timeout without worrying about duplicates.
  • The address may come back corrected. Warehance verifies and standardizes the ship-to address, so responses can differ from what you sent (for example, uppercased or with a corrected ZIP code).
  • Validation errors return 404, not 400, with one message per problem: {"errors": ["...", "..."]}. Malformed JSON also returns 404. This matches the API your platform was originally built against.
  • Import filters. If the warehouse filters this store's orders, a filtered order is rejected with 404 {"errors": ["Order was rejected by the store's import filter"]}.

Order Statuses

StatusMeaningCan you edit or cancel it?
unverifiedReceived. The warehouse hasn't started on it yet.Yes
pending_shipmentThe warehouse is working on it, or part of it has shipped.No
shippedEvery part of the order has shipped.No
cancelledCancelled by you or the warehouse.No
unverified doesn't mean the order is stuck or waiting for you. The warehouse fulfills unverified orders normally; the status only tells you edits are still accepted.

An order can also go to pending_shipment because the warehouse split it into several shipments or merged it with another order. See Split and Merged Orders below.

Read Orders

Get one order

GET /stores/{store_id}/orders/{id}.json
GET /stores/{store_id}/orders/{id}.json?order_number=10001

On any order endpoint, the order_number query parameter takes priority over the {id} in the path. If you only stored your own order number, put any placeholder in {id} and pass ?order_number=.

An unknown order returns 404 {"error": "could not find order"}. Note the singular error key.

List orders

GET /stores/{store_id}/orders.json?updated_at_start=2026-10-26T00:00:00Z&page=1&per_page=100
ParameterNotes
pageStarts at 1.
per_pageDefault 25, maximum 500.
updated_at_start, updated_at_endRFC 3339, such as 2026-10-26T14:30:00Z. Returns orders changed in that window, including status changes from the warehouse.
order_numberReturns just that order.

The response is {"total": 120, "pages": 2, "orders": [...]}, oldest order first, one entry per order number. A bad updated_at value returns 400 {"errors": "supplied updated time is invalid"}; here errors is a string, not a list.

Change an Order

All changes are accepted only while the order is unverified. After that, every change returns 403 {"errors": ["Order can no longer be modified"]}. If you get that error, contact the warehouse about the change.

Update order fields

PUT /stores/{store_id}/orders/{id}/update.json
{"order": {"address2": "Suite 300", "city": "Beaverton"}}

Only the fields you send change. You can update requested_shipping_service, ship_name, address1, address2, city, state, postal_code, country, phone, email and order_date. The order_number can't change. Change items through the item endpoints below. Returns 200 with the order.

Items

RequestBodyReturns
GET /orders/{id}/items.json200 {"items": [...]}
GET /orders/{id}/items/{item_id}.json200 {"order_item": {...}}
POST /orders/{id}/items/add.json{"order_item": {"sku": "TEA-002", "quantity": 1}}201 {"order_item": {...}} with the new item id
PUT /orders/{id}/items/{item_id}.json{"order_item": {"quantity": 4}}200 {"order_item": {...}}
DELETE /orders/{id}/items/{item_id}.json200 {"items": [...]}: the remaining items
  • Item IDs. Warehance issues each item id (a UUID) when the line is created. You can't choose it.
  • SKU changes. Only the quantity can change. A different SKU is a different line: delete the item and add a new one. Sending a different sku returns 400 {"errors": ["Item sku can't be changed; delete the item and add a new one"]}.
  • Quantities. A quantity must be 1 or more. To remove a line, delete it.
  • Deleted items disappear from every response. Requesting them afterwards returns 404 {"errors": ["could not find item"]}.
  • sku_id is the warehouse's product ID for the SKU. It is null while the warehouse still has to match your SKU to a product. See SKUs and Products below.

Cancel an order

DELETE /stores/{store_id}/orders/{id}.json

Returns 200 with the order, now cancelled. Cancelling also follows the editing rule: once the order isn't unverified (including when it's already cancelled), you get 403. In that case, ask the warehouse to cancel it if it hasn't shipped.

Get Shipments and Tracking

Each order carries a shipments list. Until a label is bought, an open order has one placeholder shipment:

  • id is pending-{order id}
  • status is pending_shipment
  • tracking_number, carrier_code, service_code and ship_date are null

Once the warehouse ships, the placeholder is replaced by the real shipment:

{
  "id": "231185181467",
  "order_number": "10001",
  "status": "shipped",
  "tracking_number": "9400111899223197428490",
  "carrier_code": "usps",
  "service_code": "usps_ground_advantage",
  "ship_date": "2026-10-27",
  "orders": [{"id": "231185181863", "order_number": "10001"}],
  "ship_name": "Jane Doe",
  "address1": "1600 SW 4TH AVE",
  "address2": "SUITE 300",
  "city": "PORTLAND",
  "state": "OR",
  "postal_code": "97201",
  "country": "US"
}
  • carrier_code and service_code are Warehance's lowercase carrier and service codes, such as usps, ups, fedex and usps_ground_advantage.
  • ship_date is YYYY-MM-DD.
  • A real shipment id is always numeric. Only placeholders start with pending-.

Recommended: poll the shipments feed

GET /stores/{store_id}/shipments.json?updated_at_start=2026-10-26T14:00:00Z&per_page=500

The response is {"total": 3, "pages": 1, "shipments": [...]}, oldest first, with real shipments only. It accepts the same page, per_page, updated_at_start, updated_at_end and order_number parameters as the orders list. Each shipment's orders tells you which of your orders it ships.

Other ways to read shipments:

  • GET /orders/{id}/shipments.json returns {"shipments": [...]} for one order, including the placeholder while the order is open.
  • GET /shipments/{shipment_id}.json returns {"shipment": {...}}. An unknown ID returns 200 with {"shipment": null}, not 404.

Split and Merged Orders

The warehouse can split one of your orders into several shipments, or merge several of your orders into one shipment (for example, two orders for the same customer). Your view stays the same:

  • Your order keeps its id and order_number. Both still work after a split or merge, and the orders list still has one entry per order number.
  • Split orders. The order shows every shipment made so far. It stays pending_shipment until the last part ships, then becomes shipped. Your items list is unchanged.
  • Merged orders. Each of your orders shows the shared shipment and its tracking, and that shipment's orders list includes every order it ships. Write the same tracking number to each of them.
  • No more edits. Split or merged orders can't be edited or cancelled through the API (403).
Always handle an order with more than one shipment, and a shipment with more than one order, even if your platform rarely sees them.

Orders Shipped Without a Label

Sometimes a warehouse marks an order as shipped without buying a label in Warehance, for example a local pickup or freight handled outside Warehance. The order becomes shipped but has no shipments and no tracking number. Treat shipped with an empty shipments list as fulfilled without tracking.

SKUs and Products

  • Matching SKUs. Send the SKU exactly as the warehouse knows the product. A matching SKU goes straight to fulfillment.
  • SKUs the warehouse doesn't recognize are still accepted; the order isn't rejected. Depending on the warehouse's settings, either a new product is created for the SKU, or the order waits until the warehouse maps your SKU to one of its products (sku_id stays null until then). Either way, the order can't ship until the warehouse resolves it.
  • Bundles. If the warehouse maps your SKU to a bundle or multi-pack, it ships the components. You keep seeing your single line.

Shipping Services

requested_shipping_service is the name of the service your customer chose. The warehouse maps each name your platform sends to a carrier service once. Until a new name is mapped, orders using it wait in the warehouse. Send a small, consistent set of names (Standard, Expedited, Overnight) rather than free text, and tell the warehouse which names to expect.

Concurrent Requests

Warehance processes one change at a time per order. If another request is still updating the same order, you may get 409 {"errors": ["Order is being updated, try again"]}. Wait a moment and retry. Send changes to the same order one after another, not in parallel. Requests for different orders can run in parallel.

Recommended Workflow

  1. Create each order once it's final (paid and approved). Store the returned order id and item ids. If the request times out, send it again: the same order_number won't create a duplicate.
  2. Send edits only while unverified. If an edit returns 403, the warehouse has started work. Contact them about the change.
  3. Poll GET /shipments.json every 15–60 minutes with updated_at_start set a few minutes before your last successful poll. Read all pages and skip shipment IDs you've already processed.
  4. Write tracking back for every order listed in each shipment's orders.
  5. Close out orders when they reach shipped or cancelled. To check a few specific orders, use GET /orders.json?order_number=… or GET /orders/{id}.json. Don't page through every order.

Errors

StatusBodyMeaningWhat to do
401emptyCredentials missing or wrong, no key yet, or store deactivatedCheck the username and key. Ask the warehouse whether the key was regenerated or the store deactivated.
404{"errors": ["Please check your store number"]}{store_id} doesn't match these credentialsUse the store ID that goes with this username.
404{"errors": [...]} on createMissing or invalid fields, or malformed JSONFix the fields listed and resend.
404{"error": "could not find order"}No order with that id or order_number in this storeCheck the id, or use ?order_number=.
404{"errors": ["could not find item"]}No such item on the order, or it was deletedRe-read the order's items.
400{"errors": [...]}Invalid edit, such as a SKU change or quantity below 1Fix the request.
400{"errors": "supplied updated time is invalid"}updated_at_start or updated_at_end isn't RFC 3339Use a format like 2026-10-26T14:30:00Z.
403{"errors": ["Order can no longer be modified"]}The order isn't unverified anymoreDon't retry. Contact the warehouse.
409{"errors": ["Order is being updated, try again"]}Another change to this order is in progressRetry after a short wait.
500{"error": "...", "request_id": "..."}Unexpected errorRetry with backoff. If it persists, send the request_id to the warehouse.

Troubleshooting Checklist

  • Base URL. Is it exactly the Base URL from the store's General tab, including /api/v1/fulfillment-api/api?
  • Credentials. Are you sending the store's username and current API key as HTTP Basic auth? A regenerated key replaces the old one immediately.
  • Store ID. Does {store_id} in the path belong to the same store as the username?
  • Edits refused. A 403 on an edit means the warehouse has started on the order, split or merged it, or it's cancelled.
  • No tracking yet. The order is still open: it shows a pending-… placeholder shipment. Ask the warehouse whether it's waiting on a SKU or shipping-service mapping, or on stock.
  • Shipped with no tracking. The warehouse marked it shipped without a Warehance label. See Orders Shipped Without a Label above.
  • Errors you can't explain. Send the warehouse the request time, the endpoint, your order number and any request_id.

Still need help?

Can't find what you're looking for? Our support team is happy to help.

Contact Support