Apply targeted changes to an existing catalog: addProducts, removeProduct, addPage, removePage, setGrid, reorderPages, setCategory, editProduct, addBlock, editBlock, removeBlock, setProductCellStyle, setHeader, setFooter, setPageStyle. EVERY edit here is scoped to THIS CATALOG, never to the merchant's store: editProduct changes the title, price, sku, description, vendor or image as this catalog shows them, and the store keeps its own values — so a price or title changed "in the catalog" is editProduct, with no change in the store needed. A value edited this way is kept on later syncs, because it is treated as the merchant's deliberate wording rather than stale data. foldsquare://schemas/catalog-edit-ops.json lists exactly which fields each op accepts. Text on a page, and header/footer text, may carry dynamic fields written bare in the html — {{shop.name}}, {{shop.url}}, {{shop.email}}, {{shop.phone}}, {{shop.address}}, {{page.number}}, {{page.category}}, {{general.current_year}} — and they are stored as live fields, updated wherever the catalog is shown. Product fields belong in the tiles, through a details block. Page blocks — cover headings, shapes, pictures — are listed by get_catalog under blocks with ids such as "p1-text-2" whether or not the template gave them a key; editBlock changes one through its html, which carries its styling. THE LISTING DESIGN — what a merchant sees inside every product tile (the photo region, the title, "Product Code:", the price box, the description) — is reported by get_catalog under productCell.blocks, each with an id such as "photos-1", "details-2" or "shp-…", and changed with editBlock and that id: lines for a details block (text and product fields with sizes, rather than html), photos for the photo region (layout, fit, thumbnails), fill for a shape, style for a block's background or border. Font sizes are px at PRINT resolution, not web sizes; get_catalog reports the sizes the design already uses. addBlock with inProductCells: true adds a block to the tiles; removeBlock takes one away. A design edit lands on EVERY tile that renders the design, so it shows throughout the catalog; productId limits it to one product's tile, which then stops following the catalog design. Positions inside a tile are percentages of the tile: at.area, at.relativeToBlock with a sibling block id, or an explicit at.box. setProductCellStyle styles the tiles themselves (border, background, padding). Which fields a tile shows changes through its details block (editBlock with lines); setFields is retired and always refused. Edits touch only what they name, so work the merchant did in the visual editor survives — but an editor tab open during the edit overwrites it on its next autosave unless it is reloaded. Page indexes come from get_catalog's pages (zero-based; not positions in document.pages), product ids from its document, block ids from blocks and productCell. A CUSTOM GRID — any number of product tiles across and down, within 10 x 50, as the editor's grid panel allows; the template sets how tiles look, not how many fit on a page — is setGrid, on any page: on a products page it re-lays-out the products; on a page with no products yet it lays out that grid of empty slots for addProducts with that page to fill; and a blank page, a cover or any other kind of page simply becomes a products page with that grid (what was on it is removed, which the confirmation says) — never refuse a grid because of the kind of page it is asked for. A NEW page on a custom grid is addPage { kind: "products", grid } followed by addProducts with its page. Operations that re-lay-out or delete a page are applied only with confirm: true; without it nothing changes and the answer lists the consequences under requiresConfirmation, for the merchant to approve. Results name a page as "page 6 (index 5)": the index is for the next op, the page number is what to say to the merchant. The first edit of a catalog in a while returns livePreviewUrl, a page that reloads by itself as edits land; the edits that follow do not repeat it.