Skip to content
Variables & placeholders

Variables & placeholders

A placeholder is a {{name}} marker in a saved request’s URL, headers, body or auth params. Request resolution replaces every placeholder with a value at send time, or stops the request and lists every problem. Nothing with an unresolved placeholder is ever sent.

Where values come from: scopes

Each value comes from one scope. When the same name is set in several scopes, the higher one wins:

Scope (lowest first)Set with
1. Environment--env NAME or gurl env switch NAME
2. Collectiongurl collection create/set-var (the request’s collection)
3. Data row--data rows.csv / rows.json
4. CLI--var key=value
5. Runtimevalues extracted from a response or set by a script earlier in the same run

The scope a variable’s final value came from is its variable origin. gurl diag shows the origin of each variable in a recorded execution, and --persist uses it to decide where to write values back.

Collection values may reference environment keys, so one collection can serve several environments:

gurl env create staging --var BASE_URL=https://staging.example.com
gurl collection create "users-api" --var 'API_URL={{BASE_URL}}/v1'

Placeholder forms

FormMeaningExample
{{name}}Plain value, inserted as text{{BASE_URL}}/users/{{id}}
{{name:num}}Must be a number{"amount": {{amount:num}}}
{{name:bool}}Must be true or false{"live": {{live:bool}}}
{{name:raw}}Inserted as-is (e.g. a JSON fragment){"meta": {{meta:raw}}}
{{$fn}}Dynamic function, computed per send{{$uuid}}

Typed placeholders keep JSON bodies valid

A bare {{amount:num}} makes the stored body invalid JSON. Quote it instead: in a JSON body, the quoted form "{{amount:num}}" (likewise "{{x:bool}}" and "{{x:raw}}") drops the quotes when it is filled.

gurl save "charge" '{{BASE_URL}}/charges' -X POST \
  -H 'Content-Type: application/json' \
  -d '{"amount":"{{amount:num}}","capture":"{{capture:bool}}"}'

gurl run "charge" --env dev --var amount=5 --var capture=true --dry-run
POST https://dev.api.example.com/charges
Content-Type: application/json

{"amount":5,"capture":true}

A value of the wrong type is a resolution problem (variable "amount" must be a number); the value itself is never echoed in the error.

Dynamic functions

FunctionValue
{{$uuid}}Random UUID
{{$timestamp}}Unix timestamp (seconds)
{{$isoTimestamp}}ISO 8601 timestamp
{{$randomInt(1,100)}}Random integer in the range
{{$randomString(8)}}Random string of the given length
{{$randomEmail}}Random email address

Dynamic functions work in run, collection run, the shell and auth params. A dry run leaves them in place. An unknown function ({{$nope}}) is a resolution problem.

Environment aliases

An environment value can name another key of the same environment: API_KEY={{SA_KEY}}. See Environments & secrets.

When resolution fails

Every problem is collected and reported at once, and the request is not sent:

Error: variable substitution failed: missing required variables: BASE, API_KEY
Problem kindCause
missingNo scope has a value for {{name}}
leftover_placeholderA value still contains a placeholder, e.g. --var 'API_KEY={{other}}'. Values are filled in one pass and never re-expanded.
bad_typeA typed placeholder got the wrong kind of value
unknown_dynamic{{$fn}} is not a known function
authThe auth config cannot be resolved

With run --json, these appear as structured problems entries (kind, variable, location, message). Use --dry-run to check a request without sending it; it exits 1 when there are problems.

Keeping runtime values: --persist

Values extracted from a response (--extract) or set by a script (gurl.setVar) live only for the current run. Without --persist, run drops them and prints a note such as note: uid not saved; add --persist to use them in later runs.

With --persist, each extracted or script-set value is written back to its variable origin:

  • a variable that came from the environment goes to that environment (--env or the active one);
  • otherwise it goes to the request’s collection, or to the environment if the request has no collection.

--persist refuses:

  • a value that contains {{ (refusing to persist "tpl": value contains "{{"), so placeholders never get stored as values;
  • a locked (passphrase-protected, not unlocked) collection, instead of overwriting it;
  • --dry-run (exit code 2).

CLI --var values and data-row values are never written back unless an extraction or a script changes them.

See also