Systems
ShipStation integration with your ERP and store: orders out, tracking back
ShipStation's V1 API allows 40 requests a minute per key, its V2 API 200, and the two name the same record differently. We build the integration between ShipStation, your ERP and your store around those limits and your order statuses, then host and run it.
What ShipStation is and who runs it
ShipStation is shipping software for online sellers: it collects orders from connected stores and marketplaces, compares carrier rates, prints labels and sends tracking back to the channel the order came from. It is part of Auctane, based in Austin, Texas. Its V1 API stamps every date in Pacific time and stores product weight in ounces.
Sellers run it between the store and the warehouse floor. The store sends the order, ShipStation prints the label, and the tracking number goes back. That works without an ERP. Once an ERP owns stock, invoices and customer accounts, ShipStation becomes one of three systems that each hold part of the order, and the integration has to decide which one is right about what.
What connects to ShipStation
ShipStation owns the shipment: carrier, service, label, weight and tracking. The ERP owns the item, the stock count and the invoice. The store owns the checkout. These are the flows we build as part of order integration:
| Flow | Direction | ShipStation endpoint |
|---|---|---|
| Orders to ship | ERP or store to ShipStation | POST /orders/createorders (V1), POST /v2/shipments (V2) |
| Order changes and cancellations | ERP to ShipStation | same endpoints, on the order key |
| Tracking and carrier | ShipStation to ERP and store | SHIP_NOTIFY webhook, GET /shipments |
| Stock per SKU and location | ERP to ShipStation, or back | POST /v2/inventory |
| Products, weights, dimensions | ERP to ShipStation | /products (V1) |
| Orders shipped outside ShipStation | ERP to ShipStation | POST /orders/markasshipped |
The order route needs one decision up front. If the store is also connected to ShipStation directly, the same order arrives twice: once from the store, once from the ERP. Either the ERP is the only source of orders for ShipStation, or the store is and the ERP only receives tracking. We set that per sales channel.
How ShipStation exposes data
Two APIs with different names for the same thing
ShipStation has a V1 API at ssapi.shipstation.com and a V2 API at api.shipstation.com/v2. ShipStation's documentation calls V1 deprecated and says it will be removed, without giving a date. V2 grew out of ShipEngine and renames the core records:
| V1 and ShipStation screen | V2 | Note |
|---|---|---|
| Order | Shipment | the intent to ship |
| Shipment | Label | the purchased label with tracking |
orderId 12345678 |
shipment_id se-12345678 |
V2 IDs carry the se- prefix |
orderKey |
external_shipment_id |
cannot be changed after creation |
awaiting_payment, awaiting_shipment, on_hold |
pending |
three statuses become one |
shipped |
label_purchased |
An integration that reads V2 cannot tell an order on hold from one waiting for payment. When the ERP needs that difference, the integration stores the V1 status itself.
Authentication and plans
V1 uses Basic authentication with an API key and secret; an account can have two V1 key pairs active. V2 takes one API-Key header, and an account has one active V2 key. The Free and Starter plans include no API access at all; Standard and Premium do, and each V2 endpoint lists the plans that can use it. ShipStation platform accounts have no sandbox, so every V2 call runs against live data.
Rate limits
| API | Limit | Over the limit |
|---|---|---|
| V1 | 40 requests a minute per key and secret | 429 with X-Rate-Limit-Reset in seconds |
| V2 | 200 requests a minute by default, higher on request | 429 with Retry-After in seconds |
V1 returns the state of the window on every response:
HTTP/1.1 429 Too Many Requests
X-Rate-Limit-Limit: 40
X-Rate-Limit-Remaining: 0
X-Rate-Limit-Reset: 20
{ "message": "Too Many Requests" }
Worked through for 2,400 orders a day on V1: one createorder call per order is 2,400 calls, at 40 a minute that is 60 minutes of the key's full capacity. createorders takes up to 100 orders per request, so the same day is 24 calls. Reading them back with pageSize=500, the maximum for the order list, is 5 pages. We batch the writes and leave most of the 40 requests free for the label printing and tracking reads that run on the same key. The pattern is in API throttling and backoff.
Webhooks carry a URL, not the data
A V1 webhook (ORDER_NOTIFY, ITEM_ORDER_NOTIFY, SHIP_NOTIFY, ITEM_SHIP_NOTIFY) holds two fields: resource_url and resource_type. The integration calls the URL with the same credentials to get the shipments, which is one more call on the same key. V2 webhooks such as fulfillment_shipped_v2 can only be created through the API. ShipStation waits 10 seconds for a 2xx answer, tries two more times, usually 30 minutes apart, and then drops the event. A reconciliation run on modifyDateStart catches what a dropped webhook missed; webhooks are not a guarantee explains why.
Where a ShipStation integration gets stuck
Pacific time in V1
V1 sends and expects every date as yyyy-mm-dd hh:mm:ss in Pacific time, PST or PDT, without an offset. An order placed at 23:30 in New York on October 2 is 2026-10-03T03:30:00Z in the ERP. ShipStation wants 2026-10-02 20:30:00. Sent without conversion, ShipStation reads it as 03:30 Pacific, seven hours after the real time, and the order lands on the next day in every report and ship-by rule. The integration converts every date both ways; see dates and time zones.
Order keys and duplicates
In V1, createorder with an existing orderKey updates that order, so a retry is safe. Only open orders can be updated: once an order is shipped or cancelled, a change from the ERP is refused. In V2, external_shipment_id is not unique: a split shipment shares it on purpose, so a retried POST /v2/shipments creates a second shipment. The integration looks up GET /v2/shipments/external_shipment_id/{id} before it creates, which is the general rule in duplicate customers and orders.
Updates replace the whole order
V1 does not support partial updates: ShipStation's documentation says the entire order must be in the request body. A change to one line therefore sends the full order with every item, address and amount. The integration rebuilds the full order from its own copy each time, so a quantity change in the ERP cannot drop the other lines or the gift message.
Shipments that do not show up
An order marked shipped through markasshipped, in the screen or through the API, does not appear in GET /shipments: ShipStation treats it as an external shipment. A tracking sync that only reads shipments misses these orders, so the integration also reads orders with status shipped on modifyDateStart.
Units and discount lines
Product dimensions in V1 use the unit set in the ShipStation screen, and ShipStation converts nothing. Weight on a product is weightOz, in ounces. An ERP that stores 1.2 kg sends 42.33 ounces. A discount goes on the order as an item with adjustment: true and a negative unitPrice, which the ERP must not book as a product line.
Platforms and systems we connect to ShipStation
ShipStation sits between the store and the ERP, so both sides matter. On the store side we work with Shopify, Magento and WooCommerce. On the ERP side with NetSuite, Business Central and Odoo. For retail trading partners, the tracking from ShipStation is also the input for an 856 advance ship notice.
We build the integration to your ShipStation account, your stores and your ERP, then host it, monitor it and fix it when ShipStation changes an endpoint or retires V1. Before go-live it runs as a dry run that writes nothing, so you see every order and tracking update it would send. Every integration comes with a dashboard, logs and a per-run diff. Tell us how your orders reach ShipStation today.
Frequently asked questions
Which ShipStation plan do I need for an integration?
ShipStation's developer documentation says the Free and Starter plans include no API access; Standard and Premium do. Each V2 endpoint page shows which plans can call it, so we check the endpoints your flows need against your plan before the build starts.
Should the integration use the V1 or the V2 API?
New work goes on V2. ShipStation calls V1 legacy and says it will be removed in the future, without a date. V2 has the inventory endpoints and a limit of 200 requests a minute against 40 on V1. Some order workflows that ShipStation users rely on, such as order statuses like awaiting_payment, only exist in V1 terms, so a mixed setup is common for now.
What happens when the integration hits the rate limit?
ShipStation answers with HTTP 429. V1 adds X-Rate-Limit-Reset, the seconds until the window resets; V2 adds Retry-After. The integration keeps the request in its queue, waits that number of seconds and sends it again. The limit is per API key, so every tool on the same key shares the 40 or 200 requests.
Can ShipStation be the source of stock levels for our store?
Through V2, yes: GET /v2/inventory returns on_hand, allocated and available per SKU, warehouse and location, and POST /v2/inventory sets them. Most setups keep the ERP as the owner of stock and push it to ShipStation, so a pick in ShipStation and a goods receipt in the ERP do not overwrite each other.
Can we test the integration in a ShipStation sandbox?
Not on the ShipStation platform. ShipStation's documentation says platform customers have no sandbox and every V2 call runs in production. Support can give a developer account, which is a regular account with a trial that expires after 90 days. We test with the integration in dry run mode, which reads from ShipStation and writes nothing.
Tell us what you need
Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.
- You know the price and the timeline before you commit to anything
- We work out the connection that takes the work off your hands
- We handle the build, hosting, monitoring and maintenance
- Your team has less information to retype and fewer discrepancies to chase