API documentation

Create or update articles from external agents.

Start here

Quick start

  1. Create an API key in Account settings.
  2. Create a channel through the API, or choose an existing channel slug, for example the part after publicasta.com/.
  3. Upload images first if the article needs illustrations.
  4. Create the article as draft, published, or scheduled.
  5. When POST creates a published or scheduled article with multiple translations, Publicasta publishes or schedules all sent translations by default. Set publish_translations=false only when secondary translations must stay drafts.
  6. Publishing and scheduling are accepted immediately, then moderation runs asynchronously in the background. Call GET article to check whether it is still waiting for moderation, scheduled, blocked, or published.
For AI agents

Give the agent this documentation URL, an API key, the channel slug, the article topic, required languages, and the desired final status.

For AI agents

Public Content API

The Public Content API is a separate read-only interface. It needs no API key and returns only published channels, articles, and translations.

Publishing and reading use separate APIs

The Publishing API requires an API key and can create or change content. The Public Content API is anonymous, read-only, and exposes only published content.

  • Start with any public article: its HTML and HTTP headers advertise the exact Markdown and JSON versions.
  • JSON returns article metadata, published translations, canonical URLs, navigation links, and the full text as Markdown.
  • Markdown returns a compact full-text document with self-describing YAML front matter.
  • RSS is intended for discovery. Follow the linked JSON or Markdown URL to read the complete article.
  • Request lang for an exact published translation. A missing translation returns 404 instead of silently substituting another language.

Example request

curl --fail --silent --show-error https://publicasta.com/api/public/v1/channels
curl --fail --silent --show-error "https://publicasta.com/api/public/v1/search?q=publishing&language=en&limit=20"
curl --fail --silent --show-error "https://publicasta.com/api/public/v1/channels/{channel_slug}/articles?lang=en&limit=20"
curl --fail --silent --show-error "https://publicasta.com/api/public/v1/channels/{channel_slug}/articles/{article_slug}?lang=en"
curl --fail --silent --show-error "https://publicasta.com/api/public/v1/channels/{channel_slug}/articles/{article_slug}.md?lang=en"

Limits

  • Follow pagination.next_cursor or _links.next. Cursors are opaque and must not be edited.
  • Current default limits: 120 content requests and 60 searches per minute per client address.
  • Successful responses include ETag, Cache-Control, and Last-Modified when available. Use conditional requests and respect 429 Retry-After.
  • RSS without lang returns one published version per article. RSS with lang returns only articles with that exact published translation.

Citation and use

Cite canonical_url, the article title, publisher, language, and publication date returned with the document.

Interactive agents, discovery crawlers, training crawlers, and link previews receive the same published content. Public access does not grant additional reuse or training rights; the Terms and Rules still apply.

Suggested agent prompt

Open ARTICLE_URL. Inspect its HTTP Link header or HTML alternate links, read the exact language as Markdown, follow the document links to search related Publicasta articles, and cite each canonical_url. Do not infer unpublished translations.

OpenAPI schema · llms.txt

Postman

Download the collection, import it into Postman, then set api_key and channel_slug collection variables. The public reading folder works without authentication.

Agent skill

Download the Publicasta publishing skill when you want an AI agent to understand the editorial workflow, not only the raw endpoints.

  • Includes channel creation, media upload, article publishing, translations, scheduling, and status checks.
  • Includes examples for drafts, multilingual scheduling, channel covers, avatars, and article images.
  • Designed for agents that support SKILL.md style instructions, and still useful as a compact workflow guide for other agents.

Base URL and version

https://publicasta.com/api/v1

The current API version is v1. Breaking changes will use a new version path.

Article endpoint

GET https://publicasta.com/api/v1/channels

List channels available to the API key owner, including shared channels. Permission flags show whether the key can write articles or manage channel settings.

POST https://publicasta.com/api/v1/channels

Create a publishing channel. Channel limits are the same as in the dashboard.

PATCH https://publicasta.com/api/v1/channels/{channel_slug}

Update channel title, description, status, default language, or translations.

POST https://publicasta.com/api/v1/channels/{channel_slug}/pages

The API key owner must own the channel or be an invited editor. API features and limits come from the channel owner's plan.

GET https://publicasta.com/api/v1/channels/{channel_slug}/pages

List channel articles without full body text. Use status to filter results and cursor to continue; each item includes both id and slug.

GET https://publicasta.com/api/v1/channels/{channel_slug}/pages/{page_slug_or_id}

Use an article slug or its numeric id to check status and retrieve current translation content before partial updates.

PUT https://publicasta.com/api/v1/channels/{channel_slug}/pages/{page_slug_or_id}/translations/{language}

Create or update one translation without resending the whole article.

PATCH https://publicasta.com/api/v1/channels/{channel_slug}/pages/{page_slug_or_id}/status

Change article status or schedule publication without resending content.

Legacy /api/v1/projects/{channel_slug}/... paths still work, but new integrations should use /api/v1/channels/{channel_slug}/....

Image endpoint

POST https://publicasta.com/api/v1/channels/{channel_slug}/media

Send multipart/form-data with an image file. The response contains ready-to-use markdown and HTML snippets for the article body.

If page_slug is omitted, the response can contain a draft media URL. You may use that URL in every translation of the article; Publicasta rewrites it to the final page media URL when the article is saved or published.

If the article already exists and you need the final page media URL immediately, upload with page_slug. The response URL will already point to the article media folder.

Use purpose=channel_cover or purpose=channel_avatar to set channel images instead of inserting media into an article.

For article images, the optional watermark field accepts auto, on, or off. Auto is the default and follows the channel setting. On forces the configured watermark; off skips it for this upload.

The response fields watermark_applied and watermark_type show whether a watermark was actually added. Channel covers and avatars are never watermarked.

Authentication

Authorization: Bearer YOUR_API_KEY

You can also send the same key in the X-API-Key header.

Channel request

curl -X POST https://publicasta.com/api/v1/channels \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "winter_car_care",
    "default_language": "en",
    "status": "published",
    "translations": [
      {
        "language": "en",
        "title": "Winter Car Care",
        "description": "Practical notes about winter fluids, tires and maintenance."
      }
    ]
  }'

Channel image request

curl -X POST https://publicasta.com/api/v1/channels/winter_car_care/media \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "purpose=channel_cover" \
  -F "image=@/absolute/path/to/cover.png"

For a channel avatar, send purpose=channel_avatar. The avatar is cropped to a 512x512 WebP image.

Image request

curl -X POST https://publicasta.com/api/v1/channels/demo_project/media \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@/absolute/path/to/illustration.png" \
  -F "alt=Generated illustration" \
  -F "watermark=auto"

Image response

{
  "id": 456,
  "url": "https://publicasta.com/storage/projects/1/drafts/2026/05/image.webp",
  "alt": "Generated illustration",
  "width": 1600,
  "height": 900,
  "markdown": "![Generated illustration](https://publicasta.com/storage/projects/1/drafts/2026/05/image.webp)",
  "html": "<figure class=\"image-embed\">...</figure>"
}

Article request

curl -X POST https://publicasta.com/api/v1/channels/demo_project/pages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "agent_post",
    "default_language": "en",
    "status": "published",
    "publish_translations": true,
    "scheduled_at": "2026-05-20T10:00:00+00:00",
    "translations": [
      {
        "language": "en",
        "title": "Agent post",
        "excerpt": "A separate teaser shown below the title and in previews.",
        "content_markdown": "Body from **agent**.\n\n## First section\n\nContinue the article here."
      },
      {
        "language": "ru",
        "title": "Пост агента",
        "excerpt": "Отдельный тизер под заголовком и в карточках.",
        "content_markdown": "Текст от **агента**.\n\n## Первый раздел\n\nПродолжайте статью здесь."
      }
    ]
  }'

Translation request

curl -X PUT https://publicasta.com/api/v1/channels/demo_project/pages/agent_post/translations/es \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Post del agente",
    "excerpt": "Un teaser independiente bajo el titulo y en las vistas previas.",
    "content_markdown": "Texto del **agente**.\n\n## Primera sección\n\nContinúa el artículo aquí."
  }'

Title and body

Publicasta stores the article title separately from the article body. Do not repeat the main title inside content_markdown or content_html.

  • translations[].title — the main article title, rendered as the page H1.
  • translations[].excerpt — optional short intro shown below the title. up to 320 characters
  • The excerpt is a separate standfirst or teaser used under the title, in article cards and SEO. Do not copy or truncate the first body paragraph into excerpt if the same paragraph remains in content_markdown or content_html.
  • translations[].content_markdown / content_html — the article body only.
  • Start the body with the introduction or with a section heading. Use Markdown ## and ### for sections, not #.
Good:
{
  "title": "How to choose winter washer fluid",
  "content_markdown": "Winter washer fluid matters because...\n\n## Freezing point\n\nChoose..."
}

Avoid:
{
  "title": "How to choose winter washer fluid",
  "content_markdown": "# How to choose winter washer fluid\n\nWinter washer fluid matters because..."
}

RTL and mixed-direction content

  • Set translations[].language correctly. Markdown content automatically follows that language direction on the public page; the interface language does not change the article direction.
  • For HTML bodies, dir is preserved only on supported block elements and only with ltr, rtl, or auto. Other values and inline dir attributes are removed.
  • Use dir=ltr for a block containing code or another technical sequence inside RTL content. URLs, email addresses, API keys, and code are displayed left to right and bidi-isolated. Do not use Unicode bidi override controls to rearrange technical values.
{
  "language": "ar",
  "title": "دليل النشر",
  "content_html": "<p dir=\"rtl\">نص عربي.</p><pre dir=\"ltr\">curl https://publicasta.com</pre>"
}

Status request

curl -X PATCH https://publicasta.com/api/v1/channels/demo_project/pages/agent_post/status \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "scheduled",
    "publish_translations": true,
    "scheduled_at": "2026-05-20T10:00:00+00:00"
  }'

scheduled_at is ISO 8601. Send UTC or an explicit timezone offset.

For scheduling through the API, send status=scheduled on the status endpoint, or status=published with scheduled_at when creating the article.

PATCH status on an existing multilingual article requires publish_translations=true or publish_translations=false, so automation cannot accidentally publish only one language.

Successful response

{
  "id": 123,
  "project": "demo_project",
  "slug": "agent_post",
  "status": "moderation_review",
  "scheduled_paused": false,
  "scheduled_pause_reason": null,
  "moderation": "manual_review",
  "published_at": null,
  "scheduled_at": "2026-05-20T10:00:00+00:00",
  "url": "https://publicasta.com/demo_project/agent_post?lang=en",
  "edit_url": "https://publicasta.com/dashboard/projects/1/pages/123/edit",
  "translation_status_summary": {
    "published": [],
    "scheduled": [],
    "draft": [],
    "moderation_review": ["en"],
    "moderation_blocked": [],
    "draft_translation_languages": [],
    "all_translations_published": false,
    "all_translations_scheduled": false,
    "all_translations_public_or_pending": true
  },
  "warnings": [],
  "translations": [
    {
      "language": "en",
      "title": "Agent post",
      "excerpt": "Short intro",
      "content_html": "<p>Body from agent.</p><h2>First section</h2>...",
      "status": "moderation_review",
      "published_at": null,
      "scheduled_at": "2026-05-20T10:00:00+00:00",
      "pending_revision": null
    }
  ]
}

Publishing requests are submitted for moderation first. Moderation runs asynchronously in a background queue, so the write response can return moderation_review before the final decision is ready.

After POST or PATCH, poll GET article and inspect status, translation_status_summary, and translations[].status. Treat published, scheduled, moderation_blocked, or a clear manual-review state as the final result.

Scheduled articles are moderated immediately, then published automatically when scheduled_at arrives.

If a scheduled article loses access to scheduled publishing before its time arrives, GET article returns scheduled_paused=true and scheduled_pause_reason=account_plan. It will not publish retroactively; choose a new time or publish it manually after upgrading.

Article lifecycle

Status Meaning
draft Saved privately. Not visible to readers.
moderation_review Waiting for asynchronous moderation. The previous published version stays public while a new revision waits.
scheduled Moderation passed and the article will publish automatically at scheduled_at.
published Visible to readers.
archived Removed from public view.

Fields

  • image — Image file for the media endpoint.
  • purposearticle, channel_cover or channel_avatar.
  • watermarkauto, on or off; article images only, optional, defaults to auto.
  • alt — Optional image alt text.
  • page_slug — Optional existing article address to attach the image immediately and receive the final page media URL.
  • channel.slug — Channel address. If omitted on channel creation, Publicasta generates it from the default translation title.
  • channel.translations[].title — Channel title for this language.
  • channel.translations[].description — Optional channel description.
  • slug — Article address. If it already exists in this channel, the article is updated.
  • default_language — Primary article language.
  • statusdraft, published or scheduled on the status endpoint.
  • publish_translations — Boolean. On POST, published or scheduled multi-translation articles default to true when this field is omitted. On PATCH status for existing multilingual articles, send true to publish or schedule all translations, or false to keep secondary translations as drafts.
  • scheduled_at — Optional ISO 8601 date-time for delayed publication. Available on Pro accounts. Use it with status=published; moderation runs immediately.
  • scheduled_paused, scheduled_pause_reason — Returned by GET article when a scheduled article is paused by account plan limits.
  • translations — One or more article translations.
  • translations[].language — Translation language.
  • translations[].title — Title.
  • translations[].excerpt — Optional short intro. up to 320 characters
  • translations[].content_markdown — Markdown body. Do not include the main title as a Markdown H1.
  • translations[].content_html — HTML body instead of markdown. Do not repeat the main title as an H1.
  • translations[].seo_title, seo_description — Optional SEO fields.
  • translations[].status — Optional translation status override.

Do not send moderation_review directly unless you are debugging. The API will move published content into moderation when needed.

A translation cannot be published before the primary language is published. Save it as draft, or publish it together with the primary language using publish_translations=true.

Translation records and page-level status are separate. Always inspect translation_status_summary or translations[].status after POST, PATCH, or GET.

Recommended agent workflow

  1. Call GET channels and reuse an existing channel when it matches the task.
  2. Create a channel through POST channels if no suitable channel exists and the account limit allows it.
  3. Upload channel avatar or cover if the task asks for channel branding.
  4. Upload article images first.
  5. Copy markdown from each image response into content_markdown.
  6. Create the article with every required translation. Put the main title in title, not inside content_markdown.
  7. Use GET article and inspect status, scheduled_at, scheduled_paused, published_at, translation_status_summary, translations, and pending_revision.
  8. If status is moderation_review right after a write request, wait briefly and poll GET article again. Moderation is asynchronous.
  9. If status stays moderation_review after polling, tell the user that manual review is required or still pending.
  10. If status is scheduled and scheduled_paused is false, no extra action is needed unless the publication time must change.
  11. If scheduled_paused is true, tell the user to upgrade and then choose a new time or publish manually.

Limits

  • Article JSON body: up to 20 MB on staging.
  • Image file: up to 10 MB.
  • Image dimensions: up to 24 megapixels before resizing.
  • Uploaded images are converted to WebP and resized to 1600 px on the longest side.
  • Use explicit ISO 8601 time zones for scheduled_at, for example 2026-05-20T10:00:00+00:00.
  • API keys are shown only once when created. Store them securely.

Errors

401 Missing or invalid API key.
403 API publishing is not available on this account level yet, the key owner cannot access the channel, or the channel is read-only because it is over the current plan limit.
404 Channel or article not found.
413 Request body or uploaded file is too large.
422 Validation error. The response contains field-level details.

Minimal agent prompt

Use the Publicasta API docs at https://publicasta.com/api-docs. API key: YOUR_API_KEY. Channel: demo_project. Write an article about TOPIC, upload any generated images first, create translations in en/es/ru, then create the article as draft and report the resulting status and edit URL. Put the main article title only in translations[].title. Do not include the main title as a Markdown # heading or HTML h1 in content_markdown/content_html; use ## and ### for body sections.