ShopEazydevelopers
API referenceMerchant API BetaOrders

Do one thing to several orders at once

Beta
Credentials
  • OAuth access token
Scopes
orders:write
Subscription
Needs an active plan. Otherwise 403 subscription_locked.
Idempotency
Send an Idempotency-Key header. A retry with the same key does the work once.
POST
/v1/merchant/stores/{storeId}/orders/bulk

Up to 200 orders. Every order is re-read and decided again (an order that cannot take the action, one already in that state, one that is gone, a sold-out item) and then goes through the same service call, audit entry and customer emails as its single-order operation. One failing never stops the rest; orders run a few at a time.

The answer is one { id, ok, error? } per id (BulkResult), always 200. A retry is safe: each order is decided again from a fresh read, so one already done is left alone (ok: false, validation_error, for example already cancelled) and nothing happens twice; the same Idempotency-Key replays the first answer.

The scope is orders:write; cancel calls off a booked courier collection per order, as cancelOrder does. The refund-bearing paths stay with refundOrder (orders:refund).

Access: OAuth scope orders:write; write-gated by the subscription.

Authorization

merchantOAuth orders:write
headerAuthorizationBearer <token>

OAuth 2.1 (authorization code + PKCE S256, public clients, dynamic registration) for connected AI apps. Effective power is scopes granted AND the person's role today AND the plan. orders:refund, billing:write and team:write are opt-in on the consent screen. Write implies read for marketing:read and messages:read, so a grant holding marketing:write passes a marketing:read check, and messages:send passes messages:read.

Scope: orders:write

Path Parameters

storeId*string

A store the person can reach. Any other id answers 404, never 403.

Header Parameters

Idempotency-Key*string

Required on every write. Minted on the device when the person taps, reused on every retry. A write without one, or with one that does not match the pattern, is refused with 422 validation_error. Scoped to the token's subject, remembered 24 hours. A replay returns the first 2xx response with Idempotent-Replay: true; a request still running answers 409 in_flight; the same key with a different method, path or body answers 409 idempotency_key_reused; non-2xx results are not remembered. If the key store cannot be read nothing is processed and the answer is 503 idempotency_unavailable: retry with the same key.

Match^[A-Za-z0-9_-]{8,128}$

Request Body

application/json
  1. body
op*string

paid marks paid (with method), fulfil hands everything over, ready marks ready to collect, cancel cancels, remind asks the customer to pay. Each is the same use case, audit entry and customer email as its single-order operation (markOrderPaid, fulfilOrder, markReadyToCollect, cancelOrder, remindToPay); there is no bulk-only write path.

Value in"paid""fulfil""ready""cancel""remind"
ids*array<string>

The orders to act on, at most 200 (the console's cap). Repeated ids are counted once.

Items1 <= items <= 200
method?string

For paid only: how it was paid. Default Cash. An order awaiting EFT keeps its EFT reference.

Value in"Cash""Card""EFT""SnapScan""Zapper""Other"

Response Body

OK

application/json
  1. response
data*

The answer to every bulk operation. One item failing never stops the rest, so the call is 200 even when some or all were left alone; read items.

Example Request
curl -X POST 'https://api.shopeazy.co/v1/merchant/stores/<storeId>/orders/bulk' \  -H 'Authorization: Bearer <access_token>' \  -H 'Idempotency-Key: <unique_key>' \  -H 'Content-Type: application/json' \  -d '{  "op": "paid",  "ids": [    "string"  ]}'
Example Response
{  "data": {    "items": [      {        "id": "string",        "ok": true,        "error": {          "code": "string",          "message": "string"        }      }    ],    "done": 0  }}