Warehance's Custom Store Interface lets you connect any system to Warehance for two-way order and shipment synchronization. Your system exposes a single HTTPS endpoint, and Warehance handles the rest: pulling new orders on a schedule and pushing tracking information back when shipments are created.
This guide covers everything you need to implement and troubleshoot the integration.
How It Works
Your endpoint handles two actions via query parameter:
| Direction | Method | Query Parameter | Purpose |
|---|---|---|---|
| Warehance → You | GET | ?action=export | Warehance pulls orders from your system |
| Warehance → You | POST | ?action=shipnotify | Warehance pushes tracking/shipment data back |
Both actions use the same endpoint URL. Warehance distinguishes them by the action query parameter and HTTP method.
Your endpoint must handle both ?action=export (GET) and ?action=shipnotify (POST). If your system uses different action names internally, add routing or aliases on your side to map to these values.
Authentication
All requests use HTTP Basic Authentication. Warehance sends an Authorization header with every request:
Authorization: Basic base64(username:password)
The username and password are configured when you connect the store in Warehance. Your endpoint should return:
- 401 Unauthorized if credentials are missing or invalid
- 403 Forbidden if the credentials are valid but lack permissions
During order sync, if your endpoint returns 5 consecutive authentication failures (401 or 403), Warehance automatically disables the interface to prevent locking out your account. You will need to re-enable it in the store settings after fixing the credentials. This auto-disable applies to the order export side only, not to ShipNotify.
Data Format
The interface supports XML and JSON. The format is configured per-store in Warehance and applies to both directions:
| Format | Content-Type | Accept Header |
|---|---|---|
| XML | application/xml | application/xml |
| JSON | application/json | application/json |
XML is the default for backwards compatibility with the ShipStation Custom Store specification. JSON uses snake_case field names throughout.
Order Export Endpoint
GET https://your-endpoint.com/api?action=export&start_date=01/15/2026+14:30&end_date=01/16/2026+14:30&page=1
Query Parameters
| Parameter | Format | Description |
|---|---|---|
| action | export | Always export for order pulls |
| start_date | MM/dd/yyyy HH:mm | Start of the date range (UTC) |
| end_date | MM/dd/yyyy HH:mm | End of the date range (UTC) |
| page | Integer | Page number, starting at 1 |
Date Format
The standard date format is MM/dd/yyyy HH:mm (e.g., 01/15/2026 14:30).
When parsing dates in your order response, Warehance also accepts:
- MM/dd/yyyy HH:mm:ss
- MM/dd/yyyy h:mm AM/PM
- MM/dd/yyyy h:mm:ss AM/PM
- ISO 8601 / RFC 3339 (e.g., 2026-01-15T14:30:00Z)
Response — XML Format
Your endpoint should return the orders that were created or modified within the requested date range.
<?xml version="1.0" encoding="utf-8"?>
<Orders pages="3">
<Order>
<OrderID>ORD-10001</OrderID>
<OrderNumber>10001</OrderNumber>
<OrderDate>01/15/2026 14:30</OrderDate>
<OrderStatus>paid</OrderStatus>
<LastModified>01/15/2026 15:00</LastModified>
<ShippingMethod>Ground</ShippingMethod>
<PaymentMethod>credit_card</PaymentMethod>
<CurrencyCode>USD</CurrencyCode>
<OrderTotal>59.99</OrderTotal>
<TaxAmount>4.50</TaxAmount>
<ShippingAmount>5.99</ShippingAmount>
<CustomerNotes>Please leave at front door</CustomerNotes>
<InternalNotes>VIP customer</InternalNotes>
<Gift>false</Gift>
<GiftMessage></GiftMessage>
<CustomField1></CustomField1>
<CustomField2></CustomField2>
<CustomField3></CustomField3>
<CustomField4></CustomField4>
<CustomField5></CustomField5>
<CustomField6></CustomField6>
<RequestedWarehouse>Main Warehouse</RequestedWarehouse>
<Source>website</Source>
<Customer>
<CustomerCode>CUST-5001</CustomerCode>
<BillTo>
<Name>Jane Smith</Name>
<Company>Smith Co</Company>
<Phone>555-123-4567</Phone>
<Email>jane@example.com</Email>
<Address1>100 Main St</Address1>
<Address2>Suite 200</Address2>
<City>Salt Lake City</City>
<State>UT</State>
<PostalCode>84101</PostalCode>
<Country>US</Country>
</BillTo>
<ShipTo>
<Name>Jane Smith</Name>
<Company>Smith Co</Company>
<Address1>100 Main St</Address1>
<Address2>Suite 200</Address2>
<City>Salt Lake City</City>
<State>UT</State>
<PostalCode>84101</PostalCode>
<Country>US</Country>
<Phone>555-123-4567</Phone>
</ShipTo>
</Customer>
<Items>
<Item>
<LineItemID>LI-001</LineItemID>
<SKU>WIDGET-BLUE</SKU>
<Name>Blue Widget</Name>
<ImageUrl>https://example.com/images/widget-blue.jpg</ImageUrl>
<Weight>1.5</Weight>
<WeightUnits>pounds</WeightUnits>
<Quantity>2</Quantity>
<UnitPrice>24.99</UnitPrice>
<UPC>012345678901</UPC>
<Location>A-1-01</Location>
<Adjustment>false</Adjustment>
<Options>
<Option>
<Name>Color</Name>
<Value>Blue</Value>
<Weight>0</Weight>
</Option>
<Option>
<Name>Size</Name>
<Value>Large</Value>
<Weight>0</Weight>
</Option>
</Options>
</Item>
</Items>
<Dimensions>
<DimensionUnits>inches</DimensionUnits>
<Length>12</Length>
<Width>8</Width>
<Height>6</Height>
</Dimensions>
</Order>
</Orders>
Response — JSON Format
{
"pages": 3,
"orders": [
{
"order_id": "ORD-10001",
"order_number": "10001",
"order_date": "2026-01-15T14:30:00Z",
"order_status": "paid",
"last_modified": "2026-01-15T15:00:00Z",
"shipping_method": "Ground",
"payment_method": "credit_card",
"currency_code": "USD",
"order_total": 59.99,
"tax_amount": 4.50,
"shipping_amount": 5.99,
"customer_notes": "Please leave at front door",
"internal_notes": "VIP customer",
"gift": false,
"gift_message": "",
"custom_field1": "",
"custom_field2": "",
"custom_field3": "",
"custom_field4": "",
"custom_field5": "",
"custom_field6": "",
"requested_warehouse": "Main Warehouse",
"source": "website",
"customer": {
"customer_code": "CUST-5001",
"bill_to": {
"name": "Jane Smith",
"company": "Smith Co",
"phone": "555-123-4567",
"email": "jane@example.com",
"address1": "100 Main St",
"address2": "Suite 200",
"city": "Salt Lake City",
"state": "UT",
"postal_code": "84101",
"country": "US"
},
"ship_to": {
"name": "Jane Smith",
"company": "Smith Co",
"address1": "100 Main St",
"address2": "Suite 200",
"city": "Salt Lake City",
"state": "UT",
"postal_code": "84101",
"country": "US",
"phone": "555-123-4567"
}
},
"items": {
"items": [
{
"line_item_id": "LI-001",
"sku": "WIDGET-BLUE",
"name": "Blue Widget",
"image_url": "https://example.com/images/widget-blue.jpg",
"weight": 1.5,
"weight_units": "pounds",
"quantity": 2,
"unit_price": 24.99,
"upc": "012345678901",
"location": "A-1-01",
"adjustment": false,
"options": {
"options": [
{ "name": "Color", "value": "Blue", "weight": 0 },
{ "name": "Size", "value": "Large", "weight": 0 }
]
}
}
]
},
"dimensions": {
"dimension_units": "inches",
"length": 12,
"width": 8,
"height": 6
}
}
]
}
Pagination
The pages attribute (XML) or pages field (JSON) in the root of the response tells Warehance how many total pages exist. Warehance starts at page=1 and increments until it reaches the total page count or receives an empty list.
If all orders fit on one page, set pages to 1.
Field Reference
| Field | Required | Description |
|---|---|---|
| OrderID / order_id | Yes | Your unique identifier for this order. Used to match orders across syncs. |
| OrderNumber / order_number | Yes | Human-readable order number displayed in Warehance. |
| OrderDate / order_date | Yes | When the order was placed. |
| OrderStatus / order_status | Yes | Your status value. Mapped to Warehance states via status mapping config (see below). |
| LastModified / last_modified | Recommended | When the order was last updated. Used for incremental sync. |
| ShippingMethod / shipping_method | No | Requested shipping method (e.g., "Ground", "Express"). |
| PaymentMethod / payment_method | No | Payment method used. |
| CurrencyCode / currency_code | No | ISO 4217 currency code (e.g., "USD"). |
| OrderTotal / order_total | No | Total order amount. |
| TaxAmount / tax_amount | No | Tax amount. |
| ShippingAmount / shipping_amount | No | Shipping charge. |
| CustomerNotes / customer_notes | No | Notes from the customer (mapped to packing note). |
| InternalNotes / internal_notes | No | Internal notes (mapped to internal note). |
| Gift / gift | No | Whether this is a gift order. |
| GiftMessage / gift_message | No | Gift message text. |
| CustomField1–6 / custom_field1–6 | No | Six custom fields for arbitrary data. Preserved and returned in ShipNotify. |
| RequestedWarehouse / requested_warehouse | No | Preferred warehouse name. Falls back to client default if not matched. |
| Source / source | No | Order source identifier. |
| Customer / customer | Yes | Customer block containing CustomerCode, BillTo, and ShipTo. |
| Items / items | Yes | Line items block. Each item has SKU, Name, Quantity, UnitPrice, LineItemID, etc. |
| Dimensions / dimensions | No | Package dimensions (Length, Width, Height, DimensionUnits). |
Item Fields
| Field | Required | Description |
|---|---|---|
| LineItemID / line_item_id | Recommended | Your unique ID for this line item. Returned in ShipNotify. |
| SKU / sku | Yes | Product SKU. Used to match products in Warehance. |
| Name / name | Yes | Product name. |
| Quantity / quantity | Yes | Quantity ordered. |
| UnitPrice / unit_price | No | Price per unit. |
| Weight / weight | No | Item weight. |
| WeightUnits / weight_units | No | Weight unit (e.g., "pounds", "ounces", "grams"). |
| UPC / upc | No | UPC/barcode. |
| ImageUrl / image_url | No | Product image URL. |
| Location / location | No | Warehouse location hint. |
| Adjustment / adjustment | No | If true, this line item is a discount/adjustment, not a physical product. Adjustment items with a negative UnitPrice are treated as discounts. |
| Options / options | No | Item options (size, color, etc.). Each option has Name, Value, and Weight. |
Adjustment Items
To represent discounts in your order, include an item with Adjustment set to true and a negative UnitPrice:
<Item>
<LineItemID>DISC-001</LineItemID>
<SKU>DISCOUNT</SKU>
<Name>10% Off Coupon</Name>
<Quantity>1</Quantity>
<UnitPrice>-5.00</UnitPrice>
<Adjustment>true</Adjustment>
</Item>
Adjustment-only orders (orders with no non-adjustment items) are skipped during import.
Ship Notify Endpoint
When an order is shipped in Warehance, a POST request is sent to your endpoint with tracking and shipment details.
POST https://your-endpoint.com/api?action=shipnotify
Content-Type: application/xml (or application/json)
Authorization: Basic base64(username:password)
Your endpoint should return any 2xx status code to indicate success. Any non-2xx response is treated as a failure and will be retried.
Request Body — XML Format
<?xml version="1.0" encoding="utf-8"?>
<ShipNotice>
<OrderNumber>10001</OrderNumber>
<OrderID>ORD-10001</OrderID>
<CustomerCode>CUST-5001</CustomerCode>
<CustomerNotes>Please leave at front door</CustomerNotes>
<InternalNotes>VIP customer</InternalNotes>
<NotesToCustomer></NotesToCustomer>
<NotifyCustomer>false</NotifyCustomer>
<LabelCreateDate>01/15/2026 16:45</LabelCreateDate>
<ShipDate>01/15/2026</ShipDate>
<Carrier>UPS</Carrier>
<Service>UPS_GROUND</Service>
<TrackingNumber>1Z999AA10123456784</TrackingNumber>
<ShippingCost>8.50</ShippingCost>
<CustomField1></CustomField1>
<CustomField2></CustomField2>
<CustomField3></CustomField3>
<CustomField4></CustomField4>
<CustomField5></CustomField5>
<CustomField6></CustomField6>
<Recipient>
<Name>Jane Smith</Name>
<Company>Smith Co</Company>
<Address1>100 Main St</Address1>
<Address2>Suite 200</Address2>
<City>Salt Lake City</City>
<State>UT</State>
<PostalCode>84101</PostalCode>
<Country>US</Country>
</Recipient>
<Items>
<Item>
<SKU>WIDGET-BLUE</SKU>
<Name>Blue Widget</Name>
<Quantity>2</Quantity>
<LineItemID>LI-001</LineItemID>
<UPC>012345678901</UPC>
</Item>
</Items>
</ShipNotice>
Request Body — JSON Format
{
"order_number": "10001",
"order_id": "ORD-10001",
"customer_code": "CUST-5001",
"customer_notes": "Please leave at front door",
"internal_notes": "VIP customer",
"notes_to_customer": "",
"notify_customer": false,
"label_create_date": "01/15/2026 16:45",
"ship_date": "01/15/2026",
"carrier": "UPS",
"service": "UPS_GROUND",
"tracking_number": "1Z999AA10123456784",
"shipping_cost": 8.50,
"custom_field1": "",
"custom_field2": "",
"custom_field3": "",
"custom_field4": "",
"custom_field5": "",
"custom_field6": "",
"recipient": {
"name": "Jane Smith",
"company": "Smith Co",
"address1": "100 Main St",
"address2": "Suite 200",
"city": "Salt Lake City",
"state": "UT",
"postal_code": "84101",
"country": "US"
},
"items": {
"items": [
{
"sku": "WIDGET-BLUE",
"name": "Blue Widget",
"quantity": 2,
"line_item_id": "LI-001",
"upc": "012345678901"
}
]
}
}
Ship Notify Field Reference
| Field | Description |
|---|---|
| OrderNumber / order_number | The order number as displayed in Warehance. |
| OrderID / order_id | Your original OrderID from the export. Use this to match the shipment back to your order. |
| CustomerCode / customer_code | The customer code from the original order. |
| TrackingNumber / tracking_number | The carrier tracking number. |
| Carrier / carrier | Carrier name (e.g., "UPS", "FedEx", "USPS"). |
| Service / service | Service code (e.g., "UPS_GROUND", "FEDEX_HOME_DELIVERY"). |
| ShippingCost / shipping_cost | Actual shipping cost charged. |
| ShipDate / ship_date | Date the shipment was created (MM/dd/yyyy). |
| LabelCreateDate / label_create_date | Timestamp when the label was created (MM/dd/yyyy HH:mm). |
| Recipient / recipient | The ship-to address for this shipment. |
| Items / items | The items included in this shipment, with SKU, Name, Quantity, LineItemID, and UPC. |
| CustomField1–6 / custom_field1–6 | Your custom field values, echoed back from the original order. |
| CustomerNotes / customer_notes | Customer notes from the original order. |
| InternalNotes / internal_notes | Internal notes from the original order. |
| NotifyCustomer / notify_customer | Always false. Warehance handles customer email notifications separately. |
Order Status Mapping
When Warehance imports orders, it maps your OrderStatus value to an internal fulfillment state. These mappings are configured per-store in Warehance:
| Your Status Value | Warehance Behavior |
|---|---|
| Unpaid Status (e.g., pending_payment, awaiting_payment) | Order is imported with a Store Hold. It will not ship until the hold is released. |
| Paid Status (e.g., paid, processing, ready) | Order is imported ready to ship with no holds. |
| Shipped Status (e.g., shipped, completed, fulfilled) | Order is skipped during import — it's already fulfilled. |
| Cancelled Status (e.g., cancelled, refunded, voided) | Order is skipped during import, or cancelled if already in Warehance. |
| On Hold Status (e.g., on_hold, pending_review, fraud_review) | Order is imported with a Store Hold. Requires manual review before shipping. |
Status matching is case-insensitive. If an order's status doesn't match any configured value, it is imported with a Store Hold by default. This prevents unrecognized statuses from accidentally shipping.
Make sure the status values you configure in Warehance match exactly what your endpoint returns in the OrderStatus field. For example, if your API returns "Paid", set the Paid Status mapping to Paid.
Sync Behavior
Schedule
Warehance checks for new orders on a configurable interval. The default is every 45 minutes. The minimum interval is 5 minutes.
Incremental Sync
After the first successful sync, Warehance uses incremental sync: it requests orders modified since the last sync, minus a 5-minute overlap buffer to catch orders modified near the boundary.
For the very first sync (or if the sync state is reset), Warehance looks back 1 day by default (configurable, up to 14 days).
Auto-Disable on Auth Failures
During order sync, if your endpoint returns 5 consecutive authentication errors (HTTP 401 or 403), Warehance automatically disables the interface. This prevents account lockout on your end. After fixing the credentials, re-enable the interface in the store settings. The counter resets to 0 after any successful sync.
Error Handling
Expected HTTP Status Codes
Your endpoint should return standard HTTP status codes:
| Status Code | Meaning | Warehance Behavior |
|---|---|---|
| 200–299 | Success | Order processed / ShipNotify accepted |
| 400 | Bad Request | Error logged, retried |
| 401 | Unauthorized | Counted toward consecutive auth failures (order sync only) |
| 403 | Forbidden | Counted toward consecutive auth failures (order sync only) |
| 404 | Not Found | Error logged, retried |
| 429 | Rate Limited | Retried |
| 500 | Server Error | Retried |
| 502 | Bad Gateway | Retried |
| 503 | Service Unavailable | Retried |
| 504 | Gateway Timeout | Retried |
Ship Notify Retries
If the ShipNotify POST fails, Warehance retries using two mechanisms:
Immediate retries: When a shipment is created, Warehance makes up to 3 attempts with exponential backoff (1s, 2s, 4s). If all 3 fail, the error is recorded on the shipment.
Background retries: A background process periodically picks up shipments that failed notification and retries them. Each background retry also makes up to 3 immediate attempts. Background retries are spaced at least ~90 minutes apart. After 3 background retry rounds, the shipment is marked as failed and no further automatic retries occur.
Request Timeout
The default HTTP timeout is 60 seconds per request (configurable between 10–120 seconds). If your endpoint is slow to respond, the request will time out and be retried.
Common Issues
"Invalid action" Error on Ship Notify
Symptoms: Orders import successfully, but tracking never pushes back. The shipment shows a marketplace error like:
BAD_REQUEST bad request: {"error":"Invalid action. Use ?action=pull or ?action=push"}
Cause: Your endpoint doesn't recognize ?action=shipnotify. Warehance uses ?action=export for pulling orders and ?action=shipnotify for pushing tracking — this follows the ShipStation Custom Store specification. If your API was built with different action names (e.g., pull / push), the shipnotify POST will be rejected.
Fix: Update your endpoint to accept ?action=shipnotify for incoming POST requests. If you can't change the action names, add routing on your side to alias shipnotify to your internal action name. For example, in a Node.js Express app:
app.all('/api/warehance', (req, res) => {
const action = req.query.action;
if (req.method === 'GET' && (action === 'export' || action === 'pull')) {
return handleOrderExport(req, res);
}
if (req.method === 'POST' && (action === 'shipnotify' || action === 'push')) {
return handleShipNotify(req, res);
}
res.status(400).json({ error: 'Invalid action' });
});
Troubleshooting from the Warehance UI
Orders Aren't Coming In
Step 1: Go to Stores in the left sidebar and click on the store that uses the Custom Store Interface.
Step 2: Click the Syncs tab. This tab is visible when the interface is enabled.
Step 3: Review the sync history table. Each sync shows:
- Status — Completed, Completed with Errors, or In Progress
- Started At / Ended At — Timestamps for the sync
- Duration — How long the sync took
- Errors — A count badge showing how many errors occurred
Step 4: If a sync has errors, click the error count badge to open a modal with the error message and error code. Common error codes:
- AUTH_ERROR — Invalid credentials (401/403). Check your username and password.
- FETCH_ERROR — Could not reach your endpoint. Check the URL and that your server is running.
- ORDER_SYNC_ERROR — An individual order failed to import. The message will include the order number and reason.
Tracking Isn't Going Back to My System
Step 1: Go to Shipments in the left sidebar and click on the shipment you want to investigate.
Step 2: On the shipment detail page, look at the Shipping Details card on the right side.
Step 3: Find the Marketplace Notified field. It shows one of two states:
- A green True badge means Warehance successfully sent tracking to your endpoint.
- A red False badge means the notification has not been sent or it failed.
Step 4: If it shows False and there was an error, a blue (?) link appears next to the badge. Click it to open a modal showing the exact error message your endpoint returned.
For example:
BAD_REQUEST bad request: {"error":"Invalid action. Use ?action=pull or ?action=push"}
This tells you precisely what went wrong, and is the starting point for debugging. See the Common Issues section above for known error patterns and fixes.
Troubleshooting Checklist
Use this quick-reference list when diagnosing any Custom Store Interface issue:
- Endpoint URL — Is the URL correct and reachable over HTTPS?
- Authentication — Are the HTTP Basic Auth username and password correct?
- Data Format — Does the format setting in Warehance (XML or JSON) match what your endpoint expects?
- Action Parameters — Does your endpoint handle ?action=export (GET) and ?action=shipnotify (POST)?
- Order Status Mapping — Do the status values configured in Warehance match exactly what your API returns?
- Syncs Tab — Check the store's Syncs tab for import errors and error details
- Marketplace Notified — Check individual shipments for the Marketplace Notified field and any error messages
- Server Logs — Check your own server logs for incoming requests from Warehance (User-Agent: Warehance/1.0 CustomStore)