Build and publish static sites on Dotsy with draft-first MCP tools, OAuth Connect, and API keys.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Propose nav wiring + blog collectionization for an imported mirror (draft, opt-in). Read-only; returns per-adapter reports + proposalEtag. Nav decline may include nextStep (e.g. mega-menu → edit fragments/header.html). Wait for mirror-vs-editable answer if requiredDecision pending.
Site slug, e.g. acme-studio
One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here.
Return the full per-member harvest report (default: compacted for the token budget).
Which adapters to analyze (default: both).
Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy.
Replace an existing UNCONSUMED proposal (otherwise re-analyze 409s proposal_exists).
Tool list last changed Oct 25, 2026.
Propose nav wiring + blog collectionization for an imported mirror (draft, opt-in). Read-only; returns per-adapter reports + proposalEtag. Nav decline may include nextStep (e.g. mega-menu → edit fragments/header.html). Wait for mirror-vs-editable answer if requiredDecision pending.
| Argument | Type | Description |
|---|---|---|
| full | boolean | Return the full per-member harvest report (default: compacted for the token budget). |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| options | object | |
| adapters | array | Which adapters to analyze (default: both). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| refreshProposal | boolean | Replace an existing UNCONSUMED proposal (otherwise re-analyze 409s proposal_exists). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"full": {
"type": "boolean",
"description": "Return the full per-member harvest report (default: compacted for the token budget)."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"options": {
"type": "object",
"properties": {
"menu": {
"type": "string",
"minLength": 1,
"description": "Menu name the nav adapter wires (default \"primary\")."
},
"index": {
"type": "string",
"minLength": 1,
"description": "Blog index content key (default: probe blog.html, posts.html, …)."
},
"prefix": {
"type": "string",
"minLength": 1,
"description": "Member key prefix override, e.g. \"post/\" (default: detected from index card links)."
},
"basePath": {
"type": "string",
"minLength": 1,
"description": "Index route path override, e.g. \"/blog\" (default: the index route)."
},
"fragment": {
"type": "string",
"pattern": "^[\\w-]+$",
"description": "Chrome fragment name the nav adapter reads (default \"header\")."
},
"pageSize": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Explicit page size (default: visible card count)."
}
},
"additionalProperties": false
},
"adapters": {
"type": "array",
"items": {
"enum": [
"nav",
"collection"
],
"type": "string"
},
"minItems": 1,
"description": "Which adapters to analyze (default: both)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"refreshProposal": {
"type": "boolean",
"description": "Replace an existing UNCONSUMED proposal (otherwise re-analyze 409s proposal_exists)."
}
},
"additionalProperties": false
}Apply the adapt proposal (draft): wire nav into the menu store and/or rewrite the blog index to a live <dotsy-collection>. One undo covers the whole apply; a second apply is refused until adapt_site_revert (or force). Queued applies are polled to completion.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| force | string | An undo record from a prior apply exists (409 adapt_undo_exists): defer-discard it — the prior record is dropped only when this apply SUCCEEDS; a partial-failure rollback reinstates it. Prefer adapt revert first. |
| dryRun | boolean | Full computation, would-write set + previews, ZERO writes, no undo. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch* | string | The proposal etag from analyze (or GET …/adapt/proposal / status). |
| adapters* | array | Which analyzed adapters to apply. |
| guestToken | string |
Atomically restore everything the last adapt_site_apply wrote (fragments, the menu doc when the op touched it, index, member configs, routes).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Connect apex and/or www on a paid plan; starts a DNS connect session.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| hosts | array | 1–2 hostnames: apex (example.com) and/or www (www.example.com). |
| domain | string | Bare domain when hosts omitted — apex expands to apex + www; a subdomain connects as-is. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"hosts": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 2,
"minItems": 1,
"description": "1–2 hostnames: apex (example.com) and/or www (www.example.com)."
},
"domain": {
"type": "string",
"description": "Bare domain when hosts omitted — apex expands to apex + www; a subdomain connects as-is."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Stage writes[] + deletes[] in one call; attach routes via writes[].route. writes[].ifMatch (hash from get_site_manifest; "" = must not exist) guards each key (a delete takes { key, ifMatch } too); atomic:true makes one stale key write nothing (409 changeset_conflict). At most 10 writes; each body ≤60KB and the call ≤80KB. Larger new pages: stage_content_chunk then writes[].bodyStaging, or dotsy push / PUT content-raw.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| atomic | boolean | All or nothing: every writes[].ifMatch and deletes[].ifMatch is checked before anything is written. One stale key writes nothing and the call fails with 409 changeset_conflict listing `conflicts`. Default: a stale write is skipped and listed, the rest apply. |
| writes | array | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| deletes | array | Keys to delete: a key, or { key, ifMatch } (the hash you read) so a page changed since is not deleted (listed in conflicts). |
| message | string | |
patch_content on multiple keys; all-or-nothing validation. Preferred edit path for pages over 60KB. replace-string value/replace ≤60KB; whole call ≤80KB.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| items* | array | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"items",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"key",
"ops"
],
"properties": {
"key": {
"type": "string",
"minLength": 1
},
"ops": {
"type": "array",
"items": {
"type": "object",
"required": [
"op"
],
"properties": {
"op": {
"enum": [
"set-attr",
"remove-attr",
"replace-text",
"remove-node",
"insert-after",
"replace-inner-html",
"replace-outer-html",
"replace-string",
"wrap",
"unwrap",
"move"
],
"type": "string"
},
"tag": {
"enum": [
"div",
"section",
"footer",
"header",
"article",
"aside"
],
"type": "string"
},
"find": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"attrs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"value": {
"type": "string"
},
"expect": {
"type": "integer",
"minimum": 0
},
"target": {
"type": "string",
"minLength": 1
},
"replace": {
"type": "string"
},
"anchored": {
"type": "boolean"
},
"position": {
"enum": [
"before",
"after"
],
"type": "string"
},
"selector": {
"type": "string",
"minLength": 1
},
"selectors": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"additionalProperties": false
},
"minItems": 1
}
},
"additionalProperties": false
},
"maxItems": 50,
"minItems": 1
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Upload 1–200 CMS assets; key = path after /assets/. Each item: exactly one of bodyBase64, bodyText (plain text for .css/.js/.mjs/.json/.svg/.txt/.xml only — not .html pages), or importFromUrl. Optional bodySha256 verifies submitted bytes before write; response sha256 is stored bytes (JS/CSS match; WebP rasters may differ). JPEG/PNG/static GIF are re-encoded to WebP (response key photo.webp; /assets/photo.jpg keeps serving it) — use the response key in CSS/JS; optimize:false stores the bytes as sent at your key; animated GIFs are always kept. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| items* | array | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"items",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "string",
"minLength": 1,
"description": "Path after /assets/ on the site — e.g. photos/hero.webp or style.css. Do not prefix with assets/ or /. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish."
},
"intent": {
"enum": [
"hero",
"column",
"inline",
"logo"
],
"type": "string"
},
"bodyText": {
"type": "string"
},
"optimize": {
"type": "boolean",
"description": "Default true: a JPEG, PNG or static GIF is re-encoded to WebP (key photo.jpg is stored as photo.webp, and /assets/photo.jpg still serves it). false stores the bytes exactly as sent, at the key given. Animated GIFs are always kept as sent."
},
"bodyBase64": {
"type": "string"
},
"bodySha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "Optional SHA-256 of the submitted upload bytes (decoded bodyBase64 or raw PUT body). Mismatch returns body_sha256_mismatch before any write. Response/get_asset sha256 is the stored blob (WebP after IMAGES optimization for rasters; unchanged for JS/CSS/SVG)."
},
"contentType": {
"type": "string",
"minLength": 1
},
"importFromUrl": {
"type": "string",
"format": "uri"
}
},
"additionalProperties": false
},
"maxItems": 200,
"minItems": 1
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Stage many content keys (pages, layouts, fragments). Content only — not routes or assets. Each body ≤60KB and the whole call ≤80KB; larger pages use stage_content_chunk, dotsy push, or PUT content-raw. May queue above the inline threshold.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| title | string | |
| content* | array | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"content",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"title": {
"type": "string"
},
"content": {
"type": "array",
"items": {
"type": "object",
"required": [
"key",
"body"
],
"properties": {
"key": {
"type": "string",
"minLength": 1
},
"body": {
"type": "string"
},
"contentType": {
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 10,
"minItems": 1
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Move the guest draft onto your signed-in Dotsy account. Requires OAuth Connect; pass the guestToken from start_site.
| Argument | Type | Description |
|---|---|---|
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken* | string | Guest token from start_site (required). Pass the pgg_ value returned by start_site. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"context",
"guestToken"
],
"properties": {
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site (required). Pass the pgg_ value returned by start_site."
}
},
"additionalProperties": false
}Create empty site; seeds brief. Globally taken slugs auto-suffix to `{slug}-{adjective}-{noun}` (default); pass onSlugTaken:"fail" to get a 409 instead of a renamed site.
| Argument | Type | Description |
|---|---|---|
| slug* | string | |
| title | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| purpose | string | |
| workspace | string | null | Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| editingMode | string | How the editor's Save behaves. 'live' (default) publishes each save immediately; 'staged' keeps saves as drafts until publish_site. Prefer 'staged' when an agent will hand the editor to a person (see start_edit_session → draftEditorUrl) so keystrokes don't go straight to the public site. API writes always stage regardless of this setting. |
Deprecated — use structure_site_analyze.
| Argument | Type | Description |
|---|---|---|
| full | boolean | Return the full manifest incl. per-page HTML samples (default: compacted — etag/action/counts kept, samples truncated — to fit the token budget). |
| site* | string | Site slug, e.g. acme-studio |
| scope | string | Default flat-only; analyze clusters flat keys only. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| persist | boolean | First call: false (preview only). true only after user confirms editable/CMS mode. |
| profileId | string | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| sampleLimit | integer | |
| refreshManifest | boolean |
Delete a static asset by key. The editor and draft preview drop it at once; the published site drops it at the next publish.
| Argument | Type | Description |
|---|---|---|
| key* | string | Path after /assets/ on the site — e.g. photos/hero.webp or style.css. Do not prefix with assets/ or /. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish. |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"context"
],
"properties": {
"key": {
"type": "string",
"minLength": 1,
"description": "Path after /assets/ on the site — e.g. photos/hero.webp or style.css. Do not prefix with assets/ or /. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Delete content key (tombstone if published). A fragments/* section that pages still place is refused with section_in_use (lists the pages) — detach it or remove it first.
| Argument | Type | Description |
|---|---|---|
| key* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"context"
],
"properties": {
"key": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Remove a draft A/B test (releases variant bodies; does not publish).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| experimentId* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"experimentId",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"experimentId": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
}Remove one item from a menu (page stays live).
| Argument | Type | Description |
|---|---|---|
| id* | string | |
| menu* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"menu",
"id",
"context"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"menu": {
"type": "string",
"minLength": 1
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Remove a route by path.
| Argument | Type | Description |
|---|---|---|
| path* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"path",
"context"
],
"properties": {
"path": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Permanently delete site; confirmSlug must equal slug.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| confirmSlug* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"confirmSlug",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"confirmSlug": {
"type": "string"
}
},
"additionalProperties": false
}Give one page its own copy of a shared section; every other page keeps the shared one. A draft — publish_site to go live. A section the layout places is hidden on that page instead (share_section name + hide).
| Argument | Type | Description |
|---|---|---|
| name* | string | Section name. Its file is fragments/<name>.html, placed with <dotsy-fragment name="<name>">. |
| site* | string | Site slug, e.g. acme-studio |
| dryRun | boolean | Default true: report what would change and write nothing. false: stage the change as a draft (publish_site makes it live). |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch | string | The page's content hash. If the page changed since, nothing is written. |
| pageKey* | string | Content key of the page that gets its own copy, e.g. 'pricing.html'. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
Discard unpublished drafts: all (omit key/keys/routes), one content key (key), or a selection (keys, routes). Destructive — check get_draft_status first.
| Argument | Type | Description |
|---|---|---|
| key | string | |
| keys | array | |
| site* | string | Site slug, e.g. acme-studio |
| routes | array | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"key": {
"type": "string",
"minLength": 1
},
"keys": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"routes": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Open the interactive page canvas to change content: the user clicks an element, then you call patch_content. Use when the intent is editing — not for verify-only checks (use preview_page).
| Argument | Type | Description |
|---|---|---|
| path | string | Route path (default /). |
| site* | string | Site slug. |
| stage | string | Preview stage. Default draft; published is planned but not supported yet. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site"
],
"properties": {
"path": {
"type": "string",
"description": "Route path (default /)."
},
"site": {
"type": "string",
"description": "Site slug."
},
"stage": {
"enum": [
"draft",
"published"
],
"type": "string",
"description": "Preview stage. Default draft; published is planned but not supported yet."
}
},
"additionalProperties": false
}Estimate days to reach promote readiness for a page (traffic baseline). Read-only.
| Argument | Type | Description |
|---|---|---|
| path* | string | Route path, e.g. /pricing |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"path",
"context"
],
"properties": {
"path": {
"type": "string",
"description": "Route path, e.g. /pricing"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Case-insensitive find→replace across pages in one staged commit. Batch all replacements into ONE call — never parallelize find_replace on the same key (concurrent edits surface as per-key conflict). find/replace ≤60KB.
| Argument | Type | Description |
|---|---|---|
| find* | string | |
| keys | array | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| replace* | string | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| expectPerKey | integer |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"find",
"replace",
"context"
],
"properties": {
"find": {
"type": "string",
"minLength": 1
},
"keys": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
}
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"replace": {
"type": "string"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"expectPerKey": {
"type": "integer",
"minimum": 1
}
},
"additionalProperties": false
}Account, user, memberships[]. Pass workspace on writes when memberships.length > 1.
| Argument | Type | Description |
|---|---|---|
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| workspace | string | null | Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"context"
],
"properties": {
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"workspace": {
"type": [
"string",
"null"
],
"description": "Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}List site activity or fetch one change diff (pass id). Filters: who, state, actor (me), since, limit≤20. Notes from context are visible to everyone on the site — no secrets.
| Argument | Type | Description |
|---|---|---|
| id | string | Event id — returns diff for this change instead of the list. |
| key | string | Content key when id is set (default first key in the event). |
| who | string | Default all. |
| slug* | string | Site slug, e.g. acme-studio |
| actor | string | Actor id or me. |
| limit | integer | Page size (default 20). |
| since | string | ISO date (default 7 days, plan retention floor). |
| state | string | needs_review = agent drafts awaiting a person's publish. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
Read adapt state: proposal summary + proposalEtag (+ applied/consumed flag), undo-record presence, active or queued job progress. Use to resume in a fresh session.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read-only traffic overview (default) or full breakdowns via include[]; optional bot id for crawler page drill-down.
| Argument | Type | Description |
|---|---|---|
| bot | string | Crawler bot id (e.g. googlebot, gptbot) → that bot's top crawled pages under `crawlerBotPages`. |
| site* | string | Site slug, e.g. acme-studio |
| range | string | Time window; default 30d. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| include | array | Full breakdown sections to add under `detail`: pages, sources, countries, devices, browsers, os, utm, goals, series, crawlers, experiments, events — or 'all'. Omit for the overview only. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"bot": {
"type": "string",
"description": "Crawler bot id (e.g. googlebot, gptbot) → that bot's top crawled pages under `crawlerBotPages`."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"range": {
"enum": [
"7d",
"30d",
"90d"
],
"type": "string",
"description": "Time window; default 30d."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"include": {
"type": "array",
"items": {
"enum": [
"pages",
"sources",
"countries",
"devices",
"browsers",
"os",
"utm",
"goals",
"series",
"crawlers",
"experiments",
"events",
"all"
],
"type": "string"
},
"description": "Full breakdown sections to add under `detail`: pages, sources, countries, devices, browsers, os, utm, goals, series, crawlers, experiments, events — or 'all'. Omit for the overview only."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read one asset (metadata + base64 + stored sha256). sha256 is the stored blob; may differ from upload bodySha256 when IMAGES re-encodes rasters. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish.
| Argument | Type | Description |
|---|---|---|
| key* | string | Path after /assets/ on the site — e.g. photos/hero.webp or style.css. Do not prefix with assets/ or /. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish. |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"context"
],
"properties": {
"key": {
"type": "string",
"minLength": 1,
"description": "Path after /assets/ on the site — e.g. photos/hero.webp or style.css. Do not prefix with assets/ or /. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read the site's collection field definitions (`_data/collections.json`, draft view): { schema: { v: 1, collections: { "<key>": { fields[], settings? } } }, hash }. hash is null when no schema exists yet — pass it as put_collection_schema ifMatch. 409 collection_schema_invalid { hash, issues } means the stored file is broken: fix it with put_collection_schema using that hash.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read one content key; optional selector (region) or published=true (live body). Bodies over 40KB without a selector return a truncated summary — use selector, batch_patch_content, or dotsy pull.
| Argument | Type | Description |
|---|---|---|
| key* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| selector | string | |
| published | boolean | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"context"
],
"properties": {
"key": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"selector": {
"type": "string"
},
"published": {
"type": "boolean"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Current connect session and nextAction (browser URL or manual DNS guide).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| sessionId | string | Connect session id from add_custom_domain; omit to resume pending. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"sessionId": {
"type": "string",
"description": "Connect session id from add_custom_domain; omit to resume pending."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Pending draft changes: content keys and routes with status. May include requiredDecision (publish_confirm) before publish_site.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read one form submission with the full field payload (explicit PII access — use only when needed).
| Argument | Type | Description |
|---|---|---|
| id* | string | Submission id from list_form_submissions |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"id",
"context"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "Submission id from list_form_submissions"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read a menu's draft items and etag; menu rules → get_skill('nav').
| Argument | Type | Description |
|---|---|---|
| menu* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"menu",
"context"
],
"properties": {
"menu": {
"type": "string",
"minLength": 1
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read the whole menu doc (all menus + shell/template), etag for put_menu_doc, and issues (by item id) — page_not_routable, page_missing, page_dead_link, page_is_redirect — computed from the draft routes, so a link that won't show or leads nowhere shows up before publish.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| source | string | Which doc to read. Default draft. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"source": {
"enum": [
"draft",
"live"
],
"type": "string",
"description": "Which doc to read. Default draft."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Get one route by path (home is '/').
| Argument | Type | Description |
|---|---|---|
| path* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"path",
"context"
],
"properties": {
"path": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Site detail, stats, publicUrl, brief head (default-on), and readiness flags. pages[] is a ~25-entry head by default (stats.pages has the true count) — pass pages: true for the full array (capped at 1000), or enumerate everything with list_content/get_site_manifest. Large sites (200+ pages): list_pages is paginated — use cursor or get_site_manifest for the full route set.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| brief | boolean | Include parsed brief head (default true). |
| pages | boolean | Return the full pages[] array instead of the default ~25-entry head (server-capped at 1000 either way). Default false. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"brief": {
"type": "boolean",
"description": "Include parsed brief head (default true)."
},
"pages": {
"type": "boolean",
"description": "Return the full pages[] array instead of the default ~25-entry head (server-capped at 1000 either way). Default false."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read-only build progress for humans (build-theater view) during structure/adapt or after import. Agent reads structuredContent.forHumans — optional; do not call in a loop during import_site_from_url (that tool blocks until done). Prefer get_site for agent logic.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug."
}
},
"additionalProperties": false
}Content keys + hashes only (optional routes=true) — static files live in list_assets, not manifest. Diff keys+hashes before apply_changeset; stage only changed bodies.
| Argument | Type | Description |
|---|---|---|
| mode | string | |
| site* | string | Site slug, e.g. acme-studio |
| limit | integer | |
| cursor | string | |
| routes | boolean | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"mode": {
"enum": [
"published",
"draft"
],
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"limit": {
"type": "integer",
"maximum": 1000,
"minimum": 1
},
"cursor": {
"type": "string"
},
"routes": {
"type": "boolean"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Site shape: every layout and shared section (`sections`: fragments/* by name, with page count, whether the file exists and staged-change flag), whether a layout is missing, redirects count, menus grouped by where they show, and collections with their page placements. Use for 'is my layout missing', 'which shared sections exist and where', 'where does this menu show' — without listing every page. Read-only; indexing mirrors list_pages (a freshly imported/graduated site may still be indexing).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Skill body + optional questions[]. Accepts an id OR a synonym (e.g. 'list', 'menu') — resolves aliases and suggests near-misses. Start with intake when ambiguous.
| Argument | Type | Description |
|---|---|---|
| id* | string | Skill id or synonym from list_skills, e.g. intake, clone, list, menu |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id",
"context"
],
"properties": {
"id": {
"type": "string",
"description": "Skill id or synonym from list_skills, e.g. intake, clone, list, menu"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
}
},
"additionalProperties": false
}Last structure apply job result (structuredKeys, conflicts, partial).
| Argument | Type | Description |
|---|---|---|
| full | boolean | Return the full manifest/detail (default: compacted for the token budget). |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"full": {
"type": "boolean",
"description": "Return the full manifest/detail (default: compacted for the token budget)."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Flat vs structured page counts; informs user — do not auto-run analyze/apply while requiredDecision pending.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Enable site search & collections (kv → do-sqlite), one-way. Unlocks search_content, collection indexes, visitor /__paige/search, and moves any R2 form-submission ledger into SiteDb. 409 blocked covers three unrelated gates: an unsupported source backend (no override, ever); strictDrafts — default true, this client sends true unless you pass strictDrafts:false — blocking on unpublished drafts or unrecovered KV content rows; or a KV snapshot that looks incomplete (e.g. a page deleted in the last couple of minutes). force:true overrides ONLY that last, incomplete-snapshot gate — never the backend or strictDrafts gates. The blocked response's `reason` names which gate fired, and `audit` (+ `audit.warnings`) is aggregate COUNTS only (published/route/pending-draft counts) — never row keys — so judge the size of the gap, not a row list, before forcing. The flip is one-way: anything outside the frozen snapshot is unreachable once it lands.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| force | boolean | Proceed past the incomplete-KV-snapshot 409 only — not the unsupported-backend or strictDrafts blocks, which force does nothing for. Read the blocked response's `reason` + `audit` first; the flip is one-way, so rows outside the snapshot are unreachable afterwards. Default false. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
Import URL to draft. On complete, response may include requiredDecision — preview then ask mirror vs editable before structure_*.
| Argument | Type | Description |
|---|---|---|
| mode | string | Default auto — per-page mirror with silent render escalation |
| site* | string | Site slug, e.g. acme-studio |
| pages | array | Explicit page list; omit to import sourceUrl as index.html |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| segments | array | Split-origin segments — each expands into pages by fetching its own `sitemap`. A segment without `sitemap` imports only its pathPrefix hub page (with a warning), not the whole prefix. |
| sourceUrl* | string | |
| workspace | string | null | Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace). |
| guestToken | string |
Suggest fields for one collection from a sample of its items' meta.custom values (published data, else drafts) — writes nothing. Returns { sampled, suggestions: [{ field: { key, type, options? }, count, samples, defined }], skipped }. Review, then add the ones you want via put_collection_schema.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| collection* | string | Collection key exactly as list_collections returned it, e.g. "blog/" or "posts". |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"collection",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"collection": {
"type": "string",
"minLength": 1,
"description": "Collection key exactly as list_collections returned it, e.g. \"blog/\" or \"posts\"."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Collection state — count, server.mode, sample entries, tag (membershipKind, match=) when discovered; plus name, noun, URL pattern, layout, where it's listed, and post fields used. Pass status/q/cursor/limit (any one, even empty) for a full items[] page instead: status draft = never published; a published post with unpublished edits is status published with hasChanges:true (never draft) and shows its staged title/date/tags/author; scheduled = future visibleAt. Never-published drafts come from staged content (no extra reads, no publish needed to see them); published/scheduled come from the index. limit defaults to 50, clamped 1-200. Omit all four for just the base inspect (no items[]).
| Argument | Type | Description |
|---|---|---|
| q | string | Case-insensitive title search within items[]. |
| site* | string | Site slug, e.g. acme-studio |
| limit | integer | Items per page (default 50, max 200). |
| cursor | string | Resume from a prior response's nextCursor. |
| prefix* | string | Collection id or prefix, e.g. "posts" or "blog/" — use the key exactly as list_collections returned it. |
| status | string | Filter items[] by status (see the tool description for what each means). Providing this (or q/cursor/limit) is what makes the response include items[]. |
CMS uploads under assets/ only — not mirrored clone CDN (get_site mirroredAssets or import warmJob). Not content — use list_content. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| limit | integer | |
| cursor | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"limit": {
"type": "integer",
"maximum": 1000,
"minimum": 1
},
"cursor": {
"type": "string"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Collections on the site — name, noun, item count (or 'not published yet'), URL pattern, and whether any member is staged. Includes a collection only a draft page lists. Returns a bare array (not wrapped in an object) — pass each row's key verbatim to inspect_collection/update_collection.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}List content keys (HTML/md); not assets — use list_assets. Defaults to 50 keys per page — raise limit (max 1000) or pass cursor (from nextCursor) to page through the rest. Per-row `size`/`missing` are measured automatically only on pages of ≤100 rows; past that they're ABSENT (not measured, never `null`) unless you pass withSize:true, which forces measurement at a cost of one storage read per returned row. Only `size: null` + `missing: true` means the page's stored bytes are gone.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| limit | integer | Keys per page (default 50, max 1000). |
| cursor | string | Resume from a prior response's nextCursor. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| withSize | boolean | Force size/missing measurement on a page bigger than 100 rows (costs one storage read per returned row). Default false — rows in a ≤100-row page are measured either way. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
List all custom hostnames and connection status for the site.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}List form submissions (metadata + bounded field preview — not full PII). Works on kv and do-sqlite backends.
| Argument | Type | Description |
|---|---|---|
| q | string | Search reply-to email (indexed) |
| form* | string | Form id from dotsy-config, e.g. contact |
| site* | string | Site slug, e.g. acme-studio |
| toMs | integer | |
| limit | integer | |
| cursor | string | |
| fromMs | integer | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
List site conversion goals (pageview paths and form submits). Required before start_test.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}List your Dotsy sites. Renders a site-picker for humans; agent reads structuredContent. Use to choose a site — not for editing content (use edit_page) or verify-only checks (use preview_page). Defaults to your active workspace; pass workspace (org id or slug from get_account_context memberships) to list another workspace's sites without switching the dashboard session.
| Argument | Type | Description |
|---|---|---|
| workspace | string | null | Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"workspace": {
"type": [
"string",
"null"
],
"description": "Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace)."
}
},
"additionalProperties": false
}List pages on a site — route settings (path/title/navLabel/purpose) by default, one row per route. Renders a page-picker for humans (redirect and worker routes left out there — nothing to open in edit_page); agent reads structuredContent. Use after picking a site — not for editing (use edit_page) or verify-only checks (use preview_page). Pass view:'pages' to group by layout instead — adds layout/noLayout/q filters, what each page places, and indexing progress; use that for 'what pages use this layout' or 'is this page indexed yet', not for route settings. Paginated — pass cursor (from nextCursor) for more; partial:true means this page is a window, not the full route set.
| Argument | Type | Description |
|---|---|---|
| q | string | Only with view:'pages'. Case-insensitive substring match on path or title. |
| site* | string | Site slug. |
| view | string | pages: group by layout — enables layout/noLayout/q below, adds page-structure fields and indexing progress. Omit for the default per-route listing. |
| limit | integer | Pages per page (server default applies when omitted). |
| cursor | string | Resume from a prior response's nextCursor. |
| layout | string | Only with view:'pages'. Layout file key (e.g. layouts/store.html, or bare 'store') — only pages using it. Exclusive with noLayout. |
Paige build skills (id + whenToUse). Pull get_skill on demand — do not duplicate in tool text.
| Argument | Type | Description |
|---|---|---|
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"context"
],
"properties": {
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
}
},
"additionalProperties": false
}List the site's published versions, newest first (who, when, pages, live, restorable). Use before restore_version.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| limit | integer | Page size (default 20). |
| cursor | string | nextCursor from the previous call. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"limit": {
"type": "integer",
"maximum": 50,
"minimum": 1,
"description": "Page size (default 20)."
},
"cursor": {
"type": "string",
"description": "nextCursor from the previous call."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Read-only scaffold for a new post — suggested key/path, membership meta, blank or duplicate body. Then put_post (+ optional put_route).
| Argument | Type | Description |
|---|---|---|
| mode | string | blank (default) or duplicate full body |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| collection* | string | Collection id or prefix, e.g. "posts" or "blog/" |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| templateKey | string | Exemplar content key; default = most recent member |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"collection",
"context"
],
"properties": {
"mode": {
"enum": [
"blank",
"duplicate"
],
"type": "string",
"description": "blank (default) or duplicate full body"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"collection": {
"type": "string",
"description": "Collection id or prefix, e.g. \"posts\" or \"blog/\""
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"templateKey": {
"type": "string",
"description": "Exemplar content key; default = most recent member"
}
},
"additionalProperties": false
}Edit one content key via ops[] (selector ops or replace-string; wrap/unwrap/move restructure siblings). Stages draft; op shapes in schema.
| Argument | Type | Description |
|---|---|---|
| key* | string | |
| ops* | array | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"ops",
"context"
],
"properties": {
"key": {
"type": "string"
},
"ops": {
"type": "array",
"items": {
"type": "object",
"required": [
"op"
],
"properties": {
"op": {
"enum": [
"set-attr",
"remove-attr",
"replace-text",
"remove-node",
"insert-after",
"replace-inner-html",
"replace-outer-html",
"replace-string",
"wrap",
"unwrap",
"move"
],
"type": "string"
},
"tag": {
"enum": [
"div",
"section",
"footer",
"header",
"article",
"aside"
],
"type": "string"
},
"find": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string",
"minLength": 1
},
"attrs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"value": {
"type": "string"
},
"expect": {
"type": "integer",
"minimum": 0
},
"target": {
"type": "string",
"minLength": 1
},
"replace": {
"type": "string"
},
"anchored": {
"type": "boolean"
},
"position": {
"enum": [
"before",
"after"
],
"type": "string"
},
"selector": {
"type": "string",
"minLength": 1
},
"selectors": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"additionalProperties": false
}
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Partial route update (only sent fields change; an OMITTED field is left alone). On a field that accepts null (contentKey, redirectTo, redirectStatus, preserveQuery), sending null CLEARS it back to its default — different from omitting it. To set redirectTo/redirectStatus, include purpose: "redirect" in the SAME call — the check looks only at what's sent, not the route's stored purpose, so a PATCH that sets redirectTo without repeating purpose: "redirect" (even on a route that's already a redirect) 400s invalid_body.
| Argument | Type | Description |
|---|---|---|
| nav | any | DEPRECATED — use put_menu_item / menu API. Menu memberships on the route row. Still accepted during transition and synced to menu items. See get_skill('nav'). |
| path* | string | |
| site* | string | Site slug, e.g. acme-studio |
| vars | any | |
| title | string | null | |
| layout | string | null | Layout NAME, bare: "default" for layouts/default.html — not the file key. It must already exist as layouts/<name>.html (400 layout_not_found otherwise). null removes the layout. |
| context* | string |
Plan check before publish or large build (counts, route soft limit, seo suggestions). When ok is false, blocking lists the failed suggestion codes. Read-only.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| requiredAssets | integer | How many assets you plan to upload |
| requiredRoutes | integer | How many routes you plan to add |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"requiredAssets": {
"type": "integer",
"minimum": 0,
"description": "How many assets you plan to upload"
},
"requiredRoutes": {
"type": "integer",
"minimum": 0,
"description": "How many routes you plan to add"
}
},
"additionalProperties": false
}Verify-only composed HTML check; home preview may include requiredDecision — ask mirror vs editable before structure_*.
| Argument | Type | Description |
|---|---|---|
| path | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| variant | string | A/B variant arm to compose (e.g. "b") — same as ?dotsy-variant= on the public URL. |
| contains | array | Assert substrings present in composed HTML. |
| selector | string | Return matched elements only (tag/attrs/text). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| notContains | array | Assert absent — e.g. `<dotsy-` for unresolved template tags. |
Promote a winning A/B variant to live — explicit user instruction only; see get_skill('verify') § A/B.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| variantId* | string | Winning variant arm id (usually "b"). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| experimentId* | string | |
| loserDisposition | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"experimentId",
"variantId",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"variantId": {
"type": "string",
"minLength": 1,
"description": "Winning variant arm id (usually \"b\")."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"experimentId": {
"type": "string",
"minLength": 1
},
"loserDisposition": {
"enum": [
"discard",
"keep_draft"
],
"type": "string"
}
},
"additionalProperties": false
}Publish draft to live. feedback and handoff required (use dummy feedback + one-line handoff if clean).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| pages | array | Publish only these pages — use when a publish returns rules_not_fully_checked; publish the rest in further batches (≤50 route paths, e.g. /pricing). |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| handoff* | string | One sentence: decisions, preferences, or open threads for the next session (appended to the brief). |
| feedback* | object | Required. Canonical dummy OK on friction-free sessions; tool intents attached automatically. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| acknowledgeSeoWarnings | boolean | Required when brief.priorities.seo is must and verify_page reported SEO errors (not warnings). User must have explicitly chosen to publish despite errors. |
Replace the whole field schema (draft; publish makes it live). Read it with get_collection_schema first and send it back edited. Collection keys exactly as list_collections returns them ("blog/" or an id). Field: { key, type, label?, help?, required?, unique?, inCard?, default? } — type text (multiline, minLength, maxLength) | number (min, max, integer) | boolean | option (options[] required) | multiOption (options[] required, max) | link | email | phone | color. Keys: letter then letters/digits/_ (≤40), not a built-in post field (title, date, excerpt, tags, image, url, slug, …; author only as text), not secret-looking. ≤60 fields per collection. settings.defaultSort: date:desc|date:asc|title:asc|slug:asc. Removing a collection's entry drops its definitions (values stay on the posts). Values live in put_post meta.custom; writes then return fieldWarnings (soft, never blocking). 400 invalid_collection_schema lists issues; 409 conflict = stale ifMatch.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| schema* | object | Whole schema file: { "v": 1, "collections": { "<key>": { "fields": [...], "settings"?: {...} } } }. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch | string | null | hash from get_collection_schema (stale → 409 conflict). null = the schema must not exist yet. Omit to write unconditionally. |
Stage one content key. Body ≤60KB. Larger pages: stage_content_chunk + apply_changeset bodyStaging, dotsy push, or PUT content-raw. Edits to an existing large page: batch_patch_content.
| Argument | Type | Description |
|---|---|---|
| key* | string | Content key: a page (about.html, blog/post.html), a layout (layouts/<name>.html) or a fragment (fragments/<name>.html). A <dotsy-fragment name> tag and a route's layout use the bare name, not the key. |
| body* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| contentType | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"body",
"context"
],
"properties": {
"key": {
"type": "string",
"description": "Content key: a page (about.html, blog/post.html), a layout (layouts/<name>.html) or a fragment (fragments/<name>.html). A <dotsy-fragment name> tag and a route's layout use the bare name, not the key."
},
"body": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"contentType": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
}Create or replace all site conversion goals (≤50). Required before start_test when no goal exists.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| goals* | array | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"goals",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"goals": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"required": [
"id",
"label",
"type",
"pathPattern"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"type": {
"type": "string",
"const": "pageview"
},
"label": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"pathPattern": {
"type": "string",
"maxLength": 200,
"minLength": 1,
"description": "Match path exactly or prefix with trailing * (e.g. \"/thanks\" or \"/blog/*\")."
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"id",
"label",
"type",
"formId"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"type": {
"type": "string",
"const": "form"
},
"label": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"formId": {
"type": "string",
"maxLength": 100,
"minLength": 1
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"id",
"label",
"type",
"eventName"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1
},
"type": {
"type": "string",
"const": "event"
},
"label": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"eventName": {
"enum": [
"download",
"cta_click"
],
"type": "string",
"description": "Built-in client event name (0.47.1)."
}
},
"additionalProperties": false
}
]
},
"maxItems": 50
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Replace the whole menu doc (ifMatch from get_menu_doc required). Each item may omit menu — the enclosing menu key in doc is used.
| Argument | Type | Description |
|---|---|---|
| doc* | object | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch* | string | Whole-doc etag from get_menu_doc. Required (sent as If-Match). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"doc",
"ifMatch",
"context"
],
"properties": {
"doc": {
"type": "object",
"additionalProperties": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"sort",
"parent",
"label",
"kind",
"ref",
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"ref": {
"type": "string"
},
"data": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"html": {
"type": "string"
},
"kind": {
"enum": [
"page",
"url",
"anchor",
"mailto",
"group"
],
"type": "string"
},
"menu": {
"type": "string",
"minLength": 1
},
"sort": {
"type": "integer"
},
"attrs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"label": {
"type": "string",
"minLength": 1
},
"newTab": {
"type": "boolean",
"default": false
},
"parent": {
"type": [
"string",
"null"
]
},
"childShell": {
"type": [
"string",
"null"
]
},
"childTemplate": {
"type": "string"
}
},
"additionalProperties": false
}
},
"shell": {
"type": [
"string",
"null"
]
},
"template": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
}
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": "string",
"description": "Whole-doc etag from get_menu_doc. Required (sent as If-Match)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Partial upsert one menu item: provided fields overwrite; omitted html/childTemplate/childShell/attrs/data are preserved. To remove those keys, use put_menu_doc. A brand-new id dedupes by (menu, ref) — reuses an existing item linking the same target instead of creating a duplicate. An id that already names an item always updates that exact item, even if another item links the same page.
| Argument | Type | Description |
|---|---|---|
| id* | string | |
| ref* | string | |
| data | object | |
| html | string | |
| kind* | string | |
| menu* | string | |
| site* | string | Site slug, e.g. acme-studio |
| sort* | integer | |
| attrs | object |
Stage a blog post via structured meta+body (?format=post). Key e.g. blog/my-post.html. Declared membership: meta.collections; schedule: meta.visibleAt; SEO title override: meta.seoTitle (card always shows meta.title); custom fields: meta.custom (typed per collection by get_collection_schema; the response's fieldWarnings flag values that don't fit — soft, never blocking).
| Argument | Type | Description |
|---|---|---|
| key* | string | |
| body* | string | |
| head | array | |
| meta* | object | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
Create/replace route; contentKey derived from path if omitted. On a field that accepts null (contentKey, redirectTo, redirectStatus, preserveQuery), sending null clears it back to its default.
| Argument | Type | Description |
|---|---|---|
| nav | any | DEPRECATED — use put_menu_item / menu API. Menu memberships on the route row. Still accepted during transition and synced to menu items. See get_skill('nav'). |
| path* | string | |
| site* | string | Site slug, e.g. acme-studio |
| vars | any | |
| title | string | null | |
| layout | string | null | Layout NAME, bare: "default" for layouts/default.html — not the file key. It must already exist as layouts/<name>.html (400 layout_not_found otherwise). null removes the layout. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| noindex |
Re-apply DNS with stored Cloudflare OAuth grant (no browser).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Poll one hostname until DNS/cert propagates.
| Argument | Type | Description |
|---|---|---|
| host* | string | Hostname to refresh, e.g. www.example.com |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"host",
"context"
],
"properties": {
"host": {
"type": "string",
"minLength": 1,
"description": "Hostname to refresh, e.g. www.example.com"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Build/finish collection indexes after publish returns collectionDataPending or collectionSqlPending.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Remove one custom hostname from the site.
| Argument | Type | Description |
|---|---|---|
| host* | string | Hostname to remove |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"host",
"context"
],
"properties": {
"host": {
"type": "string",
"minLength": 1,
"description": "Hostname to remove"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Re-key a page by slug (draft or published static). Server-side hash copy — no body round-trip. Default deletes static routes (obscure-URL); movePath:true repoints the route, rewrites menu refs and other redirects aimed at the old path, and — only for an already-PUBLISHED page — leaves a 301 there too (leaveRedirect, default true; no effect on a never-published page, or when movePath is false). Retry-safe: a part-way failure (409 rename_failed) rolls everything back, so resend the same call. On fragments/<name>.html it also rewrites every <dotsy-fragment name> reference and hide marker in the same all-or-nothing commit. Then publish_site.
| Argument | Type | Description |
|---|---|---|
| key* | string | Current content key, e.g. dashboard.html |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| newSlug* | string | New filename stem; directory prefix preserved (blog/foo → blog/bar) |
| movePath | boolean | false (default): delete routes bound to old key. true: move static route path to match slug. |
| guestToken |
Change a page's URL: moves its route from `from` to `to`. Menu links and other redirects that pointed at the old path retarget automatically; a 301 is left at the old path by default (leaveRedirect). Retry-safe (resend the same call after any error). Errors: 404 route_not_found (from isn't a route); 400 reserved_route (to is under /__dotsy/) or invalid_body (missing/malformed from or to); 422 rename_same_path (from equals to already), rename_pattern_route (from or to contains a :param segment — pattern routes can't be renamed this way), rename_redirect_route (from is itself a different redirect — edit its redirectTo instead); 409 rename_experiment_running (an A/B test is running on from — end it first) or rename_target_exists (to is already a different route — unless to already serves the exact content from would, which is treated as already done and returns 200). Then publish_site.
| Argument | Type | Description |
|---|---|---|
| to* | string | New route path, e.g. /new-page |
| from* | string | Current route path, e.g. /old-page |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
Rename the site slug (public hostname {slug}.dotsy.site). Owner-only. After success: use the returned slug in every later tool. Published site: the old slug redirects on the API (301 for reads, 308 for writes) while it stays reserved; the old host 301s and stays reserved until delete or rename-back. Never published: the old slug 404s on the API and the old hostname is released (no 301; create_site can reuse it). Analytics history stays on the old slug. HTML absolute URLs are not rewritten — publish_site refreshes sitemap; find_replace if stored HTML must change.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| newSlug* | string | New site slug (lowercase hostname stem) |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"newSlug",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"newSlug": {
"type": "string",
"minLength": 1,
"description": "New site slug (lowercase hostname stem)"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Set final menu order. Pass ifMatch from get_menu; stale → 409 with current items.
| Argument | Type | Description |
|---|---|---|
| menu* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch | string | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| orderedIds* | array |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"menu",
"orderedIds",
"context"
],
"properties": {
"menu": {
"type": "string",
"minLength": 1
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": "string"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"orderedIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1
}
},
"additionalProperties": false
}Bring an earlier published version back as unpublished changes (page content only — routes, menus, images and settings stay). version: a number from list_versions, or "previous". dryRun: show what would change. Then review and publish_site, or discard_drafts to undo; publish:true makes it live at once.
| Argument | Type | Description |
|---|---|---|
| keys | array | Restore only these content keys (single-page restore: CORE workspaces). Default: the whole version. |
| site* | string | Site slug, e.g. acme-studio |
| dryRun | boolean | Only list what would change; writes nothing. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| publish | boolean | Publish exactly the restored pages at once (live-mode sites). Default false: they stay unpublished changes. |
| version* | any | A version from list_versions, or "previous" (the one before live). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
Undo one activity event by staging the prior version as draft only — call publish_site to go live. Respects AI access.
| Argument | Type | Description |
|---|---|---|
| id* | string | Activity event id from get_activity. |
| keys | array | Undo only these keys of the change. Default: every key. |
| slug* | string | Site slug, e.g. acme-studio |
| reason | string | Why — shown next to 'Reverted by …'. Visible to everyone on the site. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug",
"id",
"context"
],
"properties": {
"id": {
"type": "string",
"description": "Activity event id from get_activity."
},
"keys": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50,
"description": "Undo only these keys of the change. Default: every key."
},
"slug": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"reason": {
"type": "string",
"maxLength": 200,
"description": "Why — shown next to 'Reverted by …'. Visible to everyone on the site."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Find pages containing a phrase (grep without reading bodies). Requires do-sqlite — graduate_site first if search_unavailable.
| Argument | Type | Description |
|---|---|---|
| q* | string | |
| site* | string | Site slug, e.g. acme-studio |
| limit | integer | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"q",
"context"
],
"properties": {
"q": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Connect a third-party analytics provider (GA4, Plausible, Fathom, Umami) or remove it (provider 'none'). Dotsy adds the provider's script to the <head> of every live page — live immediately, no publish needed. Replaces any earlier provider (one per site). Use this instead of pasting a GA4 gtag snippet into a layout. Other tags (Google Tag Manager, ads pixels, Clarity, search-console verification <meta>) still go in the layout.
| Argument | Type | Description |
|---|---|---|
| host | string | Umami only: https origin of the Umami instance, e.g. https://umami.example.com. |
| site* | string | Site slug, e.g. acme-studio |
| domain | string | Plausible only: the site domain registered in Plausible, e.g. example.com. |
| siteId | string | Fathom only: site ID (uppercase letters/digits). |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| provider* | string | |
| websiteId | string |
Record what was learned from an ended A/B test (≤500 chars; null clears).
| Argument | Type | Description |
|---|---|---|
| note* | any | The learning, in plain words (≤500 chars, multiline ok) — null clears it. |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| experimentId* | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"experimentId",
"note",
"context"
],
"properties": {
"note": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"description": "The learning, in plain words (≤500 chars, multiline ok) — null clears it."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"experimentId": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
}Set the canonical host (301 target) when multiple hostnames are connected.
| Argument | Type | Description |
|---|---|---|
| host* | string | Connected hostname to make primary |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"host",
"context"
],
"properties": {
"host": {
"type": "string",
"minLength": 1,
"description": "Connected hostname to make primary"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Make a block that repeats on several pages one shared section, or change where one shows. No arguments: lists blocks repeated on 3+ pages. sourceKey + selector (or selectors: a sibling run, one wrapper): a dry run finds every page with it; dryRun:false shares it. name + scope/hide/show: move an existing section to/from every page, or hide/show it per page. Over the per-call cap (too_many_pages, nothing written): share with keys, then again under the same name from a page that still has a copy; for every page then move with name + scope every_page + keys (max-1 pages a call; put all hide on the first) until all are moved. Always a draft (publish_site to go live; undo: revert_change).
| Argument | Type | Description |
|---|---|---|
| hide | array | every_page: pages that should not show it (they keep their own copy). Send them with the first move, never later. |
| keys | array | Pages with an exact copy to share it on (analyze's matches.keys). Omit for every exact copy. The source page is always included. |
| name | string | With sourceKey + selector: the new section's name (default: proposed). Alone: the existing section to re-place. |
| show | array | Pages that should show it again (removes their marker). |
| site* | string | Site slug, e.g. acme-studio |
| scope | string | where_found: each page that has it gets a reference. every_page: one slot in the layout, at the top or bottom of the page content; pages listed in `hide` don't show it. |
Append one ≤60KB chunk of a large new page. Omit stagingId on seq 0; pass the returned stagingId on later seq. Set finalize:true on the last chunk, then apply_changeset with writes[].bodyStaging.
| Argument | Type | Description |
|---|---|---|
| seq* | integer | |
| body* | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| finalize | boolean | |
| stagingId | string | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| contentType | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"seq",
"body",
"context"
],
"properties": {
"seq": {
"type": "integer",
"maximum": 84,
"minimum": 0
},
"body": {
"type": "string",
"minLength": 1
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"finalize": {
"type": "boolean"
},
"stagingId": {
"type": "string",
"pattern": "^stg_[a-zA-Z0-9_-]+$"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"contentType": {
"type": "string"
}
},
"additionalProperties": false
}Open a draft session. Returns preview/edit URLs for the person (see linkGuidance). draftEditorUrl only when the site gives AI agents Full access. path defaults to '/'.
| Argument | Type | Description |
|---|---|---|
| path | string | |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"path": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Start one draft site with no Dotsy account. Returns slug + guestToken — pass guestToken on every later tool call until claim_site.
| Argument | Type | Description |
|---|---|---|
| title | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| purpose | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"context"
],
"properties": {
"title": {
"type": "string",
"maxLength": 200
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"purpose": {
"type": "string",
"maxLength": 2000
}
},
"additionalProperties": false
}Start a same-URL A/B test (draft or live source). Rules → get_skill('verify') § A/B.
| Argument | Type | Description |
|---|---|---|
| name | string | |
| path* | string | |
| site* | string | Site slug, e.g. acme-studio |
| goalId* | string | |
| source* | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| weights | array | |
| handsOff | boolean | Hands-off mode (0.56e M4): Dotsy finishes the test WITHOUT further user instruction — the LIVE SITE may change later on its own (a ≥95% winner is auto-promoted, old page kept as a draft; or after 30 days with no clear winner the test auto-ends keeping the control). Only set when the user explicitly asked for hands-off / auto-finish. |
| changeNote |
Propose shared layout + fragments; persist:false first. Wait for mirror-vs-editable answer if requiredDecision pending.
| Argument | Type | Description |
|---|---|---|
| full | boolean | Return the full manifest incl. per-page HTML samples (default: compacted — etag/action/counts kept, samples truncated — to fit the token budget). |
| site* | string | Site slug, e.g. acme-studio |
| scope | string | Default flat-only; analyze clusters flat keys only. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| persist | boolean | First call: false (preview only). true only after user confirms editable/CMS mode. |
| profileId | string | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| sampleLimit | integer | |
Rewrite flat pages to layout + fragments (draft). Do not call while requiredDecision pending — user must pick editable first. It extracts header/footer only: afterwards share_section with no arguments lists the other repeated blocks (banner, CTA).
| Argument | Type | Description |
|---|---|---|
| keys | array | Required when scope is keys. |
| mode | string | Default apply. Neither value is a dry run — review-only persists the same content/layout write as apply. Only pass review-only after a review_required error (low analyze confidence); it labels the result outcome "review" and defers primary-nav auto-wiring to a later apply call. |
| site* | string | Site slug, e.g. acme-studio |
| scope | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch* | string | Manifest etag from structure_site_analyze or get_structure_status. |
| overrides | object |
Optional mid-session feedback (required feedback rides with publish_site).
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| title* | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| category* | string | missing_tool | blocking_error | extra_round_trips | confusing_response | workaround | other |
| findings | array | |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| description | string | |
| impactPercent* | integer | |
| suggestedImprovement | string |
Take back the last publish at once: restores the version before it for the pages that publish changed and publishes them, and the undone changes stay as unpublished changes (`restaged`). On a live-mode site nothing is kept (its next save would publish it again): the answer has `redo.version` — restore_version with that version and publish: true brings it back. publishVersion = the version publish_site returned. Fails with not_latest if another publish landed since. If its publish fails, the undo stays as unpublished changes — publish_site finishes it.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| publishVersion* | integer | The version the publish to undo returned. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"publishVersion",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"publishVersion": {
"type": "integer",
"description": "The version the publish to undo returned.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}Update `_intent/site.md` (site brief) or a page brief when `page` is set. See field descriptions for rules, notes, and head enums.
| Argument | Type | Description |
|---|---|---|
| body | string | Replace narrative body (site ≤50k chars; page ≤10k). |
| goal | string | Current goal (site ≤4k chars; page ≤2k). |
| head | any | Head fields to merge. Site: purpose, audience, kind (exploration|production), priorities ({seo,analytics,design,mobile}: must|nice|skip), editingModel (ai|simple-editor|creator), sections, design (strict): palette string[] max 8, type string[] max 6, layout string max 80 chars — no other keys. Page: purpose, design.{direction,hero}. |
| page | string | Content key — targets that page's brief (`_intent/pages/<key>.md`). Omit for the site brief. |
| site* | string | Site slug, e.g. acme-studio |
| notes | any | Site: free-form ## Notes string (≤4k) OR per-section notes object for Design system / Content & CMS / SEO (null clears one). Page brief: string only (≤2k). |
| rules | array | Rules & guidelines lines to add or change (upsert by id — send only fields you change; omitted fields keep their stored value; check: null turns a Rule into a Guideline). A supported check (title-max, title-suffix, description-length, one-h1, banned-words, image-alt, allowed-colors, allowed-fonts) makes a Rule — use level block for hard musts (banned words, title suffix), warn for softer checks. locked can only be set by a person; locked: false unlocks. |
Rename a collection's display name and/or noun (e.g. the generic 'posts' key shown as 'Recipes' / 'recipe') — cosmetic only, stored separately from the tag that defines membership; doesn't need publish. Provide at least one of name/noun. null (or "") resets that field back to its derived default — different from omitting it, which leaves the current value alone.
| Argument | Type | Description |
|---|---|---|
| key* | string | Collection key exactly as list_collections returned it, e.g. "posts" or "blog/" (a hand-typed key may 404 or get silently normalized). |
| name | any | Display name (≤80 chars). null resets to the derived name. |
| noun | any | Singular noun for one item, e.g. "post" (≤40 chars). null resets to the derived noun. |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"context"
],
"properties": {
"key": {
"type": "string",
"description": "Collection key exactly as list_collections returned it, e.g. \"posts\" or \"blog/\" (a hand-typed key may 404 or get silently normalized)."
},
"name": {
"anyOf": [
{
"type": "string",
"maxLength": 80
},
{
"type": "null"
}
],
"description": "Display name (≤80 chars). null resets to the derived name."
},
"noun": {
"anyOf": [
{
"type": "string",
"maxLength": 40
},
{
"type": "null"
}
],
"description": "Singular noun for one item, e.g. \"post\" (≤40 chars). null resets to the derived noun."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}Update site settings: title, keyConvention, or editingMode ('live' = each editor save publishes immediately; 'staged' = saves stay drafts until publish_site). Slug is the hostname — change it with rename_site, not this tool. Set 'staged' before handing the editor to a person via start_edit_session's draftEditorUrl. signature toggles the "Made with Dotsy" badge ({enabled, mark: logo|dot, reveal: pill|seal}); it is live immediately. trailingSlash (ignore|never|always) sets the page URL form: the other form 301s to it and canonicals/sitemap use it; live immediately. ownSeoFiles: true lets the next publish use the site's own robots.txt that blocks the whole site (Disallow: /) and its own static sitemap.xml (replaces the generated one, collection pages included); a robots.txt without Disallow: / is used anyway.
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| title | string | |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| signature | object | "Made with Dotsy" signature badge. Takes effect on the live site immediately, no publish needed. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| editingMode | string |
Pre-publish lint (tags, assets, layout, SEO, speed and accessibility). Summary first: health issues grouped by code, each with fix:{tool,args,fill?} — supply the fill args, then call. health.summary counts are whole-site (groups/codes filter only issues and assets). Pair with preview_page — see get_skill('verify').
| Argument | Type | Description |
|---|---|---|
| site* | string | Site slug, e.g. acme-studio |
| codes | array | Only these health codes, e.g. perf_image_heavy. |
| paths | array | Routes to check; omit to verify every route on the site. |
| detail | string | summary (default): grouped by code, clean pages counted. full: per-page lists. |
| groups | array | Only these groups: speed = perf_*, a11y = a11y_*, links = link_* + content_*. Omit for all. |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
Poll one hostname until it is connected or the timeout is reached.
| Argument | Type | Description |
|---|---|---|
| host* | string | Hostname to wait for, e.g. www.example.com |
| site* | string | Site slug, e.g. acme-studio |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| timeoutSec | integer | Max seconds to wait (default 300, max 600). |
| intervalSec | integer | Seconds between polls (default 30, min 10, max 60). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"host",
"context"
],
"properties": {
"host": {
"type": "string",
"minLength": 1,
"description": "Hostname to wait for, e.g. www.example.com"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"timeoutSec": {
"type": "integer",
"maximum": 600,
"minimum": 1,
"description": "Max seconds to wait (default 300, max 600)."
},
"intervalSec": {
"type": "integer",
"maximum": 60,
"minimum": 10,
"description": "Seconds between polls (default 30, min 10, max 60)."
}
},
"additionalProperties": false
}| Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"ifMatch",
"adapters",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"force": {
"type": "string",
"const": "discard-undo",
"description": "An undo record from a prior apply exists (409 adapt_undo_exists): defer-discard it — the prior record is dropped only when this apply SUCCEEDS; a partial-failure rollback reinstates it. Prefer adapt revert first."
},
"dryRun": {
"type": "boolean",
"description": "Full computation, would-write set + previews, ZERO writes, no undo."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": "string",
"minLength": 1,
"description": "The proposal etag from analyze (or GET …/adapt/proposal / status)."
},
"adapters": {
"type": "array",
"items": {
"enum": [
"nav",
"collection"
],
"type": "string"
},
"minItems": 1,
"description": "Which analyzed adapters to apply."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| guestToken |
| string |
| Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"atomic": {
"type": "boolean",
"description": "All or nothing: every writes[].ifMatch and deletes[].ifMatch is checked before anything is written. One stale key writes nothing and the call fails with 409 changeset_conflict listing `conflicts`. Default: a stale write is skipped and listed, the rest apply."
},
"writes": {
"type": "array",
"items": {
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "string",
"minLength": 1
},
"body": {
"type": "string"
},
"route": {
"type": "object",
"required": [
"path",
"input"
],
"properties": {
"path": {
"type": "string",
"minLength": 1
},
"input": {
"type": "object",
"properties": {
"nav": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"menu"
],
"properties": {
"menu": {
"type": "string",
"minLength": 1,
"description": "Menu this page joins — matches a <dotsy-nav menu=\"…\"> in the layout/fragment (e.g. \"primary\", \"footer\")."
},
"order": {
"type": "integer",
"description": "Sort position among siblings in this menu, ascending. Use gaps (10, 20, 30) to leave room for inserts."
},
"parent": {
"type": [
"string",
"null"
],
"description": "Parent route path within this menu for a nested/dropdown item (e.g. \"/services\"). Omit for top level."
}
},
"additionalProperties": false
}
},
{
"type": "null"
}
],
"description": "DEPRECATED — use put_menu_item / menu API. Menu memberships on the route row. Still accepted during transition and synced to menu items. See get_skill('nav')."
},
"vars": {
"anyOf": [
{
"type": "object",
"additionalProperties": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"title": {
"type": [
"string",
"null"
]
},
"layout": {
"type": [
"string",
"null"
],
"description": "Layout NAME, bare: \"default\" for layouts/default.html — not the file key. It must already exist as layouts/<name>.html (400 layout_not_found otherwise). null removes the layout."
},
"noindex": {
"type": [
"boolean",
"null"
],
"description": "Exclude from sitemap/RSS; inject noindex meta (0.69)."
},
"purpose": {
"type": [
"string",
"null"
]
},
"navLabel": {
"type": [
"string",
"null"
],
"description": "DEPRECATED — use put_menu_item / menu API. Menu link text for <dotsy-nav> (separate from title). Still accepted during transition and synced to menu items."
},
"contentKey": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Explicit content key (defaults to a path-derived key when omitted). null clears an explicit key back to that path default — same as omitting it, but usable on a PATCH to undo a prior set."
},
"experiment": {
"anyOf": [
{
"type": "object",
"required": [
"id",
"name",
"status",
"variants"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"description": "Stable experiment slug — cookie namespace; unique per site forever."
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"goalId": {
"type": "string",
"minLength": 1,
"description": "Optional Dotsy conversion goal; omit when tracking in external analytics."
},
"status": {
"enum": [
"draft",
"running",
"ended"
],
"type": "string"
},
"endedAt": {
"type": "string"
},
"handsOff": {
"type": "boolean",
"description": "Hands-off mode (0.56e M4): the daily sweep may auto-promote a ≥95% winner or auto-end keep-A after 30 days. Prefer setting this via start_test; kept here so route PATCH round-trips (weights/settings updates) don't strip the flag."
},
"variants": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"weight",
"contentKey"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"description": "Variant arm id — default \"a\" / \"b\" on create."
},
"label": {
"type": "string",
"maxLength": 80
},
"weight": {
"type": "integer",
"maximum": 100,
"minimum": 0
},
"contentKey": {
"type": "string",
"minLength": 1,
"description": "Published body key (may be routeless)."
}
},
"additionalProperties": false
},
"maxItems": 3,
"minItems": 2
},
"startedAt": {
"type": "string"
},
"changeNote": {
"type": "string",
"maxLength": 120,
"description": "One line on what the variant changes (0.56e M2). Kept here so route PATCH round-trips (weights/settings updates) don't strip it."
},
"hypothesis": {
"type": "string",
"maxLength": 200
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"redirectTo": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Redirect target, a root-relative path (/…). Required when purpose is \"redirect\". null clears it — only valid once purpose stops being \"redirect\" (a redirect route always needs a target)."
},
"preserveQuery": {
"type": [
"boolean",
"null"
],
"description": "Append the visitor's original query string to the redirect target (default true on a redirect). null clears an explicit override."
},
"redirectStatus": {
"anyOf": [
{
"enum": [
301,
302,
308
],
"type": "number"
},
{
"type": "null"
}
],
"description": "301 permanent / 302 or 308 temporary (default 301 on a redirect). null clears an explicit override."
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
"ifMatch": {
"type": "string"
},
"menuItems": {
"type": "array",
"items": {
"type": "object",
"required": [
"sort",
"parent",
"label",
"kind",
"ref",
"menu"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"ref": {
"type": "string"
},
"data": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"html": {
"type": "string"
},
"kind": {
"enum": [
"page",
"url",
"anchor",
"mailto",
"group"
],
"type": "string"
},
"menu": {
"type": "string",
"minLength": 1
},
"sort": {
"type": "integer"
},
"attrs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"label": {
"type": "string",
"minLength": 1
},
"newTab": {
"type": "boolean",
"default": false
},
"parent": {
"type": [
"string",
"null"
]
},
"childShell": {
"type": [
"string",
"null"
]
},
"childTemplate": {
"type": "string"
}
},
"additionalProperties": false
}
},
"bodyStaging": {
"type": "string",
"pattern": "^stg_[a-zA-Z0-9_-]+$"
},
"contentType": {
"type": "string"
}
},
"additionalProperties": false
},
"default": [],
"maxItems": 10
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"deletes": {
"type": "array",
"items": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "object",
"required": [
"key",
"ifMatch"
],
"properties": {
"key": {
"type": "string",
"minLength": 1
},
"ifMatch": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
}
]
},
"default": [],
"maxItems": 50,
"description": "Keys to delete: a key, or { key, ifMatch } (the hash you read) so a page changed since is not deleted (listed in conflicts)."
},
"message": {
"type": "string",
"maxLength": 2000
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| onSlugTaken |
| string |
| keyConvention | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug",
"context"
],
"properties": {
"slug": {
"type": "string",
"minLength": 1
},
"title": {
"type": "string",
"maxLength": 200
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"purpose": {
"type": "string",
"maxLength": 280,
"minLength": 5
},
"workspace": {
"type": [
"string",
"null"
],
"description": "Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"editingMode": {
"enum": [
"live",
"staged"
],
"type": "string",
"description": "How the editor's Save behaves. 'live' (default) publishes each save immediately; 'staged' keeps saves as drafts until publish_site. Prefer 'staged' when an agent will hand the editor to a person (see start_edit_session → draftEditorUrl) so keystrokes don't go straight to the public site. API writes always stage regardless of this setting."
},
"onSlugTaken": {
"enum": [
"fail",
"auto-suffix",
"merge"
],
"type": "string",
"default": "auto-suffix"
},
"keyConvention": {
"enum": [
"flat",
"directory"
],
"type": "string"
}
},
"additionalProperties": false
}| Replace persisted manifest when true. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"full": {
"type": "boolean",
"description": "Return the full manifest incl. per-page HTML samples (default: compacted — etag/action/counts kept, samples truncated — to fit the token budget)."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"scope": {
"enum": [
"flat-only",
"all"
],
"type": "string",
"description": "Default flat-only; analyze clusters flat keys only."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"persist": {
"type": "boolean",
"description": "First call: false (preview only). true only after user confirms editable/CMS mode."
},
"profileId": {
"enum": [
"webflow",
"wordpress",
"generic",
"framer"
],
"type": "string"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"sampleLimit": {
"type": "integer",
"maximum": 50,
"minimum": 1
},
"refreshManifest": {
"type": "boolean",
"description": "Replace persisted manifest when true."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"name",
"pageKey",
"context"
],
"properties": {
"name": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "Section name. Its file is fragments/<name>.html, placed with <dotsy-fragment name=\"<name>\">."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"dryRun": {
"type": "boolean",
"default": true,
"description": "Default true: report what would change and write nothing. false: stage the change as a draft (publish_site makes it live)."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": "string",
"minLength": 1,
"description": "The page's content hash. If the page changed since, nothing is written."
},
"pageKey": {
"type": "string",
"minLength": 1,
"description": "Content key of the page that gets its own copy, e.g. 'pricing.html'."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"slug",
"context"
],
"properties": {
"id": {
"type": "string",
"description": "Event id — returns diff for this change instead of the list."
},
"key": {
"type": "string",
"description": "Content key when id is set (default first key in the event)."
},
"who": {
"enum": [
"all",
"people",
"agents"
],
"type": "string",
"description": "Default all."
},
"slug": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"actor": {
"type": "string",
"minLength": 1,
"description": "Actor id or me."
},
"limit": {
"type": "integer",
"maximum": 20,
"minimum": 1,
"description": "Page size (default 20)."
},
"since": {
"type": "string",
"description": "ISO date (default 7 days, plan retention floor)."
},
"state": {
"enum": [
"needs_review",
"reverted"
],
"type": "string",
"description": "needs_review = agent drafts awaiting a person's publish."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| strictDrafts | boolean | Block on unpublished drafts or unrecovered KV content rows (default true — publish/discard first, or pass false to proceed anyway). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"force": {
"type": "boolean",
"description": "Proceed past the incomplete-KV-snapshot 409 only — not the unsupported-backend or strictDrafts blocks, which force does nothing for. Read the blocked response's `reason` + `audit` first; the flip is one-way, so rows outside the snapshot are unreachable afterwards. Default false."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"strictDrafts": {
"type": "boolean",
"description": "Block on unpublished drafts or unrecovered KV content rows (default true — publish/discard first, or pass false to proceed anyway)."
}
},
"additionalProperties": false
}| Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| onSlugTaken | string |
| keyConvention | string | Content key shape: directory = Astro dist (about/index.html); default flat |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"sourceUrl",
"context"
],
"properties": {
"mode": {
"enum": [
"auto",
"mirror",
"render"
],
"type": "string",
"description": "Default auto — per-page mirror with silent render escalation"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"pages": {
"type": "array",
"items": {
"type": "object",
"required": [
"url",
"key"
],
"properties": {
"key": {
"type": "string"
},
"url": {
"type": "string"
},
"mode": {
"enum": [
"auto",
"mirror",
"render"
],
"type": "string"
}
},
"additionalProperties": false
},
"description": "Explicit page list; omit to import sourceUrl as index.html"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"segments": {
"type": "array",
"items": {
"type": "object",
"required": [
"pathPrefix"
],
"properties": {
"mode": {
"enum": [
"auto",
"mirror",
"render"
],
"type": "string"
},
"sitemap": {
"type": "string",
"description": "Sitemap path relative to sourceUrl, e.g. /designs/sitemap.xml. Omit only to import this segment's single hub page — expansion does NOT happen without it, and a segment_hub_only warning is returned as a reminder."
},
"maxPages": {
"type": "integer",
"maximum": 5000,
"minimum": 1
},
"pathPrefix": {
"type": "string",
"description": "e.g. / or /designs"
}
},
"additionalProperties": false
},
"description": "Split-origin segments — each expands into pages by fetching its own `sitemap`. A segment without `sitemap` imports only its pathPrefix hub page (with a warning), not the whole prefix."
},
"sourceUrl": {
"type": "string",
"format": "uri"
},
"workspace": {
"type": [
"string",
"null"
],
"description": "Workspace org id or slug (see get_account_context memberships). Only for multi-workspace users; omit otherwise. Ignored for pga_ keys (fixed workspace)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"onSlugTaken": {
"enum": [
"fail",
"auto-suffix",
"merge"
],
"type": "string",
"default": "auto-suffix"
},
"keyConvention": {
"enum": [
"flat",
"directory"
],
"type": "string",
"description": "Content key shape: directory = Astro dist (about/index.html); default flat"
}
},
"additionalProperties": false
}| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"prefix",
"context"
],
"properties": {
"q": {
"type": "string",
"description": "Case-insensitive title search within items[]."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Items per page (default 50, max 200)."
},
"cursor": {
"type": "string",
"description": "Resume from a prior response's nextCursor."
},
"prefix": {
"type": "string",
"description": "Collection id or prefix, e.g. \"posts\" or \"blog/\" — use the key exactly as list_collections returned it."
},
"status": {
"enum": [
"all",
"published",
"scheduled",
"draft"
],
"type": "string",
"description": "Filter items[] by status (see the tool description for what each means). Providing this (or q/cursor/limit) is what makes the response include items[]."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"limit": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "Keys per page (default 50, max 1000)."
},
"cursor": {
"type": "string",
"description": "Resume from a prior response's nextCursor."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"withSize": {
"type": "boolean",
"description": "Force size/missing measurement on a page bigger than 100 rows (costs one storage read per returned row). Default false — rows in a ≤100-row page are measured either way."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"form",
"context"
],
"properties": {
"q": {
"type": "string",
"description": "Search reply-to email (indexed)"
},
"form": {
"type": "string",
"minLength": 1,
"description": "Form id from dotsy-config, e.g. contact"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"toMs": {
"type": "integer"
},
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"cursor": {
"type": "string"
},
"fromMs": {
"type": "integer"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| noLayout | boolean | Only with view:'pages'. Only pages with no layout (routeless keys included). Exclusive with layout. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site"
],
"properties": {
"q": {
"type": "string",
"description": "Only with view:'pages'. Case-insensitive substring match on path or title."
},
"site": {
"type": "string",
"description": "Site slug."
},
"view": {
"enum": [
"pages"
],
"type": "string",
"description": "pages: group by layout — enables layout/noLayout/q below, adds page-structure fields and indexing progress. Omit for the default per-route listing."
},
"limit": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "Pages per page (server default applies when omitted)."
},
"cursor": {
"type": "string",
"description": "Resume from a prior response's nextCursor."
},
"layout": {
"type": "string",
"description": "Only with view:'pages'. Layout file key (e.g. layouts/store.html, or bare 'store') — only pages using it. Exclusive with noLayout."
},
"noLayout": {
"type": "boolean",
"description": "Only with view:'pages'. Only pages with no layout (routeless keys included). Exclusive with layout."
}
},
"additionalProperties": false
}| One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| noindex | boolean | null | Exclude from sitemap/RSS; inject noindex meta (0.69). |
| purpose | string | null |
| navLabel | string | null | DEPRECATED — use put_menu_item / menu API. Menu link text for <dotsy-nav> (separate from title). Still accepted during transition and synced to menu items. |
| contentKey | any | Explicit content key (defaults to a path-derived key when omitted). null clears an explicit key back to that path default — same as omitting it, but usable on a PATCH to undo a prior set. |
| experiment | any |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| redirectTo | any | Redirect target, a root-relative path (/…). Required when purpose is "redirect". null clears it — only valid once purpose stops being "redirect" (a redirect route always needs a target). |
| preserveQuery | boolean | null | Append the visitor's original query string to the redirect target (default true on a redirect). null clears an explicit override. |
| redirectStatus | any | 301 permanent / 302 or 308 temporary (default 301 on a redirect). null clears an explicit override. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"path",
"context"
],
"properties": {
"nav": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"menu"
],
"properties": {
"menu": {
"type": "string",
"minLength": 1,
"description": "Menu this page joins — matches a <dotsy-nav menu=\"…\"> in the layout/fragment (e.g. \"primary\", \"footer\")."
},
"order": {
"type": "integer",
"description": "Sort position among siblings in this menu, ascending. Use gaps (10, 20, 30) to leave room for inserts."
},
"parent": {
"type": [
"string",
"null"
],
"description": "Parent route path within this menu for a nested/dropdown item (e.g. \"/services\"). Omit for top level."
}
},
"additionalProperties": false
}
},
{
"type": "null"
}
],
"description": "DEPRECATED — use put_menu_item / menu API. Menu memberships on the route row. Still accepted during transition and synced to menu items. See get_skill('nav')."
},
"path": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"vars": {
"anyOf": [
{
"type": "object",
"additionalProperties": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"title": {
"type": [
"string",
"null"
]
},
"layout": {
"type": [
"string",
"null"
],
"description": "Layout NAME, bare: \"default\" for layouts/default.html — not the file key. It must already exist as layouts/<name>.html (400 layout_not_found otherwise). null removes the layout."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"noindex": {
"type": [
"boolean",
"null"
],
"description": "Exclude from sitemap/RSS; inject noindex meta (0.69)."
},
"purpose": {
"type": [
"string",
"null"
]
},
"navLabel": {
"type": [
"string",
"null"
],
"description": "DEPRECATED — use put_menu_item / menu API. Menu link text for <dotsy-nav> (separate from title). Still accepted during transition and synced to menu items."
},
"contentKey": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Explicit content key (defaults to a path-derived key when omitted). null clears an explicit key back to that path default — same as omitting it, but usable on a PATCH to undo a prior set."
},
"experiment": {
"anyOf": [
{
"type": "object",
"required": [
"id",
"name",
"status",
"variants"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"description": "Stable experiment slug — cookie namespace; unique per site forever."
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"goalId": {
"type": "string",
"minLength": 1,
"description": "Optional Dotsy conversion goal; omit when tracking in external analytics."
},
"status": {
"enum": [
"draft",
"running",
"ended"
],
"type": "string"
},
"endedAt": {
"type": "string"
},
"handsOff": {
"type": "boolean",
"description": "Hands-off mode (0.56e M4): the daily sweep may auto-promote a ≥95% winner or auto-end keep-A after 30 days. Prefer setting this via start_test; kept here so route PATCH round-trips (weights/settings updates) don't strip the flag."
},
"variants": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"weight",
"contentKey"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"description": "Variant arm id — default \"a\" / \"b\" on create."
},
"label": {
"type": "string",
"maxLength": 80
},
"weight": {
"type": "integer",
"maximum": 100,
"minimum": 0
},
"contentKey": {
"type": "string",
"minLength": 1,
"description": "Published body key (may be routeless)."
}
},
"additionalProperties": false
},
"maxItems": 3,
"minItems": 2
},
"startedAt": {
"type": "string"
},
"changeNote": {
"type": "string",
"maxLength": 120,
"description": "One line on what the variant changes (0.56e M2). Kept here so route PATCH round-trips (weights/settings updates) don't strip it."
},
"hypothesis": {
"type": "string",
"maxLength": 200
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"redirectTo": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Redirect target, a root-relative path (/…). Required when purpose is \"redirect\". null clears it — only valid once purpose stops being \"redirect\" (a redirect route always needs a target)."
},
"preserveQuery": {
"type": [
"boolean",
"null"
],
"description": "Append the visitor's original query string to the redirect target (default true on a redirect). null clears an explicit override."
},
"redirectStatus": {
"anyOf": [
{
"enum": [
301,
302,
308
],
"type": "number"
},
{
"type": "null"
}
],
"description": "301 permanent / 302 or 308 temporary (default 301 on a redirect). null clears an explicit override."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"path": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"variant": {
"type": "string",
"description": "A/B variant arm to compose (e.g. \"b\") — same as ?dotsy-variant= on the public URL."
},
"contains": {
"type": "array",
"items": {
"type": "string"
},
"description": "Assert substrings present in composed HTML."
},
"selector": {
"type": "string",
"description": "Return matched elements only (tag/attrs/text)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"notContains": {
"type": "array",
"items": {
"type": "string"
},
"description": "Assert absent — e.g. `<dotsy-` for unresolved template tags."
}
},
"additionalProperties": false
}| confirmedDraftFingerprint | string | Required when get_draft_status returned requiredDecision (publish_confirm). Must match the current draft fingerprint from get_draft_status. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"feedback",
"handoff",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"pages": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50,
"description": "Publish only these pages — use when a publish returns rules_not_fully_checked; publish the rest in further batches (≤50 route paths, e.g. /pricing)."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"handoff": {
"type": "string",
"minLength": 1,
"description": "One sentence: decisions, preferences, or open threads for the next session (appended to the brief)."
},
"feedback": {
"type": "object",
"required": [
"category",
"impactPercent",
"title"
],
"properties": {
"title": {
"type": "string"
},
"category": {
"enum": [
"missing_tool",
"blocking_error",
"extra_round_trips",
"confusing_response",
"workaround",
"other"
],
"type": "string",
"description": "missing_tool | blocking_error | extra_round_trips | confusing_response | workaround | other"
},
"findings": {
"type": "array",
"items": {
"type": "object",
"required": [
"category",
"impactPercent",
"title"
],
"properties": {
"title": {
"type": "string"
},
"category": {
"$ref": "#/properties/feedback/properties/category"
},
"description": {
"type": "string"
},
"operationId": {
"type": "string"
},
"impactPercent": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"suggestedImprovement": {
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 20
},
"description": {
"type": "string"
},
"impactPercent": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"suggestedImprovement": {
"type": "string"
}
},
"description": "Required. Canonical dummy OK on friction-free sessions; tool intents attached automatically.",
"additionalProperties": false
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"acknowledgeSeoWarnings": {
"type": "boolean",
"description": "Required when brief.priorities.seo is must and verify_page reported SEO errors (not warnings). User must have explicitly chosen to publish despite errors."
},
"confirmedDraftFingerprint": {
"type": "string",
"description": "Required when get_draft_status returned requiredDecision (publish_confirm). Must match the current draft fingerprint from get_draft_status."
}
},
"additionalProperties": false
}| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"schema",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"schema": {
"type": "object",
"description": "Whole schema file: { \"v\": 1, \"collections\": { \"<key>\": { \"fields\": [...], \"settings\"?: {...} } } }.",
"additionalProperties": {}
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": [
"string",
"null"
],
"description": "hash from get_collection_schema (stale → 409 conflict). null = the schema must not exist yet. Omit to write unconditionally."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| label* | string |
| newTab | boolean |
| parent* | string | null |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| childShell | string | null |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| childTemplate | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"menu",
"id",
"sort",
"parent",
"label",
"kind",
"ref",
"context"
],
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"ref": {
"type": "string"
},
"data": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"html": {
"type": "string"
},
"kind": {
"enum": [
"page",
"url",
"anchor",
"mailto",
"group"
],
"type": "string"
},
"menu": {
"type": "string",
"minLength": 1
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"sort": {
"type": "integer"
},
"attrs": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"label": {
"type": "string",
"minLength": 1
},
"newTab": {
"type": "boolean",
"default": false
},
"parent": {
"type": [
"string",
"null"
]
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"childShell": {
"type": [
"string",
"null"
]
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"childTemplate": {
"type": "string"
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"meta",
"body",
"context"
],
"properties": {
"key": {
"type": "string"
},
"body": {
"type": "string"
},
"head": {
"type": "array",
"items": {
"type": "string"
}
},
"meta": {
"type": "object",
"required": [
"title"
],
"properties": {
"url": {
"type": "string"
},
"date": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"image": {
"type": "string"
},
"title": {
"type": "string",
"description": "Post title — shown on the blog card/listing and used as the <title> unless seoTitle overrides it."
},
"author": {
"type": "string"
},
"custom": {
"type": "object",
"additionalProperties": {}
},
"excerpt": {
"type": "string"
},
"seoTitle": {
"type": "string",
"description": "SEO override for the <title>/og:title tags only. The blog card and listing always show `title`; empty or absent inherits `title`."
},
"visibleAt": {
"$ref": "#/properties/meta/properties/date"
},
"collections": {
"type": "array",
"items": {
"type": "string"
}
},
"dateDisplay": {
"type": "string"
}
},
"additionalProperties": false
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}| boolean | null |
| Exclude from sitemap/RSS; inject noindex meta (0.69). |
| purpose | string | null |
| navLabel | string | null | DEPRECATED — use put_menu_item / menu API. Menu link text for <dotsy-nav> (separate from title). Still accepted during transition and synced to menu items. |
| contentKey | any | Explicit content key (defaults to a path-derived key when omitted). null clears an explicit key back to that path default — same as omitting it, but usable on a PATCH to undo a prior set. |
| experiment | any |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| redirectTo | any | Redirect target, a root-relative path (/…). Required when purpose is "redirect". null clears it — only valid once purpose stops being "redirect" (a redirect route always needs a target). |
| preserveQuery | boolean | null | Append the visitor's original query string to the redirect target (default true on a redirect). null clears an explicit override. |
| redirectStatus | any | 301 permanent / 302 or 308 temporary (default 301 on a redirect). null clears an explicit override. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"path",
"context"
],
"properties": {
"nav": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"required": [
"menu"
],
"properties": {
"menu": {
"type": "string",
"minLength": 1,
"description": "Menu this page joins — matches a <dotsy-nav menu=\"…\"> in the layout/fragment (e.g. \"primary\", \"footer\")."
},
"order": {
"type": "integer",
"description": "Sort position among siblings in this menu, ascending. Use gaps (10, 20, 30) to leave room for inserts."
},
"parent": {
"type": [
"string",
"null"
],
"description": "Parent route path within this menu for a nested/dropdown item (e.g. \"/services\"). Omit for top level."
}
},
"additionalProperties": false
}
},
{
"type": "null"
}
],
"description": "DEPRECATED — use put_menu_item / menu API. Menu memberships on the route row. Still accepted during transition and synced to menu items. See get_skill('nav')."
},
"path": {
"type": "string"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"vars": {
"anyOf": [
{
"type": "object",
"additionalProperties": {
"type": "string"
}
},
{
"type": "null"
}
]
},
"title": {
"type": [
"string",
"null"
]
},
"layout": {
"type": [
"string",
"null"
],
"description": "Layout NAME, bare: \"default\" for layouts/default.html — not the file key. It must already exist as layouts/<name>.html (400 layout_not_found otherwise). null removes the layout."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"noindex": {
"type": [
"boolean",
"null"
],
"description": "Exclude from sitemap/RSS; inject noindex meta (0.69)."
},
"purpose": {
"type": [
"string",
"null"
]
},
"navLabel": {
"type": [
"string",
"null"
],
"description": "DEPRECATED — use put_menu_item / menu API. Menu link text for <dotsy-nav> (separate from title). Still accepted during transition and synced to menu items."
},
"contentKey": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Explicit content key (defaults to a path-derived key when omitted). null clears an explicit key back to that path default — same as omitting it, but usable on a PATCH to undo a prior set."
},
"experiment": {
"anyOf": [
{
"type": "object",
"required": [
"id",
"name",
"status",
"variants"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"description": "Stable experiment slug — cookie namespace; unique per site forever."
},
"name": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"goalId": {
"type": "string",
"minLength": 1,
"description": "Optional Dotsy conversion goal; omit when tracking in external analytics."
},
"status": {
"enum": [
"draft",
"running",
"ended"
],
"type": "string"
},
"endedAt": {
"type": "string"
},
"handsOff": {
"type": "boolean",
"description": "Hands-off mode (0.56e M4): the daily sweep may auto-promote a ≥95% winner or auto-end keep-A after 30 days. Prefer setting this via start_test; kept here so route PATCH round-trips (weights/settings updates) don't strip the flag."
},
"variants": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"weight",
"contentKey"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"description": "Variant arm id — default \"a\" / \"b\" on create."
},
"label": {
"type": "string",
"maxLength": 80
},
"weight": {
"type": "integer",
"maximum": 100,
"minimum": 0
},
"contentKey": {
"type": "string",
"minLength": 1,
"description": "Published body key (may be routeless)."
}
},
"additionalProperties": false
},
"maxItems": 3,
"minItems": 2
},
"startedAt": {
"type": "string"
},
"changeNote": {
"type": "string",
"maxLength": 120,
"description": "One line on what the variant changes (0.56e M2). Kept here so route PATCH round-trips (weights/settings updates) don't strip it."
},
"hypothesis": {
"type": "string",
"maxLength": 200
}
},
"additionalProperties": false
},
{
"type": "null"
}
]
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"redirectTo": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Redirect target, a root-relative path (/…). Required when purpose is \"redirect\". null clears it — only valid once purpose stops being \"redirect\" (a redirect route always needs a target)."
},
"preserveQuery": {
"type": [
"boolean",
"null"
],
"description": "Append the visitor's original query string to the redirect target (default true on a redirect). null clears an explicit override."
},
"redirectStatus": {
"anyOf": [
{
"enum": [
301,
302,
308
],
"type": "number"
},
{
"type": "null"
}
],
"description": "301 permanent / 302 or 308 temporary (default 301 on a redirect). null clears an explicit override."
}
},
"additionalProperties": false
}| string |
| Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| leaveRedirect | boolean | With movePath:true on an already-published page, leave a 301 at the old path (default true). false removes the old path outright — old links break. No effect when movePath is false, or on a page that was never published. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"key",
"newSlug",
"context"
],
"properties": {
"key": {
"type": "string",
"description": "Current content key, e.g. dashboard.html"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"newSlug": {
"type": "string",
"minLength": 1,
"description": "New filename stem; directory prefix preserved (blog/foo → blog/bar)"
},
"movePath": {
"type": "boolean",
"description": "false (default): delete routes bound to old key. true: move static route path to match slug."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"leaveRedirect": {
"type": "boolean",
"description": "With movePath:true on an already-published page, leave a 301 at the old path (default true). false removes the old path outright — old links break. No effect when movePath is false, or on a page that was never published."
}
},
"additionalProperties": false
}| leaveRedirect | boolean | Leave a 301 from the old path to the new one (default true). false removes the old path outright — old links break. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"from",
"to",
"context"
],
"properties": {
"to": {
"type": "string",
"minLength": 1,
"description": "New route path, e.g. /new-page"
},
"from": {
"type": "string",
"minLength": 1,
"description": "Current route path, e.g. /old-page"
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"leaveRedirect": {
"type": "boolean",
"description": "Leave a 301 from the old path to the new one (default true). false removes the old path outright — old links break."
}
},
"additionalProperties": false
}| removeAdded |
| boolean |
| Remove pages added since the version. Default true. |
| replaceDrafts | boolean | Replace unpublished changes on the pages the restore touches. Without it such a restore answers 409 drafts_pending. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"version",
"context"
],
"properties": {
"keys": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 150,
"minItems": 1,
"description": "Restore only these content keys (single-page restore: CORE workspaces). Default: the whole version."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"dryRun": {
"type": "boolean",
"description": "Only list what would change; writes nothing."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"publish": {
"type": "boolean",
"description": "Publish exactly the restored pages at once (live-mode sites). Default false: they stay unpublished changes."
},
"version": {
"anyOf": [
{
"type": "integer",
"exclusiveMinimum": 0
},
{
"type": "string",
"const": "previous"
}
],
"description": "A version from list_versions, or \"previous\" (the one before live)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"removeAdded": {
"type": "boolean",
"description": "Remove pages added since the version. Default true."
},
"replaceDrafts": {
"type": "boolean",
"description": "Replace unpublished changes on the pages the restore touches. Without it such a restore answers 409 drafts_pending."
}
},
"additionalProperties": false
}| Umami only: website ID (UUID). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| measurementId | string | GA4 only: measurement ID, e.g. G-ABC123XYZ. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"provider",
"context"
],
"properties": {
"host": {
"type": "string",
"description": "Umami only: https origin of the Umami instance, e.g. https://umami.example.com."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"domain": {
"type": "string",
"description": "Plausible only: the site domain registered in Plausible, e.g. example.com."
},
"siteId": {
"type": "string",
"description": "Fathom only: site ID (uppercase letters/digits)."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"provider": {
"enum": [
"ga4",
"plausible",
"fathom",
"umami",
"none"
],
"type": "string"
},
"websiteId": {
"type": "string",
"description": "Umami only: website ID (UUID)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"measurementId": {
"type": "string",
"description": "GA4 only: measurement ID, e.g. G-ABC123XYZ."
}
},
"additionalProperties": false
}| dryRun | boolean | Default true: report what would change and write nothing. false: stage the change as a draft (publish_site makes it live). |
| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| ifMatch | string | The page's content hash (analyze's sourceEtag). If the page changed since, nothing is written. |
| similar | array | Pages with a similar copy (analyze's similar.keys) that take the shared version, losing their own wording. Default none. |
| wrapTag | string | With selectors: the wrapper. Default footer when the run ends the page content, else section. |
| selector | string | CSS selector of the element in the page's stored HTML (the editor's selector, or one checked with get_content?selector=). It must match exactly one element. |
| selectors | array | Instead of selector: a run of elements next to each other in one parent, in page order (each matches one element). Shared as one section inside a wrapper, on the pages with the same run. |
| sourceKey | string | Content key of the page the element is on, e.g. 'about.html'. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| keepLayout | boolean | With selectors: wrapper gets style="display:contents" so a flex/grid parent lays the run out as before. Default true. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"hide": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 1000,
"description": "every_page: pages that should not show it (they keep their own copy). Send them with the first move, never later."
},
"keys": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 1000,
"description": "Pages with an exact copy to share it on (analyze's matches.keys). Omit for every exact copy. The source page is always included."
},
"name": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{1,64}$",
"description": "With sourceKey + selector: the new section's name (default: proposed). Alone: the existing section to re-place."
},
"show": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 1000,
"description": "Pages that should show it again (removes their marker)."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"scope": {
"enum": [
"where_found",
"every_page"
],
"type": "string",
"description": "where_found: each page that has it gets a reference. every_page: one slot in the layout, at the top or bottom of the page content; pages listed in `hide` don't show it."
},
"dryRun": {
"type": "boolean",
"default": true,
"description": "Default true: report what would change and write nothing. false: stage the change as a draft (publish_site makes it live)."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": "string",
"minLength": 1,
"description": "The page's content hash (analyze's sourceEtag). If the page changed since, nothing is written."
},
"similar": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 200,
"description": "Pages with a similar copy (analyze's similar.keys) that take the shared version, losing their own wording. Default none."
},
"wrapTag": {
"enum": [
"div",
"section",
"footer",
"header",
"article",
"aside"
],
"type": "string",
"description": "With selectors: the wrapper. Default footer when the run ends the page content, else section."
},
"selector": {
"type": "string",
"maxLength": 2000,
"minLength": 1,
"description": "CSS selector of the element in the page's stored HTML (the editor's selector, or one checked with get_content?selector=). It must match exactly one element."
},
"selectors": {
"type": "array",
"items": {
"type": "string",
"maxLength": 2000,
"minLength": 1
},
"maxItems": 50,
"minItems": 1,
"description": "Instead of selector: a run of elements next to each other in one parent, in page order (each matches one element). Shared as one section inside a wrapper, on the pages with the same run."
},
"sourceKey": {
"type": "string",
"minLength": 1,
"description": "Content key of the page the element is on, e.g. 'about.html'."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"keepLayout": {
"type": "boolean",
"description": "With selectors: wrapper gets style=\"display:contents\" so a flex/grid parent lays the run out as before. Default true."
}
},
"additionalProperties": false
}| string |
| One line on what the variant changes, shown on the test card (≤120 chars). |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| hypothesis | string |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"path",
"goalId",
"source",
"context"
],
"properties": {
"name": {
"type": "string",
"maxLength": 80
},
"path": {
"type": "string",
"minLength": 1
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"goalId": {
"type": "string",
"minLength": 1
},
"source": {
"enum": [
"draft",
"live"
],
"type": "string"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"weights": {
"type": "array",
"items": {
"type": "integer",
"maximum": 100,
"minimum": 0
}
},
"handsOff": {
"type": "boolean",
"description": "Hands-off mode (0.56e M4): Dotsy finishes the test WITHOUT further user instruction — the LIVE SITE may change later on its own (a ≥95% winner is auto-promoted, old page kept as a draft; or after 30 days with no clear winner the test auto-ends keeping the control). Only set when the user explicitly asked for hands-off / auto-finish."
},
"changeNote": {
"type": "string",
"maxLength": 120,
"description": "One line on what the variant changes, shown on the test card (≤120 chars)."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"hypothesis": {
"type": "string",
"maxLength": 200
}
},
"additionalProperties": false
}| refreshManifest |
| boolean |
| Replace persisted manifest when true. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"full": {
"type": "boolean",
"description": "Return the full manifest incl. per-page HTML samples (default: compacted — etag/action/counts kept, samples truncated — to fit the token budget)."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"scope": {
"enum": [
"flat-only",
"all"
],
"type": "string",
"description": "Default flat-only; analyze clusters flat keys only."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"persist": {
"type": "boolean",
"description": "First call: false (preview only). true only after user confirms editable/CMS mode."
},
"profileId": {
"enum": [
"webflow",
"wordpress",
"generic",
"framer"
],
"type": "string"
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"sampleLimit": {
"type": "integer",
"maximum": 50,
"minimum": 1
},
"refreshManifest": {
"type": "boolean",
"description": "Replace persisted manifest when true."
}
},
"additionalProperties": false
}| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| restructure | boolean | Required true when scope all and site has structured pages. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"ifMatch",
"context"
],
"properties": {
"keys": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"description": "Required when scope is keys."
},
"mode": {
"enum": [
"apply",
"review-only"
],
"type": "string",
"description": "Default apply. Neither value is a dry run — review-only persists the same content/layout write as apply. Only pass review-only after a review_required error (low analyze confidence); it labels the result outcome \"review\" and defers primary-nav auto-wiring to a later apply call."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"scope": {
"enum": [
"flat-only",
"all",
"keys",
"new-since-last"
],
"type": "string"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"ifMatch": {
"type": "string",
"minLength": 1,
"description": "Manifest etag from structure_site_analyze or get_structure_status."
},
"overrides": {
"type": "object",
"properties": {
"forceSkipKeys": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"restructure": {
"type": "boolean",
"description": "Required true when scope all and site has structured pages."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"category",
"impactPercent",
"title",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"title": {
"type": "string"
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"category": {
"enum": [
"missing_tool",
"blocking_error",
"extra_round_trips",
"confusing_response",
"workaround",
"other"
],
"type": "string",
"description": "missing_tool | blocking_error | extra_round_trips | confusing_response | workaround | other"
},
"findings": {
"type": "array",
"items": {
"type": "object",
"required": [
"category",
"impactPercent",
"title"
],
"properties": {
"title": {
"type": "string"
},
"category": {
"$ref": "#/properties/category"
},
"description": {
"type": "string"
},
"operationId": {
"type": "string"
},
"impactPercent": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"suggestedImprovement": {
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 20
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"description": {
"type": "string"
},
"impactPercent": {
"type": "integer",
"maximum": 100,
"minimum": 1
},
"suggestedImprovement": {
"type": "string"
}
},
"additionalProperties": false
}| context* | string | One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here. |
| guestToken | string | Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy. |
| removeRules | array | Ids of rules or guidelines to remove (site brief only). |
| appendHandoff | string | Append a hand-off log line — site brief only; ignored when page is set. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"body": {
"type": "string",
"maxLength": 50000,
"description": "Replace narrative body (site ≤50k chars; page ≤10k)."
},
"goal": {
"type": "string",
"maxLength": 4000,
"description": "Current goal (site ≤4k chars; page ≤2k)."
},
"head": {
"description": "Head fields to merge. Site: purpose, audience, kind (exploration|production), priorities ({seo,analytics,design,mobile}: must|nice|skip), editingModel (ai|simple-editor|creator), sections, design (strict): palette string[] max 8, type string[] max 6, layout string max 80 chars — no other keys. Page: purpose, design.{direction,hero}."
},
"page": {
"type": "string",
"description": "Content key — targets that page's brief (`_intent/pages/<key>.md`). Omit for the site brief."
},
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "object",
"properties": {
"seo": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
]
},
"design": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
]
},
"content": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
}
],
"description": "Site: free-form ## Notes string (≤4k) OR per-section notes object for Design system / Content & CMS / SEO (null clears one). Page brief: string only (≤2k)."
},
"rules": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"card",
"text"
],
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z0-9-]{2,40}$"
},
"card": {
"enum": [
"intent",
"design",
"content",
"seo"
],
"type": "string"
},
"text": {
"type": "string",
"maxLength": 160,
"minLength": 1
},
"check": {
"anyOf": [
{
"anyOf": [
{
"type": "object",
"required": [
"type",
"max"
],
"properties": {
"max": {
"type": "integer",
"maximum": 300,
"minimum": 10
},
"type": {
"type": "string",
"const": "title-max"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type",
"suffix"
],
"properties": {
"type": {
"type": "string",
"const": "title-suffix"
},
"suffix": {
"type": "string",
"maxLength": 60,
"minLength": 1
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type",
"min",
"max"
],
"properties": {
"max": {
"type": "integer",
"maximum": 1000,
"minimum": 1
},
"min": {
"type": "integer",
"maximum": 1000,
"minimum": 0
},
"type": {
"type": "string",
"const": "description-length"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"const": "one-h1"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type",
"words"
],
"properties": {
"type": {
"type": "string",
"const": "banned-words"
},
"words": {
"type": "array",
"items": {
"type": "string",
"maxLength": 40,
"minLength": 1
},
"maxItems": 50,
"minItems": 1
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"const": "image-alt"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type",
"colors"
],
"properties": {
"type": {
"type": "string",
"const": "allowed-colors"
},
"colors": {
"type": "array",
"items": {
"type": "string",
"pattern": "^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$"
},
"maxItems": 24,
"minItems": 1
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"type",
"fonts"
],
"properties": {
"type": {
"type": "string",
"const": "allowed-fonts"
},
"fonts": {
"type": "array",
"items": {
"type": "string",
"maxLength": 60,
"minLength": 1
},
"maxItems": 12,
"minItems": 1
}
},
"additionalProperties": false
}
]
},
{
"type": "null"
}
]
},
"level": {
"enum": [
"block",
"warn"
],
"type": "string"
},
"locked": {
"type": "boolean"
}
},
"additionalProperties": false
},
"maxItems": 30,
"description": "Rules & guidelines lines to add or change (upsert by id — send only fields you change; omitted fields keep their stored value; check: null turns a Rule into a Guideline). A supported check (title-max, title-suffix, description-length, one-h1, banned-words, image-alt, allowed-colors, allowed-fonts) makes a Rule — use level block for hard musts (banned words, title suffix), warn for softer checks. locked can only be set by a person; locked: false unlocks."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"removeRules": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 30,
"description": "Ids of rules or guidelines to remove (site brief only)."
},
"appendHandoff": {
"type": "string",
"maxLength": 500,
"minLength": 1,
"description": "Append a hand-off log line — site brief only; ignored when page is set."
}
},
"additionalProperties": false
}| How the editor's Save behaves. 'live' (default) publishes each save immediately; 'staged' keeps saves as drafts until publish_site. Prefer 'staged' when an agent will hand the editor to a person (see start_edit_session → draftEditorUrl) so keystrokes don't go straight to the public site. API writes always stage regardless of this setting. |
| ownSeoFiles | boolean | Use the site's own robots.txt and sitemap.xml even when they can hurt search: a robots.txt that blocks the whole site (Disallow: /), and a static sitemap.xml, which replaces the generated one (collection pages included). Off by default; a robots.txt without Disallow: / is always used. Takes effect at the next publish. |
| keyConvention | string |
| trailingSlash | string | Page URL form. 'ignore' (default): /blog and /blog/ both serve the page. 'never': /blog/ 301s to /blog. 'always': /blog 301s to /blog/. The canonical tag and sitemap use the same form. Live immediately, no publish needed. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"title": {
"type": "string",
"maxLength": 200
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"signature": {
"type": "object",
"properties": {
"mark": {
"enum": [
"logo",
"dot"
],
"type": "string",
"description": "Resting look: 'dot' (senna dot, default) or 'logo' (Dotsy logo)."
},
"reveal": {
"enum": [
"pill",
"seal"
],
"type": "string",
"description": "On hover: 'seal' (rotating stamp, default) or 'pill' (\"Made with Dotsy\")."
},
"enabled": {
"type": "boolean",
"description": "Show the badge in the bottom-right corner of every published page."
}
},
"description": "\"Made with Dotsy\" signature badge. Takes effect on the live site immediately, no publish needed.",
"additionalProperties": false
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
},
"editingMode": {
"enum": [
"live",
"staged"
],
"type": "string",
"description": "How the editor's Save behaves. 'live' (default) publishes each save immediately; 'staged' keeps saves as drafts until publish_site. Prefer 'staged' when an agent will hand the editor to a person (see start_edit_session → draftEditorUrl) so keystrokes don't go straight to the public site. API writes always stage regardless of this setting."
},
"ownSeoFiles": {
"type": "boolean",
"description": "Use the site's own robots.txt and sitemap.xml even when they can hurt search: a robots.txt that blocks the whole site (Disallow: /), and a static sitemap.xml, which replaces the generated one (collection pages included). Off by default; a robots.txt without Disallow: / is always used. Takes effect at the next publish."
},
"keyConvention": {
"enum": [
"flat",
"directory"
],
"type": "string"
},
"trailingSlash": {
"enum": [
"ignore",
"never",
"always"
],
"type": "string",
"description": "Page URL form. 'ignore' (default): /blog and /blog/ both serve the page. 'never': /blog/ 301s to /blog. 'always': /blog 301s to /blog/. The canonical tag and sitemap use the same form. Live immediately, no publish needed."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"site",
"context"
],
"properties": {
"site": {
"type": "string",
"description": "Site slug, e.g. acme-studio"
},
"codes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Only these health codes, e.g. perf_image_heavy."
},
"paths": {
"type": "array",
"items": {
"type": "string"
},
"description": "Routes to check; omit to verify every route on the site."
},
"detail": {
"enum": [
"summary",
"full"
],
"type": "string",
"description": "summary (default): grouped by code, clean pages counted. full: per-page lists."
},
"groups": {
"type": "array",
"items": {
"enum": [
"seo",
"speed",
"a11y",
"links"
],
"type": "string"
},
"description": "Only these groups: speed = perf_*, a11y = a11y_*, links = link_* + content_*. Omit for all."
},
"context": {
"type": "string",
"minLength": 1,
"description": "One sentence: why you are calling this tool and what you are trying to accomplish. Stored on the site's activity log and visible to everyone on the site — never put secrets or personal data here."
},
"guestToken": {
"type": "string",
"minLength": 20,
"description": "Guest token from start_site. Send it on every call until claim_site. Omit when this chat is already signed in to Dotsy."
}
},
"additionalProperties": false
}