# REST

> Send HTTP requests to REST services, validate them against the services' OpenAPI specifications, and assert on the responses.

Source: https://axx.nimbusxr.us/references/steps/rest/

Send HTTP requests to REST services, validate them against the services' OpenAPI specifications, and assert on the responses.

**Services.** Register services with `the <name> service with the following properties:` (`url`, optional `openapi`). The first service registered in a scenario is the default one; the other steps name a service with `on <name>`.

**Requests.** Each service keeps its requests in the order they are added: `a GET request to /path` adds the first (default) request and `a 2nd ordered POST request to /path` the second. Header, payload, execution and response steps address a request with `for 2nd ordered request` / `for 2nd ordered response` (default: the first). A request is executed once; its response stays available to every later step.

**Payloads.** A payload starts from an OpenAPI content example (the named one, or the first in document order; `externalValue` examples are read relative to the specification) or from an empty template `{}`, and is edited with the payload property steps (JSONPath, typed values, `null`/`undefined`). `application/x-www-form-urlencoded` payloads are sent form-encoded.

**Execution.** Requests go through one HTTP client shared by the run (connections are reused and closed at the end), honor the step timeout, follow redirects for GET and HEAD, and do not verify TLS certificates unless `packs.rest.tls.verify: true` is set in axx.yaml. Without a Content-Type header a payload is sent with its payload step's media type.

**OpenAPI validation.** When a service has an `openapi` specification (OpenAPI 3.0 or 3.1, a URL or a file; parsed once per run), each executed request and its response are validated after sending. Every finding has a key in the style of the swagger request validator (the one the WireMock extension uses), and a level:

- `ERROR` (alias `FAIL`, the default for every key) fails the execute step, listing every error with its key;
- `WARN` and `INFO` are logged on the step;
- `IGNORE` drops the finding.

Levels come from `openapi.levels` in axx.yaml and are overridden per scenario with `the OpenAPI validation levels are:`. A key also sets every more specific key (`validation.request.body` covers `validation.request.body.schema.required`); the most specific configured key wins.

| Key | Reported when |
| --- | --- |
| `validation.request.path.missing` | no path of the specification matches the request path |
| `validation.request.operation.notAllowed` | the path exists but not for the request method |
| `validation.request.body.missing` | the operation requires a body and the request has none |
| `validation.request.body.unexpected` | the request has a body the operation does not declare |
| `validation.request.contentType.notAllowed` | the request Content-Type is not declared for the operation |
| `validation.request.body.schema.{keyword}` | the request body violates a schema keyword (type, required, enum, format, pattern, minimum, maxLength, additionalProperties, oneOf, ...) |
| `validation.request.body.schema.invalidJson` | the request body cannot be parsed |
| `validation.request.body.schema.processingError` | the request body schema cannot be compiled or the body cannot be read |
| `validation.request.parameter.missing` | a required path parameter is missing |
| `validation.request.parameter.query.missing` | a required query parameter is missing |
| `validation.request.parameter.header.missing` | a required header parameter is missing |
| `validation.request.parameter.cookie.missing` | a required cookie parameter is missing |
| `validation.request.parameter.schema.{keyword}` | a parameter value violates its schema (type, enum, format, pattern, minimum, ...) |
| `validation.request.parameter.schema.invalidJson` | a JSON (content) parameter cannot be parsed |
| `validation.request.parameter.collection.invalidFormat` | an array or object parameter is serialized in the wrong style |
| `validation.request.parameter.collection.tooManyItems` | an array parameter has more than maxItems items |
| `validation.request.parameter.collection.tooFewItems` | an array parameter has fewer than minItems items |
| `validation.request.parameter.collection.duplicateItems` | an array parameter with uniqueItems repeats an item |
| `validation.request.parameter.{in}.invalid` | any other parameter problem; {in} is `path`, `query`, `header` or `cookie` |
| `validation.request.security.missing` | the credentials a security requirement needs are absent |
| `validation.request.security.invalid` | credentials are present but do not match the security scheme |
| `validation.response.status.unknown` | the response status is not documented for the operation (and there is no default) |
| `validation.response.contentType.notAllowed` | the response Content-Type is not declared for the status |
| `validation.response.body.missing` | the response declares a body schema but has no body |
| `validation.response.body.unexpected` | a response to HEAD has a body |
| `validation.response.body.schema.{keyword}` | the response body violates a schema keyword |
| `validation.response.body.schema.invalidJson` | the response body cannot be parsed |
| `validation.response.body.schema.processingError` | the response body schema cannot be compiled or the body cannot be read |
| `validation.response.header.missing` | a required response header is missing |
| `validation.response.header.schema.{keyword}` | a response header value violates its schema |
| `validation.request.unknownError` | anything else the validator reports about the request |
| `validation.response.unknownError` | anything else the validator reports about the response |

Schema keywords use the draft-4 names: `const` is reported as `enum`, `exclusiveMinimum`/`exclusiveMaximum` as `minimum`/`maximum`, `unevaluatedProperties` as `additionalProperties`.

When a scenario fails, its failure context (`rest`) shows the last request and response (headers, bodies truncated to 2 KB) and the OpenAPI findings.

## `rest.service`

```gherkin
Given the {word} service with the following properties:
  | ... | ... |
```

Register a REST service. The first service registered in a scenario is the default one.

Properties (`${env:..}`/`${sys:..}` are expanded):

- `url` (required): the base URL requests are sent to, e.g. `http://localhost:8080`.
- `openapi`: the service's OpenAPI 3.0 or 3.1 specification, as a URL or a file path (resolved against the `resources` roots). When set, every executed request and its response are validated against it, and content example payloads come from it.

**Parameters:** `{word}` (one word, no spaces)

**Example:**

```gherkin
Given the parcels service with the following properties:
```

## `rest.openapi.levels`

```gherkin
Given the OpenAPI validation levels[[ on {service}]] are:
  | ... | ... |
```

Override OpenAPI validation levels for this scenario (on the default or the named service). Each row is `validation key | level`; the level is `ERROR` (or its alias `FAIL`), `WARN`, `INFO` or `IGNORE`. A key covers every more specific key: `validation.request.body` relaxes `validation.request.body.schema.required` too, and the most specific configured key wins. Rows are merged over `openapi.levels` from axx.yaml. See the pack documentation for the keys.

**Variants** (optional parts in `[[...]]` above):

- `the OpenAPI validation levels are:`
- `the OpenAPI validation levels on {service} are:`

**Parameters:** `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given the OpenAPI validation levels are:
```

## `rest.request`

```gherkin
Given a(n) {word} request to {word}[[ on {service}]]
```

Add a request with a method and a path (optionally with a query string, e.g. `/api/parcels?sender=kestrel-books`) to the default or the named service. This is the service's first (default) request; add more with the ordered form. The path is appended to the service URL; an absolute URL replaces it.

**Variants** (optional parts in `[[...]]` above):

- `a(n) {word} request to {word}`
- `a(n) {word} request to {word} on {service}`

**Parameters:** `{word}` (one word, no spaces), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given a GET request to /api/parcels/PX-1001
Given a DELETE request to /api/parcels/PX-1001 on parcels
```

## `rest.request.ordered`

```gherkin
Given a {ordinal} ordered {word} request to {word}[[ on {service}]]
```

Add the Nth request of a service. Requests are numbered in the order they are added: the 1st ordered request is the default request, and the Nth can only be added once N-1 exist.

**Variants** (optional parts in `[[...]]` above):

- `a {ordinal} ordered {word} request to {word}`
- `a {ordinal} ordered {word} request to {word} on {service}`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{word}` (one word, no spaces), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given a 2nd ordered GET request to /api/parcels/PX-1001
Given a 1st ordered POST request to /api/parcels on parcels
```

## `rest.request.header`

```gherkin
Given the request header {word} is {string}[[ for {ordinal} ordered request]]
```

Set a request header. `Content-Type` and `Accept` replace an earlier value; other headers may be added more than once and are all sent. Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the request header {word} is {string}`
- `the request header {word} is {string} for {ordinal} ordered request`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given the request header Content-Type is 'application/json'
```

## `rest.request.header.on`

```gherkin
Given the request header {word} is {string} for[[ {ordinal} ordered]] request on {service}
```

`rest.request.header` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.header`.

**Variants** (optional parts in `[[...]]` above):

- `the request header {word} is {string} for request on {service}`
- `the request header {word} is {string} for {ordinal} ordered request on {service}`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given the request header Accept is 'application/json' for 1st ordered request on parcels
```

## `rest.request.headers`

```gherkin
Given the request headers[[ for {ordinal} ordered request]] are:
  | ... | ... |
```

Set request headers from a `name | value` table (a name may repeat). Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the request headers are:`
- `the request headers for {ordinal} ordered request are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given the request headers are:
```

## `rest.request.headers.on`

```gherkin
Given the request headers for[[ {ordinal} ordered]] request on {service} are:
  | ... | ... |
```

`rest.request.headers` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.headers`.

**Variants** (optional parts in `[[...]]` above):

- `the request headers for request on {service} are:`
- `the request headers for {ordinal} ordered request on {service} are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given the request headers for request on parcels are:
```

## `rest.request.payload.empty`

```gherkin
Given a request payload using a(n) {mimeType} empty content template[[ for {ordinal} ordered request]]
```

Start the request payload from an empty JSON object `{}`, to be filled with the payload property steps; no OpenAPI specification is needed. With `application/x-www-form-urlencoded` the properties are sent form-encoded (nested objects and arrays as JSON text). Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `a request payload using a(n) {mimeType} empty content template`
- `a request payload using a(n) {mimeType} empty content template for {ordinal} ordered request`

**Parameters:** `{mimeType}` (One of `application/json`, `text/json`, `application/problem+json`, `application/x-www-form-urlencoded`), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given a request payload using an application/json empty content template
```

## `rest.request.payload.empty.on`

```gherkin
Given a request payload using a(n) {mimeType} empty content template for[[ {ordinal} ordered]] request on {service}
```

`rest.request.payload.empty` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.payload.empty`.

**Variants** (optional parts in `[[...]]` above):

- `a request payload using a(n) {mimeType} empty content template for request on {service}`
- `a request payload using a(n) {mimeType} empty content template for {ordinal} ordered request on {service}`

**Parameters:** `{mimeType}` (One of `application/json`, `text/json`, `application/problem+json`, `application/x-www-form-urlencoded`), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given a request payload using an application/json empty content template for request on parcels
```

## `rest.request.payload.example`

```gherkin
Given a request payload using a(n) {mimeType} content example[[ named {string}]][[ for {ordinal} ordered request]]
```

Use a request body example of the service's OpenAPI specification as the payload: with `named '<name>'` the example of that name, otherwise the first example in document order (or the media type's single `example`). The example is looked up under the operation that matches the request's method and path, for the given media type. An example with an `externalValue` is read relative to the specification. Requires the service's `openapi` property and a request added first. Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `a request payload using a(n) {mimeType} content example`
- `a request payload using a(n) {mimeType} content example named {string}`
- `a request payload using a(n) {mimeType} content example for {ordinal} ordered request`
- `a request payload using a(n) {mimeType} content example named {string} for {ordinal} ordered request`

**Parameters:** `{mimeType}` (One of `application/json`, `text/json`, `application/problem+json`, `application/x-www-form-urlencoded`), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given a request payload using an application/json content example named 'Standard parcel'
```

## `rest.request.payload.example.on`

```gherkin
Given a request payload using a(n) {mimeType} content example[[ named {string}]] for[[ {ordinal} ordered]] request on {service}
```

`rest.request.payload.example` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.payload.example`.

**Variants** (optional parts in `[[...]]` above):

- `a request payload using a(n) {mimeType} content example for request on {service}`
- `a request payload using a(n) {mimeType} content example named {string} for request on {service}`
- `a request payload using a(n) {mimeType} content example for {ordinal} ordered request on {service}`
- `a request payload using a(n) {mimeType} content example named {string} for {ordinal} ordered request on {service}`

**Parameters:** `{mimeType}` (One of `application/json`, `text/json`, `application/problem+json`, `application/x-www-form-urlencoded`), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given a request payload using an application/json content example for 1st ordered request on parcels
```

## `rest.request.property`

```gherkin
Given the request payload property {word} is {string}[[ for {ordinal} ordered request]]
```

Set a payload property (a JSONPath such as `weightGrams`, `recipient.postcode` or `$.recipient.name`). A value in double quotes inside the quotes (`'"42"'`) is always a string. Otherwise the value takes the type of the current value (string, boolean, integer, number, object or array, parsed from JSON text); a property that does not exist yet, or is null, gets the type the text reads as (`true`, `42`, `1.5`, `{...}`, `[...]`, else a string). Requires a payload step first. Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the request payload property {word} is {string}`
- `the request payload property {word} is {string} for {ordinal} ordered request`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given the request payload property sender is 'kestrel-books'
```

## `rest.request.property.on`

```gherkin
Given the request payload property {word} is {string} for[[ {ordinal} ordered]] request on {service}
```

`rest.request.property` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.property`.

**Variants** (optional parts in `[[...]]` above):

- `the request payload property {word} is {string} for request on {service}`
- `the request payload property {word} is {string} for {ordinal} ordered request on {service}`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given the request payload property serviceLevel is 'EXPRESS' for request on parcels
```

## `rest.request.properties`

```gherkin
Given the request payload properties[[ for {ordinal} ordered request]] are:
  | ... | ... |
```

Set payload properties from a `path | value` table, row by row, like the single-property step. `null` sets JSON null and `undefined` removes the property (any case); write `"null"` or `"undefined"` in double quotes for the strings. Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the request payload properties are:`
- `the request payload properties for {ordinal} ordered request are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given the request payload properties are:
```

## `rest.request.properties.on`

```gherkin
Given the request payload properties for[[ {ordinal} ordered]] request on {service} are:
  | ... | ... |
```

`rest.request.properties` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.properties`.

**Variants** (optional parts in `[[...]]` above):

- `the request payload properties for request on {service} are:`
- `the request payload properties for {ordinal} ordered request on {service} are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given the request payload properties for 1st ordered request on parcels are:
```

## `rest.request.property.null`

```gherkin
Given the request payload property {word} is null[[ for {ordinal} ordered request]]
```

Set an existing payload property to JSON null. Without an ordinal the step applies to the first (default) request of the service; `for 2nd ordered request` picks the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the request payload property {word} is null`
- `the request payload property {word} is null for {ordinal} ordered request`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Given the request payload property recipient.street is null
```

## `rest.request.property.null.on`

```gherkin
Given the request payload property {word} is null for[[ {ordinal} ordered]] request on {service}
```

`rest.request.property.null` on a named service: `for request on <service>` addresses the service's first (default) request, `for 2nd ordered request on <service>` its second one. Everything else works like `rest.request.property.null`.

**Variants** (optional parts in `[[...]]` above):

- `the request payload property {word} is null for request on {service}`
- `the request payload property {word} is null for {ordinal} ordered request on {service}`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Given the request payload property recipient.street is null for request on parcels
```

## `rest.execute`

```gherkin
When the[[ {ordinal} ordered]] request is executed[[ on {service}]]
```

Send a request and keep its response for the response steps. With an OpenAPI specification the request and the response are validated after sending: findings at level ERROR fail the step (all of them are listed with their keys), WARN and INFO are logged. The payload is sent as is, form-encoded for `application/x-www-form-urlencoded`; without a Content-Type header the payload's media type is used. The request honors the step timeout. A request can be executed once.

**Variants** (optional parts in `[[...]]` above):

- `the request is executed`
- `the request is executed on {service}`
- `the {ordinal} ordered request is executed`
- `the {ordinal} ordered request is executed on {service}`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
When the request is executed
When the 2nd ordered request is executed on parcels
```

## `rest.response.status`

```gherkin
Then the[[ {ordinal} ordered]] response status code is {int}[[ on {service}]]
```

Assert the HTTP status code of a response. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response status code is {int}`
- `the response status code is {int} on {service}`
- `the {ordinal} ordered response status code is {int}`
- `the {ordinal} ordered response status code is {int} on {service}`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{int}` (a 32-bit integer), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response status code is 200
Then the 2nd ordered response status code is 201 on parcels
```

## `rest.response.body.contains`

```gherkin
Then the response body contains {string}[[ for {ordinal} ordered response]]
```

Assert that the response body contains the text. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response body contains {string}`
- `the response body contains {string} for {ordinal} ordered response`

**Parameters:** `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response body contains 'already registered'
```

## `rest.response.body.contains.on`

```gherkin
Then the response body contains {string} for[[ {ordinal} ordered]] response on {service}
```

`rest.response.body.contains` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.body.contains`.

**Variants** (optional parts in `[[...]]` above):

- `the response body contains {string} for response on {service}`
- `the response body contains {string} for {ordinal} ordered response on {service}`

**Parameters:** `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response body contains 'already registered' for 2nd ordered response on parcels
```

## `rest.response.header.is`

```gherkin
Then the response header {word} is {string}[[ for {ordinal} ordered response]]
```

Assert that a response header (name matched case-insensitively) has the value; with repeated headers, one of them must. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response header {word} is {string}`
- `the response header {word} is {string} for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response header Content-Type is 'application/json'
```

## `rest.response.header.is.on`

```gherkin
Then the response header {word} is {string} for[[ {ordinal} ordered]] response on {service}
```

`rest.response.header.is` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.header.is`.

**Variants** (optional parts in `[[...]]` above):

- `the response header {word} is {string} for response on {service}`
- `the response header {word} is {string} for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response header Content-Type is 'application/json' for response on parcels
```

## `rest.response.header.matches`

```gherkin
Then the response header {word} matches {pattern}[[ for {ordinal} ordered response]]
```

Assert that a response header matches a regular expression (Java syntax; it must match the whole value). With repeated headers, one of them must match. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response header {word} matches {pattern}`
- `the response header {word} matches {pattern} for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{pattern}` (A regular expression (Java syntax) without whitespace. It must match the whole value), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response header Content-Type matches ^application/json.*$
```

## `rest.response.header.matches.on`

```gherkin
Then the response header {word} matches {pattern} for[[ {ordinal} ordered]] response on {service}
```

`rest.response.header.matches` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.header.matches`.

**Variants** (optional parts in `[[...]]` above):

- `the response header {word} matches {pattern} for response on {service}`
- `the response header {word} matches {pattern} for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{pattern}` (A regular expression (Java syntax) without whitespace. It must match the whole value), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response header Content-Type matches ^application/json$ for 1st ordered response on parcels
```

## `rest.response.header.missing`

```gherkin
Then the response header {word} is missing[[ for {ordinal} ordered response]]
```

Assert that the response has no header with the name. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response header {word} is missing`
- `the response header {word} is missing for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response header Content-Length is missing
```

## `rest.response.header.missing.on`

```gherkin
Then the response header {word} is missing for[[ {ordinal} ordered]] response on {service}
```

`rest.response.header.missing` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.header.missing`.

**Variants** (optional parts in `[[...]]` above):

- `the response header {word} is missing for response on {service}`
- `the response header {word} is missing for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response header X-Custom is missing for response on parcels
```

## `rest.response.headers.are`

```gherkin
Then the response headers[[ for {ordinal} ordered response]] are:
  | ... | ... |
```

Assert response headers from a `name | value` table, each like the single-header step (a name may repeat). Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response headers are:`
- `the response headers for {ordinal} ordered response are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response headers are:
```

## `rest.response.headers.are.on`

```gherkin
Then the response headers for[[ {ordinal} ordered]] response on {service} are:
  | ... | ... |
```

`rest.response.headers.are` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.headers.are`.

**Variants** (optional parts in `[[...]]` above):

- `the response headers for response on {service} are:`
- `the response headers for {ordinal} ordered response on {service} are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response headers for 1st ordered response on parcels are:
```

## `rest.response.headers.match`

```gherkin
Then the response headers[[ for {ordinal} ordered response]] match:
  | ... | ... |
```

Assert response headers from a `name | regular expression` table (full match, Java syntax). Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response headers match:`
- `the response headers for {ordinal} ordered response match:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response headers match:
```

## `rest.response.headers.match.on`

```gherkin
Then the response headers for[[ {ordinal} ordered]] response on {service} match:
  | ... | ... |
```

`rest.response.headers.match` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.headers.match`.

**Variants** (optional parts in `[[...]]` above):

- `the response headers for response on {service} match:`
- `the response headers for {ordinal} ordered response on {service} match:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response headers for response on parcels match:
```

## `rest.response.headers.missing`

```gherkin
Then the response headers[[ for {ordinal} ordered response]] are missing:
  | ... | ... |
```

Assert that the response has none of the headers named in the table's first column. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response headers are missing:`
- `the response headers for {ordinal} ordered response are missing:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response headers are missing:
```

## `rest.response.headers.missing.on`

```gherkin
Then the response headers for[[ {ordinal} ordered]] response on {service} are missing:
  | ... | ... |
```

`rest.response.headers.missing` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.headers.missing`.

**Variants** (optional parts in `[[...]]` above):

- `the response headers for response on {service} are missing:`
- `the response headers for {ordinal} ordered response on {service} are missing:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response headers for response on parcels are missing:
```

## `rest.response.property.is`

```gherkin
Then the response payload property {word} is {string}[[ for {ordinal} ordered response]]
```

Assert a property of a JSON response (a JSONPath such as `status`, `recipient.postcode` or `[?(@.sender=='kestrel-books')].reference`; an indefinite path yields a list). The response must be JSON (`application/json`, `text/json` or any `+json` type, charset ignored). Values are compared with their JSON type: `'John'` or `"42"` (double quotes inside) are strings, `42` an integer, `42L` a long, `1.5` a number, `true`/`false` booleans, `{...}` and `[...]` JSON objects and arrays (compared regardless of member order). An integer never equals a decimal (`5` is not `5.0`). Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} is {string}`
- `the response payload property {word} is {string} for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response payload property status is 'REGISTERED'
```

## `rest.response.property.is.on`

```gherkin
Then the response payload property {word} is {string} for[[ {ordinal} ordered]] response on {service}
```

`rest.response.property.is` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.property.is`.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} is {string} for response on {service}`
- `the response payload property {word} is {string} for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{string}` (text in single or double quotes; the quotes are removed), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response payload property status is 'REGISTERED' for 1st ordered response on parcels
```

## `rest.response.property.null`

```gherkin
Then the response payload property {word} is null[[ for {ordinal} ordered response]]
```

Assert that a response payload property exists and is JSON null. Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} is null`
- `the response payload property {word} is null for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response payload property lastLocation is null
```

## `rest.response.property.null.on`

```gherkin
Then the response payload property {word} is null for[[ {ordinal} ordered]] response on {service}
```

`rest.response.property.null` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.property.null`.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} is null for response on {service}`
- `the response payload property {word} is null for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response payload property lastLocation is null for response on parcels
```

## `rest.response.property.undefined`

```gherkin
Then the response payload property {word} is undefined[[ for {ordinal} ordered response]]
```

Assert that a response payload property does not exist. (An indefinite path always exists: it reads as a possibly empty list.) Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} is undefined`
- `the response payload property {word} is undefined for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response payload property nonexistent is undefined
```

## `rest.response.property.undefined.on`

```gherkin
Then the response payload property {word} is undefined for[[ {ordinal} ordered]] response on {service}
```

`rest.response.property.undefined` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.property.undefined`.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} is undefined for response on {service}`
- `the response payload property {word} is undefined for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response payload property nonexistent is undefined for 1st ordered response on parcels
```

## `rest.response.property.matches`

```gherkin
Then the response payload property {word} matches {pattern}[[ for {ordinal} ordered response]]
```

Assert that a response payload property is a string that matches a regular expression (Java syntax; it must match the whole value). Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} matches {pattern}`
- `the response payload property {word} matches {pattern} for {ordinal} ordered response`

**Parameters:** `{word}` (one word, no spaces), `{pattern}` (A regular expression (Java syntax) without whitespace. It must match the whole value), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response payload property barcode matches ^PX[0-9]{11}$
```

## `rest.response.property.matches.on`

```gherkin
Then the response payload property {word} matches {pattern} for[[ {ordinal} ordered]] response on {service}
```

`rest.response.property.matches` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.property.matches`.

**Variants** (optional parts in `[[...]]` above):

- `the response payload property {word} matches {pattern} for response on {service}`
- `the response payload property {word} matches {pattern} for {ordinal} ordered response on {service}`

**Parameters:** `{word}` (one word, no spaces), `{pattern}` (A regular expression (Java syntax) without whitespace. It must match the whole value), `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response payload property barcode matches ^PX[0-9]{11}$ for response on parcels
```

## `rest.response.properties.are`

```gherkin
Then the response payload properties[[ for {ordinal} ordered response]] are:
  | ... | ... |
```

Assert response payload properties from a `path | value` table. `null` and `undefined` (any case) check for JSON null and absence; `"null"` in double quotes is the string. Every other value is compared like the single-property step. All rows are checked and every mismatch is reported. Values are compared with their JSON type: `'John'` or `"42"` (double quotes inside) are strings, `42` an integer, `42L` a long, `1.5` a number, `true`/`false` booleans, `{...}` and `[...]` JSON objects and arrays (compared regardless of member order). An integer never equals a decimal (`5` is not `5.0`). Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response payload properties are:`
- `the response payload properties for {ordinal} ordered response are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response payload properties are:
```

## `rest.response.properties.are.on`

```gherkin
Then the response payload properties for[[ {ordinal} ordered]] response on {service} are:
  | ... | ... |
```

`rest.response.properties.are` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.properties.are`.

**Variants** (optional parts in `[[...]]` above):

- `the response payload properties for response on {service} are:`
- `the response payload properties for {ordinal} ordered response on {service} are:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response payload properties for 1st ordered response on parcels are:
```

## `rest.response.properties.match`

```gherkin
Then the response payload properties[[ for {ordinal} ordered response]] match:
  | ... | ... |
```

Assert response payload properties from a `path | regular expression` table (full match, Java syntax). Without an ordinal the step checks the response of the first (default) request; `for 2nd ordered response` the response of the second one. Without `on {service}` it uses the default (first registered) service.

**Variants** (optional parts in `[[...]]` above):

- `the response payload properties match:`
- `the response payload properties for {ordinal} ordered response match:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first)

**Example:**

```gherkin
Then the response payload properties match:
```

## `rest.response.properties.match.on`

```gherkin
Then the response payload properties for[[ {ordinal} ordered]] response on {service} match:
  | ... | ... |
```

`rest.response.properties.match` on a named service: `for response on <service>` addresses the service's first (default) response, `for 2nd ordered response on <service>` its second one. Everything else works like `rest.response.properties.match`.

**Variants** (optional parts in `[[...]]` above):

- `the response payload properties for response on {service} match:`
- `the response payload properties for {ordinal} ordered response on {service} match:`

**Parameters:** `{ordinal}` (A 1-based position such as `1st`, `2nd`, `3rd` or `4th`. Omitting an optional ordinal means the first), `{service}` (The name of a REST service registered in the scenario)

**Example:**

```gherkin
Then the response payload properties for response on parcels match:
```
