Docsary
Markdown Ask Claude Ask ChatGPT
On this page

Versions

A version holds pages. Every page belongs to exactly one version, and a site's default version serves from unprefixed URLs. For the behaviour this drives, see Versions.

All endpoints require an organization API key. :site and :ver each accept a slug or an id.

List versions

GET /v1/sites/:site/versions
curl -s -H "authorization: Bearer $DOCSARY_KEY" \
  "$DOCSARY_API/v1/sites/acme/versions"
{
  "versions": [
    { "id": "ver_...", "slug": "2.0", "name": "2.0", "position": 0 },
    { "id": "ver_...", "slug": "1.0", "name": "1.0", "position": 1 }
  ],
  "default_version_id": "ver_..."
}

Ordered by position, then slug. Compare default_version_id against the list to find which one is current.

Create a version

POST /v1/sites/:site/versions
curl -s -X POST "$DOCSARY_API/v1/sites/acme/versions" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: application/json" \
  -d '{"slug":"2.0","name":"2.0","position":0}'
Field Type Required Notes
slug string yes Must match ^[a-z0-9][a-z0-9._-]*$. Unique within the site. Becomes the URL prefix when this version is not the default.
name string no Label shown in the version switcher and the old-version banner. Defaults to the slug.
position number no Sort position in the version switcher and in list responses. Defaults to 0.
{ "id": "ver_...", "slug": "2.0" }

201 on success.

The first version created on a site automatically becomes its default version. Subsequent ones do not; promote them with PATCH /v1/sites/:site and a default_version field.

Rejections

Response Cause
400 {"error":"invalid slug"} Slug does not match the pattern
400 {"error":"reserved slug"} Slug is one of the paths the serving router owns — assets, search, v1, robots.txt, sitemap.xml, llms.txt, llms-full.txt, manifest.webmanifest, sw.js, __api, __health, __bench
403 with quota: "versions_per_site" This site's version ceiling is already reached
409 {"error":"version slug already exists"} The site already has this slug
409 {"error":"slug would shadow existing page URLs at that path"} Some version of this site already has a page at that path, or beneath it

The shadowing check is what keeps version prefixes and page paths from ever colliding. If any version has a page at /next or /next/anything, a version slug of next is refused. The rule is enforced in the other direction too — an import rejects a page whose first path segment matches a version slug.

The new version appears in the switcher on every page of the site straight away.

Update a version

PATCH /v1/sites/:site/versions/:ver
Field Type Notes
slug string New slug. Same pattern and reserved-word rules as creation.
name string New display label.
position number New sort position.
curl -s -X PATCH "$DOCSARY_API/v1/sites/acme/versions/1.0" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: application/json" \
  -d '{"name":"1.0 (legacy)","position":9}'
{ "ok": true }

400 {"error":"invalid or reserved slug"} for a bad slug. 404 if the site or version does not resolve. The change is live immediately.

Changing a slug changes every URL of a non-default version, and nothing is redirected automatically. Existing links to /1.0/guide/install break the moment the slug becomes legacy. Add redirects for the paths that matter, or rename before the version has an audience.

The shadow check that runs at creation is not re-run on a slug change.

Renaming with name is free — it changes only the label in the switcher and banner.

Delete a version

DELETE /v1/sites/:site/versions/:ver
curl -s -X DELETE "$DOCSARY_API/v1/sites/acme/versions/0.9" \
  -H "authorization: Bearer $DOCSARY_KEY"
{ "deleted": "0.9" }

Deletes the version, all of its pages, and its search index entries. Immediate, with no undo — export first if the content matters.

If the deleted version was the site's default, the site is left with no default version. Serving falls back to the first version by position, so the site keeps working, but nothing marks a version as current until you set one. Promote a replacement:

curl -s -X PATCH "$DOCSARY_API/v1/sites/acme" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: application/json" \
  -d '{"default_version":"1.0"}'

The deleted version's pages stop being served immediately.