Skip to main content

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.

API buttons send an outbound HTTP request every time you press them. The URL, method, headers, and body are all stored in the button spec.

Basic GET

buttons create get-user \
  --url 'https://api.example.com/users/{{user_id}}' \
  --method GET \
  --arg user_id:string:required \
  -d "Fetch a user by ID"
Press it:
buttons press get-user --arg user_id=42
The {{user_id}} placeholder in the URL path is replaced with the value you pass. Values in path segments are encoded with PathEscape to prevent injection.

POST with a body

buttons create create-issue \
  --url 'https://api.github.com/repos/{{owner}}/{{repo}}/issues' \
  --method POST \
  --header 'Authorization: Bearer {{token}}' \
  --header 'Content-Type: application/json' \
  --body '{"title": "{{title}}", "body": "{{description}}"}' \
  --arg owner:string:required \
  --arg repo:string:required \
  --arg token:string:required \
  --arg title:string:required \
  --arg description:string:optional \
  -d "Open a GitHub issue"

Context-aware encoding

{{arg}} substitution is aware of where in the request the value appears:
LocationEncoding applied
URL path segmenturl.PathEscape
URL query parameterurl.QueryEscape
JSON body (Content-Type: application/json)JSON string escape
Form body (Content-Type: application/x-www-form-urlencoded)url.QueryEscape
This means a value like O'Reilly & Sons is safe to pass into a JSON body or a query string without manual escaping. See template encoding for the full details.

Custom headers

Pass --header once per header. Headers support {{arg}} substitution just like the URL and body:
buttons create list-repos \
  --url 'https://api.github.com/users/{{username}}/repos' \
  --header 'Authorization: Bearer {{token}}' \
  --header 'Accept: application/vnd.github+json' \
  --arg username:string:required \
  --arg token:string:required

Response size limit

Responses are capped at 10 MB by default. Override with --max-response-size (value in bytes):
buttons create large-export \
  --url 'https://api.example.com/export' \
  --max-response-size 52428800 \
  -d "Download up to 50 MB"

Private network targets

By default, HTTP buttons block requests to private network ranges (loopback, RFC 1918, link-local). To allow a localhost or intranet target, pass --allow-private-networks at create time:
buttons create local-health \
  --url 'http://127.0.0.1:8080/health' \
  --allow-private-networks \
  -d "Check local service health"
Only use --allow-private-networks for buttons that target your own infrastructure. See SSRF protection for the full threat model.