API & integrations

Publishing a release with change sets over the API

Early preview: Publishing a release with change sets over the API is currently in early preview. This feature is under active development, and its behavior, endpoints, request and response formats, and availability may change in the future without prior notice. We recommend avoiding reliance on this feature for critical production workflows until it reaches general availability.

A change set is a release folder. You put staged article changes, unpublished articles or unpublished translations, and publish the whole thing in one action when your production update is out — so your documentation goes live with the feature it describes, rather than before or after it.

Nothing in an open change set is visible to readers. Removing an item never deletes the work, and deleting a change set never deletes any content — a change set only ever points at work that exists on its own.

Change sets are included in Catalyst, and build on staged changes — stage your article edits first, then group them here.

Two things worth knowing before you build against this

Publishing answers 202, never 200. A release outlives the request that starts it. A 200 would tell your deploy script the documentation is live when the job has not begun, so the response is 202 Accepted with a status_url to poll.

Adding items can answer 207. If part of your batch cannot be added — an article with nothing staged, say — the rest still lands and the response tells you which ids did not. Rejecting the whole batch would make a release depend on every article being in exactly the state you predicted.

Create a release

POST/v1/change-sets

Create a change set. Name it after the thing it ships with — that is what you will look for later.

GET/v1/change-sets

List change sets on your site, newest activity first.

GET/v1/change-sets/{changeSetId}

Read one change set with its items and its readiness summary.

Fill it

Send article ids and category ids together. Articles contribute their staged changes (every staged language), or a publish flip if they have never been published. Categories contribute a visibility change, which is how you keep a whole section hidden until launch.

POST/v1/change-sets/{changeSetId}/items

Add articles and categories to a release. Answers 207 when part of the batch could not be added.

DELETE/v1/change-sets/{changeSetId}/items/{itemId}

Take an item out of the release. The staged changes or article it pointed at are kept.

Check it before you ship

readiness separates two very different things, and the distinction is the point of the field:

  • Blockers stop a publish and cause a 422. conflict means the live article changed after the edits were staged; article_gone and category_gone mean the work was deleted.

  • Warnings never stop anything — only you know whether they are intentional. locale_gap means an article will publish untranslated; staged_not_added means an article has changes in another language that are not part of this release.

Publish it

POST/v1/change-sets/{changeSetId}/publish

Publish the release, or schedule it. Always answers 202 — the run outlives the request.

DELETE/v1/change-sets/{changeSetId}/schedule

Cancel a pending schedule. The contents are untouched.

Follow the run

Branch on done, not on the status string. It is computed for you so a polling loop always terminates — including when a release ends up only partly applied.

GET/v1/change-sets/{changeSetId}/status

Poll a release in progress. Read scope is enough — watching is not changing.

Partial publication is normal

Items apply in independent transactions, so a release can end up partly applied — and the API says so honestly rather than pretending otherwise:

  • published — every item applied.

  • partially_published — some applied, some did not. Check items[].error.

  • failed — nothing applied.

Retrying is just publishing again. Items that already applied are skipped, so nothing is published twice and no watcher is notified twice.

A worked example

Ship the documentation for a feature at the moment the feature goes out:

API=https://api.helpcenter.io/v1
KEY=your-read-write-token

# 1. Open the release.
SET=$(curl -sX POST "$API/change-sets" -H "apikey: $KEY" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Boards v2"}' | jq -r .change_set.id)

# 2. Fill it with staged articles and the hidden category.
curl -X POST "$API/change-sets/$SET/items" -H "apikey: $KEY" \
  -H 'Content-Type: application/json' \
  -d '{"article_ids":[4821,4822],"category_ids":[77]}'

# 3. Check nothing is blocking it.
curl -s "$API/change-sets/$SET" -H "apikey: $KEY" | jq .change_set.readiness

# 4. Ship it, and wait for the run to finish.
curl -X POST "$API/change-sets/$SET/publish" -H "apikey: $KEY"
until [ "$(curl -s "$API/change-sets/$SET/status" -H "apikey: $KEY" | jq -r .done)" = true ]; do
  sleep 3
done

Housekeeping

PATCH/v1/change-sets/{changeSetId}

Rename a change set or change its description. Allowed after publishing too — the name is how you find the release in history.

DELETE/v1/change-sets/{changeSetId}

Delete the release folder. No content is deleted — staged changes stay staged and unpublished articles stay unpublished.

Errors

  • 401 — the apikey header is missing or unknown.

  • 402 — change sets are not included in this site's plan.

  • 403 — a read-scoped token attempted a write.

  • 404 — the change set belongs to another site, or does not exist.

  • 409 — the change set is publishing or already published.

  • 422 — validation failed, or readiness blocked the publish.

For the staged-article endpoints these releases are built from, see Staging article changes over the API.

Was this article helpful?

Recent Articles

Articles you view will appear here.