> ## Documentation Index
> Fetch the complete documentation index at: https://docs.buttons.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# URL and body templates

> How {{arg}} placeholders work in HTTP buttons with context-aware encoding.

HTTP buttons use `{{name}}` placeholders in the URL and request body. When you press the button, each placeholder is replaced with the corresponding argument value. The substitution is context-aware: the encoding applied depends on where in the request the placeholder appears.

<Note>
  Placeholders are only allowed in the **path, query, and fragment** of the URL — never in the scheme or host. A host- or scheme-templated URL is rejected when the button is created, because letting an argument choose the target host would defeat host-locking. The scheme+host prefix is therefore never substituted at press time.
</Note>

## How substitution works

At press time, Buttons walks the URL and body and replaces every `{{name}}` with the value of the `name` argument. The encoding is chosen based on position:

| Location | Encoding |
| - | - |
| URL path segment (after the host, before `?`) | `url.PathEscape` |
| URL query parameter (after `?`) | `url.QueryEscape` |
| URL fragment (after `#`) | `url.PathEscape` |
| JSON body (`Content-Type: application/json`, `text/json`, or unset) | JSON string escape (`\"`, `\\`, control chars) |
| Form body (`Content-Type: application/x-www-form-urlencoded`) | `url.QueryEscape` |
| Any other body `Content-Type` | Raw (no encoding) |

The body's `Content-Type` is matched case-insensitively, and any `; charset=...` suffix is ignored. When no `Content-Type` header is set, the body is treated as JSON.

## Examples

### URL path injection

A user passes `../../etc/passwd` as the `file_id` argument:

```
Template:   https://api.example.com/files/{{file_id}}/download
Raw value:  ../../etc/passwd
Result:     https://api.example.com/files/..%2F..%2Fetc%2Fpasswd/download
```

`PathEscape` encodes the slashes, so the traversal attempt becomes a literal (non-functional) path segment.

### URL query injection

A user passes `q=real&admin=true` as the `query` argument:

```
Template:   https://api.example.com/search?q={{query}}&limit=10
Raw value:  real&admin=true
Result:     https://api.example.com/search?q=real%26admin%3Dtrue&limit=10
```

`QueryEscape` encodes `&` and `=`, so the injected parameter never becomes a second query key.

### JSON field injection

A user passes `","role":"admin` as the `username` argument:

```
Template:   {"username": "{{username}}", "action": "read"}
Raw value:  ","role":"admin
Result:     {"username": "\",\"role\":\"admin", "action": "read"}
```

JSON string escaping turns the quotes and commas into escape sequences, preventing the injected text from breaking out of the string field.

## Headers

Header values are **static** — `{{arg}}` substitution is **not** applied to them. Whatever you set with `--header "Key: Value"` is sent verbatim, so a header containing `{{token}}` would be transmitted with that literal text, not an argument value. Put fixed values like bearer tokens and API keys directly in the header; only the URL and body are templated.

<Note>
  A `{{name}}` that doesn't match any declared argument is left in the output unchanged — there is no separate escape syntax for literal double braces. If you need a literal `{{` in a URL or body, just don't declare an argument by that name.
</Note>

## Raw body types

For bodies with a `Content-Type` other than `application/json`, `text/json`, or `application/x-www-form-urlencoded`, Buttons inserts values without encoding. Use this only when you control the full body format and know the values are safe.

<Warning>
  Raw substitution provides no injection protection. If the body format has its own injection risks (e.g. XML, LDAP query syntax), validate or sanitize argument values before they reach the button.
</Warning>

## Related

* [HTTP API buttons](/buttons/http-api) — full flag reference for URL, method, headers, body
* [Template encoding](/security/template-encoding) — detailed security analysis of each encoding context
* [Security overview](/security/overview) — threat model and assumptions


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.