Delivery
Delivery is a second, read-only API under /d/v1 that serves only published content, from a cache, to whoever holds a delivery key for that one environment.
Why a site's key gets an API of its own
A site's key ends up somewhere a reader can find it: in a server's environment, in a build log, sometimes in a browser bundle. So the key a site holds must not be able to do anything harmful. Quillet's answer is a separate API, not a restricted mode of the management API.
Without a preview token, nothing on the delivery API can reach a draft, another environment or a write. That holds by construction. It does not rest on a permission check that someone could misconfigure. A preview token opens a narrow exception for fifteen minutes. With one, the API answers one document's draft in one locale, and it lists every draft in the environment with keys, titles and tags but no bodies. None of that is ever cached. Every other answer on the delivery API is published content, so it can be cached in Redis and put behind a CDN without anyone working out who is allowed to see what.
What the delivery API serves and caches
A repeated read costs a 304 and no body, and a publish drops the entry so the next read is fresh.
What it serves
content/<key>: one document, resolved for a locale with fallback, with its references and files inlined and_metasaying what happened.list: the folders and documents under a prefix, without bodies. A site builds its navigation from this.search: the published documents that answer a question, best match first. Search index says what is indexed and how an owner rebuilds it.assets/<id>, which sits beside the environment in the path rather than under it: a file's bytes.
The cache
Delivery stores each resolved answer in Redis. Publishing or unpublishing a document deletes its entries in every locale, because any locale may fall back to it. It also deletes the entries of the documents that include it by reference, up to two levels above it, since a page holds a copy of its components' bodies. Listings are retired in one step for the whole environment. And every entry expires after an hour anyway, as a backstop for an invalidation that never arrived.
ETags and 304s
Every answer carries an ETag, which is a hash of the resolved body. It is the same whether the answer came from the cache or from Mongo, and it changes when an included component changes. Send it back in If-None-Match, and an unchanged answer comes back as a 304 with no body. Answers also carry Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=60 and Vary: Authorization, so a CDN can hold them without mixing up the answers for two keys.
What is not cached
- A read with
?at=asks for the past, so it bypasses the cache. Such reads are rare, and every timestamp would make a new entry. - A read with
?preview=returns a draft. It isno-store, carries noETagand is never a 304. - File bytes are not kept in Redis. A public file is served with a year of
immutablecaching, because its bytes never change.
How to
Read one document twice. The first request prints the response headers above the body:
curl -s -i -u '<keyId>:<secret>' \
'http://localhost:3000/d/v1/<project>/<env>/content/<key>'
Copy the ETag value, quotes and W/ included, and send it back:
curl -s -o /dev/null -w '%{http_code}\n' -u '<keyId>:<secret>' \
-H 'If-None-Match: <etag>' \
'http://localhost:3000/d/v1/<project>/<env>/content/<key>'
It prints 304. Now publish a change to that document and run the second request again. This time it prints 200, because the body changed and so did its ETag.
Limits
- A delivery key reads one environment. A site that shows two environments needs two keys.
- Invalidation follows references two levels. A deeper chain keeps showing the old component until its entry expires, which takes at most an hour.
- References are followed three levels deep by default and five at most, and one answer inlines at most 200 references and 500 files.
- By default each delivery key may make 600 reads a minute, and each address may send 1,200 requests a minute before any key is checked.
- Search has no fuzzy or prefix matching and reaches only the first 200 results.
- A private file reaches a key only when that key holds the
assets:privatescope. For any other key, itsurlisnull.
Related
- Delivery API: every route, parameter and
_metafield. - Integrating a site: when your own cache should ask again.
- Locales and fallback: what the locale resolution does.
- Reading content: the same reads through the SDK.
- Limits and quotas: the rate limits and the variables that set them.
- Search: how the search route matches and ranks.