# Turboslide > A block document with a validator and a grammar linter; every operation is a named action in one table, reachable from the CLI, MCP, HTTP and the studio window API. Turboslide keeps a presentation as typed JSON (deck.json plus slides/.json), renders it with one renderer, lints it against the deck grammar, and exports it to PPTX with a verified report, pixel identical in its default mode. There are no coordinates: a slide is a kind, a layout and typed blocks in named slots. ## Discovery - /api/agent: the manifest (transports, rules, execution rules, action ids, skills, resources, what this instance implements) - /openapi.json: the OpenAPI 3.1 contract of POST /api/actions/ - /mcp: MCP over streamable HTTP; `turboslide mcp` is the same server over stdio - /llms-full.txt: this guide with every action and every lint rule - /docs/agents/skills.md: the four skills (turboslide-create, turboslide-api, turboslide-studio, turboslide-verify), with links to each SKILL.md and its generated reference tables - /docs/agents/grammar.md: the deck grammar (slide kinds, layouts, blocks, rules) ## Rules - Every mutating action requires baseRevision and rejects a stale one with 409 and the current document. - Every write returns the normalized result; re-read from the response, not from memory. - Unknown fields are rejected with unknown_field and a JSON pointer, except under ext on a slide, a block or an asset. - An agent write to a slide another author leased is refused with 409 and the holder unless force is set. - A claim about a deck names the revision; render both themes and lint before claiming a slide is done. ## Calling an action over HTTP - POST /api/actions/; GET /api/actions/ returns the action contract: input and output JSON Schema, transports, milestone and whether this instance implements it. - Body: One JSON object, the action input exactly as the input schema states it; unknown fields are refused with 400 and code unknown_field plus a JSON pointer. - Deck: ?deck= names the deck. A read without it reads the instance default (gt-brand); a write that lands on a deck and names none is refused with 400 and code deck_required (the share and publish actions may name their deck in the input id instead). - Author: Every write is recorded under the caller's identity: an API key's owner as agent:. x-turboslide-author: agent: (or ?author=) only labels the run; without a key, a request that names no author writes as agent:http. - Force: ?force=1 (or x-turboslide-force: 1) writes to a slide another author leased; without it the write is 409 with the holder and the current document. - Retries: Idempotency-Key: on a POST of a writing action that takes it (its OpenAPI entry names the header: the slide, block, text, section, deck setting, asset and restore writes) makes it safe to resend after a timeout: send the same key with the same body, and a write that already landed is not applied again and is answered 200 with that write's answer and the idempotent-replayed: true header. The same key with another action or body is 422 idempotency_key_reused; a key on another writing action is 400 idempotency_not_supported. 1 to 255 visible ASCII characters; anything else is 400 invalid_idempotency_key. - Auth: Authorization: Bearer on every deployed instance, an API key from turboslide login acting for its owner with its scopes (read, comment, write, export, share, admin); TURBOSLIDE_TOKEN is the bootstrap bearer until a key exists; open only on localhost when the instance has no token; a request off localhost without one is 401. A key without the share scope reads other people's ids as per deck stand-ins (ref_ and 22 characters). - Limits: 1048576 bytes per write body; 26214400 bytes per picture without an account, 52428800 signed in. A hosted studio refuses SVG and re-encodes every picture; HEIF and JXL are refused and an animated GIF keeps its first frame. - Errors: { error: { name, status, message, code?, pointer?, currentRevision?, current?, holder?, capability?, milestone? } }; TypeError 400, no key 401, ForbiddenError 403 with the capability named, RangeError 404 (also a deck the caller may not read, the same answer as a missing one), ConflictError 409, a revoked publish token or an expired download 410, NotImplementedError 501, Error 500. A quota answers 429 with Retry-After and { error: "rate_limited", message, quota }; a kill switch answers 503 with Retry-After: 60 and { error: "unavailable", message }. ## MCP over HTTP - MCP streamable HTTP: POST JSON-RPC to /mcp (initialize first), GET for the notification stream, DELETE to end the session; the mcp-session-id header carries the session. - One MCP session is bound to one deck and one caller at initialize; tools are deck_ for every implemented action on the mcp transport that the caller may call: a tool an API key's scopes or admin standing never reach is not listed, and a call to it answers 403 naming the scope it lacks. - ?deck= on the initialize request. A session without it reads the instance default (gt-brand), and its write tools are refused with 400 until a session names the deck. A share or publish tool acts on the session deck: one whose input id names another deck is refused with 400. The key's owner is the author of every write; x-turboslide-author or ?author= on the initialize request only labels the run (agent:mcp-http without one). - deck_goto_slide (view.goto) is listed when a studio page is attached to the deck and runs in that page: the editor at /edit while it is visible, and a /deck, /present or /embed page opened with ?agent=1 while it is visible; a page hidden for 10 s detaches and the call answers 404 until it is shown again. ## Leases and revisions - slide.lease takes ten minutes on a slide; an agent write to a slide another author holds is 409 with the holder unless force is set; a human write warns and goes through. - Every mutating action takes baseRevision; a stale one is 409 with currentRevision and the current document; re-read from the response and retry once. ## Renders and exports over HTTP - GET /api/render/?deck=&theme=light|dark&scale=1|2 answers the PNG with the RenderRecord in the X-Turboslide-Record header; ?format=json (or Accept: application/json) answers the record. ?w=160|320|640 is the cached thumbnail. - POST /api/export/ takes the export.run input as one JSON object (format defaults to pptx; out is ignored, the file lands in the job folder). ?sync=1 (or "sync": true in the body) runs the export inside the request and answers the file, or the ExportReport with the files and their URLs under ?format=json (or Accept: application/json); the X-Turboslide-Export-Report header carries the summary. - A hosted studio (a serverless function) runs every POST synchronously, ?sync=1 or not, and says so in X-Turboslide-Sync: hosted: a queued job would get CPU only while another request kept the instance busy, and its record lives on that instance alone. Send ?sync=1 so the request means the same everywhere. - In a checkout or against the Docker worker, a POST without ?sync=1 answers 202 with the job and a Location to poll: GET /api/export/?job= for the record (the ExportReport under report once done), GET without job for the deck's jobs. - A file over 4.5 MB cannot leave a function: with a Blob store the route answers 302 to /api/download/s., a link signed for the caller that expires in ten minutes (410 after, 403 to anyone else) and never the store address; without one it answers 413 with the JSON body; export one theme or a slide subset then. - Auth: both routes take Authorization: Bearer when the instance has a token set: an API key from turboslide login, acting for its owner with its scopes (read for a render, export for an export), or the deployment's TURBOSLIDE_TOKEN; without a token set they are open. The thumbnail variant (?w=) is answered only to a caller who can read the deck. ## Transports - cli: turboslide --json --author agent: - mcp: turboslide mcp (stdio) or POST /mcp (streamable HTTP); tools deck_ - http: POST /api/actions/ with the input as JSON - window: window.turboslide.studio.invoke(, input) after the turboslide:studio-api-ready event ## Skills - turboslide-create (skills/turboslide-create/SKILL.md): Write or revise slides in the grammar - turboslide-api (skills/turboslide-api/SKILL.md): Discover and write through the action table - turboslide-studio (skills/turboslide-studio/SKILL.md): Drive the studio through the window API - turboslide-verify (skills/turboslide-verify/SKILL.md): Render, lint, judge and verify exports ## Verification - Render both themes, read the contact sheet by its cell map, run the grammar linter, judge with the six lenses (deck_review prompt), verify exports against the web render (skills/turboslide-verify). - A claim about a deck names the revision it was verified at; a severity 3 finding blocks the ship step. ## Documentation The guides and the action reference at /docs, each page as markdown: - [Turboslide documentation](/docs/index.md): Turboslide is a slides editor in the browser. Make a presentation, present it and send the link, or have an agent run the same actions. No account is needed. - [The editor](/docs/editor.md): The parts of the editor window, what each menu holds, and where to find speaker notes, Find and replace and Version history. - [Slides and layouts](/docs/editor/slides.md): Add, duplicate, skip, move and delete slides, pick a layout for each slide, and bring slides in from another presentation. - [Text, pictures and shapes](/docs/editor/objects.md): Write and format text, add and replace pictures and logos, draw shapes and lines, edit tables and charts, and place animated patterns. - [Advanced tools](/docs/editor/advanced-tools.md): The Tools > Advanced tools switch shows more commands in the menus, on the toolbar and in the right click menus. - [Presenting](/docs/presenting.md): Present a presentation full screen, use Presenter view with your notes and a timer, and the keys that control a slideshow. - [Sharing and people](/docs/sharing.md): Share a presentation by link or with people by name, set what each person can do, and work on one presentation together. - [Themes and brand kits](/docs/themes.md): Pick one of nine themes for every slide, and set your own logo, colors, fonts and footer in a brand kit. - [Download and export](/docs/export.md): Download a presentation as PowerPoint, PDF, pictures, a web page or a Turboslide file, with or without speaker notes and skipped slides. - [Keyboard shortcuts](/docs/shortcuts.md): Every keyboard shortcut the editor answers in its default view, with the key on a Mac and on Windows. - [Run Turboslide yourself](/docs/self-hosting.md): Run the Turboslide studio from its repository on your own computer or server, and choose where presentations are stored. - [Agents](/docs/agents.md): Every command in Turboslide is an action that a program or an AI agent can run, over the command line, MCP, HTTP or an open page. - [The command line](/docs/agents/cli.md): Run every action from a terminal with the turboslide command, read its JSON output and exit codes, and move presentations to and from a studio. - [MCP](/docs/agents/mcp.md): Use Turboslide's actions as MCP tools, over standard input and output from the command line or over HTTP from a hosted studio. - [HTTP actions](/docs/agents/http.md): Call any action with one POST request, read its contract, and render slides and export files over HTTP. - [Skills](/docs/agents/skills.md): Four skills that teach an AI agent how to write slides, call the actions, drive an open page and check its work. - [Deck grammar](/docs/agents/grammar.md): How a slide is written as data, with the slide kinds, the layouts and the block types an agent writes. - [The page API](/docs/agents/browser.md): Drive an open editor or viewer page with window.turboslide.studio, the same actions with access to the page's controls and view. - [Action reference](/docs/reference.md): Every action of Turboslide by group, with its input fields and its name on the command line, over MCP and over HTTP. - [Presentations](/docs/reference/deck.md): The actions of the deck group, with their input fields and their names on every transport. - [Slides](/docs/reference/slide.md): The actions of the slide group, with their input fields and their names on every transport. - [Objects on a slide](/docs/reference/block.md): The actions of the block group, with their input fields and their names on every transport. - [Pictures and files](/docs/reference/asset.md): The actions of the asset group, with their input fields and their names on every transport. - [Renders](/docs/reference/render.md): The actions of the render group, with their input fields and their names on every transport. - [Checks](/docs/reference/lint.md): The actions of the lint group, with their input fields and their names on every transport. - [Versions](/docs/reference/version.md): The actions of the version group, with their input fields and their names on every transport. - [Downloads](/docs/reference/export.md): The actions of the export group, with their input fields and their names on every transport. - [The view](/docs/reference/view.md): The actions of the view group, with their input fields and their names on every transport. - [The studio page](/docs/reference/studio.md): The actions of the studio group, with their input fields and their names on every transport. - [Presence](/docs/reference/presence.md): The actions of the presence group, with their input fields and their names on every transport. - [Sync](/docs/reference/sync.md): The actions of the sync group, with their input fields and their names on every transport. - [Comments](/docs/reference/comment.md): The actions of the comment group, with their input fields and their names on every transport. - [Sharing](/docs/reference/share.md): The actions of the share group, with their input fields and their names on every transport. - [Accounts](/docs/reference/account.md): The actions of the account group, with their input fields and their names on every transport. - [Administration](/docs/reference/admin.md): The actions of the admin group, with their input fields and their names on every transport.