Skip to navigation

httpRequest

The httpRequest action makes arbitrary HTTP calls, allowing you to interact with and validate APIs or other web services directly within your tests.

You can specify a basic GET request using a string shorthand or use an object for more complex requests and validation:

  • String Shorthand: Provide the full URL directly as the value for the httpRequest key. This performs a basic GET request to that URL.
  • Object Format: Use an object with the following properties:
    • url: (Required unless using openApi) The target URL for the request.
    • method: (Optional) The HTTP method (for example, GET, POST, PUT, DELETE). Defaults to GET.
    • timeout: (Optional) Maximum duration in milliseconds to wait for the request to complete.
    • request: (Optional) An object defining the request details:
      • headers: (Optional) Request headers, as either key-value pairs or a newline-separated string block such as Content-Type: application/json\nAuthorization: Bearer token. In the string form, Doc Detective splits each line on its first colon. Header values can therefore contain colons themselves, including full URLs, timestamps like 12:00:00 GMT, and host:port values.
      • parameters: (Optional) Key-value pairs for query string parameters.
      • body: (Optional) The request body. Can be a string or JSON object.
    • response: (Optional) An object defining expected response validation:
      • headers: (Optional) Key-value pairs for expected response headers. Values must be strings.
      • body: (Optional) Expected response body. Can be a string or JSON object.
      • required: (Optional) Array of field paths that must exist in the response body. Uses dot notation for nested fields (for example, user.name) and bracket notation for array indices (for example, items[0].id). Fields can have any value, including null.
    • allowAdditionalFields: (Optional) Whether the response may contain fields beyond those declared in response.body. Defaults to true. Set it to false to fail the step when the response includes any field not declared in response.body. The check is recursive. It descends into nested objects and names each undeclared field by its dot-path, such as user.extra. It applies only when the top-level response.body declares fields. When response.body is unset or empty, the response has no key constraint and the check passes. A nested empty object still constrains. A response.body of { "user": {} } requires user to be empty, so any field under it fails the step.
    • statusCodes: (Optional) An array of acceptable HTTP status codes. If the response code is not in this list, the step fails (default: [200, 201]).
    • openApi: (Optional) Define the request based on an OpenAPI definition. Can be a string (operation ID) or an object:
      • name: (Optional) Name of the registered OpenAPI definition (if multiple are loaded).
      • descriptionPath: (Optional) Path or URL to the OpenAPI description file.
      • operationId: (Required) The ID of the operation to use.
      • server: (Optional) Base server URL for the request. If omitted, Doc Detective uses the first server defined in the OpenAPI description.
      • validateAgainstSchema: (Optional) Which parts of the request and response to validate against the OpenAPI schema (request, response, both, or none). The step fails on a mismatch. Defaults to both.
      • mockResponse: (Optional) When true, skips the HTTP request and uses the response example or schema from the OpenAPI description as the response data. Useful for testing an API that isn’t fully implemented yet. If statusCode isn’t set, Doc Detective uses the first response code defined for the operation.
      • statusCode: (Optional) Response code to use for validation, examples, and status-code checking. Doc Detective adds this code to the step’s accepted statusCodes.
      • useExample: (Optional) Which parts of the request and response to populate with example data from the OpenAPI description (request, response, both, or none). Defaults to none.
      • exampleKey: (Optional) Key of the specific example to use if multiple exist.
      • headers: (Optional) Request headers to add to every request built from the definition, such as an Authorization header. A step-level value overrides a matching header set in your configuration. Note: Properties like request.headers, request.parameters, request.body can override values from the OpenAPI definition or example.
    • Output Saving: You can also save the response body using path, directory, maxVariation, and overwrite properties. See the httpRequest reference for details.

Setting Variables: To capture parts of the response for later steps, use the step-level variables object. You can assign values based on the response using expressions like $$response.body, $$response.headers, $$response.status, etc. You can use dot notation for nested JSON fields (for example, $$response.body.user.id).

Depending on which validations you configure, the action also exposes the result of each check in its outputs object. To capture any of them for later steps, use the step-level variables object with the matching expression. Each output is present only when its check applies:

  • $$requiredFieldsPresent: whether every field in response.required was found (when response.required is set).
  • $$bodyMatches: whether the response body matched response.body (when response.body is set).
  • $$headersMatch: whether the expected response.headers were present (when response.headers is set).
  • $$noUnexpectedFields: whether the response contained only expected fields (when allowAdditionalFields is false).
  • $$responseSchemaValid: whether the response matched the OpenAPI schema (when validating the response against an OpenAPI definition).
  • $$variation: the fractional difference between the new response and the reference file (when you save the response with path and a reference file already exists).

For comprehensive options, see the httpRequest reference.

Examples

Here are a few ways you might use the httpRequest action:

Basic GET request (string shorthand)

{
"tests": [
{
"steps": [
{
"description": "Perform a basic GET request.",
"httpRequest": "https://reqres.in/api/users?page=2"
}
]
}
]
}

Basic GET request (object format)

{
"tests": [
{
"steps": [
{
"description": "Perform a simple GET request using object format.",
"httpRequest": {
"url": "https://reqres.in/api/users?page=2"
}
}
]
}
]
}

POST request with JSON body

{
"tests": [
{
"steps": [
{
"description": "Create a user via POST request.",
"httpRequest": {
"url": "https://reqres.in/api/users",
"method": "POST",
"request": {
"body": {
"name": "morpheus",
"job": "leader"
}
}
}
}
]
}
]
}

PUT request with headers and query parameters

{
"tests": [
{
"steps": [
{
"description": "Update a user via PUT request.",
"httpRequest": {
"url": "https://reqres.in/api/users/2",
"method": "PUT",
"request": {
"headers": {
"Content-Type": "application/json"
},
"parameters": {
"source": "test"
},
"body": {
"name": "morpheus",
"job": "zion resident"
}
}
}
}
]
}
]
}

Send request headers as a string block

You can also provide request.headers as a single newline-separated string instead of an object. Doc Detective splits each line on its first colon into a name and value. Values that contain colons, such as callback URLs or timestamps, stay intact.

{
"tests": [
{
"steps": [
{
"description": "Send request headers as a newline-separated string.",
"httpRequest": {
"url": "https://reqres.in/api/users",
"method": "POST",
"request": {
"headers": "Content-Type: application/json\nX-Callback: https://example.com/cb",
"body": {
"name": "morpheus",
"job": "leader"
}
}
}
}
]
}
]
}

Validate response status code and body

{
"tests": [
{
"steps": [
{
"description": "Create user and validate response.",
"httpRequest": {
"url": "https://reqres.in/api/users",
"method": "POST",
"request": {
"body": {
"name": "morpheus",
"job": "leader"
}
},
"response": {
"body": {
"name": "morpheus",
"job": "leader",
}
},
"statusCodes": [201] // Expect HTTP 201 Created
}
}
]
}
]
}

Use OpenAPI definition (by operation ID)

Assumes an OpenAPI definition with operation ID getUserById is loaded.

{
"tests": [
{
"steps": [
{
"description": "Get user by ID using OpenAPI definition.",
"httpRequest": {
"openApi": "getUserById",
"request": {
"parameters": { // Provide required path parameter
"id": 2
}
}
}
}
]
}
]
}

Use OpenAPI definition (detailed object)

{
"tests": [
{
"steps": [
{
"description": "Get user by ID using specific OpenAPI file.",
"httpRequest": {
"openApi": {
"descriptionPath": "./reqres.openapi.json",
"operationId": "getUserById"
},
"request": {
"parameters": {
"id": 3
}
}
}
}
]
}
]
}

Set a variable from response body

{
"tests": [
{
"steps": [
{
"description": "Create user and capture the ID.",
"httpRequest": {
"url": "https://reqres.in/api/users",
"method": "POST",
"request": {
"body": {"name": "neo", "job": "the one"}
},
"statusCodes": [201]
},
"variables": {
"USER_ID": "$$response.body.id"
}
},
{
"description": "Use the captured ID in the next request.",
"httpRequest": {
"url": "https://reqres.in/api/users/$USER_ID", // Use variable in URL
"method": "GET"
}
}
]
}
]
}

Save response body to a file

{
"tests": [
{
"steps": [
{
"description": "Get user data and save response to file.",
"httpRequest": {
"url": "https://reqres.in/api/users/2",
"method": "GET",
"path": "user_2_response.json", // File name
"directory": "./output/api_responses" // Output directory
}
}
]
}
]
}

Validate fields with dynamic values

When testing APIs that return unpredictable values (like timestamps, UUIDs, or session tokens), you can verify that fields exist without asserting their exact values.

{
"tests": [
{
"steps": [
{
"description": "Verify user response includes required fields.",
"httpRequest": {
"url": "https://api.example.com/users/123",
"method": "GET",
"response": {
"required": ["id", "email", "createdAt", "sessionToken"]
}
}
}
]
}
]
}

Validate nested fields and arrays

Use dot notation for nested object fields and bracket notation for array elements to validate complex response structures.

{
"tests": [
{
"steps": [
{
"description": "Verify nested user profile fields exist.",
"httpRequest": {
"url": "https://api.example.com/users/123",
"method": "GET",
"response": {
"required": [
"user.profile.name",
"user.profile.avatar",
"user.settings.notifications"
]
}
}
},
{
"description": "Verify array elements contain required fields.",
"httpRequest": {
"url": "https://api.example.com/orders",
"method": "GET",
"response": {
"required": [
"orders[0].id",
"orders[0].total",
"orders[0].items[0].productId"
]
}
}
}
]
}
]
}

Combine required fields with body validation

You can use both response.required and response.body together to validate that certain fields exist while asserting specific values for others.

{
"tests": [
{
"steps": [
{
"description": "Validate both specific values and required fields.",
"httpRequest": {
"url": "https://api.example.com/users",
"method": "POST",
"request": {
"body": {
"username": "testuser",
"role": "admin"
}
},
"response": {
"required": ["sessionToken", "expiresAt", "user.id"],
"body": {
"status": "success",
"user": {
"role": "admin"
}
}
},
"statusCodes": [201]
}
}
]
}
]
}

Note: Fields with null, "", 0, or false values are considered to exist and will pass validation.

Reject unexpected response fields

Set allowAdditionalFields to false to assert that the response contains only the fields you declared in response.body. The step fails if the response includes any extra field.

The check descends into nested objects. It catches an extra field at any depth and names it by its dot-path. A nested empty object is still a constraint. Declaring "user": {} in response.body requires the response’s user object to be empty, so any field it carries fails the step. Only an unset or empty top-level response.body lifts the constraint entirely.

{
"tests": [
{
"steps": [
{
"description": "Fail if the response returns fields beyond those declared.",
"httpRequest": {
"url": "https://api.example.com/users/123",
"method": "GET",
"response": {
"body": {
"id": 123,
"name": "morpheus"
}
},
"allowAdditionalFields": false
}
}
]
}
]
}