# Vizen core-api > 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_` 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](https://api.vizen.shop/docs/skills): index with descriptions - [vizen-start](https://api.vizen.shop/docs/skill/vizen-start): entry point, key passport, the three questions, routing - [vizen-transfer](https://api.vizen.shop/docs/skill/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](https://api.vizen.shop/docs/skill/vizen-widgets): platform blocks and their props — live data, bounded look - [vizen-own-markup](https://api.vizen.shop/docs/skill/vizen-own-markup): your own HTML/CSS/JS, vz- keys, the block wrapper, images - [vizen-chrome](https://api.vizen.shop/docs/skill/vizen-chrome): header, menu, footer, layouts, second chrome kit - [vizen-catalog](https://api.vizen.shop/docs/skill/vizen-catalog): products, categories, filters, the image resizer - [vizen-troubleshoot](https://api.vizen.shop/docs/skill/vizen-troubleshoot): "I set it, got 200, nothing changed" — and the acceptance checklist ## Check before you write - [Validate](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/vz-keys.json): vz- keys, the page scope, isolation levels, recipes - [OpenAPI](https://api.vizen.shop/openapi.json): 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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/transfer) *(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](https://api.vizen.shop/docs/widgets-area): 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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/promotions): 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](https://api.vizen.shop/docs/orders) *(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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/resource-access) *(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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/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](https://api.vizen.shop/docs/webcoding) *(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](https://api.vizen.shop/docs/catalog-import): products, categories, attributes, variants, groupings - [Own markup keys, readable](https://api.vizen.shop/docs/vz-keys): the same key table as prose - [Token scopes](https://api.vizen.shop/docs/scopes.json) and [webhook events](https://api.vizen.shop/docs/events.json): generated from the whitelists the API enforces — print them instead of remembering them - [Index of everything](https://api.vizen.shop/docs/index.json): 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.