Property expansion syntax
Wirebench expands ${...} expressions in the endpoint, envelope, headers, WS-Addressing fields,
attachment names and paths of every send — SOAP or REST. A property’s own value can reference
another property, so expansion is recursive.
Explicit scope, ${#Scope#name} — resolves name in exactly one named scope:
${#Env#baseUrl}${#Project#apiKey}${#Workspace#region}${#Global#userAgent}${#System#HOME}${#Sequence#token}Shorthand, ${name} — resolves through a fixed chain of scopes, stopping at the first one
that defines name:
Env → Project → Workspace → GlobalSystem (the process environment) is never reached by the shorthand form — only ${#System#name}
reads it. This keeps a plain ${name} from silently picking up an unrelated environment variable
on your machine.
Scopes
Section titled “Scopes”| Scope | Where it comes from | Available |
|---|---|---|
Env |
The active environment’s properties | When a project or workspace has an active environment |
Project |
The project’s own properties |
Always, for a project-scoped send |
Workspace |
The workspace’s properties |
When the project is inside a workspace |
Global |
Properties set once for the whole app, independent of any project | Always |
System |
The OS process environment (process.env by default) |
Always, only via the explicit ${#System#name} form |
Sequence |
Values the earlier steps of a running sequence lifted from their responses, or that a request’s scripts set | Only via the explicit ${#Sequence#name} form: in a sequence run, in wirebench run, and in the app’s single sends, which read the project’s session values |
A Sequence value came from a server, so it follows stricter rules than the others. It is never
expanded again, so ${…} inside it stays as it is. It can’t form another reference’s name: in
${${#Sequence#n}} a response would be choosing which property is read, so the reference is refused.
It is always escaped for the body it lands in. And it may not supply the scheme, host or port of a
URL. In the app, a single send reads the values its project’s scripts kept this session (the
explorer lists them under Values); with none by that name, ${#Sequence#name} is unresolved.
Precedence
Section titled “Precedence”The shorthand ${name} checks, in order: Env, then Project, then Workspace, then Global. The
first scope that defines name wins, even if its value is an empty string. Use an explicit
${#Scope#name} form to reach a scope that a higher one is shadowing.
Nesting and indirection
Section titled “Nesting and indirection”A value can itself contain ${...} expressions, and an expression’s inner text can too — so
${#Project#${#Env#which}} first resolves ${#Env#which}, then looks up a Project property
named by that result. Expansion recurses up to a depth limit (8 by default); going past it reports
the reference as too-deep and leaves it verbatim rather than looping forever. A property that
refers back to itself, directly or through a chain of other properties, is caught as a cycle and
left verbatim rather than expanded.
Escaping
Section titled “Escaping”$${ is a literal ${ — the two characters before the brace are consumed by the escape, so
$${name} produces the literal text ${name}, unexpanded. In a run of three or more $ before a
brace, the last two and the brace form the escape and every $ before them stays as it is. So
$$${x} produces the literal text $${x}, and nothing in it is expanded.
Text that comes from a contract
Section titled “Text that comes from a contract”A ${ in a definition’s own text belongs to the definition, not to you. When Wirebench makes
something you send from a WSDL, an OpenAPI or an AsyncAPI document, it writes every ${ it copies
as $${.
That covers:
- an XSD
fixedordefaultvalue, in a generated request or inserted from the form view - the SOAP action
- a WSDL
soap:address, and the endpoint made from it - an OpenAPI path, a server URL and the base URL taken from it
- an OpenAPI example or default
- an OAuth2 token URL, authorization URL and scope, and an API key’s name
- an AsyncAPI server URL and channel address, a server variable’s default or enum value, and a channel parameter’s default, enum or example value
- an AsyncAPI WebSocket binding’s query and header names and samples, and its subprotocols
- an AsyncAPI message example, or the sample made from its payload
An AsyncAPI {name} server variable or channel parameter is filled from the document’s own
default or enum value (a parameter’s example too). One with no value stays the literal text {name}
and is sent that way. It never becomes the property ${name}, because that would read whatever
property, secret or environment variable the name reaches and send it to a host the document chose.
The import report lists each such slot, so you can replace it with a value or a property of your
own.
A contract tool’s call does the same. Each ${ then goes on the wire exactly as the definition
wrote it, and never reads a property, a secret, or an environment variable through
${#System#…}. A ${…} you type later still expands as usual.
Validate checks a $${ as the literal ${ it sends, so a generated fixed value passes.
wirebench generate saves nothing, so it shows the definition’s text as written.
Anything made before this rule still holds the definition’s ${ unescaped. Regenerate a request
to fix it. Re-import the definition to fix an interface’s endpoints, an API’s servers and base URL,
or its OAuth2 settings, since regenerating a request does not change those. Or write the ${ as
$${ yourself.
An AsyncAPI API imported before this rule is not repaired by Update definition…. An update rewrites a field only while it still equals what the contract generates, and the old unescaped text no longer does, so it is kept as if you had edited it. Import the document again instead.
Undefined and malformed references
Section titled “Undefined and malformed references”An expression that cannot be resolved is left in the output exactly as written — Wirebench never silently drops or blanks it. Each one is reported separately (visible in validation and before a send) with a reason:
| Reason | When it happens |
|---|---|
missing |
The name isn’t defined in the scope (or scope chain) being checked |
unknown-scope |
An explicit ${#Foo#name} names a scope that doesn’t exist |
cycle |
The property refers back to itself, directly or indirectly |
too-deep |
Expansion recursed past the depth limit |
malformed |
A ${ was never closed with a matching } |
Disabled variables
Section titled “Disabled variables”A property can be switched off without deleting it: its name appears in that scope’s disabled
list instead of being removed from properties. A disabled variable is treated as absent for
resolution — the shorthand form falls through to the next scope in the chain exactly as if the
variable didn’t exist, and an explicit reference to it reports missing. Its value stays on disk
and is restored the moment it’s re-enabled.
Global properties have no disabled list of their own in the engine; a caller that wants a
disabled global excluded from resolution filters it out before expansion.
Entitizing
Section titled “Entitizing”When expanding a SOAP envelope (never headers or the endpoint), Wirebench can XML-escape every
substituted value — so a property containing &, < or " doesn’t corrupt the envelope. A
value is escaped once, at the outermost reference, even when it was reached through several
levels of nested property values.