The API Testing module in Thunders lets you call any HTTP endpoint from a test step, inspect the response, and turn parts of that response into automated checks or reusable variables. This page covers the two key capabilities built on top of API steps: Response Assertions and Variable Extraction.
TL;DR — Run an API step → open the Response Inspector by clicking on the API step → click Assert or Extract on any value → each click appends a step at the end of the test case → Execute
What the Feature Does
When an API step executes, Thunders captures the full HTTP response:
Status code (e.g.
200,404)Duration and load duration (in milliseconds)
Response body (parsed as JSON when possible)
Headers
From the Response Inspector you can:
Add Assertion steps to automatically verify that a value matches an expected result on every future run.
Add Extraction steps to save any value into a named variable that later steps can reuse.
Assertions and extractions are real test steps — they appear in the step list, show pass/fail results, and can be re-ordered or edited like any other step.
Saving a Full API Response Into a Variable
Every API step automatically saves its complete response into a variable. You can customize the name from the API step form.
Press
A(or click Add Step → API) to open the step modal.Fill in the method (GET, POST, PUT, PATCH, DELETE), URL, headers, body, and authentication.
In the Response variable name field, choose a name. Default values follow the pattern
API_RESPONSE_1,API_RESPONSE_2, ...Run the step — the entire response object is now available under that name.
Tip: Use descriptive names like LOGIN_RESPONSE, USER_PROFILE_RESPONSE, or LIST_ORDERS_RESPONSE so later references remain readable.
Variable name rules: uppercase letters, digits and underscores only. Must start with a letter. Regex: ^[A-Z][A-Z0-9_]*$.
Reusing Saved Response Data in Later Steps
Once a response is saved, any later step can reference it with [VARIABLE_NAME] syntax. You can also drill into nested fields with dot notation.
Reference | Resolves to |
[LOGIN_RESPONSE].body.token | The |
[LOGIN_RESPONSE].statusCode | The HTTP status code |
[LOGIN_RESPONSE].duration | Request duration (milliseconds) |
[USER_ID] | A variable explicitly extracted in a previous step |
You can place these references:
In a later API step's URL —
https://api.example.com/users/[USER_ID]In a header —
Authorization: Bearer [LOGIN_RESPONSE].body.tokenInside an assertion expected value
Start typing / (or [) in any supported field to open the Inline Variable Editor autocomplete and pick from available variables.
Asserting on Response Metadata (Status, Duration)
Response metadata appears as metric cards at the top of the Response Inspector.
To assert on a metric:
Click Assert (or open the
⋯menu on narrow screens) on theStatuscard.The assertion modal opens with the field path pre-filled, e.g.
[API_RESPONSE_1].statusCode.Pick an operator.
Enter the expected value (e.g.
200).Click Add Assert — an Assert step is appended at the end of the test case.
Common metadata assertions:
Goal | Field | Operator | Expected value |
Success status | statusCode | is equal to | 200 |
Accept any 2xx | statusCode | is less than | 300 |
Enforce latency budget | duration | is less than | 1000 |
Verify a redirect | statusCode | is equal to | 302 |
Asserting on JSON Response Values
The response body renders as an interactive JSON tree. Expand any object or array to drill into a specific field.
To assert on a JSON value:
Expand the JSON tree to the field you care about.
Click Assert next to the value.
The field path is auto-computed, e.g.
[API_RESPONSE_1].body.title.Select an operator.
Enter the expected value and click Add.
Available operators:
Operator | Use it for |
is equal to / is not equal to | Exact match (strings, numbers, booleans) |
is greater than / is greater or equal to | Numeric comparisons |
is less than / is less or equal to | Numeric comparisons |
contains | Substring or array element check |
starts with / ends with | Prefix / suffix on strings (IDs, URLs) |
has_key / not_has_key | Check that a JSON object contains (or does not contain) a given key |
Tip: Use has_key / not_has_key when you only care that a key exists, not what its value is — perfect for feature flags or optional fields.
Targeting Keys vs. Values
When you click Assert or Extract on a field that belongs to a JSON object, the modal shows a Target toggle with two options: Key and Value. It lets you decide whether the assertion or extraction applies to the field name or to its content. The path itself is filled in automatically — you never have to type it.
Value (default) — operates on the content of the field.
Key — operates on the field name itself.
The Target toggle only appears for values that are direct children of a JSON object. It is hidden for array items, metric cards (status, duration), and top-level response fields — there is no key to target there.
When to target the key:
Verify that a response object still exposes a specific field name (contract testing).
Extract a dynamically generated key (for example, an ID used as a map key) and reuse it in later steps.
Example — given a product response body:
{ "title": "Toold", "price": 9.99, "meta": { "barcode": "5784719087687", "qrCode": "https://cdn.dummyjson.com/public/qr-code.png" } }Clicking Assert on
meta.barcodewith Target → Value checks that the barcode equals"5784719087687".Clicking Assert on
meta.barcodewith Target → Key checks that the response still includes a field literally named"barcode"— a simple contract check that survives value changes.
Tip: If you only need to check that a given key exists, has_key on the parent object is usually simpler. Reach for Target → Key when you actually need the key name as a value (for example to save it into a variable).
Extracting Keys and Values Into Variables
Variable extraction stores a piece of the response under a named variable so later steps can use it.
To extract a value:
In the Response Inspector, locate the value to reuse (a metric card or any JSON tree node).
Click Extract.
The extraction modal opens with the field path pre-filled.
Enter a variable name — the input auto-uppercases and strips invalid characters.
Click Add — a Mechanical Extraction step is appended at the end of the test case.
Using the Response Inspector
The Response Inspector is the discovery surface. It has three areas:
Metric cards — status, duration, load duration.
Copy Response button — copies the full response body to the clipboard.
JSON tree — expandable view of the response body with per-value actions.
Each click on Assert or Extract immediately appends a new step at the end of the Test Case. Add them one at a time — each step appears in the step list as soon as it is created, and can be reordered or edited like any other step.
Why this matters: You stay in the Response Inspector the whole time. Click Assert or Extract on any value in the JSON tree and the step lands directly in the Test Case — no step modal, no extra confirmation.
End-to-End Examples
Example 1 — Pull product data from the API and verify it on the storefront
Goal: fetch a real product from the catalog and check that the storefront UI displays the same values.
Step 1 — API:
GET /products/42. Response variable:PRODUCT_RESPONSEStep 2 — Extract (added from the Inspector):
[PRODUCT_RESPONSE].body.title→PRODUCT_TITLEStep 3 — Extract (added from the Inspector):
[PRODUCT_RESPONSE].body.price→PRODUCT_PRICEStep 4 — Browser: navigate to
/shop/products/42Step 5 — Visual assertion: the page shows
[PRODUCT_TITLE]Step 6 — Visual assertion: the page shows
[PRODUCT_PRICE]
Example 2 — Create an item via API, then continue the journey in the browser
Goal: create a support ticket with the API so the UI test can open and act on it.
Step 1 — API:
POST /ticketswith body{"title": "Cannot upload avatar"}. Response variable:NEW_TICKETStep 2 — Extract:
[NEW_TICKET].body.id→TICKET_IDStep 3 — Browser: navigate to
/support/tickets/[TICKET_ID]Step 4 — Visual assertion:
Ticket #[TICKET_ID]is visible on the pageStep 5 — Browser: click Mark as resolved
Step 6 — Visual assertion: the Resolved status badge is visible
Example 3 — Capture server-side values so later steps work with real data
Goal: read the current account plan and credits, then confirm the same values appear on the billing page.
Step 1 — API:
GET /account/usage. Response variable:USAGE_RESPONSEStep 2 — Assert
[USAGE_RESPONSE].bodyhas_keyplanStep 3 — Extract
[USAGE_RESPONSE].body.plan→CURRENT_PLANStep 4 — Extract
[USAGE_RESPONSE].body.creditsRemaining→CREDITS_REMAININGStep 5 — Browser: navigate to
/settings/billingStep 6 — Visual assertion: the billing page displays
[CURRENT_PLAN]Step 7 — Visual assertion: the billing page displays
[CREDITS_REMAINING]
Tips and Troubleshooting
If you see
Credential or Variable not found 'VARIABLE_NAME'at runtime, check the spelling and confirm the step that produces the variable ran before the step that consumes it.Secrets (passwords, tokens) are hidden by default in auth fields — click the eye icon to reveal.
Environments: each environment keeps its own URL / headers / body for an API step, but variables extracted during a run are shared across that run.
Need to test a flow that spans several runs? Extracted step variables only live for the duration of a single Test Case run. For values that must persist across runs, use Project Variables or Environment Variables instead.
Other related reads you might find useful:
—> Variables














