Publishing API
Overview
Publishing is a three-step flow:
publish— dry-run that builds a reviewable diff manifest and a short-lived confirmation token. No data is written.publish-confirm— presents the token and kicks off the pipeline immediately. Returns{ publish_id, status: "running" }within seconds — it does not wait for the deploy to finish.publish-status— poll until the job reachessucceededorfailed.
Authentication: OAuth Bearer token or service API key. The caller must have manager role on the project.
Step 1 — publish (dry-run)
Builds a manifest of pending changes and returns a one-time confirmation token. Nothing is written or deployed in this step.
Arguments
| Field | Required | Notes |
|---|---|---|
project_id | yes | The project to publish. |
project_name | yes | Must match the stored project name exactly (case-insensitive trim). A mismatch returns an error showing both the expected and supplied values. |
Response
{ "manifest": { "project_name": "Acme Real Estate", "target_site_url": "https://tf-acme.web.app", "drafts": [ { "path": "abc123", "language": "en", "slug": "guides/intro", "title": "Getting started" } ], "theme_changes": { "colors": { "primary": "#14b8a6" } }, "translations_planned": 4 }, "confirmation_token": "ec1a4b…(64 hex)", "expires_at": "2026-05-11T01:23:45.678Z"}The confirmation_token is single-use and expires after 5 minutes.
Step 2 — publish-confirm (async kickoff)
Presents the token and enqueues the deployment pipeline. Returns immediately — the promote → translate → deploy chain runs in the background.
Arguments
| Field | Required | Notes |
|---|---|---|
project_id | yes | Must match the project bound to the token. |
confirmation_token | yes | Returned by publish. |
Response
{ "publish_id": "auto-generated-id", "status": "running", "site_url": "https://tf-acme.web.app"}Save publish_id — you need it to poll status and to revert the publish within one hour.
Step 3 — publish-status (poll until terminal)
Poll until the job status reaches succeeded or failed. The caller needs member role or above.
Arguments
| Field | Required |
|---|---|
project_id | yes |
publish_id | yes |
Response by status
status | Additional fields |
|---|---|
queued / running | Poll again. |
succeeded | published_urls: [{ title, language, slug, url }] — present as clickable links. |
failed | error — the failure message. |
Promotion pipeline
Validation
Every draft is validated before any writes occur. A validation error aborts the entire batch.
| Rule | Error |
|---|---|
metadata.title missing | Missing required field 'title' |
metadata.title not 10–60 chars | Title must be 10–60 characters |
metadata.description missing | Missing required field 'description' |
metadata.description not 50–160 chars | Description must be 50–160 characters |
metadata.slug missing | Missing required field 'metadata.slug' |
content empty | Content cannot be empty |
content starts with # | Content contains an h1. Start content with ## instead. |
Index requirement
Each published language must have a live or in-batch document with metadata.slug === "index".
Concurrency
Only one publish job runs at a time per project. A concurrent publish-confirm call returns publish in progress.
Translations
After promotion, draft copies of every promoted document are created automatically for all additional locales configured in the project. Translated drafts are validated in a second pass before promotion — a faulty translation cannot reach production directly.
Skip-on-unchanged: if a previously-translated variant’s source content and translation configuration are identical to the last publish, the translation is reused with no new AI call. This covers both content changes and AI model version bumps — a model upgrade is never silently skipped.
Reversion
revert-publish rolls back within one hour using the publish_id from publish-confirm.
Errors
| Phase | Error | Cause |
|---|---|---|
| Authorization | Insufficient permission: this tool requires 'manager' on project '…' | Caller has member role or no role. |
| Authorization | project_name does not match project …: expected 'X', got 'Y' | project_name echo failed. |
| Token | Invalid or already-used confirmation token | Token expired, already used, or wrong project. |
| Token | Confirmation token has expired | 5-minute window elapsed. Run publish again. |
| Lock | publish in progress | Another publish is already running. Wait and retry. |
| Promote | Validation failed for one or more drafts | A validation rule was violated. Details include the draft path and field. |
| Promote | Missing mandatory index page for locale(s): … | A configured language lacks an index page. |
| Deploy | { "success": false, "error": "…" } | Build or deployment failure. The error field contains the detail. |
Related
- MCP Server — publish via MCP tools (
publish,publish-confirm,publish-status) - API Authentication — OAuth Bearer and API key authentication
- Translation System — how documents are auto-translated at publish time
- API Overview — full list of endpoints