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.
- `GET /v1/account/token` — the key passport, and the only reliable statement of your rights. Public endpoints answer 200 without
catalog:readtoo, 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(prodwrites to the live shop,devto 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), andwarnings[](pass them on verbatim). - `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. - `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:
POSTthe same{"sections":[…]}you would send to/content-blocks/{id}and get a verdict per path —applied,ignored(accepted and does nothing) orunknown(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 carriesanchor.at, thefile:linethat 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 aprops.innerMaxis 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
/productscall: a filter written without thefilter.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 ofpropsis accepted and does nothing. The generated schema of those props is/docs/widgets; the area is-areabecause 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.jsonbesideindex.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 → keyladder, why only one rule wins per class, the refusal codes, andGET /promotions/landscapefor 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.
NULLmeans 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, verifyX-Vizen-Signatureover 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,noindexon 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), andPOST /storefront/access/unlockis 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_whenand 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=168is swallowed silently and returns the whole catalogue — no error, just the wrong data. Comparetotalbefore and after adding a filter. sectionsis 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
querySelectordoes not see it; walkelement.shadowRootrecursively. A transferred folder (level 3) is real page DOM:querySelectorworks, 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 onDOMContentLoaded); they never run on/cart,/checkout,/accountand the other guarded zones. - To make a block look unlike the platform, put your own class on its wrapper (
props.wrapperClass, at the root ofprops) and style that. Never style.vz-box/.vz-inner/.vz-radiusdirectly: 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 tokind. Written next tokindthey are stored, returned on read, and render nothing;POST /docs/validatecalls thatignoredand 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