How do I publish content entries?
Publishing a content entry marks it live: the entry gets a published status and a publish timestamp, and the Content API cache is purged so the new version is served immediately. Until then it stays a draft.
Publishing from the dashboard #
- Open the entry in the Content tab
- Review the content and its translations
- Click Publish
You can also choose which languages go live. Anything you leave unselected stays a draft, and a language whose body is still empty is skipped — the dashboard tells you which languages went live and which were skipped, and why. That guard is deliberate: without it an entry could show a green "Published" pill over an editor that opens blank. Models that carry no body at all (taxonomies, tags, and other metadata-only models) publish without that check.
Publishing requires an admin role on the organization.
Publishing via MCP #
"Publish the getting-started help article"The agent calls publishContentEntry with the entry id. Over MCP there is no per-language choice — every language that has content goes live.
For many entries at once it calls bulkPublishEntries, which takes up to 500 entry ids and returns a failed array, so only the entries that failed need retrying.
Where publishing happens #
| Surface | Can publish? |
|---|---|
| Dashboard | Yes — per entry, optionally per language |
MCP (publishContentEntry, bulkPublishEntries) | Yes |
Content API (content.better-i18n.com/v1/content/…) | No — read-only |
The Content API is for reading content into your app. It has no publish endpoint; publishing is a dashboard or MCP action.
Draft vs. published vs. archived #
| Status | In the dashboard | On the Content API |
|---|---|---|
draft | Visible | Returned unless you filter |
published | Visible | Returned |
archived | Visible, marked archived | Returned unless you filter |
Read this row carefully: the Content API does not filter by status on its own. Ask for what you want:
GET https://content.better-i18n.com/v1/content/your-org/your-project/models/help-article/entries?status=publishedWithout ?status=published a request returns drafts and archived entries alongside live ones. If your app renders whatever the API hands back, add the filter.
Archiving is the reversible way to take content out of circulation — the entry and its translations stay intact.
Bulk publishing #
Select multiple entries in the content list and choose a status from the bulk actions menu — up to 50 entries per action. Agents use bulkPublishEntries (up to 500 ids, partial success reported).
What happens after publishing #
Publish
→ Entry + its published translations flip to "published"
→ Webhooks fire (previous status → new status)
→ Content API cache purged for that org / project / model / entry / languages
→ Next request serves the new versionNo rebuild or redeploy is needed — consumers fetch content at runtime.
The purge is the mechanism, not the cache TTL. Responses are cached with s-maxage=60 and stale-while-revalidate=120, and the purge is retried up to three times; if every attempt fails the mutation still succeeds and the TTL bounds how long a stale response can be served. So content that stubbornly refuses to update is worth a minute's wait before it counts as a problem — see I published but my app still shows old translations.
Unpublishing #
Unpublishing takes the entry back to draft and it stops being served as published content.
You can also unpublish single languages: those translations revert to draft and the entry stays published as long as another language is still live. That is how you pull one bad translation without taking the whole entry down.
Better I18N