Skip to content

Collection YAML

noodle collections are directories of .yml files on disk. This reference covers every field, type, and constraint.

One request per file. Extension must be .yml (not .yaml).

Field Type Required Default Description
name string yes Required Display name for the request
method string yes Required GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
url string yes Required Full URL, supports $VAR substitution
timeout number no 0 Request timeout in ms. 0 = no timeout
tags array no [] Case-sensitive suite tags
followRedirects boolean no true Follow HTTP redirects
maxRedirects number no 5 Max redirect chain length
sendCookies boolean no true Send matching collection jar cookies; false still captures responses
body_type string no none none, json, xml, multipart, urlencoded, binary
headers map no {} Request headers (omit if empty)
params array no [] URL query parameters (omit if empty)
path_params array no [] Values for :name URL path tokens (omit if empty)
body string no None Raw body content
form_data array no None Multipart form entries
file_path string no None Path to binary upload file
auth object no None Auth config (omit for no auth)
tls object no None Per-request TLS override; supports only verify: true or verify: false
scripts object no None Inline JavaScript or ./file.js references for pre and/or post
capture map no None Response capture objects for manual and automated runs
assert array no None Response assertions for manual and automated runs
tests string no None Inline JavaScript or ./file.js read-only tests after assertions

Request tags are case-sensitive, non-empty strings with no surrounding whitespace. They combine with tags from every ancestor folder and can filter a collection run without creating another collection:

tags:
- smoke
- users

Use --tag smoke to include requests with that effective tag and --exclude-tag destructive to remove matches. Repeated --tag values all must match; any repeated --exclude-tag match removes the request. Exclusion wins when both filter types match.

Key-value map. Values can be simple strings (enabled) or objects with value and enabled fields:

headers:
Content-Type: application/json
Authorization: { value: "Bearer $token", enabled: false }

Array of { name, value, enabled } entries. Each entry:

  • name: string, required
  • value: string, required
  • enabled: boolean, default true
params:
- name: userId
value: $user_id
- name: _limit
value: "10"
- name: disabled_param
value: x
enabled: false

Use :name tokens in the URL and provide one required value for each token in path_params. Path params are substituted before sending, so they do not support enabled: false.

url: $base_url/users/:userId
path_params:
- name: userId
value: $user_id

Noodle synchronizes these entries with URL tokens when you edit the URL.

In JSON, text/XML bodies, and enabled text form values, $random.method and $time.method generate values during the single substitution pass before pre scripts. Optional calls accept JSON literals. Quoted JSON placeholders insert escaped text; standalone placeholders preserve JSON types. URLs, headers, auth, form names, file paths, and assertion expectations do not support generation. Saved YAML retains the templates. See random and time body values for examples, escaping, limits, and lifecycle rules.

Declare inline or external pre-request and post-response scripts in request YAML, collection settings.yml, or nested folder.yml. Start with Scripting for a walkthrough.

An optional scripts mapping accepts string-valued pre and/or post members. Empty mappings, unknown members, and non-string sources are invalid. Empty strings are valid no-ops and omitted during serialization. External references use ./path/to/file.js, always relative to the collection root. See external JavaScript files for source validation and preflight; malformed file references are rejected. Canonical YAML preserves source whitespace in literal blocks ordered pre then post immediately before capture and assert:

scripts:
pre: |-
const timestamp = new Date().toISOString();
const body = noodle.request.body.json();
noodle.request.body.setJson({ ...body, timestamp });
noodle.request.headers.set(
"X-Signature",
noodle.crypto.hmacSha256(noodle.env.get("SIGNING_SECRET"), noodle.request.body.text(), "hex"),
);
noodle.run.set("request_nonce", noodle.crypto.randomBytes(16, "base64"));
post: |-
if (noodle.response.status === 201) {
noodle.run.set("event_id", noodle.response.json().id);
}

Source is never variable-substituted. See Script API for execution order, API methods, persistence, response readers, cookies, limits, and diagnostics.

The date/time method reference is now in Script API: time.

The generator catalog and options are now in Script API: random.

Optional tests accepts an inline JavaScript string or a collection-relative ./path/to/file.js reference. Non-string values and malformed paths are rejected. Empty source is valid; source whitespace survives canonical serialization and is never substituted. Tests run after declarative assertions whenever HTTP produced a response.

Use global test(name, callback) and expect(actual) with read-only noodle.* readers. Failed callbacks remain individually ordered; a top-level error stops the script and retains completed results. Test failures use category test. Results use tests: { evaluated, results, logs, error?, errors? }, separately from pre/post scripts. Each named result contains name, passed, message, and durationMs.

See Scripted Tests for all matchers, .not, conditional and JSON examples, phase capabilities, limits, and result behavior.

An optional capture mapping assigns response expressions to run variables. Later requests in the same ordered collection run can use transient captures through the normal $VARNAME syntax:

capture:
user_id:
value: body.user.id
access_token:
value: body.access_token
persist: secret
optional_trace:
value: headers.x-trace
enabled: false

Variable names must match ^\w+$. Every entry is an object with required string value, optional persist: secret|environment, and optional boolean enabled. Scalar shorthand, unknown fields, and invalid persistence values are rejected. Omitted enabled means enabled and is omitted from canonical YAML. Disabled entries are still validated but produce no result, failure, summary count, RunScope mutation, timeline outcome, or write.

Expressions use status, response.time, case-insensitive headers.<name>, or body followed by dot properties and array indexes. They are validated when the request loads and are never variable-substituted.

Each manual TUI send and request run gets an isolated scope, while one collection run shares a scope across its ordered requests. Environment and secret values load first, then successful captures override values with the same name. The latest successful capture wins. Strings substitute verbatim; numbers, booleans, null, arrays, and objects use their JSON representation.

Captures are evaluated before assertions. Successful values commit even when another capture, the HTTP status, or a later assertion fails. A missing or invalid traversal fails the capture without creating or replacing a variable; the request fails, but a collection run continues in collection order.

Transient values disappear when the call returns and never modify request YAML, collection settings, or timeline history. On a manual TUI send or CLI request run, persist: environment writes an enabled plaintext value and refuses to downgrade an existing secret; persist: secret stores the value in the OS vault and writes only a blank secret declaration. An active or selected environment is required. Persistence keeps partial successes, and a failed write fails that capture without discarding the HTTP response. CLI collection run and the TUI Runner ignore persistence. Secret capture values and values captured from sensitive response headers are always fully redacted from results.

An optional assert list validates responses from manual TUI sends, request run, and collection run. Manual outcomes appear in Results; a failed assertion makes automation commands fail.

assert:
- expression: status
operator: equals
value: 200
- expression: body.users[0].id
operator: isNumber
- expression: headers.Content-Type
operator: contains
value: application/json
- expression: response.time
operator: lt
value: 500
enabled: false

Each assertion accepts optional boolean enabled; omitted means enabled and is omitted from canonical YAML. Disabled assertions remain validated and editable but are not substituted, evaluated, or included in results, failures, summaries, or timeline assertion outcomes.

Expressions are status, response.time, headers.<name> with case-insensitive header lookup, or body followed by dot properties and array indexes. Body expressions require valid JSON. Missing values differ from explicit JSON null, and response.time is measured in milliseconds. Equality compares typed JSON values recursively without coercion: array order matters, object key order does not, and strings are case-sensitive.

Operators without value: exists, notExists, isString, isNumber, isBoolean, isArray, isObject, isNull, notNull.

Operators with a JSON-compatible value: equals, notEquals, gt, gte, lt, lte, contains, notContains, matches. Numeric comparisons require finite numbers. Containment checks string substrings or deeply equal array members. matches accepts strings and a restricted JavaScript regular-expression subset that rejects backreferences, groups, alternation, braced quantifiers, and unsafe repetition. Matching is case-sensitive, has no flags, and is unanchored unless the pattern includes ^ or $.

String values recursively support $VARNAME substitution; expressions and operators do not. Known secrets are recursively redacted from expected and actual result values. Secret capture expressions also mask overlapping capture and assertion results. Unrelated public numbers, booleans, and null values keep their types; arbitrary server data can remain visible, so treat JSON output as sensitive response data.

Array for multipart and urlencoded body types. Each entry:

  • name: string, required
  • value: string, required
  • type: text (default) or file
  • enabled: boolean, default true
body_type: multipart
form_data:
- name: description
value: A photo
- name: file
value: ./photo.png
type: file

For urlencoded, use the same entries with text values; omit type or set it to text.

Multipart file entries and binary file_path values can use a quoted @/ prefix for the current user’s home directory:

file_path: '@/Documents/photo.png'

Noodle keeps this portable shorthand in the collection and expands it only when reading an upload file or producing an output artifact. Postman exports therefore contain absolute file paths and should be reviewed for local-path disclosure before sharing.

XML bodies are sent unchanged after environment-variable substitution. Noodle adds Content-Type: application/xml when no enabled Content-Type header exists; set an explicit header for MIME types such as text/xml or application/soap+xml.

body_type: xml
body: |-
<request>
<id>$request_id</id>
</request>
Type Fields Description
none None No auth (omit auth field entirely)
inherit None Use nearest parent folder’s auth
bearer token Bearer token auth
basic user, pass Basic auth
ntlm username, password, optional domain, workstation Connection-bound server NTLMv2 auth
api_key key, value, placement API key auth. placement: header or query
aws_sigv4 access_key, secret_key, region, service, session_token AWS Signature Version 4; session_token is optional
oauth1 consumer_key, consumer_secret, access_token, access_token_secret, signing and placement fields OAuth 1.0a request signing
oauth2 grant, endpoint, client, token lifecycle, client assertion, delivery, and additional parameter fields OAuth 2.0 secure token workflow
auth:
type: bearer
token: $api_token

NTLM uses the server’s connection-bound NTLMv2 challenge exchange. Proxy NTLM, NTLMv1, Kerberos/SPNEGO negotiation, signing, sealing, and channel binding are not supported. AWS SigV4 signs requests after variable substitution and supports text, JSON, URL-encoded, and binary bodies; multipart is not supported. Keep passwords, AWS secret keys, and session tokens in secret environment variables.

auth:
type: oauth1
consumer_key: $oauth1_consumer_key
consumer_secret: $oauth1_consumer_secret
access_token: $oauth1_access_token
access_token_secret: $oauth1_access_token_secret
signature_method: HMAC-SHA256
private_key: ""
private_key_type: text
callback_url: ""
verifier: ""
timestamp: ""
nonce: ""
version: "1.0"
realm: ""
placement: header
include_body_hash: false

signature_method supports HMAC-SHA1/256/512, RSA-SHA1/256/512, and PLAINTEXT; the default is HMAC-SHA1. RSA keys may be inline text or a collection-relative or @/ file. placement is header, query, or body; body placement requires URL-encoded form data. Blank timestamp and nonce values are generated for each signature. include_body_hash: true does not support multipart bodies, and PLAINTEXT is limited to HTTPS or loopback HTTP.

auth:
type: oauth2
grant_type: authorization_code
discovery_url: ""
discovery_url_kind: issuer
authorization_url: https://identity.example.com/oauth/authorize
access_token_url: https://identity.example.com/oauth/token
refresh_token_url: https://identity.example.com/oauth/token
client_id: $oauth2_client_id
client_secret: $oauth2_client_secret
username: ""
password: ""
scope: openid profile
audience: https://api.example.com
redirect_uri: http://127.0.0.1:8765/oauth/callback
credentials_id: example-api
auto_fetch_token: true
auto_refresh_token: true
pkce: true
pkce_method: S256
implicit_response_type: token
credentials_placement: body
client_authentication: client_secret
client_assertion_algorithm: RS256
client_assertion_key: ""
client_assertion_key_type: text
client_assertion_issuer: ""
client_assertion_subject: ""
client_assertion_audience: ""
client_assertion_lifetime: 300
token_source: access_token
token_placement: header
token_header: Authorization
token_prefix: Bearer
token_query_key: access_token
additional_parameters:
authorization:
- name: prompt
value: consent
enabled: true
placement: query
token: []
refresh: []

grant_type is authorization_code, client_credentials, implicit, or password. Authorization code defaults to S256 PKCE; pkce_method may also be plain. implicit_response_type is token, id_token, or token id_token. credentials_placement is body or basic. credentials_id is an optional stable key for sharing compatible stored token state.

discovery_url fills missing authorization and token endpoints. With the default discovery_url_kind: issuer, it accepts an OIDC issuer or its standard /.well-known/openid-configuration URL and verifies the returned issuer. Use discovery_url_kind: document to request an exact metadata URL, including custom paths. Explicit endpoint fields take precedence; an empty refresh_token_url uses the token endpoint. Discovery supports environment variables, follows the request’s proxy/TLS policy, and does not write resolved endpoints to YAML.

For signed client authentication, set client_authentication to client_assertion. Assertion algorithms are HS, RS, PS, or ES with 256, 384, or 512 suffixes. client_assertion_key_type is text or file, and the lifetime must be a positive integer. Issuer, subject, and audience are optional overrides.

token_source is access_token or id_token. token_placement is header or query, with customizable header, prefix, and query key. Authorization additional parameters use query placement. Token and refresh parameters may use body, header, or query placement; each entry has name, value, optional enabled, and placement.

OAuth endpoints require HTTPS except on loopback hosts. Browser flows use a loopback HTTP callback ending in /oauth/callback. Token responses are stored in the OS credential vault or kept in memory for the current session when the vault is unavailable; they are never serialized to request YAML.

A request can override only certificate verification:

tls:
verify: false

Omit tls to inherit the collection setting. CA bundles and client certificates are collection settings, not request fields.

name: My Request
method: GET
url: $base_url/endpoint
timeout: 0

Optional. Defines display name, sort order, suite tags, and inheritable overrides.

meta:
name: Users
seq: 1
tags:
- smoke
headers:
X-Custom: value
auth:
type: bearer
token: $folder_token
Field Type Required Description
meta object no Display metadata
meta.name string no Display name (defaults to directory name)
meta.seq number no Sort order (lower = first, undefined = last)
tags array no Suite tags inherited by descendants
headers map no Inherited headers (merge additively)
auth object no Inherited auth
scripts object no Inline or external pre/post blocks; see phase order below
tests string no Inline or external tests accumulated in ancestor order

Declare scripts.pre, scripts.post, and tests as inline JavaScript or external file references in collection settings.yml, nested folder.yml, or request YAML.

  • Pre: collection → outermost folder → nearest folder → request.
  • Post, after captures: collection → outermost folder → nearest folder → request.
  • Tests, after assertions: collection → outermost folder → nearest folder → request.

All three phases use the same scope order. The most specific successful post write wins, including persisted writes. Versions 0.9.4 and 0.9.5 ran post blocks in reverse order; update collection or folder post blocks that depend on values produced by request post blocks when upgrading.

Collection and folder blocks run once per request, including each dataset row. Root folder.yml is ignored. An empty block is a no-op and does not disable inherited blocks.

Every block has a fresh QuickJS invocation. JavaScript locals are isolated; successful RunScope writes are visible to later blocks. A pre failure stops remaining pre blocks and HTTP. A post failure rolls back only that block and continues later posts, assertions, and tests. A top-level test error stops only its block. Successful persistence intents keep execution order; collection runs and F5 suppress persistence as before. Saved noodle.runRequest() calls use the same inheritance and cycle protections.

Executed blocks identify their phase, scope, scope ID, and source kind. source.path is the declaring YAML path; source.scopeId identifies the collection, folder path, or request ID. source.sourceKind is inline or external; external blocks add the collection-relative source.sourcePath. Test groups retain ordered invocations, including blocks declaring zero tests, and errors for multiple block errors; legacy error remains the first error. CLI, Results, and history show origins and bounded, redacted diagnostics and logs without retaining source code or RunScope values.

Inherited blocks share a 64 KiB console-text budget and a 256 KiB test-record budget per request. Logs become [TRUNCATED] at the limit; exhausted test records produce a test script error, and later blocks are still invoked.

  • Tags: Request tags combine with every ancestor folder’s tags. Duplicates have no additional effect, descendants cannot remove inherited tags, and a root-level folder.yml is ignored.
  • Headers: Folder headers merge additively. Request’s headers win on same key.
  • Auth: Requests with type: inherit use nearest ancestor folder’s auth. Walk tree from child up.

Single file at collection root:

collection_id: 123e4567-e89b-42d3-a456-426614174000
name: Payments API
description: |-
Requests for the payments platform.
timeline_max_entries: 50
environment: development
cookies:
enabled: true
proxy:
mode: custom
url: http://proxy.example:8080
bypass: [localhost, .internal.example]
auth: true
tls:
verify: true
ca_bundle: ./certs/internal-roots.pem
client_certificates:
- host: api.internal.example
port: 443
cert_file: ./certs/client-chain.pem
key_file: ./certs/client-key.pem
secret_id: 123e4567-e89b-42d3-a456-426614174001
Field Type Description
collection_id UUID string Generated credential-vault namespace. Preserve it when moving a collection; do not copy it into another collection.
scripts object Optional inline or external pre/post blocks; collection scripts run before folder and request scripts in both phases.
tests string Optional inline or external tests that run before descendant test blocks.
name string Optional display name; defaults to the collection directory name.
description string Optional collection notes.
timeline_max_entries non-negative integer Per-request history retention. Defaults to 50; 0 disables recording.
environment string Default active environment. Must match a .env file in .environments/.
cookies object Optional cookie policy. enabled is a boolean and defaults to true; false prevents sending and capturing jar cookies.
proxy object Optional collection proxy policy. mode is inherit, off, or custom. A custom policy uses an http or https url and an optional string-array bypass list.
tls object Optional TLS policy with verify, ca_bundle, and exact-host client_certificates.

Custom proxy URLs reject credentials and variables. When authentication is enabled, auth: true is persisted while the username and optional password live in the OS credential vault. --noproxy forces direct connections for one TUI, collection run, or request run invocation. See Settings for proxy scope, precedence, and bypass rules.

TLS client-certificate profiles require host, cert_file, and key_file; port defaults to 443, and enabled is optional. Relative paths resolve from the collection root. Enter encrypted-key passphrases in Settings; Noodle stores them in the OS vault and persists only the generated secret_id. Use --insecure to disable verification for one invocation.

Settings are validated strictly. Malformed YAML, unknown keys, wrong types, and invalid proxy/TLS/cookie blocks fail collection opening, auditing, and automation. A missing or empty file uses defaults.

Redirects follow only HTTP or HTTPS. Noodle rejects HTTPS-to-HTTP downgrades and removes authorization, proxy authorization, cookies, Host, and header API-key credentials before following a cross-origin redirect.

Auto-generated files managed by noodle:

File Format Purpose
last-request Plain text Last selected request ID
expanded-folders YAML list Expanded folder paths in sidebar
ui-state/<requestId>.yml YAML Per-request tab index state