Docsary
Markdown Ask Claude Ask ChatGPT
On this page

Assets

Assets are files served from /assets/<path> on the site's hostname: images, diagrams, downloads, logos. They belong to the site, so every version shares one namespace.

For usage guidance — filenames, caching, and referencing from markdown — see Images and assets.

All endpoints require an organization API key. :site accepts a slug or an id.

List assets

GET /v1/sites/:site/assets
curl -s -H "authorization: Bearer $DOCSARY_KEY" \
  "$DOCSARY_API/v1/sites/acme/assets"
{
  "assets": [
    {
      "path": "img/architecture.png",
      "content_type": "image/png",
      "size": 48213,
      "sha256": "9f2c1a..."
    }
  ]
}

Ordered by path. size is in bytes; sha256 is the hash of the stored object, which lets you skip an upload whose bytes are already there.

Upload an asset

POST /v1/sites/:site/assets/<path>

The file is the raw request body. The content-type header declares the file's own type and is stored verbatim.

curl -s -X POST "$DOCSARY_API/v1/sites/acme/assets/img/architecture.png" \
  -H "authorization: Bearer $DOCSARY_KEY" \
  -H "content-type: image/png" \
  --data-binary @architecture.png
{ "path": "img/architecture.png", "size": 48213, "sha256": "9f2c1a..." }

201 on success, whether the asset was new or replaced an existing one at the same path. It is live immediately.

A missing content-type header stores the asset as application/octet-stream, and it is served back that way — browsers will download it rather than display it. Set the header explicitly.

Path rules

The path is everything after /assets/ in the request URL, percent-decoded.

Errors

Response Cause
400 {"error":"bad path"} Path fails the pattern or contains ..
400 {"error":"malformed percent-encoding in asset path"} The path could not be decoded
400 {"error":"empty body"} Zero-length body
413 {"error":"asset too large (20MB cap)"} Body over 20 MB
413 with quota: "asset_bytes" The upload would cross your organization's storage ceiling
503 Asset storage is temporarily unavailable

An overwrite is charged only the difference in size against your storage limit, so replacing a file with one the same size always fits.

Pages, search, and navigation are unaffected by a 503 here — only asset upload and asset URLs are.

Delete an asset

DELETE /v1/sites/:site/assets/<path>
curl -s -X DELETE "$DOCSARY_API/v1/sites/acme/assets/img/architecture.png" \
  -H "authorization: Bearer $DOCSARY_KEY"
{ "deleted": "img/architecture.png" }

Removes the stored file and its record, and frees the space against your storage limit. 404 {"error":"asset not found"} if there was nothing at that path.

Nothing checks whether a page still references the asset, so a delete can leave a broken image behind. Diff GET /assets against your markdown before pruning.

How assets are served

Requests to /assets/<path> on a docs hostname are resolved against the site bound to that host, then streamed from object storage with the stored content type and:

cache-control: public, max-age=31536000, immutable

That one-year immutable promise is made to the reader's browser and cannot be revoked by a publish. When an asset's content changes, change its path. See Images and assets.