Payloads
The article, question and notify payloads, field by field.
All bodies are JSON (application/json; charset=utf-8). Ignore fields you don't know; never reject a payload for having them.
Article
POST {publish_url}/articles
| Field | Type | Required | Notes |
|---|---|---|---|
slug | string | yes | The upsert key. One lowercase segment, see Slugs. |
title | string | yes | Display title |
body | array of blocks | yes | The page, structured |
excerpt | string or null | Short summary for cards and as a meta description fallback | |
copy | string or null | The page's markdown source. Store it as is; Pink reads it back through the GET endpoint. It may contain internal-link markers such as [text](page:12), so never render it to visitors: render body. | |
keywords | array of string | Free-form keywords | |
meta_title | string | Defaults to title | |
meta_description | string or null | Defaults to excerpt | |
audience | string or array of string | The audience the page is written for | |
goal | string or null | The page's goal, e.g. "convert" or "educate" | |
category | string or null | One category tag | |
cover_image | string (URL) or null | Hero image | |
canonical_url | string or null | Absolute canonical URL | |
noindex | boolean | Default false | |
schema_type | string | Schema.org type, default "Article" | |
related_article_ids | array of string | Your ids of related articles | |
related_question_ids | array of string | Your ids of related questions | |
status | "draft" or "published" | What Pink asks for. Store it, and report what you stored. | |
ai_generated | boolean | Default true | |
ai_model | string or null | The model that wrote the prose | |
updated_at | string (ISO 8601) | Defaults to your now() | |
site_id | integer | If present, must match the site your key belongs to, otherwise 403 site_mismatch |
Question
POST {publish_url}/questions: one Q&A page.
| Field | Type | Required | Notes |
|---|---|---|---|
slug | string | yes | The upsert key, derived from the question text |
question | string | yes | The question as displayed |
answer | array of blocks | yes | The answer, structured |
sources | array of source objects | [{ "id": "src-1", "title": "…", "url": "https://…", "accessed_at": "2026-05-19" }] | |
topics | array of string | Topic tags | |
meta_title | string | Defaults to question | |
meta_description | string or null | ||
related_question_ids | array of string | ||
related_article_ids | array of string | ||
status | "draft" or "published" | Defaults to "published" | |
ai_model | string or null | ||
updated_at | string (ISO 8601) | ||
site_id | integer | Same check as for articles |
Citations. Only answers carry sources. A citation in an answer (a sourceCitation inline node, or a literal [src-2] in a list item) renders only when sources has an entry with that id; otherwise drop the marker and the space before it. Articles never have sources, so render no citation markers in an article.
Answers sites. If your site keeps several answers per question (votes, community replies), store Pink's answer as one answer, replaced whole on each publish, with its sources. Pink never writes the question page's summary.
Notify (your site → Pink)
POST https://app.edit.pink/api/content/notify, with the same X-API-Key Pink sends you.
Call it whenever a page Pink published changes on your site: an edit, a status change, a delete. Pink uses it to stop linking other pages to a page readers can no longer reach.
| Field | Type | Required | Notes |
|---|---|---|---|
id | string | yes | Your id for the page, as you returned it at publish |
type | "article" or "question" | yes | |
status | "published" or "draft" | The state you now store. Send it whenever you know it: Pink trusts it over action. | |
action | "edited", "published", "unpublished" or "deleted" | What happened. deleted counts as unpublished. | |
slug | string | ||
updated_at | string (ISO 8601) |
With neither status nor action, Pink assumes the page is still live.
Response:
matched: false means Pink has no page with that id, which is normal for pages Pink never published. relink says whether Pink started updating the links that point at the page: "queued" when its published state changed, "skipped" otherwise (the usual answer to an edited call). You don't need to read it.