Set what a product is made from
- Credentials
- OAuth access token
- Scopes
listings:write- Subscription
- Needs an active plan. Otherwise
403 subscription_locked. - Plan
- Scale. A plan without it gets
403 plan_limit. - Idempotency
- Send an
Idempotency-Keyheader. A retry with the same key does the work once.
Replaces the whole recipe: the materials and the quantity of each per unit made, which recordBuild then takes off. Each line's name and unit are read from the material when it is saved. An unknown material is 422 validation_error; a product that is gone or is not physical is 404 not_found / 422.
Plan: Scale (403 plan_limit on a plan without it): starting something new needs Scale, as addSupplier does. getProductRecipe stays open after a downgrade. Replacing with the same lines changes nothing, so a retry is safe.
Access: OAuth scope listings:write; write-gated by the subscription.
merchantOAuth listings:writeAuthorizationBearer <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: listings:write
storeId*stringA store the person can reach. Any other id answers 404, never 403.
productId*stringAn item id (any kind, not only physical products).
Idempotency-Key*stringRequired 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.
^[A-Za-z0-9_-]{8,128}$application/json- body
lines*array<>What one unit is made from. Empty means no recipe.
items <= 100OK
application/json- response
data*curl -X PUT 'https://api.shopeazy.co/v1/merchant/stores/<storeId>/products/<productId>/recipe' \ -H 'Authorization: Bearer <access_token>' \ -H 'Idempotency-Key: <unique_key>' \ -H 'Content-Type: application/json' \ -d '{ "lines": [ { "materialId": "string", "quantity": 1 } ]}'{ "data": { "lines": [ { "materialId": "string", "name": "string", "quantity": 1, "unit": "each" } ] }}What a product is made from GET
The bill of materials `recordBuild` takes off the shelves for each unit made. A product with none answers `{ lines: [] }`. Only physical products have one. Access: OAuth scope `listings:read`; not write-gated.
Raw materials, A to Z GET
What the shop holds but does not sell: stock on hand, unit, cost and reorder point. Quantities are in the unit family's base (grams, millilitres, millimetres, or each). Access: OAuth scope `listings:read`; not write-gated. Paged: `{ items, nextCursor }`, `limit` (default 100, at most 200) and an opaque `cursor`.