Skip to main content
Publishing an article does three things: flips status to published, embeds the body into the vector index, and fires the article.published webhook. Unpublishing reverses the second and third.

The lifecycle

Four states, with predictable server-side effects on transition:
From → ToServer-side effects
draftpublishedEmbeddings computed; indexing_status: pending; article.published webhook
unpublishedpublishedSame as above; re-indexes
publishedunpublishedEmbeddings removed; article.unpublished webhook
publishedarchivedEmbeddings removed; article.unpublished webhook
draftarchivedNo webhook (article was never live)
Any changearticle.updated webhook
The article row itself is never deleted by a status change. archived is a soft-deletion; use DELETE /articles/{id} for a hard delete.
published_at is auto-stamped by the server on the first transition into published and is sticky from then on — re-publishing after an unpublish does not move it, and it stays set even while the article is unpublished or archived. It’s null only before the article’s first publish.

Publishing on create

Set status: "published" on the initial POST. Indexing fires as soon as the row is written.
curl https://api.awardee.dev/v1/articles \
  -X POST \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Returns & refunds",
    "slug": "returns-and-refunds",
    "content": "## Our policy\n\nReturns are accepted within 30 days...",
    "status": "published",
    "visibility": "public",
    "knowledge_base_id": "2c1b4a9f-7e8d-4a3c-9b1f-6e5d4c3b2a1f"
  }'
The response returns immediately with indexing_status: "pending". The pipeline runs out-of-band.

Publishing a draft

PATCH the article with status: "published". The same server-side effects fire as on a create-with-publish.
curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e \
  -X PATCH \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{ "status": "published" }'

Unpublishing

PATCH with status: "unpublished" or status: "archived". Embeddings are removed asynchronously.
curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e \
  -X PATCH \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  -H "Content-Type: application/json" \
  -d '{ "status": "unpublished" }'
Embedding removal is enqueued, not synchronous. There is a short window after the response in which the article may still appear in search results.

Reading the index status

indexing_status is your signal that the article is retrievable. The five states:
ValueMeaning
not_startedNever indexed. Either a draft or a brand-new published article that hasn’t dequeued yet.
pendingEnqueued, awaiting a worker.
processingA worker is actively embedding.
indexedEmbeddings written. Chatbots and search can see it.
failedPipeline error. The article won’t appear in retrieval until you re-publish or edit the content.
Poll the article detail endpoint after publishing if you need a hard signal:
curl https://api.awardee.dev/v1/articles/8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e \
  -H "Authorization: Bearer aw_live_4f8a3c7e2d1b9a5c6f8e3d2c1b4a9f7e" \
  | jq '.indexing_status'
For non-interactive flows, subscribe to the article.published webhook instead of polling. The webhook fires when indexing is kicked off, not when it completes — for a “ready to serve” signal, poll indexing_status after receiving the webhook.

Webhook signals

Four events frame the publish boundary and the indexing pipeline. Subscribe under Dashboard → Webhooks.
EventFires on
article.publishedTransition into published. Indexing has been enqueued.
article.unpublishedTransition out of published (to unpublished or archived).
article.indexedEmbedding pipeline finished. The article is now retrievable.
article.indexing_failedEmbedding pipeline errored. indexing_status is failed.
Use article.indexed as your “ready to serve” signal instead of polling indexing_status. The article.published webhook fires when indexing is kicked off, not when it completes.
Payload shape:
{
  "type": "article.published",
  "data": {
    "orgId": "8f3a9d2e-1b4c-4f5d-9e8a-7c3b2a1d0f9e",
    "orgName": "Acme Inc",
    "articleId": "1b4c4f5d-9e8a-7c3b-2a1d-0f9e8f3a9d2e",
    "title": "Returns & refunds",
    "slug": "returns-and-refunds",
    "visibility": "public",
    "language": "en",
    "publishedAt": "2026-05-22T14:01:58+00:00"
  }
}
See Webhook events for delivery, signing, and retries.