Typed routes
Everything that is not a command is a catalog route (ROUTE_CATALOG, ADR 0027 §5): reads, provider-backed ops, draft workspace writes, owner-only actions. The catalog IS the exceptions to the command bus: the API router serves exactly these entries plus the excluded platform prefixes below, and every non-owner entry is an MCP tool under its dotted id. GET /v1/routes serves this list with JSON Schemas (the twin of GET /v1/commands).
Agent policy vocabulary
| policy | meaning |
|---|---|
read | GET, no store effects: every token kind calls it directly. |
quote | a provider call with no store-state change (offers, labels, validators): every token kind calls it directly. |
workspace | writes confined to the caller's own draft workspace or staging: every token kind executes it directly. |
propose | a live mutation: an Ajan token's call is recorded into its open proposal (202 proposed: true); a Geliştirici token executes it directly. |
owner | owner sessions only: never callable by any token and never an MCP tool. |
Catalog
| route | method + path | policy | summary |
|---|---|---|---|
meta.get | GET /v1/meta | read | Platform build identity and compatibility fingerprint (buildId, registryHash, minCli). |
commands.list | GET /v1/commands | read | List commands with JSON Schemas; anonymous callers see the frozen core set, authenticated callers the scope-filtered registry. |
commands.run | POST /v1/commands | propose | Run one command envelope {command, storeId, payload, idempotencyKey|dryRun}. |
routes.list | GET /v1/routes | read | List typed routes with JSON Schemas (the twin of commands.list). |
sections.meta.get | GET /v1/sections/meta | read | Section catalog with props/blocks JSON Schemas and placement rules. |
store.health.get | GET /v1/store/health | read | Store readiness checklist (draft/live, identity, flags). |
store.identity.get | GET /v1/store/identity | read | Legal identity block (owner-only). |
store.checkoutSettings.get | GET /v1/store/checkout-settings | read | Checkout settings (owner-only). |
extensions.list | GET /v1/extensions | read | Installed + available extensions with config, secrets state and manifest UI hints (owner-only). |
extensions.ops.get | GET /v1/extensions/{ext}/ops | read | The extension's agent contract with LIVE readiness: every op, what it needs (secrets/config/enabled), and exactly what blocks it right now. Secrets appear as keys only. |
metafields.definitions.list | GET /v1/metafields/definitions | read | Metafield definitions (owner-only). |
catalog.products.list | GET /v1/catalog/products | read | List products (keyset cursor, filters). |
catalog.products.get | GET /v1/catalog/products/{prd} | read | Get one product with variants, media and stock. |
catalog.stockMovements.list | GET /v1/catalog/stock-movements | read | Stock ledger rows for a product or variant. |
catalog.collections.list | GET /v1/catalog/collections | read | List collections. |
catalog.collections.get | GET /v1/catalog/collections/{col} | read | Get one collection with members. |
catalog.categories.list | GET /v1/catalog/categories | read | List categories. |
media.list | GET /v1/media | read | List media objects. |
media.upload | POST /v1/media/upload | workspace | Stage a binary upload (raw body); commit with catalog.media.commit. |
orders.list | GET /v1/orders | read | List orders. |
orders.get | GET /v1/orders/{ord} | read | Get one order with lines, payment, shipments, returns, timeline. |
orders.belge.get | GET /v1/orders/{ord}/belge/{belge} | read | Fetch a legal document snapshot of an order. |
orders.note.add | POST /v1/orders/{ord}/not | propose | Add a merchant note to the order timeline. |
orders.cod.collect | POST /v1/orders/{ord}/tahsilat | propose | Mark a cash-on-delivery order as collected. |
orders.refund | POST /v1/orders/{ord}/refund | propose | Refund part or all of a captured payment through the original PSP extension. |
orders.cargo.offers | POST /v1/orders/{ord}/cargo/offers | quote | Create a provider quote for the order and return carrier offers (no store mutation). |
orders.cargo.book | POST /v1/orders/{ord}/cargo/book | propose | Accept a carrier offer, create the label and ship the order. |
orders.cargo.ship | POST /v1/orders/{ord}/cargo/ship | propose | Ship with the merchant's own carrier (manual tracking). |
orders.shipment.track | POST /v1/orders/{ord}/cargo/{shp}/track | propose | Record a shipment status transition by hand. |
orders.shipment.update | POST /v1/orders/{ord}/cargo/{shp}/update | propose | Poll the provider and apply the current tracking status. |
orders.shipment.cancel | POST /v1/orders/{ord}/cargo/{shp}/cancel | propose | Cancel a shipment before pickup. |
orders.shipment.label | POST /v1/orders/{ord}/cargo/{shp}/label | quote | Fetch the shipping label URL from the provider. |
cargo.carriers.list | GET /v1/cargo/carriers | read | Platform carrier reference table (codes, labels, tracking availability). |
returns.list | GET /v1/returns | read | List return requests. |
returns.get | GET /v1/returns/{ret} | read | Get one return request. |
returns.approve | POST /v1/returns/{ret}/onayla | propose | Approve a return request with shipping instructions; mails the shopper. |
returns.reject | POST /v1/returns/{ret}/reddet | propose | Reject a return request with a reason; mails the shopper. |
ext.cargo.sender | POST /v1/ext/{ext}/cargo/sender | propose | Create the sender address at the cargo provider and store its id in the extension config. |
channel.health.get | GET /v1/channel/{ext}/health | read | Channel health: credentials, last sync times, webhook state, budget/429 counters, failed batches, queue depth, unmapped orders. |
channel.listings.list | GET /v1/channel/{ext}/listings | read | Marketplace listings of this channel with status, effective price, pushed vs live stock, drift and last error. |
channel.listings.get | GET /v1/channel/{ext}/listings/{lst} | read | One listing with its provider mirror (external ids, last push/remote, errors, mapping meta). |
channel.sync.now | POST /v1/channel/{ext}/sync | propose | Run a sync task now (stock | price | orders | reconcile | finance | claims | questions), optionally scoped to listings. |
channel.catalog.pull | POST /v1/channel/{ext}/catalog/pull | propose | Import the marketplace catalog (preview or import): products, variants, images, listings, stock and prices: a durable job. |
channel.catalog.push | POST /v1/channel/{ext}/catalog/push | propose | Create/update marketplace listings for selected products (pre-flight validated; async batch tracked). |
channel.remote.products | GET /v1/channel/{ext}/remote/products | quote | The seller's products as the marketplace sees them (approval state, remote stock/price, reject reasons). |
channel.remote.categories | GET /v1/channel/{ext}/remote/categories | quote | Marketplace category tree search (leaf categories accept products). |
channel.remote.attributes | GET /v1/channel/{ext}/remote/attributes | quote | Attributes a marketplace category requires/allows (required, custom, multi, variant axis). |
channel.remote.attributeValues | GET /v1/channel/{ext}/remote/attribute-values | quote | Allowed values of one category attribute. |
channel.remote.brands | GET /v1/channel/{ext}/remote/brands | quote | Marketplace brand search by name. |
channel.brand.create | POST /v1/channel/{ext}/remote/brands | propose | Create a brand at the marketplace (multipart: name + 1-3 logo images). |
channel.jobs.list | GET /v1/channel/{ext}/jobs | read | Durable channel jobs (imports, pushes, batch polls, sweeps) with progress. |
channel.jobs.get | GET /v1/channel/{ext}/jobs/{cjb} | read | One channel job with progress, errors and result. |
channel.jobs.cancel | POST /v1/channel/{ext}/jobs/{cjb}/cancel | propose | Cancel a queued/running channel job. |
channel.package.label | POST /v1/orders/{ord}/channel/label | quote | Fetch the marketplace cargo label for a package (ZPL, or rendered PDF/PNG). |
channel.package.op | POST /v1/orders/{ord}/channel/{chop} | propose | Act on a marketplace package: status (preparing/invoiced), unsupplied (penalty acknowledged), split, invoice hand-off, cargo (carrier/box/warehouse/extend/own-carrier). |
channel.packages.labels | POST /v1/channel/{ext}/labels | quote | Bulk labels for up to 50 packages (merged PDF). |
channel.claims.list | GET /v1/channel/{ext}/claims | quote | Marketplace return/cancel claims with deadlines and fault tags. |
channel.claims.act | POST /v1/channel/{ext}/claims/{claim}/act | propose | Approve, reject (reason + file) or raise an issue on a marketplace claim; restock per policy. |
channel.questions.list | GET /v1/channel/{ext}/questions | quote | Customer questions awaiting an answer (with deadlines). |
channel.questions.answer | POST /v1/channel/{ext}/questions/{qid}/answer | propose | Answer a customer question (moderated by the marketplace). |
channel.finance.list | GET /v1/channel/{ext}/finance | read | Imported settlement rows (commission, cargo, fees, payouts) and per-order expected vs settled. |
channel.buybox.get | GET /v1/channel/{ext}/buybox | quote | Buybox rank and top prices for listings (≤100). |
channel.unlock | POST /v1/channel/{ext}/unlock | propose | Request unlock of locked listings (after the price/stock cause is fixed). |
channel.listing.archive | POST /v1/channel/{ext}/listings/archive | propose | Archive/unarchive listings at the marketplace (archive pushes stock 0 too). |
channel.listing.delete | POST /v1/channel/{ext}/listings/delete | propose | Delete listings at the marketplace (irreversible; provider rules apply, e.g. archived > 1 day and not locked). |
channel.webhook.register | POST /v1/channel/{ext}/webhook | propose | Register (or re-activate) the platform webhook at the marketplace with a fresh shared secret. |
channel.connect.test | POST /v1/channel/{ext}/connect-test | quote | Probe the marketplace with the stored credentials (no store mutation): auth, identity header, stage allowlist. |
orders.identity.reveal | POST /v1/orders/{ord}/identity | owner | Reveal the sealed buyer identity number of a marketplace order (owner session only; audited). |
store.stockSettings.get | GET /v1/store/stock-settings | read | Store-wide stock policy and per-channel policies (owner-only). |
catalog.stockMovements.since | GET /v1/catalog/stock-movements/since | read | Store-wide stock ledger rows after a seq watermark, ascending: the outbox read a connector consumes. |
design.draft.get | GET /v1/design/draft | read | Read the draft bundle (rev, hash, body, preview link). |
design.draft.put | PUT /v1/design/draft | workspace | Replace the draft bundle under optimistic concurrency (expectedRev). |
design.draft.delete | DELETE /v1/design/draft | workspace | Discard the draft (expectedRev). |
design.draftFromTemplate | POST /v1/design/draft-from-template | workspace | Instantiate a starter template as the draft. |
design.templates.list | GET /v1/design/templates | read | Starter template cards. |
design.versions.list | GET /v1/design/versions | read | Published version ledger (seq, hash, label, live marker). |
design.version.get | GET /v1/design/version/{seq} | read | Full body of a published version. |
design.previewUrl.get | GET /v1/design/preview-url | read | Signed preview link: ?hash= freezes a snapshot, ?workspace= follows that workspace's current draft (the dev-loop link). |
themes.list | GET /v1/themes | read | Installed themes + the first-party gallery, with presets/variables and the draft's active theme ref. |
themes.get | GET /v1/themes/{theme} | read | One theme's manifest, variables, presets and install state. |
design.catalog.get | GET /v1/design/catalog | read | Section catalog for the add-picker: platform sections, the active theme's sections, store composites, extension blocks. |
kit.contract.get | GET /v1/kit/contract | read | The Element Contract (elements, anatomy, tokens, zones, limits) the platform renders: same JSON as docs /schemas/kit-contract.json. |
themes.check | POST /v1/themes/check | quote | Statically check a SKIN theme package {manifest, css, variables?, presets?, against?}: manifest + variables schemas, the CSS grammar with the parent kit's variables, size gates, element coverage, V1 value-aware compatibility with this platform version (+ computed requires) and, with against (the previous version), the semver class the change needs. Public and side-effect-free (the CLI's mozaik theme check). |
compat.contracts.get | GET /v1/compat/contracts | read | The contract manifests this build was released with (storefront + api): every element/part/axis/token/section/zone/block/kit and route/command/scope a theme, skin, bundle or extension may reference. Same JSON as contracts/<kind>/<version>.json in the repo. |
compat.check | POST /v1/compat/check | quote | Check an artifact's compatibility with this platform version without installing it: {kind: css|bundle|extension|tree, artifact, kit?, variables?} → verdict {ok, breaking[], warnings[]} with TR messages and alias fixes. Public and side-effect-free (CLI mozaik compat check, Dev MCP). |
proposals.list | GET /v1/proposals | read | List proposals; agent tokens see only their own. |
proposals.get | GET /v1/proposals/{prp} | read | One proposal with its items, recorded previews and (for design items) a preview link. |
proposals.apply | POST /v1/proposals/{prp}/onayla | owner | Approve a proposal and apply its items in order, re-checking each recorded preview (store owner only). |
proposals.resume | POST /v1/proposals/{prp}/devam | owner | Resume a paused proposal after skipping or accepting the new preview of a stale item (store owner only). |
updates.list | GET /v1/updates | read | The store's update queue (Güncellemeler): pending theme/extension/generation updates with their Geçiş raporu and preview, plus applied/blocked history, and the platform versions this store runs on. |
updates.apply | POST /v1/updates/{upd}/uygula | owner | Publish a prepared update (the platform's upgraded draft) to the live site (store owner only). |
updates.dismiss | POST /v1/updates/{upd}/ertele | owner | Dismiss a pending update for now (it stays available; the old version keeps rendering). |
workspaces.list | GET /v1/workspaces | read | List draft workspaces: the builder's main draft plus every agent/developer workspace with its draft rev and sandbox state. |
workspaces.create | POST /v1/workspaces | owner | Create a workspace; for kind agent it also mints the bound Ajan token (returned once). |
workspaces.adopt | POST /v1/workspaces/{ws}/adopt | workspace | Copy a workspace draft into the builder's main draft under optimistic concurrency (never a merge). |
workspaces.exec | POST /v1/workspaces/{ws}/exec | workspace | Run one command in the workspace's hosted sandbox (the pinned CLI is preinstalled; cwd defaults to /workspace/store). Output capped at 256 KB. |
workspaces.files.list | GET /v1/workspaces/{ws}/files | quote | List a directory inside the hosted sandbox (confined to /workspace). |
workspaces.files.read | GET /v1/workspaces/{ws}/file | quote | Read a file from the hosted sandbox (≤1 MiB; base64 for binary). |
workspaces.files.write | PUT /v1/workspaces/{ws}/file | workspace | Write a file into the hosted sandbox (≤1 MiB; scratch only: store state flows through mozaik push/proposals). |
workspaces.backup | POST /v1/workspaces/{ws}/backup | workspace | Snapshot the sandbox's /workspace/store to R2 (7-day TTL); restored automatically on the next cold start. |
workspaces.preview | GET /v1/workspaces/{ws}/preview-url | read | Stable signed preview URL of this workspace's draft on the store hostname (never touches the container). |
workspaces.activity.list | GET /v1/workspaces/{ws}/activity | read | The workspace's append-only activity feed (exec/read/write/backup/refresh with exit codes and durations). |
workspaces.refresh | POST /v1/workspaces/{ws}/refresh | owner | Rebuild the hosted sandbox on the current platform image: backup, destroy, revoke its token; the next use recreates it fresh. |
scopes.list | GET /v1/scopes | read | Scope registry: TR labels, sensitivity and who may hold each scope (any token / developer tokens / sessions only). |
tokens.mint | POST /v1/tokens | owner | Mint an Ajan (propose-only) or Geliştirici (direct) token; the plaintext is returned exactly once. |
tokens.list | GET /v1/tokens | owner | List this store's tokens (never the secrets): kind, scopes, expiry, last use. |
tokens.whoami | GET /v1/tokens/me | read | Describe the calling credential: store, kind, scopes, expiry, workspace: what an agent should call first. |
audit.list | GET /v1/audit | read | Recent audit rows for the store (optionally by entity). |
validate.bundle | POST /v1/validate/bundle | quote | Validate a store bundle (schema + referential integrity) without saving anything. Media readiness is checked at draft save, which is the enforcement point. |
validate.command | POST /v1/validate/command | quote | Validate a command payload against its registered schema without running it (no preview, no mutation). |
validate.manifest | POST /v1/validate/manifest | quote | Validate an extension manifest against zExtensionManifest, including the agent-contract rules. |
Excluded prefixes
Deliberately NOT store-management capabilities: never in the catalog, never agent tools. A /v1/… literal in the router that is neither a catalog path nor one of these fails CI (G-ROUTES).
| prefix | why |
|---|---|
/v1/health | liveness probe |
/v1/auth/ | merchant login/session: platform side (ADR 0015), not store management |
/v1/account/ | apex account panel: session-only by ADR 0015; store creation is the /kur wizard |
/v1/id/ | Mozaik ID shopper identity (ADR 0025): shopper-side |
/v1/ext/{ext}/wh/ | provider-driven webhook ingestion (ADR 0026 §5): agents never call it |
/v1/assistant/ | Zeki Asistan (ADR 0028): the assistant IS an agent surface; owner-session product endpoints, never agent tools |
/v1/psp/ | legacy iyzico webhook alias: pending the user's dashboard re-registration |
/v1/cargo/geliver/webhook | legacy Geliver webhook alias: pending deletion with the above |
/v1/ops/ | V1 operator surfaces (fleet-gate runs, schema preflight): OPS_KEY-gated, CI/founder only, never a store capability |
checkout.internal | storefront→api service-binding enclave (ADR 0021) |
Generated from the live platform registries at build time: reference pages cannot go stale. Markdown variant: /reference/routes.md