Skip to content

Cross-posting and importing

An article may live both here and somewhere else. If the original stays primary, two fields carry the whole arrangement:

Terminal window
POST /v1/articles
{
"title": "",
"content": "",
"canonical_url": "https://your-site.example/the-original",
"authorship_disclosure": "human_authored"
}
POST /v1/articles/{id}/publish
{ "revision_id": "", "published_at": "2026-04-11T08:00:00.000Z" }

The imported article gets a fresh Orator identifier. The external URL is an attribute of the article, never its identity — see Identifiers.

Not today’s. It must be in the past, and it is set once. An import that stamps everything with the import date produces a history that is wrong in a way nothing can repair afterwards.

Derive the Idempotency-Key from the source document — its path, its hash, its permalink — rather than generating a fresh one per attempt. Then a run that dies halfway resumes instead of duplicating everything it already did.

Idempotency-Key: import-blog-2026-04-11-pool-halving-v1

Import through the API, never into the database

Section titled “Import through the API, never into the database”

This is a rule the platform holds itself to as well: content arrives through the public API, including its own. An insert straight into storage skips validation, quotas, the outbox, the search index and the event that tells followers something was published — and produces an article that exists but that half the system does not know about.

The repository ships node scripts/import.mjs <manifest.json> for this, which is a client of the public API like any other.

authorship_disclosure describes how the text was produced, not how it arrived. A human essay written three years ago and imported today is human_authored. Importing does not launder it into anything else, and the server checks the claim against who is publishing.