API and Webhooks
REST endpoints for orders, inventory, shipments, and returns. OAuth 2.0 authentication, idempotency keys on writes, signed webhook events on every state change. Documented like a SaaS product, because that is what it is.
TL;DR
Most 3PL APIs were retrofitted onto a WMS that predated REST. They expose 40 endpoints with inconsistent naming, a custom auth scheme, no idempotency, and documentation that has not been updated since the last leadership change. The result is integration projects that take quarters and break on every minor release. Industry coverage of 3PL technology consistently calls out API quality as one of the top criteria for engineering-led brands evaluating a partner[1].
Warpspeed's API was written this decade by engineers who had built and integrated against modern SaaS products. The conventions follow the patterns you already know from Stripe, Shopify, and the major payment platforms. Read the docs once and the rest is muscle memory.
Section 01
We support two authentication models. Service-to-service integrations use the OAuth 2.0 client credentials grant. The client receives a token that expires in one hour and refreshes through the same endpoint. For internal tools and scripts a brand can mint scoped API tokens directly from the dashboard, with an explicit scope list and an optional expiration date.
HTTP
POST https://api.gowarpspeed.com/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=ws_live_abc123
&client_secret=...
&scope=orders:write inventory:readScopes are granular: orders:read, orders:write, inventory:read, inventory:write, shipments:read, returns:write, and so on. A token issued for inventory:read cannot be used to mutate orders, even if it is leaked. We rotate signing keys on a quarterly cadence and notify integrated clients ahead of any breaking change to the auth surface.
Section 02
The API exposes the four primary objects a brand needs to integrate with a 3PL: orders, inventory, shipments, and returns. Each resource follows the same conventions: list with cursor pagination, retrieve by id, create or update with idempotency keys, and a corresponding webhook stream for state changes.
Primary REST endpoints (v1)
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/orders | List orders with filters and cursor pagination |
| POST | /v1/orders | Create an order with shipping address and line items |
| GET | /v1/orders/{id} | Retrieve a single order with full timeline |
| PATCH | /v1/orders/{id} | Update an order before fulfillment release |
| GET | /v1/inventory | List inventory with filters by SKU, lot, and channel |
| POST | /v1/inventory/adjustments | Submit a manual adjustment with reason code |
| GET | /v1/shipments | List shipments with carrier and tracking detail |
| GET | /v1/shipments/{id}/tracking | Latest tracking events from the carrier |
| POST | /v1/returns | Create a return authorization linked to an order |
| GET | /v1/returns/{id} | Retrieve a return with received units and disposition |
All list endpoints support filtering by a standard set of query parameters and return cursor-based pagination. Cursors are opaque strings that survive backend reshards, so a long-running export does not break when the underlying data partition changes. The pattern follows the recommendations in the JSON:API spec and the pagination guidance from leading API style guides[2].
HTTP
GET /v1/orders?status=released&limit=100&cursor=eyJpZCI6...
Authorization: Bearer ws_live_token_hereSection 03
Polling a 3PL API every minute for status updates is wasteful and slow. Webhooks deliver state changes in near-real-time, usually inside the same second the event happens on the warehouse floor. A brand can subscribe to any combination of event types and route them to one or more endpoints.
Available webhook events
| Event | Trigger |
|---|---|
| order.created | An order is accepted by the API |
| order.allocated | Inventory is reserved for the order |
| order.shipped | A label is generated and the order moves to in-transit |
| order.delivered | Carrier confirms delivery |
| order.exception | Any exception type is opened on an order |
| inventory.adjusted | An adjustment is committed against a SKU |
| inventory.received | An inbound PO is received and put away |
| shipment.tracking_updated | Carrier tracking event added |
| return.created | A return authorization is opened |
| return.received | Returned units arrive at the facility |
Every webhook payload is signed with an HMAC SHA-256 signature in the X-Warpspeed-Signature header. The signing convention follows the pattern popularized by Stripe and is documented with a code sample in five major languages[3]. Verify the signature on every request, then handle the payload. Never trust a webhook without verifying the signature.
Node.js
import crypto from "crypto"
const expected = crypto
.createHmac("sha256", process.env.WARPSPEED_WEBHOOK_SECRET)
.update(rawBody)
.digest("hex")
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(receivedSig))) {
return res.status(400).end("invalid signature")
}Section 04
Network failures happen. Without idempotency, a retried POST that creates an order can create two orders. Every Warpspeed write endpoint accepts an Idempotency-Key header. The first request with a given key is processed and the response is cached. Subsequent requests with the same key return the cached response, regardless of whether the original succeeded or failed.
HTTP
POST /v1/orders
Authorization: Bearer ws_live_token
Idempotency-Key: order_create_acme_8c54
Content-Type: application/json
{
"external_id": "shopify_1024",
"ship_to": { "name": "...", "address1": "...", "city": "...", "state": "..." },
"line_items": [{ "sku": "TEE-001-RED-M", "quantity": 1 }]
}The pattern follows the recommendations in the IETF idempotency draft and the implementation precedent set by Stripe[4]. Brands should generate a new key for each logical operation, typically a UUID or a deterministic hash of the source object. Reusing a key across distinct operations is the most common bug in idempotent client code.
Section 05
The default rate limit is 120 requests per minute per token, applied as a sliding window. Bursts up to 30 requests per second are allowed. Writes against the same order id are serialized to prevent race conditions on allocation. Brands with bulk replenishment or seasonal spikes can request a higher limit from their account team and we provision additional capacity at no cost when the use case is operational rather than aggressive polling.
Standard response headers
| Header | Meaning |
|---|---|
| X-RateLimit-Limit | Total requests allowed in the current window |
| X-RateLimit-Remaining | Requests remaining in the current window |
| X-RateLimit-Reset | Unix timestamp when the window resets |
| Retry-After | Seconds to wait before retrying after a 429 response |
When you hit the limit, the API returns HTTP 429 with a Retry-After header. Implement exponential backoff with jitter on retry. The Google API design guide and the AWS architecture documentation both recommend this pattern as the default for any production client[5].
Section 06
The current public API is v1. Breaking changes require a new major version, and we run any deprecated version for at least 12 months past the announcement of its successor. Non-breaking additions, such as new optional fields on a response, are released continuously without a version bump. The convention mirrors the public commitments made by major platform APIs[6].
Every response carries a Warpspeed-API-Version header that records the version served. Brands can pin a specific version with an Accept header on each request. The pin is honored for the life of that version's support window. We notify all integrated clients by email and in the dashboard at least 90 days before any version reaches end of life.
“A 12-month deprecation window is a contract, not a courtesy.”
Section 07
Most brands fall into one of three integration patterns. The first is the commerce-platform brand that runs Shopify, BigCommerce, or Amazon and wants Warpspeed to plug in transparently. For these accounts the prebuilt integrations handle order creation and tracking, and the API is used only for custom reporting or returns workflows.
The second is the headless brand that runs a custom storefront and treats the Warpspeed API as their order management system. They POST orders directly from checkout, listen for shipment webhooks, and surface tracking inside their own customer account. The API was designed for this case.
The third is the operations team that already runs an internal ERP or order management layer. They use Warpspeed as the fulfillment node, pushing orders in batches and pulling state changes through webhooks for downstream consumers like ticketing, finance, and BI. We provide reference webhook handlers and OpenAPI schemas to accelerate that integration.
For developers
Tell us a little about your stack and we will provision a sandbox tenant, issue API credentials, and connect you to a solutions engineer who can answer implementation questions.