Skip to content

The OLET public API is versioned in the URL path. Breaking changes ship as a new version path; /v1 keeps its current shape for as long as it is offered.

The version is still 1.0.0. No response shape that existed before has changed since the first release; the entries below add fields and refusals.

  • A stock write can now carry unit_cost, an integer number of cents. On PUT /products/{id}/inventory/{outlet_id} and on a set line in a batch, it becomes the outlet’s average cost. On POST /inventory/adjustments and on an adjust line, it is blended into the average when stock goes up and ignored otherwise. Leave it out to keep the current average.
  • A stock write that names a system reason, or a reason that is turned off, now answers 422 REASON_NOT_ALLOWED. A reason must be enabled and must not be a system reason.
  • A stock write at an outlet that has been deleted answers 422 OUTLET_DELETED. It used to answer the generic UNPROCESSABLE. Nothing is written, and a batch writes none of its lines.

The first public release. It covers catalog (products, brands, categories, tags, suppliers), inventory (stock reads, sets, relative adjustments, and batch writes), customers, sales and refunds (read only), and account and store settings, 44 operations in all.

Every list endpoint pages with a cursor and supports polling for changes; product and sale reads return the full document in one call rather than a slimmer summary with separate sub-resource reads. Money is always an integer number of cents. Writes to inventory endpoints support an Idempotency-Key for safe retries.

What shaped this release:

  • One product document. A product read carries its codes, tags (with names), suppliers (with supplier_name), variant_options, variant_attributes and components. POST /products and PATCH /products/{id} accept the same document: leave a collection out to keep it, send [] to clear it, and the whole write is atomic. The separate endpoints for a product’s codes, tags, suppliers, components and attributes were removed before release. See write a whole product in one request.
  • Cursors and versions. The version on a row and the list cursor follow the whole document, so a product comes back in a poll when anything attached to it changes. A cursor the server cannot read answers 400 VALIDATION_FAILED instead of restarting at the first page, and an empty page returns next_cursor: null. See pagination and polling.
  • Scopes. Catalog access uses catalog:read and catalog:write. Every scoped endpoint names the scope it needs.
  • Deletes. DELETE exists for products, brands, categories, tags, suppliers and customers, and brands, categories and tags have GET by id. Deleting a customer permanently erases their personal details and cannot be undone. See delete and erase.
  • Stock by SKU. Stock adjustments and batch lines accept sku in place of product_id.
  • Images. image_url imports a product image from an https address. A failed download answers 422 IMAGE_FETCH_FAILED with the saved product in data.
  • OAuth. Apps connect with the authorization code flow, and the spec describes both API keys and OAuth. See authentication.
  • The spec. GET /openapi.json under your store prefix serves the full OpenAPI document with your prefix in its server URL, and every operation description is written in markdown.

See the quickstart to make your first call, or the full API reference for every operation this version covers.