Get a Dynamic URL
Authorization
ApiKeyAuth API key from Settings → API Keys.
In: header
Path Parameters
Query Parameters
Response Body
curl -X GET "https://example.com/api/v1/dynamic_urls/string"Create a Dynamic URL POST
Gives a template one permanent, embeddable address. The data travels in the URL, signed, and the document is rendered the first time someone asks for it — no API call per document. **One Dynamic URL serves every recipient.** The same address renders a certificate for each student or an invoice for each customer; only the payload differs. Create a second one when you want separate controls — its own expiry, or a signing secret revocable without touching the first — never one per recipient. The response includes the signing secret and a `sample_url` that renders as-is. The secret is derived rather than stored, so it can be read again later with `include_secret=true` — losing it does not force a rotation. **Signing your own:** HMAC-SHA256 over `{token}/{extension}?{query}`, with the query sorted and `s` left out. No hostname and no path, so a signature survives the URL moving. The encoding matters as much as the algorithm — a mismatch returns the same bare `403 Invalid signature` as a wrong secret, which sends you to debug the HMAC: - `d` is **base64url** (`-` and `_`, never `+` and `/`) with padding `=` stripped. Standard base64 is the trap: it works until a payload happens to contain a `+` or a `/`, so it ships and then fails for some recipients. - The signature is **lowercase hex**. - In `params` mode, **form-encode each value and sign that**: a space is `+`, not `%20`, and reserved characters are percent-encoded (`&` becomes `%26`) — exactly what `URLSearchParams` produces. Any value works; `Ravi & Co` signs and verifies. Signing `%20` against a request that carries `+` does not. Lists still need `encoded` mode.
Update a Dynamic URL PATCH
Change the name, caps, expiry, cache TTL, formats or pinned version. `pinned_version` freezes what this URL serves to one template version, so editing the template does not change a link that is already embedded somewhere you cannot edit. `null` returns it to always-latest, which is the default. Numbers come from `GET /v1/templates/{id}/versions`. Setting `status` to `disabled` stops it serving and purges the edge cache. Until that purge lands, an already-cached document may still be served — the URL is refused at the origin either way.