Docsary
Markdown Ask Claude Ask ChatGPT
On this page

Sites

A site holds your documentation versions, shared assets, redirects, settings, and hostnames. Each version has its own navigation.

All endpoints require an organization API key. :site accepts the site slug or its site_... id.

List sites

GET /v1/sites
curl -s -H "authorization: Bearer $DOCSARY_KEY" \
  "$DOCSARY_API/v1/sites"
{
  "sites": [
    {
      "id": "site_46269ed80042407a83242c9e94262b82",
      "slug": "acme",
      "name": "Acme Docs",
      "settings": {},
      "default_version_id": "ver_34c2a0bc33254ef6bfac1b128c1d36f6"
    }
  ]
}

Only your organization's sites are returned, ordered by slug.

Create a site

POST /v1/sites
curl -s -X POST "$DOCSARY_API/v1/sites" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: application/json" \
  -d '{"slug":"acme","name":"Acme Docs"}'
Field Type Required Notes
slug string yes Must match ^[a-z0-9][a-z0-9._-]*$. Unique within your organization.
name string no Display name. Defaults to the slug.
settings object no See Settings. Validated on write.
{ "id": "site_...", "slug": "acme", "subdomain": "acme.docsary.com" }

201 on success.

Response field Meaning
id The site_... id. Usable anywhere :site appears
slug The slug you asked for
subdomain The address allocated to this site, serving already — or null
subdomain_note Present only when subdomain is null: why no address could be allocated

Read subdomain rather than assuming it. The address is derived from your slug, but when that name is taken or reserved you are given <your-org>-<your-slug>.docsary.com instead:

{ "id": "site_...", "slug": "api", "subdomain": "acme-api.docsary.com" }

If neither name is available the site is still created, with no address:

{
  "id": "site_...",
  "slug": "guide",
  "subdomain": null,
  "subdomain_note": "no subdomain available: guide.docsary.com and acme-guide.docsary.com are taken or reserved. Delete this empty site and create it again with a different slug, or attach your own hostname on Pro."
}

A null subdomain still means the site was created. Before uploading, delete the empty site using its returned ID and recreate it with a different slug. For a populated site, contact support before deleting anything. Pro also supports your own hostname. See Domains.

Response Cause
400 {"error":"invalid slug (…)"} Malformed slug: not the pattern, or longer than 64 characters
400 with a message naming the key An unsafe settings URL or colour — see Validation
403 with quota: "sites" Your organization's site ceiling is already reached
409 {"error":"site slug already exists ..."} That slug is already used in your organization

A new site has no versions and no default version. Create a version before pushing pages — until then its address answers 404.

Read a site

GET /v1/sites/:site
{
  "id": "site_...",
  "slug": "acme",
  "name": "Acme Docs",
  "settings": { "pwa": true },
  "default_version_id": "ver_...",
  "versions": [
    { "id": "ver_...", "slug": "1.0", "name": "1.0", "position": 0 },
    { "id": "ver_...", "slug": "0.9", "name": "0.9", "position": 1 }
  ],
  "domains": [
    { "hostname": "acme.docsary.com", "is_primary": 0, "kind": "saas", "verified_at": 1756300000000 },
    { "hostname": "docs.acme.com", "is_primary": 1, "kind": "custom", "verified_at": 1756300000000 }
  ]
}

Versions are ordered by position, then slug. A domain with verified_at: null still needs verification.

404 {"error":"site not found"} if the slug or id does not resolve within your organization.

Update a site

PATCH /v1/sites/:site
Field Type Notes
name string New display name
settings object Replaces the settings object entirely. Not a merge.
default_version string Version slug or id to make the default
curl -s -X PATCH "$DOCSARY_API/v1/sites/acme" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: application/json" \
  -d '{"default_version":"2.0"}'
{ "ok": true }

Send only changed fields. An unknown site or default version returns 404. Invalid settings return 400 without applying the update. Cached responses can take time to reflect successful changes.

settings is a whole-object replace. Sending {"settings":{"pwa":true}} erases every other setting the site had. Read the site first, modify the object you get back, and send the complete result.

Delete a site

DELETE /v1/sites/:site
{
  "deleted": "acme",
  "assets_deleted": 12,
  "domains": [
    { "hostname": "acme.docsary.com", "certificate": { "status": "absent" } },
    { "hostname": "docs.acme.com", "certificate": { "status": "deleted" } }
  ]
}

Deletion removes access to the site’s versions, pages, redirects, domains, search entries, and assets. Storage and external-resource cleanup can take time. Site deletion does not cancel an organization’s paid subscription.

The domains list reports certificate cleanup for each hostname. Deletion releases the allocated docsary.com address for reuse; recreating the site does not guarantee the same address.

Your own DNS records are never touched. Removing the CNAME and TXT records you published is your call.

There is no undo or customer recovery window. Export each version and save asset files separately before deleting. Cached and downloaded copies may remain.

Settings

The settings object controls presentation and per-site feature toggles. Every key is optional.

Key Type Default Effect
name string the site's name Display name in the header, browser title, PWA manifest, and llms.txt
logo URL none Image in the header, favicon, and PWA icon
colors.primary CSS colour ink #17181c Your brand colour. Takes over the header background, link colour, active nav item, focus ring, and quote/callout rules in both light and dark mode, plus the PWA theme colour and generated favicon
colors.accent CSS colour amber #b0530a light / #eda94f dark The warning callout rule; also emitted as --accent for your own markup
footer_links array of {label, url} none Links in the page footer
posthog boolean false Pageview analytics, off unless you turn it on
pwa boolean false Offline mode — see Offline and PWA
brand_stamp boolean true The "Powered by Docsary" credit in the footer
og_image URL generated Social preview image for every page. Leave it unset and one is drawn for you per page — see Social previews
verification object of {provider: token} none Search-engine ownership tags — see Verification

Example:

{
  "name": "Acme Docs",
  "logo": "/assets/img/logo.svg",
  "colors": { "primary": "#0a7d55" },
  "footer_links": [
    { "label": "Privacy", "url": "https://acme.com/privacy" },
    { "label": "Contact", "url": "mailto:docs@acme.com" }
  ],
  "pwa": true,
  "posthog": false,
  "verification": { "google": "AbC123_dEf456" }
}

Verification

Use verification to add the ownership token requested by a search service:

Provider key Tag rendered
google google-site-verification
bing msvalidate.01
yandex yandex-verification
pinterest p:domain_verify
facebook facebook-domain-verification
ahrefs ahrefs-site-verification
norton norton-safeweb-site-verification
curl -s -X PATCH "$DOCSARY_API/v1/sites/acme"   -H "authorization: Bearer $DOCSARY_KEY"   -H "content-type: application/json"   -d '{"settings":{"verification":{"google":"AbC123_dEf456"}}}'

Supply only the token, not the provider’s complete <meta> tag. Preserve all existing settings when adding it.

Only these providers are accepted. Tokens must contain 4–256 letters, digits, or _.:=+/- characters; invalid entries return 400.

Validation

Invalid settings return 400 and reject the complete update.

URLs — logo, og_image, and each footer_links[].url must be an absolute http:, https:, or mailto: URL, or a site-relative path beginning with /, or a # fragment. Rejected: javascript:, data:, vbscript:, file:, protocol-relative //host, schemeless relative paths, and anything containing control characters.

{ "error": "unsafe settings.logo URL (allowed: http:, https:, mailto:, or a /site-relative path)" }

Colours — primary and accent must be a hex value, an rgb()/rgba()/hsl()/hsla() function, or a plain CSS colour keyword. Anything else is refused:

{ "error": "invalid settings.colors.primary (hex, rgb()/hsl(), or a CSS colour keyword)" }

Valid examples include "#0a7d55", "rgb(10 125 85)", and "rebeccapurple". Values containing } or < are rejected.

Shape — settings must be an object, colors must be an object, footer_links must be an array of objects. Each returns its own message.

Invalid stored values are not rendered as active content. An unsafe footer link becomes plain text; an unsafe logo falls back to the generated favicon.

Analytics

Visitor analytics are off by default. Set posthog: true to enable PostHog analytics or false to disable them, preserving the rest of your settings.

Analytics use page-memory identifiers and a shared project operated by Robota LLC. This does not make the data anonymous. Publishers must disclose analytics and obtain any required consent before they run for visitors. See the Privacy Policy.