Postelio
EN
English Русский Español Deutsch Français Italiano 中文
Home
About
Features
Pricing
Contact
Articles
Get started

Postelio Website Publishing API Specification

Technical requirements for connecting a custom website to Postelio for automated SEO article publishing.

This documentation describes the requirements for integrating a website with Postelio to enable automated SEO article publishing.

Postelio v1 trusts the receiving site's contract. Postelio does not currently fetch or verify sitemap inclusion after publishing.

Table of contents

  1. Overview
  2. Base requirements
  3. Authentication
  4. Publishing endpoint
  5. Article slug
  6. external_id and idempotency
  7. Successful response
  8. HTTP status contract
  9. Article page SEO contract
  10. Sitemap
  11. robots.txt
  12. Atomic publication semantics
  13. Failure behavior
  14. Security requirements
  15. Reference pseudocode
  16. Acceptance checklist
  17. Scope limitations

Overview

The Website channel is for custom websites that implement Postelio Website Publishing API v1.

Postelio is the HTTP client. Your site is the receiving API. After a workspace connects a Website channel, Postelio publishes structured SEO articles to:

POST {endpoint_url}/api/postelio/v1/articles/

A successful Postelio publication means all of the following are true before you return 200 or 201:

  • the article is persisted;
  • its public canonical HTTPS URL is live;
  • the page is indexable;
  • SEO metadata is rendered;
  • the article is already included in the site's sitemap;
  • the API returns a stable remote id and canonical url.

This specification is implementation-neutral. It does not prescribe a CMS, framework, or hosting model.

Base requirements

  • The publish endpoint and every published article URL must use HTTPS.
  • Every published article must have a public page (not behind login).
  • Every article must have a stable canonical URL. Do not change that URL after a successful response.
  • Article pages must be indexable by search engines (not blocked by noindex or robots rules that hide the page).
  • Sitemap integration is mandatory for Website channel compatibility.
  • robots.txt must reference the sitemap or sitemap index.

Authentication

Postelio sends a Bearer token on every publish request:

Authorization: Bearer <api_token>

Requirements:

  • Treat api_token as a secret.
  • Do not accept the token from the query string, request body, or a public URL.
  • Compare the presented token against the stored secret using a constant-time comparison.
  • Store the token outside source code, using environment-specific secret management.

Reject missing, empty, or invalid credentials with 401 or 403. Do not echo the token in responses or error bodies.

Publishing endpoint

POST /api/postelio/v1/articles/

If the Website channel endpoint_url includes a base path, Postelio joins it structurally:

Configured endpoint_url Request URL
https://www.example.com https://www.example.com/api/postelio/v1/articles/
https://www.example.com/postelio https://www.example.com/postelio/api/postelio/v1/articles/

Request type: multipart/form-data.

Postelio waits up to 15 seconds for the HTTP response. Finish persistence, public-page publication, and sitemap inclusion before you respond. Do not require a redirect; Postelio does not follow redirects.

Request fields

Postelio currently sends exactly these fields. Do not require additional fields for v1 compatibility. Postelio does not send a slug field in API v1. The receiving website generates the slug from the article title. See Article slug.

Field Type Required Limit Meaning
external_id text yes opaque unique string generated by Postelio (v1 sends a UUID) Idempotency key for this publication
title text yes ≤ 200 characters Article title and page H1
body text yes HTML; generated within the content format character limit (default 12,000 characters for the global website article format) Article body HTML
meta_title text yes ≤ 70 characters HTML <title>
meta_description text yes ≤ 200 characters HTML meta description
excerpt text yes ≤ 500 characters Short summary / excerpt
language text yes short language code, currently up to 8 characters (example: en) Article language
image file no at most 1 file; image/jpeg, image/png, or image/webp; prepared size ≤ 10 MiB Optional hero / featured image

body is article body HTML. Render it safely according to your trusted integration model. The article title is the page H1; body should not require an additional H1.

image is omitted when Postelio has no image for the publication. When present, it is a standard multipart file field named image.

Article slug

The receiving website generates the slug from the article title. These rules are mandatory for Website Publishing API v1.

Postelio does not send a slug field in API v1. Do not require one, and do not reject a valid v1 request because slug is absent.

The slug is the stable path segment of the canonical article URL. This specification does not prescribe the rest of the URL path.

Requirements

  • Slugs must contain only lowercase ASCII letters (a-z), digits (0-9), and hyphens (-).
  • Non-Latin characters must be transliterated into Latin ASCII.
  • Accented Latin characters must be normalized to unaccented ASCII letters. Strip diacritics (Ü / ü becomes u). Do not expand them (ü must not become ue).
  • Remove unsupported characters.
  • Replace whitespace with hyphens so separate words stay separate.
  • Collapse repeated hyphens into a single hyphen.
  • Remove leading and trailing hyphens.
  • Slugs must not be empty.
  • When transliteration produces an empty slug, use the deterministic fallback article. Do not use a random value, a timestamp, or external_id.
  • Slug collisions must produce unique URLs without overwriting existing articles.
  • Once assigned, the canonical URL and slug must remain stable.

Generation steps

Apply these steps in order to title:

  1. Transliterate non-Latin letters to Latin ASCII.
  2. Normalize accented Latin letters by removing diacritics.
  3. Lowercase ASCII letters.
  4. Replace each whitespace run with a single hyphen.
  5. Remove every remaining character that is not a-z, 0-9, or -.
  6. Collapse repeated hyphens.
  7. Remove leading and trailing hyphens.
  8. If the result is empty, use article.

The following results are required when that slug is not already assigned to another article:

Title Slug
Как выбрать брокера kak-vybrat-brokera
Über den Devisenmarkt uber-den-devisenmarkt

In the Russian example, ы transliterates to y and the soft sign ь is omitted.

Collisions

If the candidate slug is already assigned to a different article, append the smallest integer suffix starting at 2 that yields an unused slug: kak-vybrat-brokera-2, then kak-vybrat-brokera-3, and so on.

Apply the same suffix rule to the fallback slug article.

Do not overwrite the existing article. Do not change its slug or canonical URL. Do not reuse its remote id.

A slug collision is only a URL constraint. It does not mean the two publications are the same article.

Stability

Once assigned, keep that slug and canonical URL for the article. An idempotent replay must return the stored URL and must not generate the slug again, even if the title would now produce a different base slug or a different collision suffix.

external_id and idempotency

external_id is created by Postelio. The receiving site must store it.

  • It must be unique in the receiving site / integration scope.
  • A safe retry with the same external_id must not create a duplicate article.
  • Do not treat Postelio-internal identifiers as part of this contract. external_id is the only publication identity Postelio sends.

Required behavior:

Situation Response
First valid request for an external_id 201 Created and persist the article
Same external_id + same immutable article 200 OK and return the existing article id / url
Same external_id but conflicting immutable content 409 Conflict

After the first successful publication, the article content bound to that external_id is immutable. Compare the incoming payload against the stored article. If it matches, return the existing article. If it differs, return 409. Do not overwrite the existing article.

Publication identity

  • A retry with the same external_id and identical immutable content must return the existing article with HTTP 200.
  • The existing article ID and canonical URL must be reused.
  • Never regenerate the slug during an idempotent replay.
  • The same external_id with different immutable content must return HTTP 409.
  • A previously unseen external_id represents a new article.
  • Do not deduplicate different external_id values by title, slug, body, or canonical URL.
  • Successor republish in Postelio creates a new external_id and therefore a new remote article. Store that article separately. Do not replace an earlier article because the title, body, slug, or canonical URL text matches.

Successful response

Return a JSON object on 200 and 201.

Required fields:

Field Rules
id JSON string (no integer coercion). Non-empty after trim. Maximum 128 characters. This is your stable remote article id.
url Absolute https URL. Maximum 2048 characters. No username/password in the URL. Hostname must be a valid DNS name or IP literal. DNS hostnames: no trailing dot; labels 1–63 characters matching [a-z0-9] with optional internal hyphens; total hostname length ≤ 253. Query string and fragment are allowed.

Optional field:

Field Rules
status Optional. If you send it, Postelio stores it only when the value is one of: published, created, ok, success, updated. Other values are ignored. You may omit status.

Extra JSON keys are ignored. Do not put secrets, tokens, or debug dumps in the success body.

Example:

{
  "id": "article_7f3c2a91",
  "url": "https://www.example.com/blog/seo-article-slug/"
}

Example with optional status:

{
  "id": "article_7f3c2a91",
  "url": "https://www.example.com/blog/seo-article-slug/",
  "status": "published"
}

url must be the public canonical HTTPS URL of the live article page.

HTTP status contract

Status Meaning Postelio behavior
201 Created New article created and fully published Success when the JSON body is valid
200 OK Idempotent replay of the same external_id and same immutable article Success when the JSON body is valid
400 Bad Request Invalid payload Permanent failure
401 Unauthorized Missing or invalid credentials Permanent failure
403 Forbidden Credentials rejected Permanent failure
409 Conflict external_id already exists with different immutable content Permanent failure
429 Too Many Requests Rate limited Retryable. A numeric Retry-After value in seconds is honored
5xx Temporary server error Retryable
3xx Redirect Permanent failure. Postelio does not follow redirects

Other 4xx responses are treated as permanent failures. Do not rely on a redirect from HTTP to HTTPS, a trailing-slash redirect, or a CDN challenge. Answer 200 or 201 at the exact request URL.

Article page SEO contract

These requirements apply to the URL returned in the success response.

Requirements

  • Public https URL
  • HTTP 200 for ordinary visitors and crawlers
  • Page is not blocked by noindex
  • title is rendered as the article H1
  • meta_title is rendered as the HTML <title>
  • meta_description is rendered as the HTML meta description
  • Canonical URL points to the returned article URL
  • Language is exposed appropriately by the site (for example lang on <html> or equivalent)
  • Article body is visible in the rendered HTML
  • If image was supplied, render it appropriately on the article page

Recommendations

These are recommended for SEO quality. They are not currently verified by Postelio:

  • Open Graph metadata (og:title, og:description, og:url, og:image when an image exists)
  • Article structured data / JSON-LD
  • Accurate published and modified timestamps
  • Semantic HTML (<article>, heading hierarchy after H1)

Sitemap

Sitemap integration is mandatory for Website channel compatibility.

Requirements

  • Every successfully published article must be included automatically in the site's sitemap.
  • Do not require a manual sitemap update for normal Postelio publishing.
  • The article must already be represented in the sitemap before the API returns successful 200 or 201.
  • The sitemap must be publicly reachable over HTTPS.
  • The sitemap may be a sitemap file or a sitemap index.
  • This specification does not prescribe one fixed sitemap path.
  • robots.txt must reference the sitemap or sitemap index.
  • Each article <loc> must equal the canonical article URL returned as url.
  • <lastmod> is recommended when the timestamp is correct and current.

Example URL-set entry:

<url>
  <loc>https://www.example.com/blog/seo-article-slug/</loc>
  <lastmod>2026-09-13</lastmod>
</url>

Important

Postelio v1 does not fetch or verify sitemap inclusion after publishing. The receiving site is responsible for honoring this contract.

robots.txt

robots.txt must include a Sitemap directive pointing at your actual sitemap or sitemap index location. Do not assume /sitemap.xml.

User-agent: *
Allow: /

Sitemap: https://www.example.com/<actual-sitemap-location>

Examples of valid locations include /sitemap.xml, /sitemap_index.xml, or another HTTPS path your site actually serves.

Atomic publication semantics

Required receiving-side sequence, conceptually:

  1. Authenticate the Bearer token.
  2. Validate the payload (required fields, types, sizes).
  3. Resolve external_id.
  4. Create and persist the article, assigning a unique slug from the title, or reuse the existing article, its slug, and its canonical URL when the retry is identical.
  5. Make the public canonical page live.
  6. Ensure the sitemap includes that canonical URL.
  7. Only then return 201 (create) or 200 (identical replay).

For an idempotent replay, return the existing article only after confirming it is still available under this contract: public canonical page live, indexable, SEO metadata rendered, and sitemap still includes it.

This specification does not mandate a particular database transaction model. Use whatever atomicity your site can implement so that a success response is not returned unless the full contract is met.

Failure behavior

  • Return a non-2xx status if the article cannot be published fully.
  • Do not return 201 or 200 if persistence, the public page, or sitemap inclusion failed.
  • Use 409 only for an external_id conflict with different immutable content.
  • Use 429 for rate limiting.
  • Use 5xx for temporary server failures.
  • Use 400 for invalid or incomplete payloads.
  • Use 401 or 403 for authentication or authorization failure.

Keep error responses stable and free of secrets. You may return JSON, but Postelio does not require a specific error body schema in v1.

Security requirements

  • HTTPS only
  • Bearer token authentication
  • Do not log the Authorization token, api_token, or other secrets
  • Validate input sizes and types
  • Protect the receiving endpoint from public anonymous write access
  • Handle HTML/content safely according to the site's trust model
  • Do not echo the Authorization token in responses or errors
  • Return stable error responses without secrets

The Website channel is a trusted integration: Postelio sends article HTML your site asked to receive. Sanitize or render that HTML in a way that is safe for your readers.

Reference pseudocode

authenticate(request)
validate_payload(request)

existing = find_article_by_external_id(request.external_id)

if existing:
    if same_immutable_content(existing, request):
        ensure_public_page_and_sitemap_are_valid(existing)
        return 200 {id: existing.id, url: existing.canonical_url}
    return 409

article = create_article(request)
article.slug = unique_slug_from_title(request.title)
publish_canonical_page(article)
include_in_sitemap(article)

return 201 {id: article.id, url: article.canonical_url}

unique_slug_from_title follows Article slug. Call it only when creating an article. An identical replay returns the stored id and canonical URL and does not generate the slug again. A different external_id always creates a separate article, even when the generated slug needs a collision suffix.

Acceptance checklist

Use this list when implementing or reviewing a receiving site:

  • [ ] HTTPS endpoint
  • [ ] Bearer authentication
  • [ ] POST /api/postelio/v1/articles/
  • [ ] Exact request fields supported (external_id, title, body, meta_title, meta_description, excerpt, language, optional image)
  • [ ] No slug request field; the receiving site generates the slug from the title
  • [ ] Slug contains only lowercase ASCII letters, digits, and hyphens
  • [ ] Non-Latin characters transliterated into Latin ASCII
  • [ ] Accented Latin characters normalized
  • [ ] Unsupported characters removed, repeated hyphens collapsed, leading and trailing hyphens removed
  • [ ] Slug is never empty; empty transliteration uses the deterministic fallback article
  • [ ] Slug collisions produce unique URLs without overwriting existing articles
  • [ ] Once assigned, the canonical URL and slug remain stable
  • [ ] external_id uniqueness
  • [ ] Idempotent 200 replay reuses the existing article ID, canonical URL, and slug
  • [ ] Never regenerate the slug during an idempotent replay
  • [ ] 409 when the same external_id has different immutable content
  • [ ] A previously unseen external_id creates a new article
  • [ ] Different external_id values are not deduplicated by title, slug, body, or canonical URL
  • [ ] Successor republish creates a new external_id and a new remote article
  • [ ] Stable public HTTPS canonical URL
  • [ ] H1 / title / meta / canonical rendered
  • [ ] Page indexable
  • [ ] Sitemap automatic
  • [ ] robots.txt references sitemap
  • [ ] Successful response id / url valid
  • [ ] Optional image handled
  • [ ] Redirects not required
  • [ ] Secrets not logged

Scope limitations

Website Publishing API v1 does not provide:

  • update article
  • delete article
  • multi-image publishing
  • sitemap verification by Postelio
  • a client-supplied slug field

Do not assume future endpoints or callbacks. Implement the current create/idempotent-replay contract only.

Postelio

AI-powered content creation and publishing on autopilot, across languages, channels, and social networks.

Legal
  • Privacy Policy
  • Terms of Service
  • Legal Notice
  • Third-Party Services
  • Cookie settings

© 2026 Rannev Dmitry. All rights reserved.

We use optional analytics cookies to understand how Postelio is used. Until you accept, measurement stays cookie-free. Rejecting keeps it cookie-free rather than stopping measurement. Necessary cookies always remain active.