Custom Store Interface — Developer Guide

Updated 2/25/20267 min read

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:

DirectionMethodQuery ParameterPurpose
Warehance → YouGET?action=exportWarehance pulls orders from your system
Warehance → YouPOST?action=shipnotifyWarehance 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:

FormatContent-TypeAccept Header
XMLapplication/xmlapplication/xml
JSONapplication/jsonapplication/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

ParameterFormatDescription
actionexportAlways export for order pulls
start_dateMM/dd/yyyy HH:mmStart of the date range (UTC)
end_dateMM/dd/yyyy HH:mmEnd of the date range (UTC)
pageIntegerPage 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

FieldRequiredDescription
OrderID / order_idYesYour unique identifier for this order. Used to match orders across syncs.
OrderNumber / order_numberYesHuman-readable order number displayed in Warehance.
OrderDate / order_dateYesWhen the order was placed.
OrderStatus / order_statusYesYour status value. Mapped to Warehance states via status mapping config (see below).
LastModified / last_modifiedRecommendedWhen the order was last updated. Used for incremental sync.
ShippingMethod / shipping_methodNoRequested shipping method (e.g., "Ground", "Express").
PaymentMethod / payment_methodNoPayment method used.
CurrencyCode / currency_codeNoISO 4217 currency code (e.g., "USD").
OrderTotal / order_totalNoTotal order amount.
TaxAmount / tax_amountNoTax amount.
ShippingAmount / shipping_amountNoShipping charge.
CustomerNotes / customer_notesNoNotes from the customer (mapped to packing note).
InternalNotes / internal_notesNoInternal notes (mapped to internal note).
Gift / giftNoWhether this is a gift order.
GiftMessage / gift_messageNoGift message text.
CustomField1–6 / custom_field1–6NoSix custom fields for arbitrary data. Preserved and returned in ShipNotify.
RequestedWarehouse / requested_warehouseNoPreferred warehouse name. Falls back to client default if not matched.
Source / sourceNoOrder source identifier.
Customer / customerYesCustomer block containing CustomerCode, BillTo, and ShipTo.
Items / itemsYesLine items block. Each item has SKU, Name, Quantity, UnitPrice, LineItemID, etc.
Dimensions / dimensionsNoPackage dimensions (Length, Width, Height, DimensionUnits).

Item Fields

FieldRequiredDescription
LineItemID / line_item_idRecommendedYour unique ID for this line item. Returned in ShipNotify.
SKU / skuYesProduct SKU. Used to match products in Warehance.
Name / nameYesProduct name.
Quantity / quantityYesQuantity ordered.
UnitPrice / unit_priceNoPrice per unit.
Weight / weightNoItem weight.
WeightUnits / weight_unitsNoWeight unit (e.g., "pounds", "ounces", "grams").
UPC / upcNoUPC/barcode.
ImageUrl / image_urlNoProduct image URL.
Location / locationNoWarehouse location hint.
Adjustment / adjustmentNoIf true, this line item is a discount/adjustment, not a physical product. Adjustment items with a negative UnitPrice are treated as discounts.
Options / optionsNoItem 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

FieldDescription
OrderNumber / order_numberThe order number as displayed in Warehance.
OrderID / order_idYour original OrderID from the export. Use this to match the shipment back to your order.
CustomerCode / customer_codeThe customer code from the original order.
TrackingNumber / tracking_numberThe carrier tracking number.
Carrier / carrierCarrier name (e.g., "UPS", "FedEx", "USPS").
Service / serviceService code (e.g., "UPS_GROUND", "FEDEX_HOME_DELIVERY").
ShippingCost / shipping_costActual shipping cost charged.
ShipDate / ship_dateDate the shipment was created (MM/dd/yyyy).
LabelCreateDate / label_create_dateTimestamp when the label was created (MM/dd/yyyy HH:mm).
Recipient / recipientThe ship-to address for this shipment.
Items / itemsThe items included in this shipment, with SKU, Name, Quantity, LineItemID, and UPC.
CustomField1–6 / custom_field1–6Your custom field values, echoed back from the original order.
CustomerNotes / customer_notesCustomer notes from the original order.
InternalNotes / internal_notesInternal notes from the original order.
NotifyCustomer / notify_customerAlways 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 ValueWarehance 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 CodeMeaningWarehance Behavior
200–299SuccessOrder processed / ShipNotify accepted
400Bad RequestError logged, retried
401UnauthorizedCounted toward consecutive auth failures (order sync only)
403ForbiddenCounted toward consecutive auth failures (order sync only)
404Not FoundError logged, retried
429Rate LimitedRetried
500Server ErrorRetried
502Bad GatewayRetried
503Service UnavailableRetried
504Gateway TimeoutRetried

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)

Still need help?

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

Contact Support