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.
- Must match
^[a-z0-9][a-z0-9._/-]*$, case-insensitively: letters, digits, dots, underscores, hyphens, and slashes. - Must begin with a letter or a digit.
- May not contain
..anywhere.
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.