Overview
Order Supliful products from your own systems.
The Supliful public API lets a partner list the products a connection exposes and place orders against them, authenticated with an API key issued from the store list in the Supliful app.
Supliful fulfills every order you place: we pack it, ship it to your customer, and report each step back to you through webhooks.
Start here
- API Reference — every endpoint, with request and response schemas.
- Errors — every problem type the API returns, and what to do about each one.
- Webhooks — the events Supliful sends you, how to verify them, and a page that fires a real one at your endpoint.
- Order lifecycle — drive a test order from created to completed, and watch the webhooks follow it.
If you use a coding agent for your integration, install the agent skill. It provides the endpoint reference, webhook verification, error types and OpenAPI spec, so the agent works from the documented contract.
Authentication
Send your key as Authorization: Bearer <key>; x-api-key: <key> is accepted
too. GET /v1/me has no side effects and returns the connection a key acts
as, which makes it the quickest way to check a credential.
Products
GET /v1/products lists what a merchant has exposed to your connection,
oldest first. Page with limit (50 by default, 100 at most) and the opaque
nextCursor from the previous page — do not parse a cursor, and do not page by
offset: the merchant may publish while you sync, and the cursor is what keeps a
new product from displacing rows you have not read yet.
A product the merchant exposes while you are paging may land on a later page,
or not until your next pass. product.published tells you about it straight
away.
sku is a filter, not a lookup. Nothing stops a merchant giving two
products the same SKU, so ?sku= returns a list that may legitimately hold
more than one product — do not assume data[0]. To fetch exactly one product,
use GET /v1/products/{id} with the UUID.
A product whose status is discontinued still resolves, so orders already
placed against it stay readable, but a new order naming it is refused with
422 validation-failed. Stop offering it.
Ordering
POST /v1/orders takes a shipping address and a list of
{ productId, quantity } lines, where each productId comes from
GET /v1/products. A product the merchant has not exposed to your connection
is refused exactly like one that does not exist.
Send an Idempotency-Key header, or an externalOrderId — your own identifier
for the order, which is used as the key when the header is absent. Retrying a
request that already succeeded returns that order, as it stands now, with
200 rather than creating a second one. A request carrying neither is refused
with 400, because there would be no safe way to retry it.
A key belongs to the request it was first sent with. Reusing it for a different
request is refused with idempotency-key-reused
rather than answered with the first order. An externalOrderId is unique per
connection, so a second order claiming one is refused with
order-already-exists, even under a new key.
Prices are the merchant's, not yours: an order records what Supliful charges
the merchant, and your own retail pricing never reaches us. Shipping is priced
when the order is routed, so the order you get back carries no shipping cost.
Carrier tracking mail goes to the merchant's account email. To keep your buyer
informed, use the trackingUrl on each shipment, returned by
GET /v1/orders/{orderId} and the order.shipmentCreated webhook. It is
null until the carrier has issued tracking.