Skip to content

Schema specification

Every key below is read by the parser. Anything not listed here is ignored silently — there is no strict mode, so a misspelled key is dropped rather than reported.

For guided introductions see the authoring guide; this page is the lookup table.

version: 1
name: MarketplaceAPI
default_environment: local
imports:
- environments/*.yaml
- actors/*.yaml
- resources/*.yaml
environment: { baseUrl: http://localhost:3000 }
actors: { ... }
resources: { ... }
auth: { type: bearer, token: "{{secret.TOKEN}}" }
transport: { connect_timeout: 5s }
latency_slo: { p95_ms: 800 }
KeyTypeRequiredDefault
versionintegeryes— must be 1–3
namestringnoUnnamed Project
default_environmentstringnolocal
importssequence or map of glob patternsno—
environmentmapno— becomes the default environment
actorsmap of id → actorno—
resourcesmap of id → resourceno—
authinline-auth mapno— target of auth: { type: inherit }
transportmapno— applies to the default environment only
latency_slo{ p95_ms: integer }nounset

There is no environments: (plural) root key. The singular environment: defines one environment, named by default_environment; others are files under environments/. See file structure.

name: vendor
description: Marketplace vendor
auth: { strategy: simple, ... }
session: { ttl: 15m, refresh: { ... } }
inject: { headers: { Authorization: "Bearer {{vendor.token}}" } }
KeyTypeDefault
descriptionstring""
authmap—
sessionmap—
injectmap with only headers—

inject has no sub-key other than headers.

One of: simple (default), chain, basic, api_key, oauth2_client_credentials, oauth2_password, oauth1, aws_sigv4, bearer, jwt, mtls. An unrecognised value falls back to simple.

Keys read per strategy:

StrategyKeys
simplemethod (POST), path, headers, body, expect_status (scalar), extract
chainsteps: sequence of { id, method, path, headers, body, expect_status, extract }
basicusername, password
api_keykey, location (header|query|cookie), name
bearertoken
oauth2_client_credentialstoken_url, client_id, client_secret, scope
oauth2_passwordthe above plus username, password
oauth1consumer_key, consumer_secret, token, token_secret, realm
aws_sigv4access_key, secret_key, region, service, session_token
jwtsecret, payload, algorithm (HS256|HS512)
mtlscert_path, format (pem|p12), key_path, key_password, ca_cert_path
KeyTypeDefault
ttlduration s/m/h/d15m — malformed input also yields 15m
refreshmap—

refresh reads method (POST), path, headers, body, expect_status (scalar or sequence), extract. Unset expect_status accepts any 2xx.

name: order
description: Customer orders
operations:
create: { ... }
KeyTypeDefault
descriptionstring""
operationsmap of name → operation—

Nothing else. There is no resource-level base_path, headers, or actor. Operation ids are composed as <resource>.<operation>.

KeyTypeDefaultNotes
methodstringGETUnknown value → GET
pathstring""Appended to baseUrl. There is no url: key
actoractor id—
authinline-auth map—See below
headersmap—
query_paramsmap—Not query: or params:
bodyscalar or structured—Scalar passes through verbatim; map/sequence → JSON
body_formmap—Form-encoded or multipart
expect_statusinteger or sequence—Sequence wins over scalar
poll_untilmap—See below
for_eachmap—See below
extractmap—See below
assertsequence—A map is ignored
depends_onsequence of resource.op—A scalar is ignored
pre_requeststring—Inline JS or relative ./x.js
post_responsestring—Same
retry{ max, backoff }3, 500backoff in ms; max backoff fixed at 30s
timeoutinteger ms30000Not a duration string
forceboolfalseOpt out of step caching
_provenancemap—Importer metadata, runtime-ignored

Map of variable name → path, or → { path, source }.

sourceAuto-detected from
jsonpath (default)anything else
header$.headers. prefix
cookie$.cookies. prefix
status_codeexactly $.status_code
xpathnever — requires the map form
regexnever — requires the map form

A [*] in the path produces one resource instance per match.

Sequence of bare predicates, or { expr, name } maps. Items with an empty expr are dropped.

Predicate grammar: ==, !=, <, <=, >, >=, in, matches, combined with && / ||; $.json.path references; $.status_code; bare JSONPath truthiness.

KeyTypeDefault
methodstringGET
pathstring""
actoractor idthe parent operation’s actor
success_whenpredicate— required in practice
fail_whenpredicate— wins over success_when
intervalduration2s
backoff{ base, max }max 30s; setting base disables interval
timeoutduration60s
max_attemptsinteger30

Polling engages only if the initial status matches expect_status, so the sequence form is effectively required.

KeyTypeDefault
overresource id— required; block dropped without it
continue_on_errorboolfalse

No alias, no limit, no parallelism.

type: accepts bearer, basic, apikey/api_key, aws_sigv4/awssigv4/aws, oauth1/oauth_1, oauth2/oauth_2/oauth2_client_credentials, jwt/jwt_bearer, mtls/mutual_tls, inherit. Anything else, including none, means no inline auth.

Value keys: token, username, password, key, value, in, access_key, secret_key, region, service, session_token, consumer_key, consumer_secret, oauth_token, token_secret, grant_type, token_url, client_id, client_secret, scope, client_auth, auth_url, callback_url, pkce_method, algorithm, secret, payload, format, cert_path, key_path, key_password, ca_cert_path.

name: local
variables:
baseUrl: http://localhost:3000
admin_password: !secret ADMIN_PASSWORD
transport:
connect_timeout: 2s

Wrapped form uses name + variables. Flat form puts variables at the top level, skipping name and transport. Without name:, the filename stem is used.

!secret NAME on a value expands to {{secret.NAME}}. This is the only way to declare a secret — there is no secrets: block.

baseUrl is magic: request URLs are baseUrl + path. camelCase.

KeyTypeDefault
tls_verifybooltrue
tls_verify_hostbooltrue
ca_bundlepath—
proxyURL—
connect_timeoutduration, accepts ms5s

Single sigil {{ ... }}. Scopes, in resolution order: builtins ($.), env, secret, actor sessions, indexed resources (name[N], 1-based), resources (newest instance first).

Builtins: $.uuid, $.now (with signed ± duration offset), $.env.NAME (process environment), $.faker.email, $.faker.phone, and the codec functions $.base64.encode|decode, $.hex.encode|decode, $.url.encode|decode.

Full detail in variable syntax.

LimitValue
Schema file size8 MiB per file
YAML body nesting depth64
Hook script size1 MiB
Upload file size50 MiB
Env value re-expansion depth4

Inside a structured body:, quoting decides the JSON type: "01234" stays a string, 01234 becomes the number 1234; "true" stays a string, true becomes a boolean. Quote identifiers.

VersionStatus
1Supported
2Supported
3Supported

Anything outside 1–3 is rejected with E_SCHEMA_VERSION.