Request Chaining
Request chaining allows you to extract values from API responses and use them in subsequent requests. This is essential for testing workflows where later requests depend on data returned by earlier ones.
Common use cases:
- Create a resource and use its ID in subsequent requests
- Extract authentication tokens and pass them to other endpoints
- Extract session IDs for stateful testing
- Coordinate multi-step API workflows in a single load test
How It Works
- Extract: Define extractors on an endpoint to pull values from its response
- Store: Extracted values are stored in a per-worker variable store
- Use: Reference extracted values in URLs, headers, and bodies of subsequent requests using `` placeholders
- Fallback: Optionally provide default values with `` syntax
Extractor Configuration
Extractors are defined at the endpoint level in the extractors array. Each extractor specifies:
- jsonpath or regex: The extraction pattern (mutually exclusive)
- var: The variable name to store the extracted value
- on_error (optional, default false): Whether to extract from error responses (4xx/5xx)
JSON Path Extraction
Extract values from JSON responses using JSON path notation.
endpoints:
- name: create-user
path: /users
method: POST
body: '{"name":"Alice","email":"alice@example.com"}'
extractors:
- jsonpath: "id" # Simple field
var: "user_id"
- jsonpath: "metadata.session_id" # Nested field
var: "session_id"
- jsonpath: "items.0.sku" # Array index
var: "first_sku"
- jsonpath: "$" # Entire JSON object
var: "full_response"
JSON path formats supported:
idor$.id– Top-level fielduser.profile.nameor$.user.profile.name– Nested fieldsitems.0.id– Array access by index$– Entire response as a string
Regex Extraction
Extract values from any response using regular expressions with capture groups.
endpoints:
- name: get-token
path: /auth/token
method: GET
extractors:
- regex: '"access_token":"([^"]+)"' # Capture first group
var: "token"
- regex: '\d+' # Match first number
var: "count"
If your regex has capture groups (parentheses), the first capture group is extracted. If no capture group exists, the entire match is extracted.
Using Extracted Values
Once extracted, values are available as placeholders in:
- URL paths and query strings
- HTTP headers
- Request bodies
Example: Complete Workflow
target: https://api.example.com
endpoints:
- name: create-order
path: /orders
method: POST
weight: 10
body: '{"items":2,"total":99.99}'
extractors:
- jsonpath: "id"
var: "order_id"
- jsonpath: "confirmation_code"
var: "confirmation"
- name: get-order
path: /orders/
method: GET
weight: 5
extractors:
- jsonpath: "status"
var: "order_status"
- name: confirm-order
path: /orders//confirm
method: POST
weight: 1
body: '{"code":""}'
headers:
X-Order-Status: ""
concurrency: 10
rate: 50
duration: 1m
In this example:
create-orderextractsorder_idandconfirmationfrom the responseget-orderuses `` in its URL pathconfirm-orderuses bothin the URL andin the body (with a default fallback)confirm-orderalso uses `` (extracted byget-order) in a header
Default Values
If an extracted value is not found (extraction fails), the variable remains empty. You can specify a fallback default using the | syntax:
# Without default - placeholder stays as-is if extraction fails
path: /users/
# With default - use "anonymous" if user_id extraction fails
path: /users/
# Empty default - remove placeholder if not found
value: "Bearer " # Results in "Bearer " if token not found
Default values work with both extracted variables and feeder data.
Extraction from Error Responses
By default, extractors only run on successful responses (2xx status codes). To extract from error responses (4xx/5xx), set on_error: true:
extractors:
- jsonpath: "error_code"
var: "error_code"
on_error: true # Extract even from 400/500 responses
This is useful for capturing error IDs, error messages, or retry tokens from failed responses.
Variable Scope and Persistence
- Per-worker: Each worker (concurrent thread) has its own variable store
- Persistent within worker: Variables persist across all requests made by a single worker
- Isolated: Workers don’t share variables with each other
This means:
- Worker 1 can extract
user_id=123and use it in all its subsequent requests - Worker 2 can extract
user_id=456independently - Variables are cleared when a worker finishes
Combining with Feeders
Extractors and feeders both provide placeholders. If a value exists in both, extractors take precedence:
feeder:
path: ./users.csv # Contains: user_id, email
endpoints:
- name: create-session
path: /users/ # Uses feeder user_id
method: POST
extractors:
- jsonpath: "session_id"
var: "user_id" # Overwrites feeder user_id
- name: use-session
path: /sessions/ # Uses extracted session_id
method: GET
Best Practices
- Use descriptive variable names:
is clearer than - Test extraction patterns locally: Use
jqor regex testers before adding to config - Handle missing values: Always consider using defaults for optional extractions
- Verify extraction works: Check logs for “JSONPath not found” warnings
- Keep JSON paths simple: Complex nested paths are fragile; consider API redesign if needed
- Use weights: Coordinate request frequency so dependent requests run after their dependencies
- Regex capture groups: Always use
()for single captures to avoid extracting too much
Limitations
- JSON only for jsonpath: The
jsonpathextractor requires valid JSON responses - Single value per extractor: Each extractor extracts one value; use multiple extractors for multiple values
- No transformation: Extracted values are used as-is; no post-processing is available
- No cross-worker sharing: Variables are isolated per worker and cannot be shared between workers
- No nested variable references: You cannot use
}}syntax - Regex is greedy: Use non-greedy patterns
(.*?)if needed to avoid overmatching
Example: Multi-Step Order Workflow
target: https://orders-api.example.com
endpoints:
# Step 1: Create order and extract ID
- name: create-order
path: /v1/orders
method: POST
weight: 10
body: |
{
"customer_id": "",
"items": [
{"sku": "WIDGET-1", "qty": 2},
{"sku": "GADGET-1", "qty": 1}
]
}
extractors:
- jsonpath: "order_id"
var: order_id
- jsonpath: "invoice_url"
var: invoice_url
# Step 2: Get order details and extract shipment ID
- name: get-order
path: /v1/orders/
method: GET
weight: 5
extractors:
- jsonpath: "shipment.tracking_number"
var: tracking_number
on_error: false
# Step 3: Confirm shipment
- name: confirm-shipment
path: /v1/orders//shipment/confirm
method: PATCH
weight: 3
body: |
{
"tracking": "",
"notification_url": ""
}
# Step 4: Get final status
- name: get-final-status
path: /v1/orders//status
method: GET
weight: 1
feeder:
path: ./customers.csv
type: csv
concurrency: 20
rate: 100
duration: 5m
Running this configuration will:
- Extract
order_idandinvoice_urlfrom the create response - Use `` in subsequent requests to the correct endpoint
- Extract
tracking_numberfrom the order details - Pass tracking information to the confirm endpoint with a fallback to “pending”
- Use the same
order_idacross all four requests - Each worker maintains its own
order_id, so concurrent workers don’t interfere
Debugging Extraction Issues
If extraction isn’t working:
- Check for “JSONPath not found” warnings in stderr
- Verify JSON is valid: Use
jqto test the path - Check variable spelling:
≠ - Test regex separately: Use an online regex tester
- Enable detailed logging: Warnings are printed for failed extractions
- Verify endpoint is returning expected data: Manually call the API to confirm response format
Example testing:
# Test JSON path extraction
curl https://api.example.com/users | jq .id
# Test regex extraction
curl https://api.example.com/auth | grep -oP '"token":"[^"]+"'
See Also
- Data Feeders – Combine feeders with extractors for powerful data-driven testing
- Endpoints – Configure multiple endpoints with extraction
- Authentication – Extract auth tokens from login endpoints