add_block_to_page | pages:edit | Add a block to a page (auto-generates the block id). Pass layoutRegion to add a layout block; omit it for a content block in the page body. If the result includes blockWarnings, the saved content violates the workspace block manifest (unknown field, wrong value shape, or a stored block whose type is no longer registered) - correct the content and save again, unless the warning is about a stored block whose type is no longer registered: that one is a manifest problem, so restore or sync the type, or find the block with list_block_usage and migrate or remove it. When the warnings also say when the workspace block manifest was last synced, the field or type may simply be newer than the manifest: if the site's code declares it, keep the content and sync the manifest (cmssy sync-manifest in the site's repo) instead. A block whose type the workspace block manifest does not register is refused unless the page already stores that block - pick registered types from list_block_types. |
approve_return | orders:manage | Approve a return the customer requested. |
bulk_delete_products | models:delete | Bulk-delete selected product records permanently. A product an open order or a page block still references is skipped rather than deleted; each entry of `skipped` carries its reason. |
bulk_update_products | models:edit | Bulk-update selected product records with a single patch (status, set/adjust stock, set/adjust price). Stock is whole units; price is major units - the stored price field value, not cents - and changes the default-currency price only; prices in additional currencies are left as they are. |
bulk_update_records | models:edit | Apply one change (field values, status and/or published) to many records of a model in a single call: the records named by ids, or every record matching filter with allMatching. Each record is validated, audited and announced to webhooks like update_record. Handles up to 200 records per call; a non-null nextCursor means more records match - pass it back with the same arguments to continue. Returns updated, unchanged (records already at the requested status and visibility, with no data to write), failedCount, a sample of failures (id + reason) and nextCursor. |
cancel_order | orders:manage | Cancel an order. Takes only the order id - there is no reason field; when the user gives a reason, record it in the order's notes with update_order_details first. |
cancel_return | orders:manage | Cancel a requested or approved return that has not been refunded. |
clear_cart_config | site:config:edit | Remove the workspace's commerce settings entirely, putting the cart back to never-configured. A workspace with orders or carts is refused unless force: true is passed. To change individual settings rather than remove them, use update_cart_config. |
close_order | orders:manage | Mark an order done (state closed). Paid and fulfilled orders usually close by themselves; it reopens by itself if it later stops being paid or fulfilled. |
complete_return | orders:manage | Close a received return without a refund, e.g. after store credit or a failed inspection. |
create_discount | discounts:manage | Create a discount code. `type` is 'percentage' (value 0-100), 'fixed' (value in minor currency units, requires currency e.g. 'USD'; it applies only to carts in that currency), or 'free_shipping' (value 0). Optional limits: minSubtotal, maxUses, startsAt, endsAt. A cart is in its sales channel's currency; for a 'percentage' or 'free_shipping' code with a minimum, minSubtotal is the default-currency minimum and minSubtotalByCurrency the minimum in each additional currency. |
create_form | forms:create | Create a new form with a name and slug. Optional: field definitions, per-field showWhen/requiredWhen conditions, and settings (action type, notifications). Fields can also be added later in the Forms editor. |
create_manual_order | orders:manage | Create a manual (admin-entered) order. Each item references a product recordId or is an ad-hoc line with name+price (minor units of the order's currency). currency picks the order's currency (default currency when omitted); payments and refunds on the order are in that currency. shippingAddress is optional; for a customer of a company with a verified VAT id its country decides whether the order is reverse charge, and the order freezes that tax treatment (get_order taxTreatment). |
create_media_folder | media:edit | Create a media folder for organizing assets. Returns the folder, whose id can be passed to upload_media (folderId) or move_media. |
create_model | models:create | Create a data model in the workspace. Every field label (and description) is text per language code of the workspace: { en: "Title", pl: "Tytuł" }. Field types include select/multiselect (provide `options` as [{ value, label }] - the value is what records store), relation (link to another model via `relationTo` = the target model's slug + `relationType`), and object/list (nested `fields`/`itemFields`). Optional model-level config: slug, description, icon, color, displayField, defaultSort, statusField, `product` (commerce capability: enabled, priceField, skuField, inventoryField, variantAxes), `auth` (accounts: enabled, identityField, companyField for a B2B company link - a relation to a model with Company enabled; a field's `memberCanSet` opens it to the member on their own account and at sign-up - registration accepts only those fields, never password fields or the company field), `company` ({ enabled }: its records are the companies an accounts model links; a model is at most one of product, account (auth) or company), `uniqueFields` (field keys whose value must be unique - lets import_records update by that key) and `deliveryAccess` - a model is "none" (admin only) by default, so pass "public" when the user's app must read it through the delivery API. `urlPattern` (e.g. /p/{slug}) says where its records live on the storefront, so their `url` becomes a working link - ask the user for their route rather than inventing one. |
create_page | pages:create | Create a new draft page with a name and slug (content/blocks are added later in the editor). Optional: parentId, pageType, multilingual displayName/seoTitle/seoDescription, customFields. |
create_page_type | page:types:manage | Create a page type (template) with a custom-field schema. Pages of this type carry these custom fields. |
create_price_list | models:edit | Create a price list: a percent off the catalogue (percentOff, -1000 to 99.99 with 2 decimals, default 0; negative = a markup) plus fixed prices per product or variant added with set_price_list_entry / set_price_list_entries. A fixed price overrides the percent for its product or variant; every other product gets the catalogue price minus percentOff. Then assign it to a company (set_company_price_list) or to a customer without a company (set_customer_price_list) - each buyer has one list: a company's members pay the company's list. startsAt / endsAt limit when it prices; outside that window its buyers pay catalogue prices. channels publishes it to sales channels by key: storefronts sending that channel are priced from it (a buyer's own or company list still wins for every product it prices), and anyone can read the prices of a list published to a PUBLIC channel. |
create_record | models:edit | Add a record (entry) to a data model. Pass the model id or slug and a `data` object whose keys are the model's field keys (use get_model first if unsure). A product is a record too: pass a model whose product capability is enabled (get_model shows `product.enabled`), and list_products then lists it with its stock. Each record carries `url`: its live storefront link, built by the server from the model's urlPattern and the site's public site URL. Use it whenever you link to a record and never build a storefront URL yourself (not from a slug, not from the site address). When url is null or missing, say why instead of guessing: the model has no urlPattern (set it with update_model), the model is not delivered (deliveryAccess none, or it is the login model), the site has no public site URL, or the record - or one it links to - is unpublished. |
create_return | orders:manage | Open a return on an order for items the customer is sending back. A return opened by the merchant starts approved. It does not move money or stock: receive_return restocks, refund_return records the refund. |
create_sales_channel | models:edit | Create a sales channel, at most 20 per workspace; a duplicate key is refused. The channel prices nothing until a price list is published to it (create_price_list / update_price_list with channels): one undated base list plus dated lists whose windows do not overlap. Channel keys are public - any storefront can send one - so priceAccess decides who sees its prices and may buy through it. currency picks what the channel sells in (the default currency when omitted): its carts, orders, shipping and discounts are in it, and a product with no price in it is not sold there. |
create_shipment | orders:manage | Add a parcel to an order: the items it carries, carrier, tracking and status. This is also how an order is marked fulfilled. The order's fulfillment and delivery status follow its parcels; a pending parcel (no label yet) fulfils nothing. |
create_webhook | webhooks:manage | Create a webhook endpoint subscribed to one or more events. The URL must be a public https endpoint. Returns the endpoint AND its signing secret (shown only once). |
delete_carts | carts:view, carts:manage | Permanently delete 1 to 100 carts with their analytics events, the visitor sessions only they used and any discount use they held (the code's use count goes back down). All or nothing: an id that is not a cart of this workspace, or a cart already turned into an order (status ordered - anonymize the order instead), refuses the whole call and deletes nothing. Returns how many carts were deleted. Cannot be undone. |
delete_form | forms:delete | Permanently delete a form and all its submissions. |
delete_form_submission | forms:submissions:manage | Permanently delete a form submission. |
delete_media_folder | media:delete | Delete a media folder. By default only empty folders are removed; pass deleteContents to also delete the assets inside, and force to override the refusal that protects assets still in use. |
delete_model | models:delete | Delete a data model. WARNING: this cascades - ALL records of the model are permanently deleted. |
delete_page | pages:delete | Move a page and all its descendants to the trash. The page leaves the site at once; the group stays restorable with restore_page (as unpublished drafts) for 30 days, after which it is deleted permanently. Cannot delete the homepage. |
delete_page_type | page:types:manage | Delete a page type. Refused for system types and for a type any page still uses - move or delete those pages first. |
delete_price_list | models:edit | Delete a price list with all its fixed prices and unassign it from every company and customer it prices (see assignedCount in list_price_lists) - they pay catalogue prices from then on - and unpublish it from every sales channel it is published to (see channels). Orders keep the list name they were priced under. Cannot be undone. |
delete_record | models:delete | Permanently delete one record (entry) by its id. A record still used by page blocks is refused and the error lists those pages; force: true deletes it anyway and leaves those references stale. |
delete_sales_channel | models:edit | Delete a sales channel and unpublish every price list from it. Its open carts are abandoned - activeCartCount in list_sales_channels / get_sales_channel says how many - and storefronts still sending its key are refused (BAD_USER_INPUT). Orders keep the channel they were placed through. Cannot be undone. |
delete_webhook | webhooks:manage | Delete a webhook endpoint permanently. |
edit_order | orders:manage | Replace an order's line items (full replace of the items array). Recomputes totals. |
get_customer | customers:view | Get one customer by id: the account summary (identity, status, verification, lock, last login, company, companyRole - the effective company role, a key of the workspace's role catalogue (v1: admin, buyer), buyer unless staff set another for the company they belong to now, null without a company - priceList (the list assigned to the customer themselves, ignored while they belong to a company), effectivePriceList (the list that prices their carts and orders: id, name, source MEMBER or COMPANY, companyName when COMPANY; null = catalogue prices) and orderStats: non-canceled order count, last order date and net spend in minor units per currency, null without orders:view) plus the profile record's data. Read-only. |
get_discount | discounts:view | Get one discount's full details by id or code: type, value, currency, minSubtotal (default currency, or a fixed code's own), minSubtotalByCurrency (per additional currency), usage limits and validity window. |
get_form | forms:view | Get one form's full details (fields, settings, submission count) by id or slug. |
get_form_submission | forms:submissions:view | Get one form submission's full details by its id. |
get_model | models:view | Get the full details of one data model by id or slug: complete field definitions (type, options, relations, validation) the product capability config (enabled, field roles incl. the resolved `roles`, variantAxes) the accounts config (`auth`: identityField, companyField - a relation to a Company model; each field's `memberCanSet` says whether the member may change it on their own account and send it at sign-up, never for password fields or the company field) the Company capability (`company`: { enabled }, null when never set; a model is at most one of product, account or company) and `urlPattern`, the storefront route its records' `url` is built from (null when none). Use before update_model and when the user asks about a model's structure. |
get_order | orders:view | Get one order's full details by its id: items, the full money column (subtotal, discount, shipping, tax, total - all minor units), displayMode (net or gross, how the buyer read prices), taxRoundingMethod (per_line or per_rate), taxTreatment (kind standard, reverse_charge, exempt or export - goods shipped out of the EU VAT area, or from a seller outside the EU to another country, frozen at checkout with the facts it rests on: legalNote, the text to print on the invoice, null for standard; buyerVatId, buyerVatCountry and buyerVatVerifiedAt of the VAT id that decided it; sellerCountry; shipToCountry; orders placed before it was recorded read standard), removedTax (VAT taken out of gross-stored prices on a reverse_charge, exempt or export order, minor units, 0 otherwise; total = subtotal - discount + shippingTotal - removedTax), amounts (net, tax and gross of subtotal, discount, shipping and total), the frozen discount code, channel (the sales channel the order was placed through: id, key, name; null for none), priceList / priceListName (the primary price list the order was priced from, name frozen at checkout; null when none) and priceListSource (MEMBER, COMPANY or CHANNEL - whose list it was), pricingChain (the lists tried in order: buyer, channelDated, channelBase; each null when none) - every list reference carries deleted, true once that list was deleted after the order, and each item's priceListId / priceListSource name the list that priced that line, PO number, shipping address, payment/fulfillment status, amountPaid (collected so far), balanceDue (total - amountPaid, what the buyer still owes; a refund does not change it), refundedAmount (refunded so far across every refund, minor units; left to refund = amountPaid - refundedAmount), refundedAt (when the latest refund was recorded, null when none), refundReferences (the refund references recorded, oldest first - refund_order and refund_return ignore a reference already listed), invoices (every invoice recorded, oldest first: kind invoice - at most one, the order's invoice - then its corrections of kind correction, each with number, url, provider and issuedAt; record_order_invoice adds the invoice, record_order_invoice_correction a correction), and the parcels (shipments: id, carrier, tracking number and link, status, history) - a parcel's id is what update_shipment takes - the returns (id, number, status, lines with reason and received/restocked units, return-parcel tracking, refunded amount, history) - a return's id is what the *_return tools take - and customFields, the order's custom field values by key. |
get_order_pipeline | orders:view | Get the workspace order pipeline (the configurable stages orders move through). |
get_page | pages:view | Get one page's full details (blocks, layout, page type, custom fields, the SEO title/description/display name per language, and its version - pass it as expectedVersion to patch_block_content) by id or slug. Use when the user asks about a specific page's content, structure or SEO. |
get_page_type | page:types:view | Get one page type with its full custom-field schema - the field keys, types and options that pages of this type carry in customFields, and for relation fields their relationTo / relationType. Use before writing customFields on a page, because list_page_types does not return the fields. |
get_price_list | models:view | Get one price list by id with a page of its fixed prices (entries, oldest first, at most 200 per page; pass nextCursor back as after for the next page, null on the last). An entry is a fixed unit price in minor units for one product (variantKey null) or one variant of a product with variants, with its own volume breaks (tiers), its order bounds (minQuantity / maxQuantity, null = none) and its currency (an additional currency's row names it; a default-currency row reads the product's currency); recordMissing true means the product or variant was removed and the entry prices nothing - remove it with remove_price_list_entries. Filter by recordId to see one product's entries. Read-only. |
get_record | models:view | Get one record (entry) of a data model by its id, including all its field values and status. A company record (a model with the Company capability) also carries vatId, vatCountry, vatVerifiedAt, vatVerifiedBy and taxExemptReason, null when unset (set_company_vat_id, set_company_vat_verified, set_company_tax_exemption). A product record also carries currencyPrices and variantCurrencyPrices - its prices in additional currencies, minor units, enabled false while that currency is not an additional currency (set_product_currency_prices, set_product_variants); its data holds the default-currency price. Each record carries `url`: its live storefront link, built by the server from the model's urlPattern and the site's public site URL. Use it whenever you link to a record and never build a storefront URL yourself (not from a slug, not from the site address). When url is null or missing, say why instead of guessing: the model has no urlPattern (set it with update_model), the model is not delivered (deliveryAccess none, or it is the login model), the site has no public site URL, or the record - or one it links to - is unpublished. |
get_sales_channel | models:view | Get one sales channel by id: key, name, displayMode, priceAccess, activePriceList (the dated list whose window holds now, else the base list), priceLists published to it with their windows, nextChangeAt and activeCartCount (open carts a delete would abandon). Read-only. |
get_site_config | brak | Get the workspace's site configuration: languages, site name, enabled features, and the cart/commerce settings (currency, tax rates, shipping methods, custom order fields). |
get_workspace_info | brak | Get the current workspace's info: name, slug, plan and limits (max pages, users, storage, AI tokens). |
import_records | models:edit | Bulk-import records into a data model (up to 1000 rows). Without upsertKey each row CREATES a record; with upsertKey (a unique field or the product SKU field) a row matching an existing record UPDATES it instead, so a repeated sync does not duplicate. A translatable field takes a language map ({ title: { en: '...', no: '...' } }); a language the workspace has not enabled is rejected. Returns importedCount (created), updatedCount, per-row errors, and per-row record ids with CREATED / UPDATED / UNCHANGED. |
list_block_types | brak | List the block types available on the workspace's site, each with its content field schema and default values. Use a block type's `schema` to shape `content` for add_block_to_page / update_block_content / patch_block_content - content is language-keyed ({ en: { fieldKey: value } }), and a relation field stores record id(s) per its relationTo/relationType. A non-empty `layoutRegions` marks a layout block (header/footer) managed via update_page_layout, not page body blocks. |
list_block_usage | pages:view | Show where each block type is stored across the workspace: draft and published page blocks, layout regions (draft and published) and developer drafts, with per-surface counts and the pages that hold it. `registered` says whether the active block manifest still declares the type; `orphanTypes` lists types stored but no longer registered (the site renders nothing for them), `unusedTypes` lists registered types no page uses. Use it before renaming or removing a block type in code, then migrate or remove the instances it lists with update_block_content / remove_block_from_page. |
list_carts | carts:view | List shopping carts (admin view) with optional status filter and pagination. totalValue is in minor units. channel is the key of the sales channel the cart was started on (null for none): a buyer has one active cart per channel. |
list_customers | customers:view | List the customers - accounts that sign in to the user's site (records of an accounts model), with status, verification, last login, their company, companyRole (the effective company role: admin or buyer in v1, null without a company), effectivePriceList (the price list that prices them, source MEMBER or COMPANY; null = catalogue prices) and orderStats (non-canceled order count, last order date, and net spend = paid minus refunded, in minor units, one entry per currency; null when the caller may not view orders). Not the team: those are list_team. Read-only; filter by model, status, company or an identity search; paginated, newest first. |
list_discounts | discounts:view | List discount codes in the workspace. Filter by enabled, type, or a code search; paginated. |
list_form_submissions | forms:submissions:view | List form submissions, optionally filtered by form and status; paginated. Returns submission rows with their data and status. |
list_forms | forms:view | List the forms in the workspace. Filter by status; paginated. |
list_media | media:view | List media files (images and files) in the workspace; paginated. |
list_media_folders | media:view | List media folders in the workspace (optionally under a parent folder). Use this to discover a folderId before uploading or moving assets. |
list_models | models:view | List the data models (content types) defined in the current workspace. Use to answer 'do we have models / a Product model?' or to see what data structures already exist. |
list_orders | orders:view | List orders in the workspace. Filter by payment, fulfillment or delivery status, state (open/closed/canceled), customer, company (B2B), pipeline stage, warehouse queue (to pack, in transit, shipping problem, returns), a search string (customer email or company name), currency, or a date range; paginated with skip and limit. Each order carries customerId, companyId and companyName when it was placed for a customer or a company. |
list_page_types | page:types:view | List the workspace's page types (templates) with their id, name, slug and url prefix. |
list_pages | pages:view | List the workspace's pages (id, name, slug, published), optionally filtered by a search string. |
list_price_lists | models:view | List the workspace's price lists (Gold, Silver, dealer tiers ...), by name: each with percentOff (percent off the catalogue, 2 decimals; negative = a markup), startsAt / endsAt and active (false outside that window: the list prices nobody and its buyers pay catalogue prices), overrideCount (fixed prices it holds), assignedCount (companies and customers it prices) and channels (the sales channels it is published to, with key and priceAccess). A list prices a buyer from a fixed price per product or variant where it has one, else the catalogue price minus percentOff. Read-only; entries are in get_price_list. |
list_products | models:view | List a product model's catalog with stock and variant info (onHand/reserved/available per record and variant). A product is a record of a model whose product capability is enabled (get_model shows `product.enabled` and the field roles): create one with create_record on that model and change it with update_record; set_product_tiers and the bulk_* product tools work on the same records. Each record carries `url`: its live storefront link, built by the server from the model's urlPattern and the site's public site URL. Use it whenever you link to a record and never build a storefront URL yourself (not from a slug, not from the site address). When url is null or missing, say why instead of guessing: the model has no urlPattern (set it with update_model), the model is not delivered (deliveryAccess none, or it is the login model), the site has no public site URL, or the record - or one it links to - is unpublished. |
list_records | models:view | List the records (entries) of a data model, by the model's id or slug. Supports filtering (per key: scalar equality, $in, $gte/$lte, $regex), sort, and pagination. Each record includes its full data, so you can find a record by a field value (e.g. sku) without extra lookups. Each record carries `url`: its live storefront link, built by the server from the model's urlPattern and the site's public site URL. Use it whenever you link to a record and never build a storefront URL yourself (not from a slug, not from the site address). When url is null or missing, say why instead of guessing: the model has no urlPattern (set it with update_model), the model is not delivered (deliveryAccess none, or it is the login model), the site has no public site URL, or the record - or one it links to - is unpublished. |
list_roles | roles:view | List the roles defined in this workspace and the permissions each one grants. Read-only. Useful for understanding who can do what. |
list_sales_channels | models:view | List the workspace's sales channels (retail, horeca, b2b ...), by key. A storefront sends a channel's key to be priced from the price lists published to it: per product the buyer's own or company list wins, then the channel's dated list whose window holds now, then its base (undated) list, then the catalogue. Each channel has key (what the storefront sends, fixed once created), name, displayMode (net or gross prices for visitors and customers without a company), priceAccess (PUBLIC - anyone; MEMBERS - signed-in customers, registration is open; COMPANY_MEMBERS - buyers of an approved company), activePriceList (the list pricing it now), priceLists (every list published to it), nextChangeAt (when its prices next change) and activeCartCount (open carts on it). Read-only. |
list_team | users:view | List the team - the people who manage this workspace - with their role and status (active, suspended, or a pending invitation). Not shoppers: those are records of the customer model. Read-only; filter by status or a search string; paginated. |
list_trashed_pages | pages:view | List the page trash, newest first. Each entry is one deleted group - a page plus the descendants deleted with it: id (the trash id restore_page takes), name, slug, deletedAt, deletedById and deletedByName, descendantCount, and expiresAt, when the group is deleted permanently (30 days after deletion). Only groups the caller holds pages:delete on are listed; without it the list is empty. |
list_webhook_deliveries | webhooks:view | List recent webhook delivery attempts (status: pending/success/failed) for debugging. |
list_webhook_event_types | webhooks:view | List the event types a webhook can subscribe to (the authoritative allowlist). |
list_webhooks | webhooks:view | List the workspace's webhook endpoints (signing secrets are never returned here). |
mark_order_paid | orders:manage | Record a full payment for an order (manual reconciliation - does NOT verify with a payment provider). amount is in minor units of the order's currency. |
move_media | media:edit | Move one or more media assets into a folder (or to the root with folderId: null). Use list_media_folders to find the destination folderId. |
patch_block_content | pages:edit | Apply surgical edits (insert_before/insert_after/replace_section, or replace_all to set the whole string, given the value it replaces) to one string in a block's localized content without re-sending the full content - including a string nested in a list or object, via a dotted fieldPath such as 'tabs.0.label'. Each marker must match exactly once. If the result includes blockWarnings, the saved content violates the workspace block manifest (unknown field, wrong value shape, or a stored block whose type is no longer registered) - correct the content and save again, unless the warning is about a stored block whose type is no longer registered: that one is a manifest problem, so restore or sync the type, or find the block with list_block_usage and migrate or remove it. When the warnings also say when the workspace block manifest was last synced, the field or type may simply be newer than the manifest: if the site's code declares it, keep the content and sync the manifest (cmssy sync-manifest in the site's repo) instead. A block whose type the workspace block manifest does not register is refused unless the page already stores that block - pick registered types from list_block_types. |
promote_dev_draft | pages:edit | Promote YOUR per-user dev draft overlay onto the page's shared draft (replaces the shared draft blocks; the overlay belongs to the token's user). Do this after the block code for the composed types is deployed to the site. Fails when you have no dev draft for the page. If the result includes blockWarnings, the promoted content violates the workspace block manifest - correct the content and save again. Promoting a block whose type the workspace block manifest does not register is refused - run cmssy sync-manifest from the deployed code first. |
publish_page | pages:publish | Publish a page (or re-publish with the latest draft changes). Publishes both content and layout. |
receive_return | orders:manage | Record the return parcel as received: how many units of each line arrived and how many go back to stock. Stock is adjusted by the restocked units only. |
record_order_invoice | orders:manage | Attach an invoice (number, optional URL and provider) to an order. |
record_order_invoice_correction | orders:manage | Attach a correction invoice (credit note: number, optional URL and provider) to an order that already has its invoice, e.g. after a refund. Allowed on canceled and refunded orders; the number must be new to the order. |
record_order_payment | orders:manage | Record a (possibly partial) payment against an order's outstanding balance. amount is in minor units of the order's currency and capped at the balance due. |
redeliver_webhook_delivery | webhooks:manage | Send a finished webhook delivery again. The stored payload goes out as a NEW delivery with its own id and its own retry ladder; the original row is left untouched and the new one records replayOf. A delivery that is still pending is refused. |
refund_order | orders:manage | Refund an order. Omit amount for a full refund; pass amount (minor units of the order's currency) for a partial refund. |
refund_return | orders:manage | Record a refund for a return - money already sent back at the payment provider. It counts against the order's refunds and completes a received return. |
reject_return | orders:manage | Reject a return the customer requested; it frees its items for another return. |
remove_block_from_page | pages:edit | Remove a specific block from a page by its instance id. Works for content and layout blocks. |
remove_price_list_entries | models:edit | Remove up to 1000 fixed prices from a price list by key: recordId alone for a product without variants, recordId + variantKey for one variant of a product with variants; currency limits a key to that currency's row, without it every currency's row goes. Those products then fall back to the catalogue price minus the list's percentOff. Returns how many were removed; a key with no entry removes nothing. |
reopen_order | orders:manage | Reopen a closed order so it shows as work in progress again. A canceled order cannot be reopened. |
resend_customer_verification | customers:manage | Issue a fresh verification token for a customer whose status is pending and hand it to the workspace's app as the webhook event account.verification_requested - cmssy never emails a customer, the app does. The previous token stops working and the new one lasts 24 hours. Refused for a customer who is already verified or is suspended, and after five account requests for the same customer in an hour. `endpointSubscribed: false` means the token was issued but no enabled webhook endpoint receives the event, so nothing reaches the customer. |
restore_page | pages:delete | Restore a deleted page group from the trash: the page and every descendant deleted with it come back, all as unpublished drafts, with their content, history and ids. When the original parent no longer exists the page comes back at the top level. Refused with CONFLICT, restoring nothing, when a live page already uses one of the group's slugs (the error names the slug) or one of the pages is still live; refused with PLAN_LIMIT_EXCEEDED when the restored pages would exceed the organization's page limit. Needs pages:delete. Returns the restored root page with its published state. |
revert_to_published | pages:edit | Discard all draft changes and revert a page to its last published version. |
rotate_webhook_secret | webhooks:manage | Rotate a webhook endpoint's signing secret. Returns the endpoint and the NEW secret (shown only once). |
send_customer_password_reset | customers:manage | Issue a password reset token, the same one the site's forgot-password flow issues, and hand it to the workspace's app as the webhook event account.password_reset_requested - cmssy never emails a customer, the app does. The token works for one hour. For an active customer who cannot sign in. Refused for a suspended customer, for one who has not verified yet (use resend_customer_verification), for a customer whose account model has no password sign-in, and after five account requests for the same customer in an hour. `endpointSubscribed: false` means the token was issued but no enabled webhook endpoint receives the event, so nothing reaches the customer. |
set_company_price_display_mode | customers:manage | Set how the buyers of a company record read prices: net (VAT added on top) or gross (VAT inside); null falls back to the default, net for a company buyer. Applies to carts started after the change; existing carts and orders keep the mode they were priced in. Refused for a record that is not a company (a model with the Company capability). Returns the record id with its priceDisplayMode and taxRoundingMethod. |
set_company_price_list | customers:manage | Assign a price list to a company record; null unassigns. Every member of the company pays this list - one list per buyer, and a member's own list is ignored while they belong to the company. A company without a list leaves its members on catalogue prices. Refused for a record that is not a company (a model with the Company capability) - for a customer use set_customer_price_list. Returns the record id and its priceListId. |
set_company_tax_exemption | customers:manage, site:config:edit | Exempt a company record's orders from VAT, or clear the exemption with null. An exempt company's carts and orders carry 0% and 0 tax with reason as the legal note, whatever its VAT id; in a workspace that stores gross prices the VAT inside them is removed, not charged. Carts already holding the old status are refused at checkout (BUYER_CHANGED) and orders keep the treatment they were placed with. Needs customers:manage and site:config:edit, the same pair as set_company_vat_verified and as linking a customer to a company whose VAT id is verified or that is tax exempt. Refused for a record that is not a company (a model with the Company capability). Returns the record id with vatId, vatCountry, vatVerifiedAt, vatVerifiedBy and taxExemptReason. |
set_company_tax_rounding | customers:manage | Set how VAT is rounded for the net-price buyers of a company record: per_line or per_rate; null falls back to the workspace's companyTaxRounding (update_cart_config). Gross-price buyers and consumers are always rounded per_line. Applies to carts started after the change; existing carts and orders keep the method they were priced with. Refused for a record that is not a company (a model with the Company capability). Returns the record id with its priceDisplayMode and taxRoundingMethod. |
set_company_vat_id | customers:manage | Set the EU VAT id of a company record. cmssy normalizes it (spaces, dots and dashes dropped, GR read as EL) and checks it against the member state's format; a malformed id is refused (BAD_USER_INPUT). null or empty clears it. A changed id is no longer verified, so its orders are taxed as standard until set_company_vat_verified attests the new value. Needs customers:manage. Verifying the id or exempting the company (set_company_vat_verified, set_company_tax_exemption) needs customers:manage and site:config:edit, and so does linking a customer to a company whose VAT id is verified or that is tax exempt. Refused for a record that is not a company (a model with the Company capability). Returns the record id with vatId, vatCountry, vatVerifiedAt, vatVerifiedBy and taxExemptReason. |
set_company_vat_verified | customers:manage, site:config:edit | Attest that a company record's VAT id was checked (for example in VIES), or withdraw that attestation. A verified EU VAT id of another member state than the workspace's sellerCountry (update_cart_config) zero-rates the company's orders as reverse charge, unless an order ships to the seller's country, or out of the EU as an export; withdrawing it taxes them as standard again. Carts already holding the old status are refused at checkout (BUYER_CHANGED) and orders keep the treatment they were placed with. Refused when the company has no VAT id (set it with set_company_vat_id) and with CONFLICT when the stored id differs from expectedVatId. Needs customers:manage and site:config:edit, the same pair as set_company_tax_exemption and as linking a customer to a company whose VAT id is verified or that is tax exempt. Refused for a record that is not a company (a model with the Company capability). Returns the record id with vatId, vatCountry, vatVerifiedAt, vatVerifiedBy and taxExemptReason. |
set_customer_company_role | customers:manage | Give a customer a company role in the company they belong to now. Roles come from the workspace's catalogue; v1 has two: 'admin' sees every order placed for the company, 'buyer' (the default) only their own. The role holds only while the customer stays in that company - moved to another, they are buyer there. Refused when the customer has no company, and for a key outside the catalogue. Returns the customer with companyRole as the effective role. |
set_customer_price_list | customers:manage | Assign a price list to a customer without a company (a B2C VIP); null unassigns. One list per buyer: a customer in a company pays the company's list, so assigning to them is refused - assign the list to the company with set_company_price_list instead. Returns the customer with priceList (their own) and effectivePriceList (the one that prices them, source MEMBER or COMPANY). |
set_discount_enabled | discounts:manage | Enable or disable a discount code. |
set_order_pipeline_stage | orders:manage | Move an order to a pipeline stage (use get_order_pipeline for valid stage ids). |
set_price_list_entries | models:edit | Upsert up to 1000 fixed prices on a price list in one call (an ERP or spreadsheet import). Each row is one product (no variantKey) or one variant of a product with variants (variantKey required there), price in minor units of the row's currency (currency omitted = the default currency; an additional currency writes that currency's own row) with optional volume breaks and optional minQuantity / maxQuantity order bounds; a row replaces the whole entry already set for the same product/variant and currency, so bounds it had are cleared unless the row re-sends them (read them with get_price_list); every other entry stays. All or nothing: one invalid row refuses the whole call and the error names every bad row by index. Fixed prices override the list's percentOff. Never removes entries - use remove_price_list_entries for that. |
set_price_list_entry | models:edit | Set a price list's fixed price for one product, or one variant of a product with variants (variantKey required there - a list prices each variant on its own, never the product as a whole; omit it for a product without variants). currency picks the row: omitted is the default-currency row, an additional currency writes that currency's own row, which prices only carts in it. The fixed price (minor units of the row's currency, with optional volume breaks) overrides the list's percentOff for that product or variant; replaces the entry already set for it as a whole, so an existing minQuantity / maxQuantity left out of the call is cleared - read it with get_price_list and re-send it to keep it. For many rows use set_price_list_entries. |
set_product_currency_prices | models:edit | Set a product's prices in the workspace's additional currencies (update_cart_config additionalCurrencies), e.g. [{currency: 'EUR', price: 4500, tiers: [{minQty: 10, price: 4000}]}]. Prices and breaks are minor units of each currency; nothing is converted from the default-currency price. price is read only while the product has no variants - a product with variants takes each variant's price from variants (here) and these tiers price every variant without breaks of its own in that currency (price null keeps just the tiers). variants sets each variant's prices per currency by its key (list_products variants[].key), e.g. [{variantKey, prices: [{currency: 'EUR', price: 4500}]}], and never touches stock, SKU or the default-currency price - this is the safe way to price variants per currency; prefer it over set_product_variants currencyPrices, which rewrites every variant's stock and SKU. A product with no price in a sales channel's currency is not sold on that channel (NO_PRICE_IN_CURRENCY). prices replaces the record's whole list: send every currency the product keeps. A variant removed while the call ran fails it with CONFLICT - re-read list_products and retry. |
set_product_tiers | models:edit | Set the record-level volume price breaks on a product (B2B quantity discounts). They price the product and every variant that defines no breaks of its own; a variant's own breaks are part of its definition, so set those with set_product_variants. A line's unit price steps down to the highest break its quantity reaches, and the cart and the order both charge that price. Prices are minor units of the default currency; breaks in an additional currency are set with set_product_currency_prices. Passing an empty array removes the breaks. increment sets the order step on the same record. |
set_product_variants | models:edit | Define a product's variants. Each variant is one combination of values for the model's variantAxes (set those with update_model) and carries its own price, stock, SKU and volume breaks. The call replaces the whole set, so send every variant the product keeps - a variant left out is deleted. Every field but tiers and currencyPrices is written as sent (those two are kept when omitted), so copy sku and stock (onHand) from list_products for each variant you keep; both are required, null for none. Stock already reserved by carts stays with the variant that keeps its selection. Prices are minor units: price and tiers in the default currency, currencyPrices in each additional currency (omitted = kept, like tiers). To change only prices per currency use set_product_currency_prices variants instead - it never touches stock or SKU. |
suspend_customer | customers:manage | Suspend a customer: blocks sign-in and ends every live session. Orders and carts stay. Refused for an account that has not verified yet or is already suspended. |
take_over_page_lock | pages:publish | Take over the edit lock on a page another editor is holding open, so the next write (publish_page, update_page_blocks, update_page_layout, ...) is not refused with PAGE_LOCKED. The previous holder is bounced to read-only and may lose unsaved work. Needs pages:edit or pages:publish on the page. |
unlock_customer | customers:manage | Unlock a customer who was locked out after too many failed sign-ins: clears the failed-attempt counter, `lockedUntil` and the sign-in throttle for that identity, so the next sign-in with the right password succeeds. Does not change the password and does not reinstate a suspended customer (that is unsuspend_customer, which also clears the lock). |
unpublish_page | pages:publish | Unpublish a published page (toggles its published state off). |
unsuspend_customer | customers:manage | Let a suspended customer sign in again and clear any lockout. Refused for a customer who is not suspended. |
update_block_content | pages:edit | Update a specific block's content on a page. Defaults to merging with existing content; pass mode: 'replace' to overwrite the block's whole content. Works for content and layout blocks. If the result includes blockWarnings, the saved content violates the workspace block manifest (unknown field, wrong value shape, or a stored block whose type is no longer registered) - correct the content and save again, unless the warning is about a stored block whose type is no longer registered: that one is a manifest problem, so restore or sync the type, or find the block with list_block_usage and migrate or remove it. When the warnings also say when the workspace block manifest was last synced, the field or type may simply be newer than the manifest: if the site's code declares it, keep the content and sync the manifest (cmssy sync-manifest in the site's repo) instead. A block whose type the workspace block manifest does not register is refused on the shared draft unless the page already stores that block - compose types that are not deployed yet in target: 'devDraft' and promote once the code ships; pick registered types from list_block_types. |
update_cart_config | site:config:edit | Configure the workspace's commerce settings: default and additional currencies, whether prices include tax, tax rates, shipping methods, custom order fields, stock thresholds, cart limits, session lifetimes and the B2B toggles. Only provided fields change; arrays replace the whole list. companyTaxRounding is the workspace's VAT rounding for company buyers who read net prices (a company can override it with set_company_tax_rounding); consumers are always rounded per_line. sellerCountry and reverseChargeNote drive reverse charge: a company with a verified EU VAT id of another member state (set_company_vat_verified) pays 0% VAT and its orders carry the note. An order shipped out of the EU VAT area, or to any other country from a sellerCountry outside the EU, is zero-rated as an export for any buyer, with exportNote on the order. Nothing is converted between currencies: a sales channel sells in one of them (create_sales_channel currency), and every price in an additional currency is set explicitly (set_product_currency_prices, set_product_variants, set_price_list_entries currency, shippingMethods currencyPrices). Which models the store sells is not set here: a model is sellable when its product capability is enabled (update_model, product.enabled). |
update_discount | discounts:manage | Update a discount (partial). code/type/currency become immutable once the discount has been used. A code with any minimum (minSubtotal for the default currency, minSubtotalByCurrency for additional currencies) applies only in the currencies those minimums name. |
update_form | forms:edit | Update an existing form's name, slug, status, fields or settings. Name the settings keys you are changing - the rest keep their stored values. 'fields' is the opposite: it replaces the whole array, so send every field you want the form to keep. |
update_form_submission_status | forms:submissions:manage | Update a form submission's status (pending, processed, spam, archived). |
update_media_folder | media:edit | Rename a media folder and/or move it under a different parent folder. |
update_model | models:edit | Update a data model by id or slug: name, slug, description, icon, color, displayField, defaultSort, statusField, fields, product capability config, uniqueFields (replaces the whole list; refused while records already share a value), deliveryAccess ("public" lets the user's app read the model through the delivery API; "none" is admin only), or urlPattern (where its records live on the storefront, e.g. /p/{slug} - their `url` is built from it; null removes it). `fields` is a PATCH - listed fields are added or replaced by key, unlisted fields stay untouched; use `removeFields` to delete fields and `fieldOrder` (every remaining key, in order) to reorder them. `product` is also a PATCH of the commerce capability config (enabled, priceField, skuField, inventoryField, variantAxes) - omitted keys keep their stored values. While the product is enabled, a call that changes product, fields, removeFields or displayField is graded against every product role, and refused when one would name a missing field or a field of a type it cannot read. `auth` is a PATCH of the accounts config (enabled, identityField, companyField for B2B companies over customers - a relation to a model with Company enabled, verification, lockout) - omitted keys keep their stored values, null unlinks the company. Which fields a member may change on their own account and send at sign-up is each field's `memberCanSet` (registration accepts only those; password fields and the company field never). `company` is a PATCH of the Company capability ({ enabled }) - a model is at most one of product, account (auth) or company; turning it off is refused while an accounts model's companyField links it. |
update_order_details | orders:manage | Update order metadata: customer email, internal notes, PO number, delivery address and custom order fields. Only provided fields change. A delivery address whose country would change the order's frozen tax treatment (taxTreatment in get_order, e.g. reverse_charge to standard) is refused (BAD_USER_INPUT, TAX_TREATMENT_CHANGED); cancel the order and place it again instead. |
update_page_blocks | pages:edit | Set the full content blocks array on a page (replaces all existing content blocks). Blocks with matching ids keep their existing content when not provided. If the result includes blockWarnings, the saved content violates the workspace block manifest (unknown field, wrong value shape, or a stored block whose type is no longer registered) - correct the content and save again, unless the warning is about a stored block whose type is no longer registered: that one is a manifest problem, so restore or sync the type, or find the block with list_block_usage and migrate or remove it. When the warnings also say when the workspace block manifest was last synced, the field or type may simply be newer than the manifest: if the site's code declares it, keep the content and sync the manifest (cmssy sync-manifest in the site's repo) instead. A block whose type the workspace block manifest does not register is refused on the shared draft unless the page already stores that block - compose types that are not deployed yet in target: 'devDraft' and promote once the code ships; pick registered types from list_block_types. |
update_page_layout | pages:edit | Update page-level layout: inheritance, overrides, or replace all layout blocks. If the result includes blockWarnings, the saved content violates the workspace block manifest (unknown field, wrong value shape, or a stored block whose type is no longer registered) - correct the content and save again, unless the warning is about a stored block whose type is no longer registered: that one is a manifest problem, so restore or sync the type, or find the block with list_block_usage and migrate or remove it. When the warnings also say when the workspace block manifest was last synced, the field or type may simply be newer than the manifest: if the site's code declares it, keep the content and sync the manifest (cmssy sync-manifest in the site's repo) instead. A block whose type the workspace block manifest does not register is refused unless the page already stores that block - pick registered types from list_block_types. |
update_page_settings | pages:edit | Update page metadata: name, slug, parent and position in the tree, display name, SEO fields and custom fields. Only the languages and fields you pass change - the ones you omit keep their current values. |
update_page_type | page:types:manage | Update a page type: name, slug, icon, url prefix, allowChildren, or its custom-field schema. Fields you omit keep their current value, EXCEPT `fields`, which replaces the whole schema. |
update_price_list | models:edit | Rename a price list, change its percentOff (-1000 to 99.99, 2 decimals, negative = a markup; it prices every product the list holds no fixed price for) its startsAt / endsAt window (null clears a bound), or the sales channels it is published to (channels replaces the whole set, [] unpublishes it from every channel, leave it out to keep). Fixed prices are changed with set_price_list_entry / set_price_list_entries. Carts already priced from the list keep their prices until the buyer adds again; orders keep theirs. |
update_record | models:edit | Update an existing record by id (from list_records). Pass `data` to merge field values (fields you don't pass are unchanged), `status` to transition the record's lifecycle state, and/or `published` to take it on or off the site. At least one of data/status/published is required. Each record carries `url`: its live storefront link, built by the server from the model's urlPattern and the site's public site URL. Use it whenever you link to a record and never build a storefront URL yourself (not from a slug, not from the site address). When url is null or missing, say why instead of guessing: the model has no urlPattern (set it with update_model), the model is not delivered (deliveryAccess none, or it is the login model), the site has no public site URL, or the record - or one it links to - is unpublished. |
update_region_settings | pages:edit | Set the settings of one layout region on a page, e.g. a sidebar's width or a header's variant. Reads the page's current region settings, replaces only the named region and writes the whole list back (page.updateLayout with layoutRegionSettings, one version-guarded write); entries for regions or keys the manifest no longer declares are pruned on the way. Values are validated against the workspace layout manifest's region settings schema: an unknown region, an unknown key, or non-empty values on a region that declares no settings (such a region accepts {} only) is rejected with the backend's BAD_USER_INPUT message. Child pages inherit the region's settings unless they set their own (see get_page.resolvedRegions). |
update_return_tracking | orders:manage | Set or correct the carrier and tracking number of the parcel the customer sends back. |
update_sales_channel | models:edit | Rename a sales channel or change its displayMode, priceAccess or currency. The key cannot change. Changing the currency abandons the carts open on the channel - check activeCartCount first. Narrowing priceAccess refuses carts and checkout to buyers who no longer qualify; their carts are kept and come back if access returns. Which lists price the channel is changed on the price list (update_price_list channels). |
update_shipment | orders:manage | Change a parcel's delivery status or correct its tracking. Only provided fields change; sending the stored values changes nothing. |
update_webhook | webhooks:manage | Update a webhook endpoint (partial). Pass enabled to enable/disable. Pass description=null to clear it. The signing secret is not returned. |
upload_media | media:upload | Upload a file to the workspace media library from a local path or a remote URL (max 50MB; images, video, audio, PDF and common office documents). Returns the stored asset whose `url` can be used in block content and record media fields. |