ShipStation is a multi-carrier shipping and order management platform owned by Auctane, used mostly by small and mid-size merchants in the United States, Canada, the United Kingdom and Australia. It pulls orders from marketplaces and carts (Amazon, eBay, Shopify, Walmart, BigCommerce, WooCommerce and around a hundred more), lets the merchant rate-shop across USPS, UPS, FedEx, DHL and regional carriers, buys the label, and pushes the tracking number back to the sales channel. For a unified commerce database, ShipStation is valuable in two directions: it is a shipment and tracking source of truth for merchants who ship through it, and it is a second-hand order source for the marketplaces it is already connected to. There are two live APIs with different hosts, different auth and different object models, and a connector has to pick one deliberately.
At a glance
What it is
ShipStation started as an independent shipping app, was acquired by Stamps.com, and now sits inside Auctane alongside ShipEngine, Stamps.com, ShipWorks and Endicia. The merchant-facing product is a web app: orders flow in from connected stores, the merchant batches them, compares rates, prints labels and manifests, and ShipStation writes the tracking number back to the originating channel. Pricing is a monthly subscription banded by shipment volume, with carrier postage bought either through ShipStation's own reseller accounts or through the merchant's own carrier contracts.
Two API surfaces exist because of that corporate history.
- ShipStation API v1, hosted at
https://ssapi.shipstation.com/, is the original app API. It is order-centric: it exposes the same objects the web app manages, including stores, orders, products, customers and warehouses. This is the API you want if you are reading a merchant's order and shipment history. - ShipStation API v2, hosted at
https://api.shipstation.com/v2, is the ShipEngine engine rebranded. It is label-centric: addresses, rates, labels, manifests, pickups, tracking, batches. It also has a sales order layer for importing orders from order sources. This is the API you want if you are buying labels or subscribing to tracking events.
The two do not share identifiers. A v1 shipmentId is an integer; a v2 label_id is a prefixed string such as se-28529731. A connector that needs both has to keep a mapping table.
ShipStation v2 and ShipEngine v1 are the same engine. The ShipEngine OpenAPI specification published at github.com/ShipEngine/shipengine-openapi is the most complete machine-readable description of the v2 object model, but its paths are written against api.shipengine.com/v1. When calling ShipStation, substitute the host and version prefix: /v1/labels in that spec is /v2/labels on api.shipstation.com.
API access
v1. Any paid ShipStation account can mint a key. In the web app, Settings, Account, API Settings, Generate API Keys. You get a key and a secret, both opaque strings. One pair per account. The key inherits full account permissions; there is no scoping and no per-user restriction. Revoking is a regenerate, which invalidates the old pair immediately.
v2. The API Settings page in the same web app generates a v2 key. ShipStation states that a Platform account can hold one V2 key at a time. Customers of the standalone ShipStation API product (the former ShipEngine) get their keys from the separate ShipStation API dashboard instead, and those accounts also get TEST_-prefixed sandbox keys.
Versions and deprecation. v1 is still documented and still in service as of September 2026, but ShipStation's own materials describe v2 as the forward path and ship new capabilities (batch shipments, manifests, return labels, service points) there first. Assume v1 is in maintenance. There is no published sunset date.
SDKs. ShipStation does not publish an official v1 SDK. For v2 the ShipEngine-branded SDKs are the official ones and are maintained by Auctane on GitHub: shipengine-js (Node and browser), shipengine-python, shipengine-dotnet, shipengine-php. Community v1 wrappers exist in PHP, Python and Ruby but are not vendor supported.
Partner path. Building a store integration that appears inside ShipStation's own store list (so merchants can connect your platform as an order source) is a separate programme: you implement ShipStation's Custom Store XML specification, or for v2 you register as an order source. That is not needed to read a single merchant's data.
Authentication
v1: HTTP basic auth
- Obtain the API key and API secret from the merchant's ShipStation account settings.
- Concatenate them as
API_KEY:API_SECRET. - Base64 encode the result using the RFC 2045 MIME variant of Base64.
- Send the result on every request as
Authorization: Basic <encoded>.
There is no token, no expiry and no refresh. The credential is long-lived until the merchant regenerates it, which is the main operational risk: you find out through a wall of 401s, not through a notification. Store the pair per merchant account and treat a 401 as a credential-invalid signal that should page the merchant, not as a retryable error.
Multi-account is trivial because there is no OAuth: one key and secret pair per ShipStation account, stored against your channel_account_id.
Obtain nothing: the credential is the key and secret pair itself. Encode it once and cache the header. printf '%s' "$SS_API_KEY:$SS_API_SECRET" | base64
GET /orders?orderStatus=awaiting_shipment&pageSize=500&page=1 HTTP/1.1 Host: ssapi.shipstation.com Authorization: Basic U2hpcFN0YXRpb246Um9ja3M= Accept: application/json
All v1 timestamps are in the account's PST/PDT time zone, and date filter parameters use yyyy-mm-dd hh:mm:ss in 24 hour notation, for example 2026-09-21 23:59:59. This bites every connector once: if you send UTC to modifyDateStart you will silently skip or duplicate up to eight hours of orders. Convert both directions at the boundary.
v2: static API key header
- Obtain the v2 API key from the merchant's API Settings page, or from the ShipStation API dashboard for standalone API customers.
- Send it on every request as an
API-Keyheader. There is noBearerprefix and noAuthorizationheader. - TLS 1.2 or higher is mandatory; plain HTTP and older TLS versions are rejected outright.
POST /v2/labels HTTP/1.1
Host: api.shipstation.com
API-Key: TEST_hRzWTIJGZUUAlKf8oIvBfCLZ0vCkLLXFbuzPfCrLsuA
Content-Type: application/json
{
"shipment": {
"service_code": "usps_priority_mail",
"ship_to": {
"name": "Amanda Miller",
"phone": "555-555-5555",
"address_line1": "525 S Winchester Blvd",
"city_locality": "San Jose",
"state_province": "CA",
"postal_code": "95128",
"country_code": "US",
"address_residential_indicator": "yes"
},
"ship_from": {
"company_name": "Example Corp.",
"name": "John Doe",
"phone": "111-111-1111",
"address_line1": "4009 Marathon Blvd",
"city_locality": "Austin",
"state_province": "TX",
"postal_code": "78756",
"country_code": "US",
"address_residential_indicator": "no"
},
"packages": [
{
"weight": { "value": 20, "unit": "ounce" }
}
]
}
}
Both keys are bearer-equivalent secrets with full account authority. Keep them in the same credential store you use for marketplace refresh tokens, even though nothing expires, so that rotation is a single code path.
Objects we can read
Everything in this section is v1 unless marked v2. The v1 host is https://ssapi.shipstation.com.
Orders
GET /orders
Filters: customerName, itemKeyword, orderNumber, orderStatus, storeId, and four date windows, each with a start and end parameter: createDateStart/createDateEnd, modifyDateStart/modifyDateEnd, orderDateStart/orderDateEnd, paymentDateStart/paymentDateEnd. Sorting is sortBy (OrderDate, ModifyDate, CreateDate) with sortDir (ASC or DESC).
orderStatus accepts awaiting_payment, awaiting_shipment, pending_fulfillment, shipped, on_hold, cancelled, rejected_fulfillment.
Pagination is classic offset paging: page starting at 1 and pageSize capped at 500. The response carries total, page and pages. For incremental sync, use modifyDateStart plus sortBy=ModifyDate&sortDir=ASC and keep a high-water mark, since modifyDate moves whenever a label is bought or a tag is applied.
GET /orders/{orderId} returns a single order. GET /orders/listbytag filters by tag.
{
"orderId": 94113592,
"orderNumber": "TEST-ORDER-API-DOCS",
"orderKey": "0f6bec18-9-4771-83aa-f392d84f4c74",
"orderDate": "2015-06-29T08:46:27.0000000",
"createDate": "2015-07-16T14:00:34.8230000",
"modifyDate": "2015-09-08T11:03:12.3800000",
"paymentDate": "2015-06-29T08:46:27.0000000",
"shipByDate": "2015-07-05T00:00:00.0000000",
"orderStatus": "awaiting_shipment",
"customerId": 37701499,
"customerEmail": "customer@example.com",
"billTo": {
"name": "The President",
"company": null,
"street1": null,
"city": null,
"state": null,
"postalCode": null,
"country": null,
"phone": null
},
"shipTo": {
"name": "The President",
"company": "US Govt",
"street1": "1600 Pennsylvania Ave",
"street2": "Oval Office",
"city": "Washington",
"state": "DC",
"postalCode": "20500",
"country": "US",
"phone": "555-555-5555",
"residential": false,
"addressVerified": "Address validation warning"
},
"items": [
{
"orderItemId": 128836912,
"lineItemKey": "vd08-MSLbtx",
"sku": "ABC123",
"name": "Test item #1",
"weight": { "value": 24, "units": "ounces" },
"quantity": 2,
"unitPrice": 99.99,
"taxAmount": null,
"shippingAmount": null,
"warehouseLocation": "Aisle 1, Bin 7",
"options": [{ "name": "Size", "value": "Large" }],
"productId": 7239919,
"fulfillmentSku": null,
"adjustment": false,
"upc": null
}
],
"orderTotal": 194.43,
"amountPaid": 218.73,
"taxAmount": 5,
"shippingAmount": 10,
"paymentMethod": "Credit Card",
"requestedShippingService": "Priority Mail",
"carrierCode": "fedex",
"serviceCode": "fedex_home_delivery",
"packageCode": "package",
"shipDate": "2015-07-02",
"weight": { "value": 48, "units": "ounces" },
"dimensions": { "units": "inches", "length": 7, "width": 5, "height": 6 },
"insuranceOptions": { "provider": "carrier", "insureShipment": true, "insuredValue": 200 },
"advancedOptions": {
"warehouseId": 24079,
"storeId": 26815,
"source": "Webstore",
"mergedOrSplit": false,
"parentId": null,
"customField1": "Custom data that you can add to an order",
"billToParty": null,
"billToAccount": null
},
"externallyFulfilled": false,
"externallyFulfilledByName": "Example Fulfillment Provider Name"
}
shipTo, billTo and customerEmail are PII. advancedOptions.storeId identifies which connected sales channel the order came from, and is the field that lets you attribute a ShipStation order back to Amazon, Shopify or eBay. orderKey is the originating channel's identifier and is what you should treat as the channel_order_id when ShipStation is a relay rather than the primary channel.
Money is quirky: orderTotal is a computed value and ShipStation's own docs describe it as read-only. There is no explicit currency field on the order; currency follows the store. Treat that as a per-store constant you configure, not something you can read per order.
Order items
Items are embedded in the order under items[], never fetched separately. adjustment: true marks a pseudo-item such as a discount line with a negative unitPrice; exclude those from quantity maths and fold them into the order discount instead. lineItemKey is the channel's line identifier, orderItemId is ShipStation's.
Products and listings
GET /products and GET /products/{productId}.
This is ShipStation's internal product catalogue, populated from the items that arrive on orders. It is a shipping catalogue, not a sales listing. Published fields:
Sample response not published on the product model page.
Inventory
ShipStation added a stock-tracking feature to the web app, but the v1 reference exposes no inventory endpoint and no quantity field on the product model. Treat inventory as not readable through this API. If a merchant needs stock, read it from the underlying sales channel connector instead.
Shipments and tracking
GET /shipments
Filters: recipientName, recipientCountryCode, orderNumber, orderId, carrierCode, serviceCode, trackingNumber, customsCountryCode, storeId, plus createDateStart/createDateEnd, shipDateStart/shipDateEnd and voidDateStart/voidDateEnd. Set includeShipmentItems=true to get the line items inside each shipment. Pagination is page and pageSize with total, page and pages in the response, same as orders.
{
"shipments": [
{
"shipmentId": 33974374,
"orderId": 43945660,
"orderKey": "8061c220f0794a9b92460b8bae6837e4",
"orderNumber": "100038-1",
"createDate": "2014-10-03T06:51:33.6270000",
"shipDate": "2014-10-03",
"shipmentCost": 1.93,
"insuranceCost": 0,
"trackingNumber": "9400111899561704681189",
"isReturnLabel": false,
"batchNumber": "100301",
"carrierCode": "stamps_com",
"serviceCode": "usps_first_class_mail",
"packageCode": "package",
"confirmation": "delivery",
"warehouseId": 16079,
"voided": false,
"voidDate": null,
"marketplaceNotified": true,
"notifyErrorMessage": null,
"shipTo": {
"name": "Yoda",
"street1": "12223 LOWDEN LN",
"city": "MANCHACA",
"state": "TX",
"postalCode": "78652-3602",
"country": "US",
"phone": "2101235544"
},
"weight": { "value": 1, "units": "ounces" },
"dimensions": null,
"shipmentItems": [
{
"orderItemId": 56568665,
"sku": "SQ3785739",
"name": "Potato Kitten -",
"quantity": 1,
"unitPrice": 1,
"productId": 7565777,
"fulfillmentSku": null
}
],
"labelData": null,
"formData": null
}
],
"total": 2,
"page": 1,
"pages": 0
}
shipmentCost plus insuranceCost is the postage the merchant actually paid, which makes this the best source for real per-order shipping cost in the whole unified model. voided: true shipments stay in the list, so filter them or you will double count postage.
Event history is not in v1. The v1 shipment object gives you a tracking number and a delivery notification flag, not a scan history. For scan-level events you have to use v2:
GET /v2/tracking?carrier_code={carrier_code}&tracking_number={tracking_number}, or GET /v2/labels/{label_id}/track when you bought the label through v2.
Status codes are two-letter: AC accepted, IT in transit, DE delivered, EX exception, UN unknown, AT delivery attempt, NY not yet in system, SP delivered to the collection location.
{
"tracking_number": "9405511899223197428490",
"status_code": "DE",
"carrier_code": "usps",
"status_description": "Delivered",
"events": [
{
"occurred_at": "2021-09-20T19:03:00Z",
"description": "Delivered, In/At Mailbox",
"city_locality": "SARCOXIE",
"state_province": "MO",
"postal_code": "64862",
"event_code": "01"
}
]
}
To avoid polling, register the tracking number once with POST /v2/tracking/start and stop with POST /v2/tracking/stop; scan updates then arrive on the API_TRACK webhook described below. POST /v2/tracking/start is the single most useful call on the whole platform for a shipment database.
Returns and cancellations
There is no return object. Returns exist only as return labels: a v1 shipment with isReturnLabel: true, or a v2 label created with is_return_label set. Cancellation shows as an order in orderStatus: cancelled. Refund amounts are not exposed. Anything richer has to come from the underlying sales channel.
Payments and settlements
None. ShipStation is not a money mover for order revenue. amountPaid and paymentMethod on the order are copied from the sales channel; there is no payout, settlement or fee object. Postage spend is visible only per shipment via shipmentCost, and as a carrier balance through GET /carriers and GET /carriers/getcarrier.
Customers
GET /customers and GET /customers/{customerId}. Customers are derived from order history, keyed on customerId with customerUsername and customerEmail on the order. All of it is PII, unmasked. Store it only if the merchant has told you to.
Locations
GET /warehouses returns the merchant's ship-from locations, referenced from the order as advancedOptions.warehouseId and from the shipment as warehouseId. GET /stores returns the connected sales channels, referenced as advancedOptions.storeId; this is the table that turns a ShipStation order into an attributed marketplace order. POST /stores/refreshstore forces a pull from a connected channel.
GET /carriers, GET /carriers/listservices?carrierCode= and GET /carriers/listpackages?carrierCode= give you the code vocabulary you need to interpret carrierCode, serviceCode and packageCode on every order and shipment. Cache all three at connector start; they are small and change rarely.
Writing back: listings, price and stock
Not applicable in the marketplace sense. ShipStation is a shipping platform, not a sales channel: it does not own a buyer-facing listing, and there is no endpoint that changes the price or the stock of anything a customer can see. Price changes belong in the Shopify, Amazon or eBay connector.
What ShipStation does accept is a write path for its own catalogue and, far more importantly, for shipments.
The real write path is shipment creation and cancellation.
POST /shipments/createlabelcreates a shipment and returns the label. The response includestrackingNumberandlabelData, a base64 encoded PDF. SettestLabel: trueto exercise the call without buying postage.
{
"carrierCode": "fedex",
"serviceCode": "fedex_ground",
"packageCode": "package",
"confirmation": "delivery",
"shipDate": "2014-04-03",
"weight": { "value": 3, "units": "ounces" },
"dimensions": { "units": "inches", "length": 7, "width": 5, "height": 6 },
"shipFrom": {
"name": "Jason Hodges",
"company": "ShipStation",
"street1": "2815 Exposition Blvd",
"city": "Austin",
"state": "TX",
"postalCode": "78703",
"country": "US",
"residential": false
},
"shipTo": {
"name": "The President",
"company": "US Govt",
"street1": "1600 Pennsylvania Ave",
"street2": "Oval Office",
"city": "Washington",
"state": "DC",
"postalCode": "20500",
"country": "US",
"residential": false
},
"testLabel": false
}
{
"shipmentId": 123456789,
"createDate": "2016-04-03T12:11:36.8630000",
"shipDate": "2016-04-03",
"shipmentCost": 9.06,
"insuranceCost": 0,
"trackingNumber": "782390443992",
"isReturnLabel": false,
"carrierCode": "fedex",
"serviceCode": "fedex_ground",
"packageCode": "package",
"confirmation": "delivery",
"voided": false,
"labelData": "JVBERi0xLjQKJeLjz9MKMiAwIG9iago8PC9MZW5ndGgg..."
}
POST /orders/createlabelfororderdoes the same but attaches the label to an existing order and moves it toshipped.POST /shipments/voidlabelwith{"shipmentId": 12345}cancels a label. The response is{"approved": true, "message": "Label voided successfully"}. Voiding is subject to the carrier's own window, so afalseinapprovedis a carrier refusal, not a transport error.POST /shipments/getratesreturns rate quotes for a shipment shape before you commit.POST /orders/markasshippedrecords a shipment bought elsewhere against an order. Required fields areorderIdandcarrierCode; optional areshipDate,trackingNumber,notifyCustomerandnotifySalesChannel.
Order write path. POST /orders/createorder creates or updates one order: if the orderKey in the body matches an existing order it updates, otherwise it creates. There is no partial update, you must send the whole order resource, and only orders in awaiting_payment, awaiting_shipment or on_hold can be modified. cancelled and shipped orders are immutable. POST /orders/createorders does the same in bulk, and there are helpers for holds (/orders/holduntil, /orders/restorefromhold), tags and user assignment. DELETE /orders/{orderId} soft-deletes.
Product write path. Products can be updated in ShipStation's own catalogue, which is useful for keeping shipping defaults and customs data correct. It has no effect on any sales channel.
v2 equivalents. POST /v2/labels buys a label directly, POST /v2/labels/{label_id}/void voids it, POST /v2/rates quotes, POST /v2/pickups schedules a carrier collection, POST /v2/manifests closes out the day, and POST /v2/batches runs bulk label creation asynchronously.
Webhooks and notifications
v1 webhooks
POST /webhooks/subscribe with:
{
"target_url": "https://example.com/neworder",
"event": "ORDER_NOTIFY",
"store_id": null,
"friendly_name": "My Webhook"
}
The response is {"id": 123456}. GET /webhooks lists subscriptions, DELETE /webhooks/{webhookId} removes one. Setting store_id scopes the subscription to one connected sales channel; leaving it null covers all of them.
Event types: ORDER_NOTIFY, ITEM_ORDER_NOTIFY, SHIP_NOTIFY, ITEM_SHIP_NOTIFY, FULFILLMENT_SHIPPED, FULFILLMENT_REJECTED.
The important design point: a v1 webhook does not carry the object. It carries a resource_url that you then call with your basic auth credential to fetch the changed records. Budget for that second call in your rate limit planning, and be aware that it means the webhook itself needs no signature verification to be useful, because nothing sensitive is in the body. It also means an attacker can make you burn requests, so rate-limit your own receiver.
v2 webhooks
POST /v2/environment/webhooks with a body of url and event:
{
"url": "https://example.com/batch",
"event": "batch"
}
Resource types delivered: API_BATCH (batch completed), API_RATE (shipment rate updated), API_TRACK (any tracking event), API_CARRIER_CONNECTED, API_SALES_ORDERS_IMPORTED, API_ORDER_SOURCE_REFRESH_COMPLETE, API_REPORT_COMPLETE.
Verification is a real signature, unlike v1. Each delivery carries three headers:
x-shipengine-rsa-sha256-key-idx-shipengine-rsa-sha256-signaturex-shipengine-timestamp
Rebuild the signed string as timestamp then a full stop then the raw request body, and verify the RSA-SHA256 signature against the public key fetched from https://api.shipengine.com/jwks, selecting the key by the key id header. Verify against the raw bytes, not a re-serialised JSON object.
Retries: you have 10 seconds to return a 2xx. If you do not, there are two further attempts roughly 30 minutes apart. After three total failures the event is dropped, with no replay endpoint. That makes an idempotent receiver plus a nightly reconciliation sweep mandatory rather than optional.
A sample API_TRACK body:
{
"resource_url": "https://api.shipengine.com/v1/tracking?carrier_code=usps&tracking_number=9400111298370264401222",
"resource_type": "API_TRACK",
"data": {
"tracking_number": "9400111298370264401222",
"status_description": "In Transit"
}
}
If you cannot take webhooks
Poll GET /orders?modifyDateStart=...&sortBy=ModifyDate&sortDir=ASC and GET /shipments?createDateStart=... on a 15 minute cadence with an overlap of a few minutes to absorb clock skew. That is comfortably inside the v1 budget even for a large merchant.
Rate limits and pagination
v1. 40 requests per minute per API key and secret pair, measured across the whole account. Exceeding it returns HTTP 429 with the body Too Many Requests. Every response carries:
X-Rate-Limit-Limit: the maximum requests per minute for the endpointX-Rate-Limit-Remaining: requests left in the current windowX-Rate-Limit-Reset: seconds until the window resets
Sleep for X-Rate-Limit-Reset seconds on a 429 rather than backing off blindly; the window is a fixed minute, so a naive exponential backoff wastes most of it. 40 per minute is tight. With pageSize=500 a full order backfill of 100,000 orders is 200 requests, about five minutes of continuous quota, which is fine, but a webhook-driven design that fetches a resource_url per event will hit the ceiling on a busy merchant. Queue the fetches and drain at a fixed 30 requests per minute to leave headroom for the sync job.
v2. 200 requests per minute by default. A 429 includes a Retry-After header giving the seconds to wait. Responses may include an error_source field distinguishing a ShipStation limit from a downstream carrier or marketplace limit, which matters because a carrier-sourced 429 will not clear when your own window resets. Higher limits are granted on request to apisupport@shipstation.com.
Pagination. v1 is offset paging everywhere: page from 1, pageSize up to 500, with total, page and pages returned. Offset paging over a moving result set will skip and duplicate rows, so always pin the window with a date filter and sort ascending on the same field you are filtering. v2 uses page and page_size with a links object carrying first, last, prev and next hrefs; follow links.next rather than incrementing yourself.
Mapping to the unified model
orders
order_items
listings
inventory
No inventory object is exposed. Leave the table unpopulated from this connector.
shipments
returns
settlements
Not available. ShipStation exposes no payout or fee statement.
customers
locations
Gaps and open questions
- No currency field on the order. Confirmed absent from the documented order model. It has to be configured per store, which is fragile for merchants selling in several currencies through one ShipStation account. Worth a support question before going live in a multi-currency account.
- The v1 sunset. ShipStation ships new capability on v2 and describes it as the current API, but has published no end-of-life date for v1. Since v1 is the only place orders, products, customers and stores are exposed in the shape the web app uses, a v1 retirement would force a rewrite. Ask an account manager for a written position before building on v1 alone.
- v2 sales orders. There is a sales order layer on v2 (
list_sales_orders,get_order_by_id, order sources) that overlaps with v1 orders. Its availability appears tied to the ShipStation API product rather than the Platform product, and the docs site is client-rendered so the reference pages could not be read directly by the fetcher. Which accounts can use it was not verified. - Rate limit scope. The v1 documentation says 40 per minute per key pair, but the
X-Rate-Limit-Limitheader is described as the maximum for "the endpoint", which suggests some endpoints may carry their own budget. Not resolvable from the docs; measure it against a real account. - Inventory. The web app has stock tracking; the API reference has no inventory endpoint. Whether a v2 inventory surface exists for some account tiers was not confirmed.
- Batch labels.
POST /v2/batchesis asynchronous and reports through theAPI_BATCHwebhook, but the failure semantics of a partially successful batch were not verified. - The v2 reference pages on docs.shipstation.com render client side and returned empty or 404 bodies to the fetcher. The v2 facts on this page come from the official guides that do render server side (authentication, rate limits, webhooks, tracking) and from the first-party ShipEngine OpenAPI specification. Individual v2 request and response samples should be re-read from the live docs before implementation.
Sources
- ShipStation API v1 reference
- ShipStation API v1 requirements: base URL, basic auth, rate limits, date format
- List orders
- Get order
- Create or update order
- Mark an order as shipped
- List shipments
- Create shipment label
- Void a label
- Subscribe to a webhook
- Product model
- ShipStation API v2 authentication and security
- ShipStation API v2 rate limits
- ShipStation API v2 webhooks guide
- ShipStation API v2 tracking guide
- ShipEngine OpenAPI specification on GitHub, first party
- docs.shipstation.com sitemap, used to enumerate the documented endpoint set