Vizen Shop

llms.txt — reading order for agents

/llms.txtcurrentEN

Multi-tenant e-commerce platform. One personal token lets an agent build and fill an entire shop: catalogue, pages, layouts, own HTML/CSS/JS with live shop data, orders and forms. Base URL: https://api.vizen.shop — send Authorization: Bearer vz_pat_<key> on every request.

Read in this order. The first two are not optional: skipping them is how agents end up rebuilding work they already did.

  1. `GET /v1/account/token` — the key passport, and the only reliable statement of your rights. Public endpoints answer 200 without catalog:read too, using an anonymous projection, so "200 on /products" proves nothing. Before the first write, take these from it: writes_to_live (tell the owner visitors see changes immediately), contour (prod writes to the live shop, dev to a draft a human then publishes), store.currency (a price in the wrong currency is rejected, and a token cannot change the currency), store.storefront_url (the address of the shop you are editing — do not guess it), capabilities (what this key may actually call: holding a scope is not the same as the method being open to it), and warnings[] (pass them on verbatim).
  2. `GET /docs/skills` — the platform explained by the path your task takes. Start with vizen-start: it asks the three questions that decide everything else. One agent skipped this fork and threw away 12% of its work.
  3. `GET /docs/skill/vizen-transfer` — when a finished site, template or export already exists (a folder, a React/Vite build, a design-tool export). It moves the folder as it is, one command per folder, in real page DOM. Do not rebuild it, and do not open the web-coding guide for that: the guide describes blocks built from scratch, and one shop spent three generations of documents and 31 releases before its finished design reached the site 1:1.

Two rules that hold everywhere. Look up before writing — field names, enum values and defaults come from the generated references below, never from memory. Verify by looking, not by status code — a 200 means the value was stored, not that it is used; an unknown enum value is accepted and the default is drawn.

Skills — by the path the task takes

  • All skills: index with descriptions
  • vizen-start: entry point, key passport, the three questions, routing
  • vizen-transfer: a finished site or template into the shop as it is — folder = widget, layout folder, header/footer, product template, data re-binding
  • vizen-widgets: platform blocks and their props — live data, bounded look
  • vizen-own-markup: your own HTML/CSS/JS, vz- keys, the block wrapper, images
  • vizen-chrome: header, menu, footer, layouts, second chrome kit
  • vizen-catalog: products, categories, filters, the image resizer
  • vizen-troubleshoot: "I set it, got 200, nothing changed" — and the acceptance checklist

Check before you write

  • Validate: POST the same {"sections":[…]} you would send to /content-blocks/{id} and get a verdict per path — applied, ignored (accepted and does nothing) or unknown (value not understood, default drawn). Nothing is written. This is the cheapest way to catch the class of failure where the API answers 200 and the site does not change.

Generated references — derived from the storefront code, not retyped by hand

  • Widgets: every block kind, its write path, a JSON Schema of its props with defaults and enums, plus the wrapper — the axes every block has AND the defaults of the wrapper divs themselves. Both halves are generated from the storefront code, and since 2026-08-19 every wrapper row carries anchor.at, the file:line that sets the value. Print it instead of remembering it: curl -s .../docs/widgets | jq -r '.wrapper.elements[] as $e | $e.defaults[] | [$e.selector, .property, .value, .anchor.at] | @tsv'. This section used to be a hand-written table and it lied about three things; anything you hold that names a props.innerMax is a copy of that table.
  • Own markup keys: vz- keys, the page scope, isolation levels, recipes
  • OpenAPI: 170+ paths, feed it to a client generator

Areas — read the one your task lands in, before its endpoints

An area is behaviour that no single endpoint explains. They are in the order they become useful, not alphabetical: catalogue first because everything else shows its data, diagnosis last because you open it when something already went wrong. Five are drafts — measured and accurate, but no external run has used them yet.

  • Catalogue: products, categories, filters, images — reading a shop and filling it. Read it before the first /products call: a filter written without the filter. prefix is swallowed and returns the whole catalogue with a 200.
  • Transfer a finished site *(draft)*: you already have a site — move it, do not rebuild it. What the platform does to your file (the wrapper, the head, CSS scoping, the site cascade and its preflight, the script lifecycle), the copy · remap · drop table, and notes for React/Vite, Tailwind and design-tool exports.
  • Widgets: the fast path — platform blocks with live data, a look as wide as their props. Read it before configuring one: props are nested (props.listing.…), and a write to the root of props is accepted and does nothing. The generated schema of those props is /docs/widgets; the area is -area because that name was already taken by it.
  • Own markup: the bespoke path — your own HTML, CSS and JS over live shop data. vz- keys and substitutions, the live products[] feed and its four boundaries, images through the resizer, and §5: the wrapper every block lives in, plus the two ways to make a block unique — your own class on the wrapper (props.wrapperClass) or one wrapper axis switched off.
  • Components *(draft)*: the same markup on many pages with different content — a folder with component.json beside index.html, {{key}} in the markup, values per insertion, one new release updating all of them. Substitution is typed and server-side: no raw {{ }} ever reaches the storefront. One page, one piece of code — stay on own markup.
  • Site chrome: header, menu, footer, LAYOUTS and which pages get which set. The fact no guide states: a chrome group takes any block, including your own markup — that is how a custom header is built.
  • Quantity pricing: fixed product/variant prices by quantity. Read it before adding wholesale tiers: a winning rule hard-locks promotions, is protected by dedicated sensitive pricing:* scopes, and is not a cost or payout field.
  • Promotions, coupons and sets: the discount engine — rule kinds, the item → order → key ladder, why only one rule wins per class, the refusal codes, and GET /promotions/landscape for the whole picture in one call. Read it before printing any price next to a discount: the price a shopper sees is computed, not stored, so a client that recomputes it disagrees with the cart on the first product two rules touch.
  • Orders and the cart *(draft)*: an order is a snapshot. Checkout freezes prices, discounts and composition, and no code path rewrites them afterwards — so editing a promotion changes no order that already exists. Four statuses, movable in both directions; the cart itself is closed to a personal token.
  • Stock *(draft)*: a number on the product plus a ledger beside it. NULL means not tracked (a service, a made-to-order item), not zero — without that distinction a seller who never set stock reads as sold out. The ledger explains the number but does not reconstruct it.
  • Webhooks: a signed POST per event, delivered at least once and unordered — dedupe by event_id, answer 2xx within 10 s, verify X-Vizen-Signature over the raw body. Subscriptions are made by a person in the cabinet, not by a token; events that carry personal or commercial data need the owner. The event names an object — read it, do not reconstruct it. Machine list: /docs/events.json.
  • Resource access and site publication *(draft)*: a shop's site can be unpublished — closed behind a short numeric PIN while it is built, Disallow: / for crawlers, noindex on every response, and three wrong PINs locking an address out for 10 minutes. Two methods (GET/PUT /site-publication; the GET returns the PIN in plain text, by design, to the owner only), and POST /storefront/access/unlock is how a visitor gets in. The per-resource password matrix in the same document is still staged — do not build on it yet.
  • Troubleshooting: open it when the API answered 200 and the site did not change — the order of diagnosis (re-read the object, then open the page), the table of silent refusals, and the acceptance checklist every storefront change has to pass.

Guides

  • Quickstart *(Russian)*: issue a token, read its passport, create products (one or 100 per batch), upload images (presign or by URL), respect the rate limits, hand the work over
  • Web coding *(Russian, 178 KB — open on demand, section by section)*: level-1 html blocks inside a page built from widgets — wrapper modes, resizer image rules, page assembly, forms. Not the transfer path: a finished folder is level 3 and lives in /docs/transfer; its sections 5, 7, 8a and 11 describe level 1 and do not apply to a level-3 widget.
  • Catalogue import: products, categories, attributes, variants, groupings
  • Own markup keys, readable: the same key table as prose
  • Token scopes and webhook events: generated from the whitelists the API enforces — print them instead of remembering them
  • Index of everything: every document with its path, title, read_when and status — the same list the human site at https://vizen.shop/docs is built from

Things that cost other agents real time

  • Catalogue filters need the filter. prefix. ?category_id=168 is swallowed silently and returns the whole catalogue — no error, just the wrong data. Compare total before and after adding a filter.
  • sections is a replace-set: read the block, change one element, send the whole list back. Sending one section deletes the rest.
  • Own markup at level 1 renders inside a shadow root — a plain querySelector does not see it; walk element.shadowRoot recursively. A transferred folder (level 3) is real page DOM: querySelector works, and the site's own stylesheet (Tailwind preflight) applies to it — ship your own base styles.
  • A finished site is moved, not rebuilt. If the owner hands you a folder, a build or an export, take vizen-transfer; rebuilding a finished design costs the whole build.
  • Author scripts run on first parse and are re-run after an in-site click (re-init on vz:navigate, not on DOMContentLoaded); they never run on /cart, /checkout, /account and the other guarded zones.
  • To make a block look unlike the platform, put your own class on its wrapper (props.wrapperClass, at the root of props) and style that. Never style .vz-box / .vz-inner / .vz-radius directly: they are internal names that have moved before. And that CSS must live in a level 3 document — a level 1 stylesheet is inside the shadow root and cannot see the wrapper at all.
  • Wrapper axes go at the root of props, not next to kind. Written next to kind they are stored, returned on read, and render nothing; POST /docs/validate calls that ignored and names the right place.
  • A page must be checked twice: opened by direct URL and reached by clicking a link inside the site. They are different code paths.

Never

  • print the token anywhere — answers, files, markup, reports;
  • write to cabinet, cart or checkout flows;
  • treat a 200 as evidence that anything changed.

Исходник: https://api.vizen.shop/llms.txt

Работает в демо-режиме