Getting Started
Dynamic Templates
Turn on Dynamic template on a route (in the Advanced section of the route editor) and its response body is rendered as a sandboxed Jinja2 template before being sent — so it can echo back parts of the request, or generate a fresh id/timestamp on every call instead of returning the same static JSON.
What's available in a template
request.method → "POST"
request.path → "/users/42"
request.query.<name> → a query string parameter
request.headers.<name> → a request header (case-insensitive)
request.body.<path> → a field from the JSON request body, dot-path for nested fields
request.raw_body → the original, unparsed request body
request.path_params.<name> → a value captured from a {name} path segment
Helper functions
{{ uuid4() }} a fresh UUID
{{ now_iso() }} the current time, ISO 8601
{{ random_int(1, 100) }} a random integer in [low, high]
random_int uses a cryptographically secure random source, not a predictable pseudo-random generator.
Example
Route: POST /users/{id}, template enabled, response body:
{
"id": "{{ request.path_params.id }}",
"name": "{{ request.body.name }}",
"request_id": "{{ uuid4() }}",
"received_at": "{{ now_iso() }}"
}
Calling it with {"name": "Ada"} against /users/42 returns the id from the URL, the name you sent, and a fresh id/timestamp pair every time.
Limits
Templates run in a sandboxed Jinja2 environment (no access to Python internals, file system, or imports) and are bounded in input length, output length, and recursion depth. A template that exceeds those limits, or fails to render, returns 422 instead of a response body.