Complete reference for every module, assertion operator, and tool in Hephaestus v4.0.
Per-field assertion rules using a shorthand map. Supports all operators below. Each field can have multiple operators. Conditional logic via when.
soft: true per-rule to log warning instead of failingwhen: "expression" to conditionally skipsoftFail: true applies soft behavior to all assertionsSimple key existence check. Specify a dot-notation path β the engine walks the response body and confirms the key exists (or is absent with ! prefix).
assertions: { "data.id": { exists: true, type: "number" }, "data.email": { matches: "@" }, "data.score": { gte: 0, lte: 100 }, "data.name": { minLen: 1, maxLen: 100 }, "data.active": { eq: true, soft: true, // warning only when: "ctx.response.code === 200" }, "data.items": { type: "array", minLen: 1 }, "error": { absent: true }, }, keysToFind: ["data.id", "data.name", "!error"],
existsKey exists in response
absentKey must NOT be present
eqStrict equality
neNot equal
gtGreater than (number)
gteGreater than or equal
ltLess than (number)
lteLess than or equal
typetypeof check
minLenMin string/array length
maxLenMax string/array length
includesString/array includes
matchesRegex or substring match
softLog warning, don't fail
whenConditional skip expression
absentMust not exist
Quick one-liner per field: declare the expected type. Options:
"string" "number" "boolean""object" "array""absent" β field must NOT exist"any" β field must exist, any typeChecks that an array is sorted by a field in the given direction ("asc" or "desc"). Specify type: "number" or "string".
Checks that all values in an array (or sub-field values) are unique. Set by to check a nested field (e.g. "id").
assertShape: { "data": "object", "data.id": "number", "data.name": "string", "data.items": "array", "data.active": "boolean", "error": "absent", "meta": "any", }, assertOrder: { path: "data.items", by: "price", direction: "asc", type: "number", }, assertUnique: { path: "data.items", by: "id", // check item.id uniqueness },
Validates every element of an array against a set of rules. Same operator syntax as assertions map. Supports minCount / maxCount for array length, and per-rule soft mode.
Global softFail: true makes all rule violations non-fatal.
assertEach: { path: "data.products", minCount: 1, maxCount: 200, rules: { "id": { type: "number", gt: 0 }, "name": { type: "string", minLen: 1 }, "price": { gte: 0 }, "category": { exists: true }, "active": { eq: true, soft: true, // warn only per item }, } },
On first run, response body is saved as a baseline in a collection variable. On subsequent runs, the current response is compared against that baseline.
ignorePaths β skip dynamic fields (timestamps, IDs)checkPaths β only compare specific sub-pathssnapshot: { enabled: true, mode: "non-strict", ignorePaths: [ "data.updatedAt", "data.requestId", "meta.timestamp" ], checkPaths: ["data.status", "data.type"], record: false, // set true to force-rewrite the baseline (snapshotRecord) },
auth: { enabled: true, type: "basic", basic: { username: "{{user}}", password: "{{pass}}" } },
auth: { enabled: true, type: "bearer", bearer: { token: "{{access_token}}" } },
auth: { enabled: true, type: "oauth2cc", oauth2cc: { tokenUrl: "{{tokenUrl}}", clientId: "{{clientId}}", clientSecret: "{{secret}}", scope: "read write", } },
// Option 1: use ctx.random directly in scripts ctx.random.uuid() // β "a7f3..." ctx.random.email() // β "test42@example.com" ctx.random.str(8) // β "xK9mPqRt" ctx.random.int(1, 100) // β 42 ctx.random.bool() // β true/false ctx.random.pick(['a','b']) // β "a" ctx.random.date() // β "2026-04-07" // Option 2: auto-inject into pm.variables randomData: { "email": "random.email", "userId": "random.int:1:9999", "orderId": "random.uuid", "name": "random.str:10", } // β {{email}}, {{userId}}, {{orderId}} in URL/Body
// Configure in hephaestus.defaults or override dates: { today: "today", tomorrow: "today+1d", yesterday: "today-1d", nextWeek: "today+7d", lastMonth: "today-1m", startOfMonth: "startOfMonth", endOfMonth: "endOfMonth", q1Start: "startOfQuarter", } // β {{today}}, {{tomorrow}} injected as pm.variables
// Auto-retry on 503 (service unavailable) or 429 (rate limit) retryOnStatus: { statuses: [503, 429], maxRetries: 3, } // Uses pm.setNextRequest to loop. // Assertion pipeline is skipped on intermediate retries. // Counter auto-cleaned on success.
// Pre-flight: halt collection if required vars missing envRequired: [ "BASE_URL", "API_KEY", "CLIENT_SECRET" ] // Fails fast with clear error message: // [Hephaestus] β Required env var missing: API_KEY
No console output. Only CI JSON if ci: true. Good for data-driven runs with thousands of iterations.
Single-line summary per request: method, URL, status, time. Compact output for watch mode or large test suites.
Default. Full bordered summary box with response preview, all assertion results, saved variables.
Normal + response headers. Useful for debugging auth, CORS, and caching issues.
Global flag. All assertion failures log as warnings instead of failing the Postman test. Overrides per-rule soft.
Outputs structured JSON to console alongside human-readable output. Consumed by ci-to-junit.js.
Generate Markdown API docs from a Postman collection. Your tests become your documentation.
npm run docs -- col.json -o API.md
Rich Newman run summary: per-folder stats, slowest endpoints, most-failed assertions.
npm run summary -- results.json --md
Diff two Newman runs. Detect regressions, new failures, performance changes. Exit 1 on regression.
npm run compare -- before.json after.json
Auto re-run Newman when collection or env changes. Press R to force rerun. Debounced.
npm run watch -- -c col.json
Beautiful self-contained HTML report from Newman JSON. Charts, pass rates, details.
npm run report -- results.json
Convert Newman JSON to JUnit XML for Jenkins, GitLab CI, and other tools.
npm run ci-to-junit -- results.json
Interactive setup wizard. Generates defaults.json and environment template.
npm run init
Scan existing Postman collection and classify which requests need migration to Hephaestus.
npm run migrate -- col.json
Run full Newman + report pipeline in Docker. No local Node.js needed.
bash scripts/docker-run.sh -c col.json
The locale setting selects the language of every user-facing string the engine emits: generated test names, console logs, error messages, and status labels.
"ru" β default. Byte-identical output to prior releases."en" β the exact same engine, rendered in English.Nothing about assertions or request behaviour changes β only the text you read. Defined in setup/defaults.json, resolved through the shared i18n catalog.
Existing suites keep their exact wording β test IDs, snapshots, and log-scraping stay stable across the upgrade. Opt into English by setting a single field.
// setup/defaults.json (or per-request override) locale: "ru", // default β unchanged output // switch the whole engine to English: locale: "en", // affects test names, logs, errors, status labels: // ru β "π’ Π‘ΡΠ°ΡΡΡ: 200 β Π£ΡΠΏΠ΅ΡΠ½ΠΎ" // en β "π’ Status: 200 β OK"
Opt-in module (enabled: false by default). When on, each check emits its own pm.test so failures surface individually.
requireHeaders β security headers that must be presentforbidHeaders β headers that must NOT leak (server, tech fingerprints)forbidBodyPatterns β strings that must not appear in the body (stack traces, DB errors)checkCors β flags a wildcard Access-Control-Allow-Origin combined with Allow-CredentialsWhen enabled without lists, the engine applies OWASP-style defaults: requires HSTS, CSP, X-Frame-Options, X-Content-Type-Options; forbids server, x-powered-by, x-aspnet-version; and scans the body for SQLSTATE, stack traces, ORA-0, and MySQL warnings. Default { enabled: false, checkCors: true }.
securityAudit: { enabled: true, checkCors: true, // wildcard ACAO + credentials requireHeaders: [ "strict-transport-security", "content-security-policy", "x-frame-options", "x-content-type-options", ], forbidHeaders: [ "server", "x-powered-by", "x-aspnet-version", ], forbidBodyPatterns: [ "SQLSTATE", "stack trace", "ORA-0", ], }, // each check β its own pm.test
When an endpoint intentionally changes, you need a fresh baseline. Set snapshot.record: true (or top-level snapshotRecord: true), run once, then remove the flag.
collection-vars backendsnapshot.storage defaults to "collection-vars", the only backend that works offline. "postman-api" is unavailable offline β the engine warns once and falls back to collection-vars automatically.
// Step 1 β force a new baseline this run: snapshot: { enabled: true, record: true, // rewrite baseline, ignore old storage: "collection-vars", }, // or the top-level shorthand: snapshotRecord: true, // Step 2 β run once. // Step 3 β remove the flag; back to compare mode.
The summary tool now reports p50 / p90 / p95 / p99 response times across the run. Pass --sla=<ms> to turn it into a gate.
1 when p95 exceeds the budget# percentiles in the summary output node scripts/summary.js results.json # gate the run: fail if p95 > 800ms node scripts/summary.js results.json --sla=800 # β Response time p50 120ms p90 410ms # p95 690ms p99 1.2s # β SLA OK: p95 690ms <= 800ms (exit 0)
Turn an existing API spec into a ready-to-run collection. Reads OpenAPI 3.x and Swagger 2.0 (JSON, or a common YAML subset).
expectedStatus pre-filled from the spec's 2xx responsesschema pre-filled from the spec's schemas--negative also generates error-path tests--negative only generates cases the spec lets it actually
trigger — withheld auth, a substituted id, an emptied required body, a
dropped required parameter. A spec that declares a 400 does not say what makes a request
invalid, so no test is invented for it. Each negative request differs from the happy path
by exactly one mutation.
# OpenAPI 3.x or Swagger 2.0 β collection node bin/hephaestus.js openapi openapi.json # YAML subset also accepted node bin/hephaestus.js openapi swagger.yaml # plus error-path tests node bin/hephaestus.js openapi openapi.json --negative # each generated request comes with: # expectedStatus (from 2xx responses) # schema (from spec component schemas) # # --negative adds a "<tag> β negative" folder: # no auth 401/403 (auth disabled in pre-request) # unknown id 404 (path parameter substituted) # empty body 400/422 (required body sent as {}) # missing <p> 400/422 (required query parameter dropped)
The sync-examples tool writes your saved snapshot baselines into a collection's native Postman Example Responses.
# write saved snapshots into native # Postman Example Responses node bin/hephaestus.js sync-examples collection.json # β each request with a snapshot baseline # gains a matching Example Response, # visible in the Postman app.
graphql β GraphQL answers 200 even with an errors[] array; assert noErrors, errorCount/errorContains for negative tests, and dataShape under data.*.snapshot.mode: "structural" β compares the response shape (leaf path β type) and ignores values, so volatile timestamps and ids stop causing false diffs while a field added, removed or retyped still fails.retryOnStatus.respectRetryAfter β honours the server's Retry-After, waiting up to retryAfterCapMs and refusing to hammer past it.maxBytes β a response-size budget; the maxResponseTime for payload size.cookieFlags, checkJwt (rejects alg:none and expired tokens) and requireNoStore.strictMode: true fails the run so CI blocks on a typo.Locale selection was hardcoded to ru/en, so a fully translated third language could never be used. Any locale the catalog carries is now selectable, and npm run check:locales validates a contribution β completeness, parameter parity, argument types, status coverage.
doctor β pre-flight: engine integrity, version drift, config sanity.coverage --spec β % of an OpenAPI spec your collection covers, with a --min gate.flaky β assertions that flap across repeated runs (--fail-on-flaky).trends + summary --history β pass-rate and p95 sparklines from a local run log.bench β what the engine actually costs per request (~1.6 ms), with a --max-ms budget.mock β replay saved snapshots as a local API.generate β interactive wizard that prints a ready-to-paste override.panel β local dev panel: run history, snapshots, defaults editor, docs.Every gate exits 1 when it trips β see the CI guide.
// a few of the new fields const override = { graphql: { noErrors: true }, snapshot: { enabled: true, mode: "structural" }, retryOnStatus: { statuses: [503, 429], respectRetryAfter: true }, maxBytes: 1048576, strictMode: true };