Skip to main content

Asserts & tests

Asserts validate data. Add an assert: block with a list of tests to an action (to gate it) or to an interface (to check the final result). Each test resolves a value — with value (a JSON path), jq, pointer, or an action reference — then checks it with one or more conditions.

actions:
- name: CheckBody
input: a|body|
assert:
http_code_on_error: 400
tests:
- value: email
is_not_null: true
is_not_empty: true
- value: age
is_greater_than_or_equal_to: 18

The condition vocabulary is large — equality and ordering, string/pattern (contains, like, regex, …), type and emptiness, and specialized validators (is_valid_jwt, is_valid_hmac, verify_bcrypt, verify_signature, verify_schema, semver_matches, …). The filter transform reuses the same Test vocabulary. Every field of Assert and Test follows.

Assert

Assertion block for validating action output or interface results. Groups one or more tests with shared error handling and HTTP response codes.

Example - Action-level assertion

actions:
- name: ValidateBody
input: a|body|
assert:
tests:
- value: email
is_not_empty: true
regex: "^[^@]+@[^@]+\\.[^@]+$"
- value: age
is_greater_than: 0
error_message: "Validation failed"
http_code_on_error: 400

Example - Interface-level assertion

interfaces:
getUser:
method: GET
actions:
- name: FetchUser
database: main
query: SELECT * FROM users WHERE id = $1
params:
- a|params::id|
assert:
tests:
- value: count()
is_equal_to: 1
error_message: "User not found"
http_code_on_error: 404
http_code_on_success: 200
FieldTypeDescription
success_messagestring (nullable)Message returned on successful assertion.
error_messagestring (nullable)Message returned when any test fails. Overrides individual test error messages at the assert level.
http_code_on_errornumber (nullable)HTTP status code to return when any test fails. Individual test-level http_code_on_error takes precedence when set.
http_code_on_successnumber (nullable)HTTP status code to return when all tests pass.
testsArray<Test> (nullable)List of test definitions to evaluate. All tests run concurrently; errors from all tests are collected and returned together. Example ↓

Field examples

tests

List of test definitions to evaluate. All tests run concurrently; errors from all tests are collected and returned together.

Example

tests:
- value: username
is_not_empty: true
error_message: "Username is required"
http_code_on_error: 422
- value: password
is_not_empty: true
contains_upper: true
contains_number: true
is_greater_than: 7

Test

Test definition for asserting conditions against a resolved value. Tests support value resolution (via value, jq, pointer, or action), type-aware comparisons, pattern matching, and structural schema validation.

When used inside an assert block, multiple tests run concurrently. When used inside verify_schema via FieldType.validate, the test runs against the leaf value at that schema path.

Example - Basic value checks

tests:
- value: email
is_not_empty: true
regex: "^[^@]+@[^@]+\\.[^@]+$"
error_message: "Invalid email"
http_code_on_error: 422

Example - Numeric comparisons

tests:
- value: age
is_greater_than: 0
is_less_than: 150
- value: count()
is_greater_than_or_equal_to: 1

Example - Using jq for nested access

tests:
- jq: ".data.users | length"
is_greater_than: 0

Example - Cross-action reference

tests:
- action: FetchUser
value: email
is_not_null: true

Example - Allowed/disallowed values

tests:
- value: status
contains:
allowed:
- "active"
- "pending"
- "suspended"
disallowed:
- "deleted"

Example - Schema validation with deep nested assertions

tests:
- verify_schema:
disallow_unknown_keys: true
structure:
email:
type: String
validate:
is_not_empty: true
regex: "^[^@]+@[^@]+\\.[^@]+$"
age:
type: Number
validate:
is_greater_than: 0
settings:
theme:
type: String
notifications:
type: Boolean
FieldTypeDescription
namestring (nullable)Human-readable name for identifying this test in logs and error output.
descriptionstring (nullable)Description of what this test validates.
valuestring (nullable)JSON path to the target value within the input data (e.g., email, user.name). Also supports count() to get the length of an array. Example ↓
actionstring (nullable)Reference a previous action's output as the target value. Example ↓
action_valuestring (nullable)Reference a previous action's output using interpolation syntax. Example ↓
custom_valuestring (nullable)Override the target value with a custom literal string. Example ↓
jqstring (nullable)Extract the target value using a jq filter expression. Example ↓
pointerstring (nullable)Extract the target value using a JSON pointer (RFC 6901). Example ↓
http_code_on_errornumber (nullable)HTTP status code to return when this specific test fails. Takes precedence over the parent Assert.http_code_on_error.
success_messagestring (nullable)Message returned when this test succeeds.
error_messagestring (nullable)Custom error message when this test fails. Replaces the default auto-generated error detail. Example ↓
hide_errorsboolean (nullable)Suppress error details from the response output for this test.
http_responseanyStatic HTTP response value to return when this test is evaluated.
case_insensitiveboolean (nullable)Enable case-insensitive matching for is_equal_to and contains checks. Example ↓
is_equal_toanyAssert the value equals the expected value. Behavior varies by type: strings compare as text, numbers as numeric value, booleans as bool, arrays and objects compare as full… Example ↓
is_not_equal_toanyAssert the value does not equal the expected value. Example ↓
is_less_thananyAssert the value is less than the threshold. For strings and arrays, compares the length. For numbers, compares the numeric value. Example ↓
is_less_than_or_equal_toanyAssert the value is less than or equal to the threshold. Same type-dependent behavior as is_less_than.
is_greater_thananyAssert the value is greater than the threshold. Same type-dependent behavior as is_less_than. Example ↓
is_greater_than_or_equal_toanyAssert the value is greater than or equal to the threshold. Same type-dependent behavior as is_less_than.
starts_withanyAssert the string value starts with the given prefix. Example ↓
not_starts_withany
ends_withanyAssert the string value ends with the given suffix. Example ↓
not_ends_withany
contains_textboolean (nullable)Assert the string contains at least one alphabetic character.
contains_numberboolean (nullable)Assert the string contains at least one numeric digit.
contains_upperboolean (nullable)Assert the string contains at least one uppercase letter.
contains_lowerboolean (nullable)Assert the string contains at least one lowercase letter.
contains_specialboolean (nullable)Assert the string contains at least one special character.
containsContainOptions (nullable)Assert containment. Behavior varies by target type: - String: substring match (or exact match in advanced/any mode) - Number: substring match against the string… Example ↓
likestring (nullable)SQL LIKE-style pattern matching (case-sensitive). Uses % as wildcard. Example ↓
ilikestring (nullable)SQL ILIKE-style pattern matching (case-insensitive). Uses % as wildcard. Example ↓
not_containsContainOptions (nullable)Inverse of contains. Assert the value does NOT contain the specified content. Same mode support as contains (standard, advanced, any). Example ↓
regexstring (nullable)Assert the string value matches a regular expression pattern. Example ↓
is_not_nullboolean (nullable)Assert the value is not null. Example ↓
is_not_emptyboolean (nullable)Assert the value is not empty. Checks strings, arrays, and objects. Example ↓
is_nullboolean (nullable)Assert the value is null (when true) or is not null (when false). Example ↓
is_uuidboolean (nullable)Assert the value is a valid UUID string. Example ↓
is_arrayboolean (nullable)Assert the value is a JSON array. Example ↓
is_valid_jwtJwtConfig (nullable)Validate the value as a JWT token using the provided secret. On success, decoded claims are stored in ok_data under the key specified by result_key (default: jwt_claims). Example ↓
is_valid_hmacIsValidHmacConfig (nullable)Verify an HMAC signature. The value field should point to the signature received in the request (e.g. x-hub-signature-256). The assertion recomputes HMAC over body using… Example ↓
is_authorizationboolean (nullable)Parse an HTTP Authorization header value. Supports Basic (decodes base64 username:password) and Bearer (extracts token). Decoded data is stored in ok_data keyed by scheme… Example ↓
result_keystring (nullable)Key name for storing extracted data (e.g., JWT claims) in the action's ok_data output.
expressionstring (nullable)Evaluate a string expression as a boolean condition. Supports interpolation via a|...| syntax before evaluation. Example ↓
compare_valueCompareValue (nullable)Compare the target value against another value or file for structural differences. Supports JSON, XML, and string comparison with optional field exclusions. Example ↓
bcrypt_verifystring (nullable)Verify a plaintext value against a bcrypt hash. Deprecated: use verify_bcrypt.
verify_bcryptstring (nullable)Verify a plaintext value against a bcrypt hash. Example ↓
verify_signatureVerifySignature (nullable)Verify an Ed25519 signature against the target value. Example ↓
verify_schemaVerifySchema (nullable)Validate the value against a structural schema with recursive type checking and optional per-field assertions. Supports nested objects, arrays, and leaf-level validation via… Example ↓
semver_matchesstring (nullable)Assert the string value satisfies a semver version constraint. Example ↓
size_limitstring (nullable)Assert the serialized byte size of the value does not exceed a limit. Accepts human-readable sizes (e.g., 1 MB, 500 KB) or raw byte counts. Example ↓

Field examples

value

JSON path to the target value within the input data (e.g., email, user.name). Also supports count() to get the length of an array.

Example

value: email             # simple key
value: user.address.city # nested path
value: count() # array length

action

Reference a previous action's output as the target value.

Example

action: FetchUser
value: email # key within that action's output

action_value

Reference a previous action's output using interpolation syntax.

Example

action_value: a|FetchUser::email|

custom_value

Override the target value with a custom literal string.

Example

custom_value: "some_static_value"
is_equal_to: "some_static_value"

jq

Extract the target value using a jq filter expression.

Example

jq: ".users[0].email"
is_not_empty: true

pointer

Extract the target value using a JSON pointer (RFC 6901).

Example

pointer: "/data/0/email"
is_not_empty: true

error_message

Custom error message when this test fails. Replaces the default auto-generated error detail.

Example

value: email
is_not_empty: true
error_message: "Email address is required"

case_insensitive

Enable case-insensitive matching for is_equal_to and contains checks.

Example

value: status
is_equal_to: "active"
case_insensitive: true # matches "Active", "ACTIVE", etc.

is_equal_to

Assert the value equals the expected value. Behavior varies by type: strings compare as text, numbers as numeric value, booleans as bool, arrays and objects compare as full JSON equality.

Example

is_equal_to: "active"      # string
is_equal_to: 42 # number
is_equal_to: true # boolean

is_not_equal_to

Assert the value does not equal the expected value.

Example

is_not_equal_to: "deleted"

is_less_than

Assert the value is less than the threshold. For strings and arrays, compares the length. For numbers, compares the numeric value.

Example

# String: length < 256
value: title
is_less_than: 256

# Number: value < 100
value: percentage
is_less_than: 100

# Array: length < 10
value: items
is_less_than: 10

is_greater_than

Assert the value is greater than the threshold. Same type-dependent behavior as is_less_than.

Example

value: age
is_greater_than: 0

starts_with

Assert the string value starts with the given prefix.

Example

value: url
starts_with: "https://"

ends_with

Assert the string value ends with the given suffix.

Example

value: filename
ends_with: ".pdf"

contains

Assert containment. Behavior varies by target type:

  • String: substring match (or exact match in advanced/any mode)
  • Number: substring match against the string representation
  • Array: element membership
  • Object: key existence

Supports three modes: standard (single value or array), advanced (with at_least threshold), and any (with allowed/disallowed lists).

Example - String substring

value: email
contains: "@"

Example - Array membership

value: tags
contains: "featured"

Example - Allowed values

value: status
contains:
allowed:
- "active"
- "pending"
disallowed:
- "deleted"

Example - At least N matches

value: roles
contains:
values:
- "admin"
- "editor"
- "viewer"
at_least: 1

like

SQL LIKE-style pattern matching (case-sensitive). Uses % as wildcard.

Example

value: name
like: "John%" # starts with "John"

ilike

SQL ILIKE-style pattern matching (case-insensitive). Uses % as wildcard.

Example

value: email
ilike: "%@gmail.com" # any Gmail address

not_contains

Inverse of contains. Assert the value does NOT contain the specified content. Same mode support as contains (standard, advanced, any).

Example

value: content
not_contains: "<script>"

regex

Assert the string value matches a regular expression pattern.

Example

value: phone
regex: "^\\+?[1-9]\\d{1,14}$"

is_not_null

Assert the value is not null.

Example

value: user_id
is_not_null: true

is_not_empty

Assert the value is not empty. Checks strings, arrays, and objects.

Example

value: name
is_not_empty: true

is_null

Assert the value is null (when true) or is not null (when false).

Example

value: deleted_at
is_null: true # must be null

value: email
is_null: false # must not be null

is_uuid

Assert the value is a valid UUID string.

Example

value: id
is_uuid: true

is_array

Assert the value is a JSON array.

Example

value: items
is_array: true

is_valid_jwt

Validate the value as a JWT token using the provided secret. On success, decoded claims are stored in ok_data under the key specified by result_key (default: jwt_claims).

Example

value: token
is_valid_jwt: "my_jwt_secret" # HS256 secret (bare string), or an object:
# is_valid_jwt: { jwks_url: "...", alg: RS256, iss: "...", aud: "..." }
result_key: user_claims

is_valid_hmac

Verify an HMAC signature. The value field should point to the signature received in the request (e.g. x-hub-signature-256). The assertion recomputes HMAC over body using secret and compares against the target.

Example (GitHub webhook)

value: x-hub-signature-256
is_valid_hmac:
secret: a|env::GITHUB_WEBHOOK_SECRET|
body: a|raw_body|
algorithm: sha256 # sha1 | sha256 | sha512 (default: sha256)
prefix: "sha256=" # stripped from target before comparison

is_authorization

Parse an HTTP Authorization header value. Supports Basic (decodes base64 username:password) and Bearer (extracts token). Decoded data is stored in ok_data keyed by scheme name.

Example

value: authorization
is_authorization: true

expression

Evaluate a string expression as a boolean condition. Supports interpolation via a|...| syntax before evaluation.

Example

expression: "a|body::count| > 0"

compare_value

Compare the target value against another value or file for structural differences. Supports JSON, XML, and string comparison with optional field exclusions.

Example - Compare against inline target

compare_value:
target: '{"status": "ok"}'
data_type: json
ignore_fields:
- timestamp

Example - Compare against file

compare_value:
file_path: "/path/to/expected.json"
data_type: json

verify_bcrypt

Verify a plaintext value against a bcrypt hash.

Example

value: password
verify_bcrypt: "$2b$12$LJ3m..."

verify_signature

Verify an Ed25519 signature against the target value.

Example

value: request_body
verify_signature:
public_key: "a1b2c3..." # hex-encoded Ed25519 public key
signature: "d4e5f6..." # hex-encoded signature

verify_schema

Validate the value against a structural schema with recursive type checking and optional per-field assertions. Supports nested objects, arrays, and leaf-level validation via the validate field on each FieldType.

Example - Flat structure

verify_schema:
disallow_unknown_keys: true
structure:
name:
type: String
validate:
is_not_empty: true
age:
type: Number
validate:
is_greater_than: 0
active:
type: Boolean

Example - Nested objects with validation

verify_schema:
structure:
user:
email:
type: String
validate:
is_not_empty: true
regex: "^[^@]+@[^@]+\\.[^@]+$"
settings:
theme:
type: String
validate:
contains:
allowed:
- "light"
- "dark"
- "system"
notifications:
type: Boolean

Example - Array with positional validation

verify_schema:
structure:
- id:
type: Number
validate:
is_greater_than: 0
title:
type: String
validate:
is_not_empty: true
is_less_than: 256

semver_matches

Assert the string value satisfies a semver version constraint.

Example

value: api_version
semver_matches: ">=1.0.0, <2.0.0"

size_limit

Assert the serialized byte size of the value does not exceed a limit. Accepts human-readable sizes (e.g., 1 MB, 500 KB) or raw byte counts.

Example

value: payload
size_limit: "1 MB"

ContainOptions

Containment check options. Supports three modes depending on the YAML structure provided: standard (single value or array), advanced (with at_least threshold), and any (with allowed/disallowed lists).

Example - Standard single value

contains: "search_term"

Example - Standard array (match at least one)

contains:
- "admin"
- "editor"

Example - Advanced (at least N matches)

contains:
values:
- "read"
- "write"
- "delete"
at_least: 2

Example - Allowed/disallowed lists

contains:
allowed:
- "active"
- "pending"
disallowed:
- "banned"

One of:

  • ContainsAny — Allowed/disallowed list mode. Target must match an allowed value and must not match any disallowed value.
  • ContainsAdv — Advanced mode with explicit value list and minimum match threshold.
  • any — Standard mode: a single value or array of values to check for containment.

ContainsAny

Allowed/disallowed containment check. For strings, checks exact match against each list. For arrays, checks that all elements are in allowed and no elements are in disallowed.

Example

contains:
allowed:
- "published"
- "draft"
- "archived"
disallowed:
- "deleted"
- "banned"
FieldTypeDescription
allowedArray<any> (nullable)Values the target is allowed to match.
disallowedArray<any> (nullable)Values the target must not match.

ContainsAdv

Advanced containment check with a minimum match threshold.

Example

contains:
values:
- "read"
- "write"
- "admin"
at_least: 2 # target must match at least 2 of the listed values
FieldTypeDescription
valuesArray<any>Required. List of candidate values to check against.
at_leastnumberRequired. Minimum number of values that must match for the check to pass.

JwtConfig

Configuration for the is_valid_jwt assertion.

Accepts either a bare string (the HS256 shared secret — the original form, still supported) or an object for asymmetric algorithms and OIDC providers:

# HS256 (unchanged):
is_valid_jwt: "my-shared-secret"

# RS256/ES256 with a static PEM public key:
is_valid_jwt:
alg: RS256
public_key: a|ap_var::IDP_PUBLIC_KEY|

# RS256/ES256 verified against a provider's rotating JWKS (Auth0/Clerk/Cognito):
is_valid_jwt:
jwks_url: https://YOUR.auth0.com/.well-known/jwks.json
alg: RS256 # optional; falls back to the token header's alg
iss: https://YOUR.auth0.com/
aud: https://your-api

One of:

  • string — Bare HS256 shared secret (back-compatible form).
  • JwtVerifyConfig — Structured verification config for HS*/RS*/ES*/EdDSA and JWKS.

JwtVerifyConfig

Structured form of [JwtConfig] — a symmetric secret, a static public key, or a JWKS URL, plus optional algorithm and issuer/audience checks.

FieldTypeDescription
secretstring (nullable)HS256/384/512 shared secret. Mutually exclusive with public_key/jwks_url.
public_keystring (nullable)PEM-encoded public key for RS*/ES*/EdDSA verification (no network calls).
jwks_urlstring (nullable)URL of a JWKS document; the signing key is selected by the token's kid. Fetched once and cached (with a short TTL), so provider key rotation is handled.
algstring (nullable)Signature algorithm, e.g. HS256, RS256, ES256, EdDSA. Required for public_key; for jwks_url it defaults to the token header's alg.
issstring (nullable)Expected iss claim. When set, tokens with a different issuer are rejected.
audstring (nullable)Expected aud claim. When set, tokens with a different audience are rejected.

IsValidHmacConfig

Configuration for the is_valid_hmac assertion.

FieldTypeDescription
secretstringRequired. HMAC secret key. Supports interpolation: a|env::MY_SECRET|
bodystringRequired. The message to authenticate. Use a|raw_body| for webhook signature verification so the bytes match exactly what the sender signed.
algorithmstring (nullable)Hash algorithm: sha1, sha256 (default), or sha512.
prefixstring (nullable)Optional prefix to strip from the target value before comparing. GitHub uses "sha256=", Stripe uses "v1=".
encodingstring (nullable)How the signature in the target value is encoded: hex (default) or base64. GitHub, Stripe and Slack send hex; Shopify sends standard base64 in X-Shopify-Hmac-Sha256.

CompareValue

Value comparison configuration for diffing against an expected value. Supports inline target strings or file paths, with optional field exclusions.

Example - Inline comparison

compare_value:
target: '{"status": "ok", "code": 200}'
data_type: json
ignore_fields:
- timestamp
- request_id

Example - File comparison

compare_value:
file_path: "./fixtures/expected_response.json"
data_type: json

One of:

  • target → string
  • file_path → string

CompareDataType

Type: string — one of: json, xml, string

VerifySignature

Ed25519 signature verification parameters.

Example

value: request_body
verify_signature:
public_key: "a1b2c3d4e5f6..." # hex-encoded Ed25519 public key
signature: "f6e5d4c3b2a1..." # hex-encoded signature bytes
FieldTypeDescription
public_keystringRequired. Hex-encoded Ed25519 public key.
signaturestringRequired. Hex-encoded signature bytes to verify against the target value.

VerifySchema

Schema validation configuration. Validates a JSON value against a recursive type structure with optional per-field assertions and unknown key rejection.

Example - Basic object validation

verify_schema:
disallow_unknown_keys: true
structure:
name:
type: String
validate:
is_not_empty: true
email:
type: String
validate:
regex: "^[^@]+@[^@]+\\.[^@]+$"
age:
type: Number
validate:
is_greater_than: 0
is_less_than: 150

Example - Nested with unknown key rejection

verify_schema:
disallow_unknown_keys: true
structure:
user:
name:
type: String
role:
type: String
validate:
contains:
allowed:
- "admin"
- "editor"
- "viewer"
metadata:
created_at:
type: Number
version:
type: String
validate:
semver_matches: ">=1.0.0"

Example - Array of objects (positional)

verify_schema:
structure:
- id:
type: Number
validate:
is_greater_than: 0
status:
type: String
validate:
is_not_empty: true
settings:
category:
type: String
featured:
type: Boolean
FieldTypeDescription
disallow_unknown_keysboolean (nullable)When true, any keys present in the value but not defined in the schema are reported as errors. Applies recursively to all nested objects.
structureValueTypeRequired. The expected structure definition. Can be a nested object map, a positional array, or a single leaf field type.

ValueType

Schema value type for recursive structural validation. Represents either a leaf field with a type constraint, a nested object with named fields, or a positional array of typed elements.

Example - Leaf field

email:
type: String
validate:
is_not_empty: true

Example - Nested object

user:
name:
type: String
settings:
theme:
type: String

Example - Positional array

structure:
- name:
type: String
id:
type: Number

One of:

  • FieldType — Leaf field with type constraint and optional validation.
  • Map<string, ValueType> — Nested object where each key maps to another ValueType.
  • Array<ValueType> — Positional array where each index maps to a ValueType.

FieldType

Leaf field definition within a verify_schema structure. Specifies the expected data type and optional validation assertions that run against the resolved value at this path.

Supported types: String, Number, Boolean, Array, Object, Null, Any.

Example - Type check only

email:
type: String

Example - Type check with assertions

rating:
type: Number
validate:
is_greater_than_or_equal_to: 0
is_less_than_or_equal_to: 5

Example - String with pattern and length

slug:
type: String
validate:
is_not_empty: true
regex: "^[a-z0-9]+(-[a-z0-9]+)*$"
is_less_than: 128

Example - Enum-like string constraint

status:
type: String
validate:
contains:
allowed:
- "published"
- "draft"
- "archived"
FieldTypeDescription
typestringRequired. Expected data type. One of: String, Number, Boolean, Array, Object, Null, Any.
validateTest (nullable)Optional test assertions to run against the leaf value after the type check passes. Uses the same Test definition as the normal assertion system, giving full access to all… Example ↓

Field examples

validate

Optional test assertions to run against the leaf value after the type check passes. Uses the same Test definition as the normal assertion system, giving full access to all checks (is_equal_to, regex, contains, is_greater_than, etc.).

Example

validate:
is_not_empty: true
regex: "^[a-z0-9-]+$"
is_less_than: 64