# Billing & Subscriptions
Source: https://docs.requestly.com/account/billing-subscriptions
Learn how to manage billing teams, assign licenses, update payment info, and view billing history with Requestly's easy-to-use tools.
***
Efficient license management is essential for seamless operations. Requestly allows organizations to effortlessly manage their subscriptions and licenses.
Billing, subscriptions, and license management are handled on the **BrowserStack billing dashboard**, not inside the Requestly desktop app. The desktop app's Settings does not include a Billing section. Open the **Billing** area of your [BrowserStack account](https://www.browserstack.com/) to complete the steps below.
### Role Overview
| | Billing Manager | Admin | Member |
| --------------------------------------------- | --------------- | ----- | ------ |
| Subscriptions (Upgrade or Cancel) | Yes | - | - |
| Payment Details (Edit card & billing details) | Yes | - | - |
| License Management | Yes | Yes | - |
| Manage Admins | Yes | Yes | - |
| Manage Members | Yes | Yes | - |
| Access Premium Features | No | Yes | Yes |
To better understand how Billing Teams works, watch the following video:
***
## Creating a Billing Team
Setting up a billing team is the first step in managing your organization's licenses. Follow these steps to create one:
Sign in to your [BrowserStack account](https://www.browserstack.com/) and open the **Billing** dashboard.
After you open Billing, click the **Upgrade** button to select your plan and begin the process of allocating seats.
Choose the number of seats you want to allocate for your team. This will determine how many licenses are available for assignment.
After selecting the number of seats, click the **Upgrade** button to go to the checkout page.
Review your order summary on the checkout page. Enter the required payment details and complete the purchase.
After the checkout is complete, a Billing Team will be created automatically. You’ll be redirected to the **Billing Dashboard**, where you can manage your plan.
In the **Billing Dashboard**, you can view the details of your current plan, including the number of licenses purchased and their status.
***
## Managing Licenses
The **Billing Dashboard** provides a simple way to manage license holders, ensuring your team has seamless access to premium features.
### Assigning a License
Easily allocate licenses to team members who need premium access to tools and features.
Open the **Billing** dashboard in your [BrowserStack account](https://www.browserstack.com/).
Click the **Assign License** button to begin the allocation process.
Select a user from the list of available members and click **Assign**.
If the user is not listed, use the **Invite & Assign License** option. Enter the user’s email to send an invitation. Once the user signs up, they will be automatically assigned a license.
### Revoking a License
Revoking a license ensures that premium access is no longer available to users who no longer need it, helping maintain efficient license usage.
Open the **Billing** dashboard in your [BrowserStack account](https://www.browserstack.com/).
Find the user whose license you wish to **revoke**.
Click the ellipsis(**three-dot**) menu next to their name and select **Revoke License**.
***
## Updating Billing Information
Keep your billing details up to date to avoid service disruptions.
### Modify Billing Information
Navigate to the **Billing Information** section. Update your billing addresses and contact details as needed.
### Change Payment Method
Go to the **Payment Methods** section. Add a new payment option or edit existing ones to ensure uninterrupted service.
***
## Billing History and Invoices
Stay on top of your financial records with easy access to billing history and invoices.
### View Billing History
Navigate to the **Billing History** section to review records of past billing activities.
### Download Invoices
Go to the **Invoices** section and click **Download** next to the invoice you wish to save.
### Handle Unpaid Invoices
Locate any outstanding payments in the **Billing Dashboard** and follow the prompts to complete the payment process.
***
### Billing Teams vs. Team Projects
* **Billing Teams**: Responsible for managing licenses and billing processes on the BrowserStack dashboard.
* **Team Projects**: Enable collaboration by letting teams share and manage API collections, environments, and variables inside the Requestly app.
# Data Recovery Policy
Source: https://docs.requestly.com/account/data-recovery
How Requestly retains and recovers deleted projects, collections, requests, and environments.
***
When you delete a project, collection, request, environment, or any other resource in a **team or personal cloud project**, the data is retained for **7 days** before being permanently removed.
## Recovering deleted data
If you need to restore something that was deleted, contact our support team within the 7-day window and we will restore it for you.
Email [support@requestly.io](mailto:support@requestly.io) from the email address associated with your Requestly account.
Include the following so our team can locate the right data quickly:
* **Project name** (and project ID, if you have it)
* **Resource type:** project, collection, request, environment, etc.
* **Resource name** of the item(s) you would like restored
* **Approximate time of deletion** (date and time, with timezone)
Our team will recover the data and confirm once it is available in your project. Restored items reappear in the same location they were deleted from.
After **7 days**, deleted data cannot be recovered. We recommend reaching out as soon as you notice an accidental deletion.
## Local projects
Data in [local projects](../collaboration/local-workspace) lives entirely on your device and is **not backed up by Requestly**. If you delete a local project, or the files and folders backing it, the data cannot be recovered by our team.
For local projects, we recommend keeping the project folder under your own backup (Time Machine, OneDrive, Git, etc.) so you can restore from there if needed.
## What's covered
| Resource type | Recoverable within 7 days? |
| ------------------------ | -------------------------- |
| Projects (cloud) | Yes |
| Collections | Yes |
| Requests / Endpoints | Yes |
| Environments & variables | Yes |
| Local project data | No (stored on your device) |
# How is the Browser Extension Different from the Desktop App
Source: https://docs.requestly.com/account/how-is-browser-extension-different-from-a-desktop-app
Requestly is available as both a **browser extension** and a **desktop application**. While both platforms offer a similar set of features, their capabilities differ slightly to address platform-specific limitations and better cater to distinct use cases.
This comparison covers Requestly's interception and rules capabilities. For the API client, the **desktop app** is the primary and recommended experience.
The **browser extension** is comparatively a **lighter tool** that runs directly within the browsers and is ideal for **browser-focused workflows**. The **desktop app** is designed to provide more control over network traffic across the **entire system**, including apps outside the browser. This comparison outlines functional differences to help you choose the right setup for your use case.
## Platform & Browser Support
**Browser Extension -** Supports all major web browsers, including all Chromium-based browsers, Firefox, and Safari (limited support)
**Desktop App -** Supports all browsers and any app making network requests. like desktop apps, backend services, mobile devices, etc.
> 📎 The extension runs inside the browser environment. The desktop app operates system-wide and works with any browser, application or even hardware devices like smartphones etc.
## HTTP Interception
> 🔧 Use the desktop app if you need to work with network traffic beyond the browser, such as from curl, Postman, mobile devices, or backend services.
| **Feature** | **Browser Extension** | **Desktop App** |
| ---------------------------------- | --------------------- | --------------- |
| Browser Interception | ✅ | ✅ |
| System-wide Proxy | ❌ | ✅ |
| Mobile App Interception | ❌ | ✅ |
| Locally Installed App Interception | ❌ | ✅ |
## HTTP Rules
| **Feature** | **Browser Extention** | **Desktop App** |
| --------------------------- | ------------------------------------------------------ | --------------- |
| HTTP Rules | ✅ \[Limitations below]👇 | ✅ |
| Delay Rule max delay | 5000ms (Fetch/ XHR requests) 10000ms (Other resources) | Unlimited |
| Redirect to local file | ❌ | ✅ |
| Serve local file Response | ❌ | ✅ |
| Modify HTML/JS/CSS Response | ❌ | ✅ |
| Map Local | ❌ | ✅ |
| Map Remote | ✅ | ✅ |
> 💡 The extension works within the limitations of browser APIs. Features like serving local files or modifying HTML/CSS content are only supported in the desktop app due to broader system access.
## Mocking & Debugging
| **Feature** | **Browser Extension** | **Desktop App** |
| ---------------- | --------------------- | --------------- |
| File Server | ✅ | ✅ |
| Bulk Mocking | ❌ | ✅ |
| Session Book | ✅ | ❌ |
| Network Sessions | ❌ | ✅ |
> 📌 Tip: Use Desktop App when mocking multiple endpoints or importing HAR files.
## Workspaces & Import/Export
| **Feature** | **Browser Extension** | **Desktop App** |
| ------------------------ | --------------------- | --------------- |
| Local Workspace (Beta) | 🚧 (Coming Soon) | ✅ |
| Import / Export HAR file | 🚧 (Coming Soon) | ✅ |
## Visibility of Executed Rules
The way Requestly shows rule executions varies between the browser extension and desktop app, tailored to their respective environments:
1\. A **pop-up notification** shows which rule was triggered when browsing.
2\. Requestly Extension’s **icon turns green** in the extension toolbar.
3\. The **extension popup panel** also lists recently executed rules, making it easy to confirm if a rule applied.
The **rules table** visually highlights which rules were applied by turning the corresponding request rows **green**.
# Set up Microsoft Entra ID
Source: https://docs.requestly.com/account/sso/how-to-set-up-sso-with-microsoft-entra-id
Set up SSO with Microsoft Entra ID
If your company uses [Microsoft Entra ID](https://www.microsoft.com/en-us/security/business/identity-access/microsoft-entra-id), you can set up the single sign-on feature for use with Requestly. This gives your employees the convenience of a one-click login, without using additional multi-factor authentication.
SSO is an enterprise-plan feature. Contact the Requestly team to enable it for your organization.
## Step 1. **Create an Microsoft Entra ID enterprise application**
1. Go to the **Microsoft Entra ID** portal.
2. Go to **Identity > Applications > Enterprise applications.**
3. Click on **+** **New application.**
4. Enter app name as desired, select **Integrate any other application you don’t find in the gallery (Non-gallery)**, and click **Create**
5. After this you're redirected to the newly created Requestly application **Overview**.
## Step 2. Configure Microsoft Entra ID SAML Application
1. On the app's **Overview** page, select **2. Set up single sign-on**. You can assign users and groups later.
2. On the app's **Single sign-on** page, select **SAML** as the single sign-on method.
3. Under the **Basic SAML Configuration** section, click **Edit.**
4. Add the following values and **save**:
* **Identifier (Entity ID):** `urn:requestly.io`
* **Reply URL:** `https://app.requestly.io/__/auth/handler`
* **Sign on URL (optional):** Leave it empty. We don’t support IDP initiated SSO right now
## Step 3. Setup SAML claims
1. Under the **Attributes and Claims** section, click **Edit**.
2. Enter the following values:
| Unique User Identifier (Name ID) | user.mail |
| -------------------------------- | -------------- |
| first\_name | user.givenname |
| last\_name | user.surname |
| email | user.mail |
## Step 4. Share SAML metadata with Requestly
1. Under **SAML Certificates** section, copy the **App Federation Metadata URL**.
2. Share the copied value with us `contact@requestly.io`
# SAML SSO with Okta
Source: https://docs.requestly.com/account/sso/setup-sso-with-okta
If your company uses Okta as an Identity Provider, then you can set up the single sign-on feature for use with Requestly. This gives your employees the convenience of a one-click login, without using additional multi-factor authentication.
SSO is an enterprise-plan feature. Contact the Requestly team to enable it for your organization.
## **Step 1. Create and configure a SAML application in Okta**
1. Log in to your Okta account and head to the **Applications** page.
2. Click on `Create App Integration` and select `SAML 2.0`
In the `1. General Settings` step, add App Name as `Requestly` and then click `Next`
4. In the `2. Configure SAML` step, add the following details and then click `Next`
| Single sign-on URL | `https://app.requestly.io/__/auth/handler` |
| --------------------------- | ------------------------------------------ |
| Audience URI (SP Entity ID) | `urn:requestly.io` |
| Name ID format | Email Addresss |
| Application username | Email |
## **Step 2. Share SAML metadata with Requestly**
Copy the **Metadata URL**.
2. Share the copied value with us [`contact@requestly.io`](mailto:contact@requestly.io)
# Generate API Test Cases using the Test Authoring Agent
Source: https://docs.requestly.com/api-client/ai-test-generator
Learn how to automatically author Post-response API test scripts using the Test Authoring Agent in Requestly. Use natural language instructions to create reliable, comprehensive API tests without manually writing JavaScript.
The Test Authoring Agent is a Requestly-integrated AI agent that authors executable Post-response test scripts directly from real API request and response data. It removes repetitive, error-prone manual work and helps engineers and QA teams validate API behavior faster with consistent coverage.
Simply describe what you want to validate in plain English. The agent analyzes your latest API response and produces ready-to-run test cases for your current request.
**Availability:** The Test Authoring Agent requires a **Pro plan or above**, AI features enabled for your organization, and your one-time AI consent (you are prompted the first time you use it). It is rolling out gradually; if you don't see it, update to the latest version.
## Getting Started with AI Test Cases Generator
The Test Authoring Agent requires an actual API response to understand structure, values, and risk areas.
1. Open any request in the API Client
2. Click the **Send** button to execute the request
3. Wait for the response to be received
Once the response is available:
1. Navigate to the **Scripts** section
2. Open the **Post-response** tab
3. Click **Generate tests** (the button reads **Improve tests** if the request already has a post-response script)
This opens the test generation panel.
Describe what the tests should validate using plain English. The agent understands API context, response payloads, and common testing patterns.
**Example instructions**
* "Generate test cases"
* "Test that status is 200 and success is true"
* "Ensure the response has id, name, and email fields"
* "Validate pagination fields like page, limit, and total"
* "Check that items array is not empty"
* "Verify all timestamps are valid ISO 8601 dates"
* "Add schema validation for the response"
* "Test missing required fields"
Click **Generate** to continue.
The Test Authoring Agent presents the generated output in a git-style diff view:
* Green lines show new tests that will be added
* Red lines show tests that will be removed
* Unchanged lines remain neutral
This human-in-the-loop review ensures full control before any script changes are applied.
After reviewing the diff, you can:
* **Accept** to replace the full Post-response script with the generated tests
* **Edit prompt** to refine your prompt and regenerate tests
* **Close** to discard all changes and keep the existing script
Accepted tests are saved immediately and are ready to run.
## What the Test Authoring Agent Creates
The agent authors structured, runnable API test cases using:
* rq.test blocks for clear test intent
* Chai-based assertions via rq.response and rq.expect
* Field-level, schema-level, and behavior-based validations
All generated tests are compatible with the Collection Runner and CI workflows.
## What the Test Authoring Agent Creates
The agent creates comprehensive test scripts using Requestly's [`rq.test`](/api-client/rq-api-reference/rq-test) and [`rq.expect`](/api-client/rq-api-reference/rq-expect) APIs with [Chai.js assertions](/api-client/tests#example-tests).
### Example Generated Tests
For a user API endpoint returning:
```json theme={null}
{
"status": 200,
"success": true,
"data": {
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"role": "admin"
}
}
```
With instruction: **"Test that status is 200, success is true, and user object has required fields"**
The AI generates:
```javascript theme={null}
rq.test("Status code is 200", () => {
rq.response.to.have.status(200);
});
rq.test("Response is valid JSON", () => {
rq.response.to.have.jsonBody();
});
rq.test("Success field is true", () => {
rq.response.to.have.jsonBody("success", true);
});
rq.test("User data object has required fields (id, name, email, role)", () => {
rq.response.to.have.jsonBody("data.id");
rq.response.to.have.jsonBody("data.name");
rq.response.to.have.jsonBody("data.email");
rq.response.to.have.jsonBody("data.role");
});
```
## Advanced Test Scenarios
The AI Test Generator can handle complex scenarios:
### Schema Validation
Instruction: **"Validate the entire response structure against a schema"**
Generates schema validation tests that ensure the response conforms to the expected data structure.
```javascript theme={null}
rq.test("Response has valid schema", () => {
rq.response.to.have.jsonSchema({
type: "object",
required: ["status", "success", "data"],
properties: {
status: { type: "number" },
success: { type: "boolean" },
data: { type: "object" }
}
});
});
```
## Tips for Better AI-Generated Tests
1. **Be Specific**: Clearly state what you want to test. Instead of "test the response," say "test that status is 200 and email is a valid email address"
2. **Reference Field Names**: Mention specific fields you want validated. The AI understands JSON paths like "user.email" or "data.items\[0].status"
3. **Use Examples**: Phrases like "similar to POST requests" or "like production data" help the AI understand context
4. **Combine Multiple Concerns**: You can ask for multiple validations in one instruction: "Validate status is 200, success is true, and items array is not empty"
5. **Iterative Refinement**: Use the "Edit Instruction" feature to progressively enhance your tests
## Current Limitations
* AI Test Generator currently generates **Post-response scripts only**
* Requires an actual API response to analyze.
* Best results when the response has a well-structured JSON format
## Combining AI-Generated and Manual Tests
You don't need to rely entirely on AI-generated tests. You can:
1. **Start with AI**: Let the AI generate basic validation tests
2. **Add Custom Logic**: Manually add additional test cases or pre-request scripts
3. **Refine Iteratively**: Use the Edit Instruction feature to improve generated tests over time
4. **Mix Approaches**: Combine AI-generated assertions with custom JavaScript logic
## Running and Debugging Tests
After accepting the AI-generated tests, you can:
* **Run Tests**: Click the **Send** button again to execute the request and run all tests
* **View Results**: Check the test results in the **Test Results** panel
* **Debug**: Use `console.log()` in the script to debug test execution
* **Modify**: Edit the generated code directly if you need fine-grained control
See [Writing Tests](/api-client/tests) for more information about executing and debugging tests.
## Related Topics
* [Writing Tests](/api-client/tests) - Learn about manual test writing and all available assertion methods
* [Scripts](/api-client/scripts) - Understand Pre-request and Post-response scripts
* [Collection Runner](/api-client/collection-runner) - Run multiple requests and tests in sequence
* [RQ API Reference](/api-client/rq-api-reference) - Full documentation of the `rq` object and its methods
# API Collections
Source: https://docs.requestly.com/api-client/api-collections
Organise and manage APIs with Requestly’s API Collections. Learn to create, rename, delete collections, use folders, and explore collection variables.
***
API Collections help developers and QA teams organize and group APIs for better management. They also offer additional features such as detailed API information and collection-specific variables. Let's explore how to create, manage, and utilize API Collections and their features.
## Create API Collection
**Step 1:** Click **+ New** and select **Collection**.
**Step 2:** Provide a descriptive name (e.g., “User Management APIs”) and hit **Enter**.
Once a collection is created, you can add requests and sub-collections.
## Rename API Collection
**Step 1:** Click the **More** icon next to the collection name you want to rename, then select Rename.
**Step 2:** An inline input field will appear with the current name. Update the name and press **Enter** to save the changes.
## Delete API Collection
**Step 1:** Click the **More** icon next to the collection name and select `Delete`.
**Step 2:** Confirm the action in the Delete Collection prompt.
Make sure you are deleting the correct collection. Deleted collections in cloud projects can be restored within 7 days by contacting support. See the [Data Recovery Policy](../account/data-recovery) for details.
## Create Folders
Folders allow you to create sub-groups within a collection. They can have their own collection variables and share all the features of a collection. Folders(Sub-Collections) inherit all the collection variables from its parent. However, You can override parent-collection variables by defining a collection variable inside the sub-collection.
**Step 1:** Click on the Add Folder icon next to the collection name.
**Step 2:** Provide a descriptive name (e.g., “Login APIs”) and press **Enter**.
## Collection Variables
Collections include a **collection variables** feature that allows you to define and manage reusable values specific to the collection. Collection Variables are defined as key-value pairs that work as the base set of variables for collections. They can be used in API definitions with double curly braces `{{collection_variable}}`
Learn more about this feature on the [Variables](/api-client/environments-and-variables) page.
## Collection Runner
The **Collection Runner** allows you to execute multiple API requests from a collection sequentially in a single run. It helps automate request workflows such as *login → create resource → fetch resource* while utilizing existing variables and scripting capabilities.
Use it to configure iterations, delays, and environments, view detailed run results, debug failed requests, and export summaries for analysis.
Learn more about this feature on the [**Collection Runner**](https://docs.requestly.com/api-client/collection-runner) page.
# CLI
Source: https://docs.requestly.com/api-client/cli
Run HTTP and GraphQL collections from the command line using the Requestly CLI binary.
The Requestly CLI lets you run collections, inspect environments, and list projects directly from your terminal or CI pipeline - no browser or desktop app required.
## Installation
Download the binary for your platform, unzip it, and run it directly. The binary is self-contained with no additional dependencies.
| Platform | Download |
| ----------- | -------------------------------------------------------------------------------------------------- |
| Linux x64 | [binary-linux-x64-1.35.0.zip](https://sdk-assets.browserstack.com/binary-linux-x64-1.35.0.zip) |
| Linux arm64 | [binary-linux-arm64-1.35.0.zip](https://sdk-assets.browserstack.com/binary-linux-arm64-1.35.0.zip) |
| macOS x64 | [binary-macos-x64-1.35.0.zip](https://sdk-assets.browserstack.com/binary-macos-x64-1.35.0.zip) |
| macOS arm64 | [binary-macos-arm64-1.35.0.zip](https://sdk-assets.browserstack.com/binary-macos-arm64-1.35.0.zip) |
| Windows x64 | [binary-win-x64-1.35.0.zip](https://sdk-assets.browserstack.com/binary-win-x64-1.35.0.zip) |
After downloading, unzip and make the binary executable:
```bash theme={null}
unzip binary-macos-arm64-1.35.0.zip
mv binary-macos-arm64 browserstack-binary
chmod +x browserstack-binary
```
To run it as `browserstack-binary` from any directory, move it onto your `PATH`. On macOS and Linux:
```bash theme={null}
sudo mv browserstack-binary /usr/local/bin/
```
On Windows, move `browserstack-binary.exe` into a folder that is on your `Path` (or add its folder to the `Path` environment variable via System Properties → Environment Variables).
Some operating systems block execution of binaries downloaded from the internet by default. Run `chmod +x browserstack-binary` if you see a permission error.
All examples in this guide assume the binary is on your `PATH`. If you skip the step above, run it with a path prefix (`./browserstack-binary`) from the folder where it lives.
All examples in this guide use `browserstack-binary` as the executable name. The actual filename after unzipping is platform-dependent (e.g. `binary-macos-arm64` on macOS arm64) - rename it to match.
## Invocation
```text theme={null}
browserstack-binary requestly [subcommand] [target] [flags]
```
## Authentication
Cloud operations - fetching a collection by cloud ID, listing cloud projects, collections, and environments - require BrowserStack credentials set as environment variables:
| Variable | Description |
| ------------------------- | ---------------------------- |
| `BROWSERSTACK_USERNAME` | Your BrowserStack username |
| `BROWSERSTACK_ACCESS_KEY` | Your BrowserStack access key |
Both must be set together. Local filesystem runs, Postman JSON files, and URL-fetch targets do not require credentials.
```bash theme={null}
export BROWSERSTACK_USERNAME=your_username
export BROWSERSTACK_ACCESS_KEY=your_access_key
browserstack-binary requestly collection run --project
```
To find your username and access key, open your [BrowserStack account profile](https://www.browserstack.com/accounts/profile/details).
## Commands
### `collection run`
Run a collection or request. The target type is auto-detected - no explicit type flag needed.
```text theme={null}
browserstack-binary requestly collection run [flags]
```
#### Target detection
The CLI resolves the target in this order:
| Target | Detected as |
| --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Starts with `http://` or `https://` | URL fetch - downloads JSON and runs it. Must be a valid Postman v2.1 or Requestly collection. |
| Directory containing `__requestly.json` | Requestly local project - runs all collections under `apis/`. |
| Directory containing `__metadata.json` with `"type": "collection"` | Specific Requestly collection - runs only that collection. |
| `.json` file with Postman v2.1 schema (`info._postman_id` or `info.schema` containing `v2.1`) | Postman v2.1 collection file. |
| Cloud collection ID (e.g. `abc123-def456`) | Fetches the collection from Requestly cloud. Requires `--project ` plus `BROWSERSTACK_USERNAME` + `BROWSERSTACK_ACCESS_KEY`. |
If the target cannot be resolved, the CLI exits with code `1` and a descriptive error message.
#### Execution flags
| Flag | Short | Default | Description |
| ---------------------------------- | ----- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--project ` | | | Cloud project ID. Required for cloud collection-ID targets. Not used for local/file/URL targets. |
| `--environment ` | `-e` | | Environment to activate. Accepts: environment name (resolved from a Requestly project's `environments/` directory), file path to a standalone environment JSON, or a cloud environment ID. |
| `--env-var ` | | | Override an environment variable. Repeatable. |
| `--global-var ` | | | Override a global variable. Repeatable. |
| `--iteration-data ` | `-d` | | CSV or JSON data file for data-driven runs. The collection runs once per row (CSV) or object (JSON). |
| `--iteration-count ` | `-n` | `1` | Number of times to run the collection. With `-d`, multiplies iterations: total = N x rows. |
| `--delay-request ` | | `0` | Pause between consecutive requests (milliseconds). |
| `--on-error ` | | `continue` | Behavior on assertion failure. `end`: stop on first failure. `continue`: run to completion, exit `1` if any failed. `ignore`: run to completion, failures do not affect exit code. |
| `--bail` | | | Shortcut for `--on-error end`. When used with `-d` or `-n`, stops the entire run (all remaining iterations), not just the current one. |
| `--timeout-request ` | | `0` | Per-request timeout. `0` = no limit. |
| `--folder ` | | | Run only the named folder within a Postman v2.1 collection. Repeatable. Postman targets only. |
| `--insecure` | `-k` | | Disable TLS certificate validation. |
| `--verbose` | | | Log detailed request/response info (method, URL, status, headers, timing) for each request. |
#### Reporter flags
| Flag | Short | Default | Description |
| --------------------------------- | ----- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `--reporters ` | `-r` | `cli` | Comma-separated reporters to activate: `cli`, `json`, `junit`, `html`. All listed reporters run simultaneously. |
| `--reporter-json-export ` | | `./rq-reports/rq-report.json` | Output path for the JSON report (Newman-compatible schema). |
| `--reporter-junit-export ` | | `./rq-reports/rq-report.xml` | Output path for JUnit XML. Compatible with GitHub Actions, GitLab CI, Jenkins, CircleCI, and Bamboo. |
| `--reporter-html-export ` | | `./rq-reports/rq-report.html` | Output path for a self-contained HTML report. |
| `--reporter-omit-request-bodies` | | | Remove request bodies from all reporter output. |
| `--reporter-omit-response-bodies` | | | Remove response bodies from all reporter output. |
| `--reporter-omit-headers` | | | Remove all headers from all reporter output. |
| `--reporter-skip-headers ` | | | Remove specific headers by name (comma-separated). |
| `--reporter-omit-all` | | | Omit all request bodies, response bodies, and headers. Equivalent to combining the three `--reporter-omit-*` flags. |
Missing export directories are created automatically. If a directory cannot be created, the CLI exits `1` after the run completes - tests still execute.
`--reporter-omit-*` flags affect the JSON and HTML reporters regardless of `--verbose`. In terminal output, they suppress the additional headers/bodies that `--verbose` would otherwise show.
#### Global flags
| Flag | Short | Description |
| ----------------------- | ----- | ------------------------------------------------- |
| `--color ` | | ANSI color output. Default: `auto` (detects TTY). |
| `--help` | `-h` | Show help. |
| `--version` | `-v` | Print CLI version and exit. |
#### Exit codes
| Code | Meaning |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `0` | All assertions passed (including an empty collection with zero requests). HTTP 4xx/5xx responses are not failures - only [`rq.test()`](/api-client/rq-api-reference/rq-test) assertion failures count. |
| `1` | Any of: assertion failures; target not found or unreadable; invalid or unrecognized JSON; URL/cloud fetch failed; missing credentials for a cloud target; reporter export write failed. |
| `2` | Fatal/uncaught error (e.g. process crash). |
***
### `project list`
List all projects the authenticated user is a member of.
```text theme={null}
browserstack-binary requestly project list [--output ]
```
| Flag | Default | Description |
| ----------------------- | ------- | --------------------------------------------- |
| `--output ` | `table` | Output format. `json` is suitable for piping. |
Requires `BROWSERSTACK_USERNAME` and `BROWSERSTACK_ACCESS_KEY`.
***
### `collection list`
List collections in a project.
```text theme={null}
browserstack-binary requestly collection list --project [--output ]
```
| Flag | Default | Description |
| ----------------------- | ------- | -------------------------- |
| `--project ` | | **(Required)** Project ID. |
| `--output ` | `table` | Output format. |
Requires `BROWSERSTACK_USERNAME` and `BROWSERSTACK_ACCESS_KEY`.
***
### `environment list`
List environments in a project (cloud or local).
```text theme={null}
browserstack-binary requestly environment list --project [--output ]
browserstack-binary requestly environment list [--output ]
```
| Flag | Default | Description |
| ----------------------- | ------- | ---------------------------------------------------------- |
| `--project ` | | Cloud project ID. Required when targeting a cloud project. |
| `--output ` | `table` | Output format. |
Pass a local project path as the positional argument to list environments from the filesystem without credentials.
***
### `environment view`
Show variable details for a specific environment.
```text theme={null}
browserstack-binary requestly environment view --project [--output ]
browserstack-binary requestly environment view [--output ]
```
| Flag | Default | Description |
| ----------------------- | ------- | ------------------------------------------------------------------------ |
| `--project ` | | Cloud project ID. Required when identifying the environment by cloud ID. |
| `--output ` | `table` | Output format. |
Pass a local environment file path as the positional argument to inspect it without credentials.
***
## Terminal output
The default `cli` reporter streams results in real time. Each request prints as it completes:
```text theme={null}
Requestly - Running your collection...
→ Auth Types Demo
API Keys
GET https://httpbin.org/headers [200 OK, 342ms]
✓ Status is 200
→ Basic Authentication
GET https://httpbin.org/basic-auth/demo_user/demo_pass [200 OK, 215ms]
✓ Basic auth successful
✕ Response contains token
expected response body to contain 'token'
┌─────────────────────────────┬─────────────────────┬─────────────────────┐
│ │ executed │ failed │
├─────────────────────────────┼─────────────────────┼─────────────────────┤
│ iterations │ 1 │ 0 │
├─────────────────────────────┼─────────────────────┼─────────────────────┤
│ requests │ 2 │ 0 │
├─────────────────────────────┼─────────────────────┼─────────────────────┤
│ test-scripts │ 2 │ 0 │
├─────────────────────────────┼─────────────────────┼─────────────────────┤
│ prerequest-scripts │ 0 │ 0 │
├─────────────────────────────┼─────────────────────┼─────────────────────┤
│ assertions │ 3 │ 1 │
├─────────────────────────────────────────────────────────────────────────┤
│ total run duration: 0.6s │
├─────────────────────────────────────────────────────────────────────────┤
│ total data received: 4.2kB (approx) │
├─────────────────────────────────────────────────────────────────────────┤
│ average response time: 278ms [min: 215ms, max: 342ms, s.d.: 63ms] │
└─────────────────────────────────────────────────────────────────────────┘
```
`console.log()` output from scripts appears between the request line and assertions, wrapped in dash-pipe delimiters:
```text theme={null}
-
| Total posts: 100
| Response time: 622ms
-
```
***
## Examples
**Run a local Requestly project:**
```bash theme={null}
browserstack-binary requestly collection run ./my-project/
```
**Run a specific collection within a project:**
```bash theme={null}
browserstack-binary requestly collection run ./my-project/apis/Auth-Types-Demo/
```
**Run a Postman v2.1 file with JUnit output:**
```bash theme={null}
browserstack-binary requestly collection run ./postman-collection.json \
-r cli,junit \
--reporter-junit-export results.xml
```
**Run a specific folder from a Postman collection:**
```bash theme={null}
browserstack-binary requestly collection run ./postman-collection.json \
--folder "Posts API" \
--folder "Auth Tests"
```
**Run a collection from a URL:**
```bash theme={null}
browserstack-binary requestly collection run https://example.com/collection.json
```
**Run a cloud collection with an environment:**
```bash theme={null}
browserstack-binary requestly collection run abc123-def456 --project -e production
```
**Data-driven run (3 repetitions of a CSV file):**
```bash theme={null}
browserstack-binary requestly collection run ./my-project/ -d test-data.csv -n 3
```
**Bail on first failure with variable overrides:**
```bash theme={null}
browserstack-binary requestly collection run ./my-project/ \
--bail \
--env-var host=localhost \
--env-var port=8080
```
**All four reporters with sensitive headers stripped:**
```bash theme={null}
browserstack-binary requestly collection run ./my-project/ \
-r cli,json,junit,html \
--reporter-json-export reports/run.json \
--reporter-junit-export reports/junit.xml \
--reporter-html-export reports/report.html \
--reporter-skip-headers Authorization,X-Api-Key
```
**CI pipeline (JUnit output, fail fast, credentials from env):**
```bash theme={null}
BROWSERSTACK_USERNAME=$BS_USER \
BROWSERSTACK_ACCESS_KEY=$BS_KEY \
browserstack-binary requestly collection run --project \
--bail \
-r cli,junit \
--reporter-junit-export test-results/junit.xml
```
**List projects:**
```bash theme={null}
browserstack-binary requestly project list
browserstack-binary requestly project list --output json
```
**List collections in a project:**
```bash theme={null}
browserstack-binary requestly collection list --project proj-abc123
browserstack-binary requestly collection list --project proj-abc123 --output json
```
**View an environment:**
```bash theme={null}
browserstack-binary requestly environment view env-xyz789 --project proj-abc123
browserstack-binary requestly environment view ./my-project/environments/staging.json
```
# Collection Runner
Source: https://docs.requestly.com/api-client/collection-runner
Learn how to run collections, configure iterations, delays, and environments, reorder or skip requests, view and debug results, and export run summaries
**Collection Runner** enables you to execute multiple saved API requests from a collection in one go, sequentially, while leveraging existing variable and scripting features. Think of it as automating a workflow of requests\
(for example: login → create resource → fetch resource) in one run.
This documentation covers how to run collections, configure variables, view results, rerun or debug, explore automation options, and export results.
### Running a Collection
Follow these steps to run a collection using the Runner:
In the Collections sidebar, find the collection you want to execute and click the **Run** icon on menu option next to it.
*You can also click* ***Runner*** *from collections tab*
* **Iterations:** Number of times to execute the full collection
* **Delay:** Wait time between requests (milliseconds)
If you want your collection to run with an environment, select it using the environment selector at the upper left corner, then select the environment you want to use
You can drag to reorder requests or uncheck ones you don’t want to include in this run.
Click Save and then Run . The Runner will execute each request in order.
### How a Collection Runner Works
When you execute requests using the **Collection Runner**, here’s how things work:
#### Variable Resolution
* All `{{variable}}` placeholders resolve based on their **scope**.
* **Environment variables** override values from the global scope.
* **Collection-level variables** defined earlier are available to all requests within that collection.
#### Script Execution
* **Pre-request** and **Post-response** scripts execute as usual.
* You can **set or modify variables** dynamically during the run.
* Use `rq.expect(...)` for writing **test assertions** to validate responses.
#### Viewing Run Results
Once the run completes, the Runner displays a detailed **Run Summary**, including:
* Total number of requests executed
* Tests passed and failed
* Total duration and time taken
You can click on any request in the summary to view:
* Request details - URL, headers, and body
* Response data - status, headers, and body
* The result of each test assertion
## What's Next?
Use CSV or JSON data files to parameterize collection runs across multiple inputs.
Run a collection automatically on a recurring schedule from the Runner tab's Scheduled sub-tab.
Add assertions to validate response status, body, and headers on every run.
Set and modify variables dynamically during a run using pre/post scripts.
# Run Collections with Custom Data
Source: https://docs.requestly.com/api-client/collection-runner-data-file
Learn how to use CSV or JSON data files with the Requestly Collection Runner to iterate requests with multiple input values.
You can use **custom data files** (CSV or JSON) when running a collection manually in Requestly.\
This enables you to iterate through your requests using multiple sets of input values, without modifying your request parameters each time.
**Note:** This feature is currently available only on the [Requestly Desktop App](https://requestly.com/downloads/desktop/).
Use this feature to test APIs with dynamic inputs, such as running the same workflow for multiple users, IDs, or configurations.
### Using a Data File in Collection Runner
Follow these steps to run a collection with custom data:
In the Collections sidebar, find the collection you want to execute and click the **Run** icon next to it.
In the Runner configuration panel, click **Select Data File**.
Supports JSON & CSV files (max 100MB)
Once added, Requestly will automatically detect the file type and preview its structure.
After selecting the file, a **preview** of your data will appear.
* For CSV files: verify column names and types
* For JSON files: check object keys and structure
Each key or column name should match the variable used in your requests, such as `{{storyId}}`.
Click **Save** and then **Start Run**.\
The Collection Runner will replace variables with data from your file for each iteration.
### How Data Files Work
When you attach a CSV or JSON file to your manual run:
* Each **row (CSV)** or **object (JSON)** represents one **iteration**
* Variables inside your requests (like `{{storyId}}`) will be replaced with the corresponding values
* Requestly automatically cycles through each data set until all iterations are complete
### Supported File Formats
#### CSV Format
* The first row defines variable names
* Each subsequent row represents one iteration
* Each row must have the same number of columns
**Example:**
```bash theme={null}
city,temperature
Vancouver,10
Austin,24
London,12
```
#### JSON Format
* Must be an array of key-value objects
* Each object defines one iteration
**Example:**
```json theme={null}
[
{ "city": "Vancouver", "temperature": 10 },
{ "city": "Austin", "temperature": 24 },
{ "city": "London", "temperature": 12 }
]
```
### Example Use Case
For a request like
```bash theme={null}
GET https://api.example.com/weather?city={{city}}
```
and a data file containing
```bash theme={null}
city
Vancouver
Austin
London
```
Requestly will automatically replace `{{city}}` with each value during the run.
### Accessing Data in Scripts
You can access data file values programmatically in your pre-request and post-response scripts using the `rq.iterationData` object. This allows you to implement conditional logic, validate responses, or perform calculations based on the input data.
**Example:**
```javascript theme={null}
// Pre-request script
const city = rq.iterationData.get("city");
console.log(`Testing weather API for: ${city}`);
// Post-response script
const expectedCity = rq.iterationData.get("city");
const responseData = rq.response.json();
rq.test("Response contains correct city", function() {
rq.expect(responseData.city).to.equal(expectedCity);
});
```
# DevTools
Source: https://docs.requestly.com/api-client/devtools
Inspect script logs, network activity, and cookies from your API requests in a single panel inside the Requestly API Client.
DevTools is Requestly's built-in debugger for API requests. It captures console output from your pre and post-request scripts, every outgoing request and its matching response, and the cookies attached to each call. Use it the same way you would use the browser's DevTools, but for the requests you fire from inside Requestly.
**Cookies availability:** Cookie capture in DevTools depends on the cookie jar, a desktop-app feature that is rolling out gradually. If the cookie jar is not enabled for your build, the **Cookies** panel and the per-request Cookies tab do not appear. See [Cookies](/api-client/send-api-request/cookies).
## Open DevTools
There are two ways to open DevTools, depending on whether you want to see activity across the whole app or scope it to a single request.
Click the **DevTools** button in the application footer at the bottom of the window. The panel docks to the bottom of the workspace and shows everything that has happened in the current session: every script log, every network request, and every cookie set or sent. Click the **X** in the top-right of the panel to close it.
Use this when you want a session-wide view, for example to compare two recent requests or scan logs from a script that ran across several calls.
Open any HTTP request and send it. In the response area you will see a **Debug** tab next to **Body**, **Headers**, and **Test Results**. The Debug tab shows DevTools scoped to that one request's most recent execution.
Use this when you want to inspect what a single request did without scrolling through unrelated activity. It is the fastest path from "this request misbehaved" to "here is the log line that explains why."
## Console tab
The Console shows log output produced while a request runs. That includes anything you wrote with `console.log()` or `console.error()` in a pre or post-request script, plus system events Requestly emits (for example, when a script throws an error).
The toolbar at the top of the panel gives you four controls:
* **Search**. Filters the visible log lines by substring match. Useful when you want to find a specific value you logged.
* **Level filter**. Toggle **Info**, **Warnings**, and **Errors**. By default all three are on. Turn off a level to hide those entries.
* **Source filter**. Toggle between **Users** (logs your scripts produced), **System** (errors and lifecycle events from Requestly itself), and **Network requests** (one-line summaries of each request the runtime made). All three are on by default.
* **Clear**. Empties the panel. Note that clear wipes both the Console and Network tabs at once, since they share a single store.
Logs from your pre and post-request scripts are tagged so you can find them quickly. Type `#script` into the search box to show only your own log output and hide everything else.
## Network tab
The Network tab lists every request the runtime sent on your behalf, including requests fired by `rq.sendRequest` from inside scripts and requests made by the collection runner. Each row shows the method, status code, URL, timestamp, response time, and response size.
### Filter the request list
The toolbar at the top of the panel offers three filters:
* **Search**. Matches against the URL, so you can locate a specific endpoint without scrolling.
* **Status**. Multi-select: **2xx Success**, **3xx Redirect**, **4xx Client Error**, **5xx Server Error**, and **No status (failed)**. The last option captures requests that never received a response, for example because of a network error or DNS failure.
* **Method**. Multi-select: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD.
Filters combine with AND. A request shows up only if it matches the search text AND the active status set AND the active method set.
### Inspect a single request
Click any row in the list to open a side panel with detail tabs:
* **Headers**. Request and response headers, side by side.
* **Payload**. Query string, path parameters, and request body. Multipart and form-encoded bodies are decoded so you can read each field.
* **Response**. The response body rendered in the response viewer. JSON and XML are pretty-printed and syntax-highlighted, with collapsible sections. Image responses render as the actual picture, and other binary responses show a **Binary response** placeholder with the response size instead of unreadable characters.
* **Info**. TLS handshake details for HTTPS requests: the TLS version and cipher suite, the server certificate (subject, issuer, and expiry), and the client certificate that was sent, if any. This tab only appears for HTTPS requests. See [SSL Certificates](/api-client/send-api-request/ssl-certificates) for how to configure custom CA and client certificates.
* **Cookies**. The cookies attached to the request and any cookies set by the response. Only appears when at least one cookie is involved. See [Cookies](/api-client/send-api-request/cookies) for how the cookie jar works end-to-end.
* **Variables**. Every variable that was referenced anywhere in the request, with the scope it resolved from (environment, collection, runtime, or global) and the value it resolved to.
Headers and Payload have a **Show resolved values** toggle in the top-right. With it off, you see your request as you wrote it, including `{{variable}}` placeholders. With it on, you see the exact bytes that went over the wire after every variable was substituted. Flip the toggle when a request is failing and you suspect a variable resolved to the wrong value.
## Retention
DevTools keeps the most recent activity in memory and drops older entries once the panel fills up. The defaults are tuned to hold a long debugging session without slowing the app down:
* Up to **25,000** console log lines.
* Up to **10,000** network requests.
* Up to **5,000** system events and **5,000** cookies.
Once a category is full, the oldest entries fall off as new ones come in. Activity is cleared when you reload the app, so if you want to keep a log around, copy it before closing.
## What's Next?
Write JavaScript that runs around your requests and shows up in the Console
Assert on response data and watch the results in the Test Results tab
Manage the cookie jar that DevTools observes on every request
# Variables and Environment
Source: https://docs.requestly.com/api-client/environments-and-variables
Learn how to use variables and environments in Requestly to manage dynamic values like API keys, base URLs, and tokens across your API requests.
Variables in Requestly’s API Client let you store and reuse dynamic values, like API keys, base URLs, and user IDs, across your API requests. They help you avoid hardcoding, make your collections more modular, and simplify switching between different environments like development, staging, and production.
A **variable** is a named placeholder you define once and reference anywhere in your API collections using the `{{variable_name}}` syntax.
When you run a request, Requestly replaces each `{{variable}}` with its actual value based on its scope.
Example: `https://{{base_url}}/users/{{user_id}}`
If you've defined `base_url = api.example.com` and `user_id = 123`, the request resolves to - `https://api.example.com/users/123`
+TIP: Hover over any `{{variable}}` in your request to preview its resolved value instantly.
### Explore Variable Types and Features
[Global Variables](/api-client/environments-and-variables/global-variables)
Use values that apply across all requests and collections.
[Environment Variables](/api-client/environments-and-variables/environment-variables)
Define values based on your working environment (e.g., dev, staging, prod).
[Runtime Variables](/api-client/environments-and-variables/runtime-variables)
Temporary values that last only for the current session, ideal for tokens or session IDs. They aren’t synced and can auto-clear after use.
[Collection & SubCollection Variables](/api-client/environments-and-variables/collection-and-subcollection-variables)
Scope variables to specific collections or groups of requests.
[Variable Precedence](/api-client/environments-and-variables/variable-precedence)
Understand how Requestly resolves variable conflicts when the same name exists in multiple scopes.
[Using Variables in API Requests](/api-client/environments-and-variables/using-variables-in-api-requests)
Learn where and how to use variables in your API request URLs, headers, bodies, and scripts.
# Collection & SubCollection Variables
Source: https://docs.requestly.com/api-client/environments-and-variables/collection-and-subcollection-variables
**Collection** and **SubCollection Variables** in Requestly let you define scoped values that are only available within a specific collection or a nested sub-group of requests. These variables are ideal when you want to manage shared data for a group of related requests, without affecting global or environment-level variables.
They help you build modular, reusable collections and make it easy to organize values related to a particular service, API module, or test scenario.
If both a collection and subcollection define a variable with the same name, **SubCollection variables take precedence** during execution.\`
## **How to Create Collection Variables**
### **Step 1: Access the Collections Tab**
**Sub-collection** variables can be created and take precedence over their parent collection variables. If a variable in the sub-collection shares the same key as one in the parent collection, the sub-collection variable will be used during request execution.
Click on the **Collection Name** to open **Collection Overview** and switch to **Variables** tab.
### **Step 2: Add Variables**
Add variables in the table by specifying the following details:
* **Key:** The name of the variable that you will be referencing when sending requests. Note, an environment cannot have keys with the same name.
* **Type:** The type of value the variable will store. It can be a **string**, **number**, **boolean**, **secret** (a masked value), or **array** (a list of values). See [Entering an array value](/api-client/environments-and-variables/environment-variables#entering-an-array-value) for how to type a list.
* **Initial value (synced):** Initial values will be synced across the project. These values will be used by default if no user-defined Current value is set for the variable.
* **Current value (local):** Current values are user-defined entries that are not synced across the project. These values will override the defined Initial values. If the current value is empty or left blank, then the initial value of the variable will be used.
# Dynamic Variables
Source: https://docs.requestly.com/api-client/environments-and-variables/dynamic-variables
Dynamic variables are built in values that are generated automatically at request execution time. They remove the need for manual inputs or custom scripts when you need commonly used data like timestamps, random values, or unique identifiers.
Unlike environment, collection, or global variables which you define yourself, dynamic variables are available out of the box and always generate a fresh value when a request runs.
Requestly uses [**Faker.js**](https://fakerjs.dev/) to generate realistic data for dynamic variables.
They are accessed using the special `$` prefix syntax:
```
{{$variableName}}
```
## Using dynamic variables
You can use dynamic variables anywhere in a request including the URL, headers, query params, and body.
Use dynamic variables like `{{$randomFirstName}}`, `{{$randomLastName}}`, and `{{$randomEmail}}` to create unique user data for each request:
Dynamic variables are great for generating unique query parameters or path segments:
You can also use dynamic variables in headers to generate unique values for each request:
When using dynamic variables in scripts, call them as functions with the `rq.$` prefix:
**Script syntax:** When using dynamic variables in scripts, call them as functions: `rq.$variableName()` instead of the template syntax `{{$variableName}}`.
## Variable precedence
When the same variable name is defined as both a dynamic variable and a user-defined variable (environment, collection, or global), the **user-defined variable takes precedence**.
### Precedence order
**User-defined variables** (Runtime → Environment → SubCollection → Collection → Global) **>** **Dynamic variables**
**Example :** If you define an environment variable named `$randomUUID`:
```javascript theme={null}
rq.environment.set("$randomUUID", "123e4567-e89b-12d3-a456-426614174000");
```
And then use `{{$randomUUID}}` in your request, it will resolve to `"123e4567-e89b-12d3-a456-426614174000"` (your custom value), **not** the dynamic UUID value.
**Best practice:** Never use the `$` prefix (e.g., `{{$randomUUID}}`) for user-defined variables.
## Use arguments with dynamic variables
Some dynamic variables support optional arguments to customize their output.
For a complete list of variables that support arguments and their available options, see the [Variables with arguments](#variables-with-arguments) section below.
### Syntax
```
{{$variableName arg1 arg2 ...}}
```
**Example:**
```json theme={null}
{
"id": "{{$randomAlphaNumeric 10}}",
"email": "{{$randomEmail 'John' 'Doe'}}",
"age": "{{$randomInt 18 65}}",
"price": "{{$randomPrice 10 100 2 '$'}}"
}
```
**Script syntax:** When using dynamic variables in scripts, call them as functions: `rq.$variableName(arg1,arg2 ...)`
## Supported dynamic variables
Requestly provides a comprehensive set of built-in dynamic variables organized by category.
### Common
| Variable | Description | Example |
| ------------------- | --------------------------------- | -------------------------------------- |
| `{{$guid}}` | uuid-v4 style guid | `f47ac10b-58cc-4372-a567-0e02b2c3d479` |
| `{{$timestamp}}` | Current UNIX timestamp in seconds | `1739404800` |
| `{{$isoTimestamp}}` | Current ISO timestamp at zero UTC | `2026-02-13T14:25:30.177Z` |
| `{{$randomUUID}}` | A random 36-character UUID | `a3bb189e-8bf9-3888-9912-ace4e6543002` |
### Text, Numbers and Colors
| Variable | Description | Example |
| ------------------------- | ------------------------------------ | --------- |
| `{{$randomAlphaNumeric}}` | A random alpha-numeric character | `t` |
| `{{$randomBoolean}}` | A random boolean value | `FALSE` |
| `{{$randomInt}}` | A random integer between 0 and 10000 | `472` |
| `{{$randomColor}}` | A random human readable color | `blue` |
| `{{$randomHexColor}}` | A random hex value | `#2f8a45` |
| `{{$randomAbbreviation}}` | A random abbreviation | `HTTP` |
### Internet and IP Addresses
| Variable | Description | Example |
| ----------------------- | --------------------------------------------- | ----------------------------------------- |
| `{{$randomIP}}` | A random IPv4 address | `192.168.45.233` |
| `{{$randomIPV6}}` | A random IPv6 address | `2001:0db8:85a3:0000:0000:8a2e:0370:7334` |
| `{{$randomMACAddress}}` | A random MAC address | `aa:bb:cc:dd:ee:ff` |
| `{{$randomPassword}}` | A random 15-character alpha-numeric password | `8kP2mX9qL4nB5wV3` |
| `{{$randomLocale}}` | A random two-letter language code (ISO 639-1) | `fr` |
| `{{$randomUserAgent}}` | A random user agent | `Mozilla/5.0 ...` |
| `{{$randomProtocol}}` | A random internet protocol | `https` |
### Names
| Variable | Description | Example |
| ----------------------- | ---------------------------- | ------------------ |
| `{{$randomFirstName}}` | A random first name | `Sarah` |
| `{{$randomLastName}}` | A random last name | `Johnson` |
| `{{$randomFullName}}` | A random first and last name | `Michael Anderson` |
| `{{$randomNamePrefix}}` | A random name prefix | `Ms.` |
| `{{$randomNameSuffix}}` | A random name suffix | `Jr.` |
### Profession
| Variable | Description | Example |
| -------------------------- | ----------------------- | --------------------- |
| `{{$randomJobArea}}` | A random job area | `Security` |
| `{{$randomJobDescriptor}}` | A random job descriptor | `Chief` |
| `{{$randomJobTitle}}` | A random job title | `Senior Data Analyst` |
| `{{$randomJobType}}` | A random job type | `Engineer` |
### Phone, Address and Location
| Variable | Description | Example |
| --------------------------- | ----------------------------------------------------- | ------------------- |
| `{{$randomPhoneNumber}}` | A random ten-digit phone number | `555-987-6543` |
| `{{$randomPhoneNumberExt}}` | A random phone number with extension | `555-456-7890 x321` |
| `{{$randomCity}}` | A random city name | `Riverside` |
| `{{$randomStreetName}}` | A random street name | `Oak Avenue` |
| `{{$randomStreetAddress}}` | A random street address | `456 Elm Drive` |
| `{{$randomCountry}}` | A random country | `Canada` |
| `{{$randomCountryCode}}` | A random two-letter country code (ISO 3166-1 alpha-2) | `US` |
| `{{$randomLatitude}}` | A random latitude coordinate | `-23.5475` |
| `{{$randomLongitude}}` | A random longitude coordinate | `151.2095` |
### Images
| Variable | Description | Example |
| --------------------------- | -------------------------------------- | ------------------------------------------- |
| `{{$randomAvatarImage}}` | A random avatar image | `https://example.com/avatar/512x512` |
| `{{$randomImageUrl}}` | A URL of a random image | `https://example.com/images/640/480` |
| `{{$randomAbstractImage}}` | A URL of a random abstract image | `https://loremflickr.com/640/480/abstract` |
| `{{$randomAnimalsImage}}` | A URL of a random animal image | `https://loremflickr.com/640/480/animals` |
| `{{$randomBusinessImage}}` | A URL of a random stock business image | `https://loremflickr.com/640/480/business` |
| `{{$randomCatsImage}}` | A URL of a random cat image | `https://loremflickr.com/640/480/cats` |
| `{{$randomCityImage}}` | A URL of a random city image | `https://loremflickr.com/640/480/city` |
| `{{$randomFoodImage}}` | A URL of a random food image | `https://loremflickr.com/640/480/food` |
| `{{$randomNightlifeImage}}` | A URL of a random nightlife image | `https://loremflickr.com/640/480/nightlife` |
| `{{$randomFashionImage}}` | A URL of a random fashion image | `https://loremflickr.com/640/480/fashion` |
| `{{$randomPeopleImage}}` | A URL of a random image of a person | `https://loremflickr.com/640/480/people` |
| `{{$randomNatureImage}}` | A URL of a random nature image | `https://loremflickr.com/640/480/nature` |
| `{{$randomSportsImage}}` | A URL of a random sports image | `https://loremflickr.com/640/480/sports` |
| `{{$randomTransportImage}}` | A URL of a random transportation image | `https://loremflickr.com/640/480/transport` |
| `{{$randomImageDataUri}}` | A random image data URI | `data:image/svg+xml;charset=UTF-8...` |
### Finance
| Variable | Description | Example |
| ---------------------------- | ------------------------------------------ | ------------------------------------ |
| `{{$randomBankAccount}}` | A random 8-digit bank account number | `78945612` |
| `{{$randomBankAccountName}}` | A random bank account name | `Savings Account` |
| `{{$randomCreditCardMask}}` | A random masked credit card number | `1234` |
| `{{$randomBankAccountBic}}` | A random BIC (Bank Identifier Code) | `DEUTDEFF` |
| `{{$randomBankAccountIban}}` | A random 15-31 character IBAN | `GB82WEST12345698765432` |
| `{{$randomTransactionType}}` | A random transaction type | `payment` |
| `{{$randomCurrencyCode}}` | A random 3-letter currency code (ISO-4217) | `EUR` |
| `{{$randomCurrencyName}}` | A random currency name | `US Dollar` |
| `{{$randomCurrencySymbol}}` | A random currency symbol | `€` |
| `{{$randomBitcoin}}` | A random bitcoin address | `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` |
### Business
| Variable | Description | Example |
| -------------------------- | --------------------------------- | --------------------------------- |
| `{{$randomCompanyName}}` | A random company name | `TechStart Solutions` |
| `{{$randomCompanySuffix}}` | A random company suffix | `LLC` |
| `{{$randomBs}}` | A random phrase of business-speak | `streamline innovative platforms` |
| `{{$randomBsAdjective}}` | A random business-speak adjective | `dynamic` |
| `{{$randomBsBuzz}}` | A random business-speak buzzword | `optimize` |
| `{{$randomBsNoun}}` | A random business-speak noun | `solutions` |
### Catchphrases
| Variable | Description | Example |
| ---------------------------------- | ------------------------------- | --------------------------------- |
| `{{$randomCatchPhrase}}` | A random catchphrase | `Innovative scalable methodology` |
| `{{$randomCatchPhraseAdjective}}` | A random catchphrase adjective | `Robust` |
| `{{$randomCatchPhraseDescriptor}}` | A random catchphrase descriptor | `cloud-based` |
| `{{$randomCatchPhraseNoun}}` | A random catchphrase noun | `framework` |
### Databases
| Variable | Description | Example |
| ------------------------------ | ----------------------------- | ----------------- |
| `{{$randomDatabaseColumn}}` | A random database column name | `userId` |
| `{{$randomDatabaseType}}` | A random database type | `varchar` |
| `{{$randomDatabaseCollation}}` | A random database collation | `utf8_unicode_ci` |
| `{{$randomDatabaseEngine}}` | A random database engine | `InnoDB` |
### Dates
| Variable | Description | Example |
| ----------------------- | ------------------------ | -------------------------- |
| `{{$randomDateFuture}}` | A random future datetime | `2027-11-05T18:30:22.000Z` |
| `{{$randomDatePast}}` | A random past datetime | `2023-08-14T15:45:33.000Z` |
| `{{$randomDateRecent}}` | A random recent datetime | `2026-02-07T10:20:15.000Z` |
| `{{$randomWeekday}}` | A random weekday | `Monday` |
| `{{$randomMonth}}` | A random month | `September` |
### Domains, Emails and Usernames
| Variable | Description | Example |
| ------------------------- | --------------------------------------------- | -------------------------- |
| `{{$randomDomainName}}` | A random domain name | `test-site.net` |
| `{{$randomDomainSuffix}}` | A random domain suffix | `org` |
| `{{$randomDomainWord}}` | A random unqualified domain name | `sample` |
| `{{$randomEmail}}` | A random email address | `sample@gmail.com` |
| `{{$randomExampleEmail}}` | A random email address from an example domain | `alex.johnson@example.org` |
| `{{$randomUserName}}` | A random username | `techuser2024` |
| `{{$randomUrl}}` | A random URL | `https://demo-website.io` |
### Files and Directories
| Variable | Description | Example |
| --------------------------- | ------------------------------------------------------ | -------------------------- |
| `{{$randomSemver}}` | A random semantic version number | `3.12.4` |
| `{{$randomFileName}}` | A random file name (includes uncommon extensions) | `report_2024.pdf` |
| `{{$randomFileType}}` | A random file type (includes uncommon file types) | `video` |
| `{{$randomFileExt}}` | A random file extension (includes uncommon extensions) | `csv` |
| `{{$randomCommonFileName}}` | A random file name | `presentation.pptx` |
| `{{$randomCommonFileType}}` | A random, common file type | `image` |
| `{{$randomCommonFileExt}}` | A random, common file extension | `jpg` |
| `{{$randomFilePath}}` | A random file path | `/var/www/html/index.html` |
| `{{$randomDirectoryPath}}` | A random directory path | `/opt/apps` |
| `{{$randomMimeType}}` | A random MIME type | `image/jpeg` |
### Stores
| Variable | Description | Example |
| ----------------------------- | --------------------------------------- | ------------------------ |
| `{{$randomPrice}}` | A random price between 0.00 and 1000.00 | `247.99` |
| `{{$randomProduct}}` | A random product | `Shoes` |
| `{{$randomProductAdjective}}` | A random product adjective | `Premium` |
| `{{$randomProductMaterial}}` | A random product material | `Cotton` |
| `{{$randomProductName}}` | A random product name | `Ergonomic Wooden Chair` |
| `{{$randomDepartment}}` | A random commerce category | `Electronics` |
### Grammar
| Variable | Description | Example |
| ---------------------- | ---------------------------- | ------------------------------------- |
| `{{$randomNoun}}` | A random noun | `network` |
| `{{$randomVerb}}` | A random verb | `generate` |
| `{{$randomIngverb}}` | A random verb ending in -ing | `processing` |
| `{{$randomAdjective}}` | A random adjective | `efficient` |
| `{{$randomWord}}` | A random word | `system` |
| `{{$randomWords}}` | Some random words | `quick brown fox jumps high` |
| `{{$randomPhrase}}` | A random phrase | `Try to compress the TCP protocol...` |
### Lorem Ipsum
| Variable | Description | Example |
| ---------------------------- | --------------------------------------------- | -------------------------------------------- |
| `{{$randomLoremWord}}` | A random word of lorem ipsum text | `ipsum` |
| `{{$randomLoremWords}}` | Some random words of lorem ipsum text | `dolor sit amet` |
| `{{$randomLoremSentence}}` | A random sentence of lorem ipsum text | `Sed ut perspiciatis unde omnis iste natus.` |
| `{{$randomLoremSentences}}` | A random 2 to 6 sentences of lorem ipsum text | `Nemo enim ipsam voluptatem...` |
| `{{$randomLoremParagraph}}` | A random paragraph of lorem ipsum text | `Lorem ipsum dolor sit amet...` |
| `{{$randomLoremParagraphs}}` | 3 random paragraphs of lorem ipsum text | `Voluptatem rem magnam...` |
| `{{$randomLoremText}}` | A random amount of lorem ipsum text | `Temporibus autem quibusdam...` |
| `{{$randomLoremSlug}}` | A random lorem ipsum URL slug | `lorem-ipsum-dolor` |
| `{{$randomLoremLines}}` | 1 to 7 random lines of lorem ipsum | `Sed ut perspiciatis unde...` |
## Variables with arguments
The following dynamic variables support optional arguments for customization.
### Common
**Arguments:** `version` (`4`|`7`), `refDate`
```javascript theme={null}
{{$guid 7}}
{{$guid 4 "2026-01-01"}}
```
**Arguments:** `version` (`4`|`7`), `refDate`
```javascript theme={null}
{{$randomUUID 7}}
{{$randomUUID 4 "2026-01-01"}}
```
### Text, Numbers and Colors
**Arguments:** `length | (min max)`, `casing` (`upper`|`lower`|`mixed`), `exclude`
```javascript theme={null}
{{$randomAlphaNumeric 5}}
{{$randomAlphaNumeric 3 8 "upper"}}
```
**Arguments:** `probability` (`0-1`)
```javascript theme={null}
{{$randomBoolean 0.8}}
```
**Arguments:** `max | (min max)`
```javascript theme={null}
{{$randomInt 100}}
{{$randomInt 1 100}}
{{$randomInt 0 100}}
```
**Arguments:** `format` (`hex`|`css`|`binary`), `includeAlpha` (`true`|`false`), `prefix`, `casing` (`upper`|`lower`|`mixed`)
```javascript theme={null}
{{$randomHexColor "css"}}
{{$randomHexColor "hex" "true" "#" "upper"}}
```
### Internet and IP Addresses
**Arguments:** `cidrBlock | network`
```javascript theme={null}
{{$randomIP "192.168.0.0/16"}}
```
**Arguments:** `separator`
```javascript theme={null}
{{$randomMACAddress "-"}}
```
**Arguments:** `length`, `memorable` (`true`|`false`), `pattern`, `prefix`
```javascript theme={null}
{{$randomPassword 20}}
{{$randomPassword 12 "true"}}
```
### Names
**Arguments:** `gender` (`male`|`female`)
```javascript theme={null}
{{$randomFirstName "male"}}
```
**Arguments:** `gender` (`male`|`female`)
```javascript theme={null}
{{$randomLastName "female"}}
```
**Arguments:** `gender` (`male`|`female`)
```javascript theme={null}
{{$randomFullName "male"}}
```
**Arguments:** `gender` (`male`|`female`)
```javascript theme={null}
{{$randomNamePrefix "female"}}
```
### Phone, Address and Location
**Arguments:** `style` (`human`|`national`|`international`)
```javascript theme={null}
{{$randomPhoneNumber "international"}}
```
**Arguments:** `useFullAddress` (`true`|`false`)
```javascript theme={null}
{{$randomStreetAddress "true"}}
```
**Arguments:** `variant` (`alpha-2`|`alpha-3`|`numeric`)
```javascript theme={null}
{{$randomCountryCode "alpha-3"}}
```
**Arguments:** `max | (min max)`, `precision`
```javascript theme={null}
{{$randomLatitude 50}}
{{$randomLatitude -10 50 4}}
```
**Arguments:** `max | (min max)`, `precision`
```javascript theme={null}
{{$randomLongitude 100}}
{{$randomLongitude -100 100 4}}
```
### Images
**Arguments:** `width`, `height`
```javascript theme={null}
{{$randomImageUrl 800 600}}
```
**Arguments:** `width`, `height`, `color`, `type` (`svg-uri`|`svg-base64`)
```javascript theme={null}
{{$randomImageDataUri 200 200 "blue" "svg-base64"}}
```
### Finance
**Arguments:** `length` (default `8`)
```javascript theme={null}
{{$randomBankAccount 10}}
```
**Arguments:** `issuer`
```javascript theme={null}
{{$randomCreditCardMask "visa"}}
```
**Arguments:** `includeBranchCode` (`true`|`false`)
```javascript theme={null}
{{$randomBankAccountBic "true"}}
```
**Arguments:** `formatted` (`true`|`false`), `countryCode`
```javascript theme={null}
{{$randomBankAccountIban "true" "DE"}}
```
**Arguments:** `type` (`legacy`|`segwit`|`bech32`), `network` (`mainnet`|`testnet`)
```javascript theme={null}
{{$randomBitcoin "segwit" "mainnet"}}
```
### Dates
**Arguments:** `years`, `refDate`
```javascript theme={null}
{{$randomDateFuture 5}}
{{$randomDateFuture 2 "2025-01-01"}}
```
**Arguments:** `years`, `refDate`
```javascript theme={null}
{{$randomDatePast 3}}
{{$randomDatePast 1 "2024-06-01"}}
```
**Arguments:** `days`, `refDate`
```javascript theme={null}
{{$randomDateRecent 7}}
{{$randomDateRecent 30 "2026-01-01"}}
```
**Arguments:** `abbreviated` (`true`|`false`), `context` (`true`|`false`)
```javascript theme={null}
{{$randomWeekday "true"}}
```
**Arguments:** `abbreviated` (`true`|`false`), `context` (`true`|`false`)
```javascript theme={null}
{{$randomMonth "true"}}
```
### Domains, Emails and Usernames
**Arguments:** `firstName`, `lastName`, `provider`, `allowSpecialCharacters` (`true`|`false`)
```javascript theme={null}
{{$randomEmail "John"}}
{{$randomEmail "John" "Doe" "gmail.com"}}
```
**Arguments:** `firstName`, `lastName`, `allowSpecialCharacters` (`true`|`false`)
```javascript theme={null}
{{$randomExampleEmail "John" "Doe"}}
```
**Arguments:** `firstName`, `lastName`
```javascript theme={null}
{{$randomUserName "John" "Doe"}}
```
**Arguments:** `protocol` (`http`|`https`), `appendSlash` (`true`|`false`)
```javascript theme={null}
{{$randomUrl "https" "true"}}
```
### Files and Directories
**Arguments:** `extensionCount | (min max)`
```javascript theme={null}
{{$randomFileName 2}}
{{$randomFileName 1 3}}
```
**Arguments:** `mimeType`
```javascript theme={null}
{{$randomFileExt "image/jpeg"}}
```
### Stores
**Arguments:** `max | (min max)`, `dec`, `symbol`
```javascript theme={null}
{{$randomPrice 500}}
{{$randomPrice 10 100 2 "$"}}
```
### Grammar
**Arguments:** `length | (min max)`, `strategy` (`fail`|`closest`|`shortest`|`longest`|`any-length`)
```javascript theme={null}
{{$randomNoun 5}}
{{$randomNoun 3 8 "closest"}}
```
**Arguments:** `length | (min max)`, `strategy` (`fail`|`closest`|`shortest`|`longest`|`any-length`)
```javascript theme={null}
{{$randomVerb 5}}
{{$randomVerb 3 8 "closest"}}
```
**Arguments:** `length | (min max)`, `strategy` (`fail`|`closest`|`shortest`|`longest`|`any-length`)
```javascript theme={null}
{{$randomAdjective 5}}
{{$randomAdjective 3 8 "closest"}}
```
**Arguments:** `length | (min max)`, `strategy` (`fail`|`closest`|`shortest`|`longest`|`any-length`)
```javascript theme={null}
{{$randomWord 5}}
{{$randomWord 3 8 "closest"}}
```
**Arguments:** `count | (min max)`
```javascript theme={null}
{{$randomWords 3}}
{{$randomWords 2 5}}
```
### Lorem Ipsum
**Arguments:** `length | (min max)`, `strategy` (`fail`|`closest`|`shortest`|`longest`|`any-length`)
```javascript theme={null}
{{$randomLoremWord 5}}
{{$randomLoremWord 3 8 "closest"}}
```
**Arguments:** `count | (min max)`
```javascript theme={null}
{{$randomLoremWords 5}}
{{$randomLoremWords 3 7}}
```
**Arguments:** `wordCount | (min max)`
```javascript theme={null}
{{$randomLoremSentence 10}}
{{$randomLoremSentence 5 12}}
```
**Arguments:** `count | (min max)`, `separator`
```javascript theme={null}
{{$randomLoremSentences 3}}
{{$randomLoremSentences 2 5}}
```
**Arguments:** `sentenceCount | (min max)`
```javascript theme={null}
{{$randomLoremParagraph 5}}
{{$randomLoremParagraph 3 7}}
```
**Arguments:** `count | (min max)`, `separator`
```javascript theme={null}
{{$randomLoremParagraphs 5}}
{{$randomLoremParagraphs 2 4}}
```
**Arguments:** `count | (min max)`
```javascript theme={null}
{{$randomLoremSlug 5}}
{{$randomLoremSlug 2 4}}
```
**Arguments:** `count | (min max)`
```javascript theme={null}
{{$randomLoremLines 3}}
{{$randomLoremLines 2 5}}
```
## What's Next?
Store and manage auth tokens securely with variables
Use temporary variables for request execution
# Environment Variables
Source: https://docs.requestly.com/api-client/environments-and-variables/environment-variables
**Environment Variables** in Requestly allow you to configure API requests based on different environments, such as **Development**, **Staging**, or **Production**. They help you manage environment-specific values like base URLs, tokens, or credentials without manually editing each request when switching contexts.
### Why Use Environment Variables?
Environment variables let you:
* Switch between Dev, Staging, and Prod configurations easily
* Avoid editing request details manually for each environment
* Keep secrets scoped to the environment where they’re needed
* Enable environment-specific behavior in scripts and tests
Example use cases:
* `{{base_url}}` points to `https://dev.api.com` in development and `https://api.com` in production
* Different `{{auth_token}}` for each environment
## **How to Create Environment Variables**
### **Step 1: Access the Environments Tab**
Click on the **Environments** tab in the side menu.
### **Step 2: Select an Environment**
Select the environment you want to add variables to.
### **Step 3: Add Variables**
Add variables in the table by specifying the following details:
* **Key:** The name of the variable that you will be referencing when sending requests. Note, an environment cannot have keys with the same name.
* **Type:** The type of value the variable will store. It can be a **string**, **number**, **boolean**, **secret** (a masked value), or **array** (a list of values).
* **Initial value (synced):** Initial values will be synced across the project. These values will be used by default if no user-defined Current value is set for the variable.
* **Current value (local):** Current values are user-defined entries that are not synced across the project. These values will override the defined Initial values. If the current value is empty or left blank, then the initial value of the variable will be used.
### **Step 4: Switch Environments**
To switch environments, use the dropdown on the top bar of the API Client’s sidebar. Select the desired environment to ensure that the variables associated with it are used in your API requests.
## Entering an array value
Choose **array** as the type when a variable should hold a list of items instead of a single value. Type the items into the value field and Requestly parses them into a list when you save:
* `1, 2, 3` becomes a list of numbers.
* `a, b, c` becomes a list of strings.
* Wrap an item in quotes to keep it a string: `"1", "2"` stays a list of the strings `1` and `2`.
* Paste exact JSON to control each item's type precisely, for example `[1, "2", true]`.
* A single value with no comma becomes a one-item list, and an empty value becomes an empty list.
When you reference an array variable inline with `{{variable_name}}`, it renders as the JSON text of the list, for example `["a","b"]`. In scripts, an array variable is returned as a real array. See [rq.environment](/api-client/rq-api-reference/rq-environment#working-with-array-variables) for reading and writing array values in scripts.
# Global Variables
Source: https://docs.requestly.com/api-client/environments-and-variables/global-variables
Learn about global variables in requestly
**Global Variables** in Requestly are shared values accessible across all requests, environments, and collections in your project. They are ideal for constants or secrets that don’t change frequently, like API keys, common headers, or service base URLs.
Using global variables makes your API collections more reusable, consistent, and easier to update across your project.
## **How to Create Global Variables**
### **Step 1: Access Global Variables**
Click on the **Environments** icon in the side menu. The first item in the list is labeled as "Global variables."
### **Step 2: Add Variables**
Add variables in the table by specifying the following details:
* **Key:** The name of the variable that you will be referencing when sending requests. Note, global variables cannot have duplicate keys.
* **Type:** The type of value the variable will store. It can be a **string**, **number**, **boolean**, **secret** (a masked value), or **array** (a list of values). See [Entering an array value](/api-client/environments-and-variables/environment-variables#entering-an-array-value) for how to type a list.
* **Initial value (synced):** Initial values will be synced across the project. These values will be used by default if no user-defined Current value is set for the variable.
* **Current value (local):** Current values are user-defined entries that are not synced across the project. These values will override the defined Initial values. If the current value is empty or left blank, then the initial value of the variable will be used.
# Runtime Variables
Source: https://docs.requestly.com/api-client/environments-and-variables/runtime-variables
Runtime variables in Requestly are **temporary variables** that last until the session is closed. Unlike environment or collection variables, they are available globally across all projects.
Runtime variables are the only type of variables that work **across multiple projects**.
You can choose whether variables should **persist** it’s value after restarting the app .
## Why use runtime variables?
Runtime variables are designed to give you flexibility when testing APIs across different projects. Some common use cases include:
* **Quick testing**: Store temporary values like access tokens or session IDs while debugging.
* **Cross-project usage**: Share the same variable across multiple local projects without redefining it each time.
* **Persistence control**: Choose whether the variable should survive after restarting the app or clear automatically for a fresh start.
Runtime variables are **not synced to the cloud**. They only exist locally on your device. If you switch machines or reinstall the app, these variables will not carry over.
## Creating a runtime variable
From the sidebar, click on **Runtime variables**.
In the variables table, click **+ Add More** and enter the variable details:
* **Key** - The variable name (e.g., `session_id`).
* **Value** - The value you want to store.
* **Type** - Select from **String**, **Number**, **Boolean**, **Secret**, or **Array** (a list of values). See [Entering an array value](/api-client/environments-and-variables/environment-variables#entering-an-array-value) for how to type a list.
* **Persistent** - Toggle whether the variable should be saved across app restarts.
* **Yes** → Keeps its value after restarting the app.
* **No** → Clears itself automatically on restart.
## Using runtime variables
**Method 1: Insert variables directly in requests**
You can use runtime variables just like environment or collection variables. Wrap the variable name in double curly braces `{{ }}`:
`https://api.example.com/users/{{session_id}}`
**Method 2: Set variables in scripts**\
You can define or update runtime variables in the **Scripts** tab using the `rq.variables` object.
```javascript theme={null}
rq.variables.set("token", "12345");
rq.variables.get("token");
```
# Using Variables in API Requests
Source: https://docs.requestly.com/api-client/environments-and-variables/using-variables-in-api-requests
Once you've defined variables in Requestly, whether global, environment, collection, or subcollection, you can reference them directly in your API requests. This allows you to dynamically inject values into URLs, headers, request bodies, scripts, and more.
## **Use Variables in API Requests**
### **Step 1: Create or Open a Request**
Create or open an existing request in the **API Client**.
### **Step 2: Replace Static Values**
Replace static values with your environment variables using the `{{variable_name}}` syntax.
### **Step 3: View Variable Values**
Hover over a variable to see its resolved value.
## **Test Your Setup**
### **Step 1: Execute the Request**
Click **Send** to execute the request.
### **Step 2: Verify Resolved Values**
Check the resolved values in the **Request Preview** to ensure that variables are substituted correctly.
If a variable isn't resolving, verify that the variable name matches exactly (case-sensitive) and is present in the selected environment.
## **Array variables**
When a variable holds an [array value](/api-client/environments-and-variables/environment-variables), referencing it inline with `{{variable_name}}` renders the JSON text of the list. For example, an array variable holding `a` and `b` resolves to `["a","b"]` in a URL, header, or body.
To work with individual items, read the variable in a script, where it is returned as a real array. See [rq.environment](/api-client/rq-api-reference/rq-environment#working-with-array-variables) for reading array variables in scripts.
## **Composite variables**
Composite variables allow you to reference one variable inside another variable's value. This is useful when you want to build dynamic values from other variables.
### **How it works**
Define a variable that references another variable using the `{{variable_name}}` syntax:
| Variable Name | Value |
| -------------- | ------------------------- |
| `base_url` | `api.example.com` |
| `api_endpoint` | `https://{{base_url}}/v1` |
When `api_endpoint` is resolved, it becomes `https://api.example.com/v1`.
### **Example: Building dynamic URLs**
You can chain multiple variables together:
| Variable Name | Value |
| ------------- | ------------------------------------ |
| `env` | `staging` |
| `region` | `us-east` |
| `base_url` | `{{env}}.{{region}}.api.example.com` |
| `full_url` | `https://{{base_url}}/users` |
The `full_url` resolves to `https://staging.us-east.api.example.com/users`.
### **Circular dependency handling**
If you create circular references (e.g., `var_a = {{var_b}}` and `var_b = {{var_a}}`), Requestly detects this and leaves the variables unresolved to prevent infinite loops.
Autocompletion and syntax highlighting for variable references inside the variables table is not currently supported.
# Variable Precedence
Source: https://docs.requestly.com/api-client/environments-and-variables/variable-precedence
Variable precedence in Requestly defines how a variable value is resolved when the same variable name exists in multiple scopes. The value is picked based on scope priority, ensuring the most relevant context is always applied.
## Precedence order
> Data File (iteration) Variables → Runtime Variables → Environment Variables → SubCollection Variables → Collection Variables → Global Variables → Dynamic Variables
During a Collection Runner data-file run, the per-iteration variables from the CSV/JSON take the highest precedence, above Runtime Variables.
**Dynamic variables** are built-in variables (like `{{$timestamp}}`, `{{$randomUUID}}`, etc.) that have the lowest precedence. If you define a custom variable with the same name, your custom value will be used.
## How it works
* **Runtime variables** have the highest priority. If a runtime variable with the same name exists, it overrides all other scopes for the duration of the session.
* **Environment variables** are checked next and override SubCollection, Collection, and Global variables.
* **SubCollection variables** apply only within that SubCollection and override Collection and Global variables.
* **Collection variables** apply to all requests in the collection unless overridden by a higher scope.
* **Global variables** act as the final fallback when the variable is not found in any other scope.
This model makes it easy to reuse variables globally while still allowing precise overrides for environments, collections, or temporary runtime use cases.
## Developer style explanation
```javascript theme={null}
if (variable_name in runtime_variables) { // Check runtime
return runtime_variables[variable_name];
} else if (variable_name in environment_variables) { // Check environment
return environment_variables[variable_name];
} else if (variable_name in subcollection_variables) { // Check sub-collection
return subcollection_variables[variable_name];
} else if (variable_name in collection_variables) { // Check collection
return collection_variables[variable_name];
} else if (variable_name in global_variables) { // Check global
return global_variables[variable_name];
} else if (is_dynamic_variable(variable_name)) { // Check dynamic variables
return generate_dynamic_value(variable_name); // e.g., $timestamp, $randomUUID
} else {
return null; // Variable not found in any scope
}
```
When using the `$` prefix (e.g., `{{$timestamp}}`), the system skips user-defined variable lookups and directly generates the dynamic value.
## Example scenario
Assume the variable `{{base_url}}` is defined in multiple scopes:
| Scope | Value |
| ------------- | ---------------------------- |
| Global | `https://global.api.com` |
| Collection | `https://collection.api.com` |
| SubCollection | `https://sub.api.com` |
| Environment | `https://env.api.com` |
| Runtime | `https://runtime.api.com` |
If you send a request inside a **SubCollection** with an active **Environment**, and a **runtime variable** with the same name exists, `{{base_url}}` resolves to:
`https://runtime.api.com`
If the runtime variable is removed, the value falls back to the **environment variable**, followed by SubCollection, Collection, and finally Global based on availability.
## Dynamic variables precedence example
Assume you want to use a timestamp in your request:
**Scenario 1: Using `{{timestamp}}`** (without `$` prefix)
| Scope | Value (if defined) |
| ----------- | -------------------------------------- |
| Environment | `"2024-01-15"` |
| Dynamic | Current timestamp (e.g., `1613360320`) |
Result: `{{timestamp}}` resolves to `"2024-01-15"` (your custom environment variable)
**Scenario 2: Using `{{$timestamp}}`** (with `$` prefix)
Result: `{{$timestamp}}` **always** resolves to the current Unix timestamp (e.g., `1613360320`), regardless of whether you have a custom `timestamp` variable defined.
**Best Practice:**
```javascript theme={null}
// In pre-request script
// This uses your custom variable if defined, otherwise falls back to dynamic
const myTimestamp = "{{timestamp}}";
// This always generates a fresh dynamic timestamp
const freshTimestamp = rq.$timestamp();
```
Use the `$` prefix (`{{$variableName}}` or `rq.$variableName()`) when you explicitly want to use a dynamic variable, even if a custom variable with the same name exists.
# Create Request & Response Examples
Source: https://docs.requestly.com/api-client/examples
Save, manage, and reuse examples in Requestly. Create snapshots of your API requests with different configurations for quick reuse.
Examples are a pairing of a request and its corresponding response. Each example captures the complete state of an API call, including the request details (method, URL, parameters, headers, and body) and the response details (status code, body, and headers).
You can attach multiple examples to a single request, all organized under that parent request in the sidebar. This makes it easy to navigate between different scenarios without duplicating or modifying the original request.
Having multiple examples for one request helps you represent how an API behaves in different situations. For instance, you can save examples for successful responses, error states like 400 or 404, or cases where the response data changes.
## Why Use Examples
* **Test multiple scenarios**\
Save different configurations like valid inputs, edge cases, and error states, and switch between them instantly.
* **Collaborate with your team**\
Examples are shared within your project so others can view and use the exact configurations.
* **Retain request and response data**\
Each example stores both the request and its response, making it easy to revisit past executions.
## Save a request & responses as an example
You can create an example from any HTTP or GraphQL request that has been sent at least once.
Navigate to an existing API request in your project or send a new request.
Click the **Save** dropdown in the request view and select **Save as example**. \
This stores the current configuration including URL, method, headers, parameters, and body.
The example opens in a new tab. The parent request in the sidebar expands to show the newly created example beneath it.
You can also save examples from the request's context menu in the sidebar by right-clicking the request and selecting the save option.
## Manage examples in the sidebar
Examples appear as collapsible children under their parent request in the sidebar. Click the expand arrow next to any request to reveal its examples.
### Open an example
Click on an example in the sidebar to open it in a new tab. The example loads with the saved request configuration and response data.
### Rename an example
Right-click the example in the sidebar and select **Rename**, or double-click the example name. Type the new name and press **Enter** to save.
### Duplicate an example
Right-click the example in the sidebar and select **Duplicate**. A copy of the example is created under the same parent request.
### Delete an example
Right-click the example in the sidebar and select **Delete**. Confirm the action in the prompt that appears.
Deleting an example is permanent and cannot be undone.
## Use an example as a template
When viewing a saved example, click **Try it** in the URL bar to open a new draft request pre-filled with the example's configuration (URL, method, headers, parameters, and body). This lets you start a new request based on an existing example without modifying the original. The example's saved response is not carried into the draft.
## What's next?
Organize your requests into collections and folders
Use variables to make requests reusable across environments
Add pre-request scripts and tests to automate your workflow
# Overview
Source: https://docs.requestly.com/api-client/import-export
Learn how to import and export API collections, environments, and requests
in Requestly.
Requestly makes it easy to move your work across devices, collaborate with teammates, and back up your collections and environments using powerful import/export features.
This section covers everything you need to know about:
* Bringing external data into the API client (like cURL, Postman, or `.json` files)
* Exporting your collections or environments for sharing, syncing, or backup
## Supported Imports
* [Import from cURL](/api-client/import-export/import-from-curl)
Paste a raw `curl` command and convert it into a fully configured request.
* [Import/Export Collections](/api-client/import-export/import-export-api-collections)
Upload or download `.json` files to share, back up, or migrate your API collections.
* [Import/Export Environments](/api-client/import-export/import-export-api-environment)
Bring in or export environment variables like tokens, base URLs, and custom keys, all using simple `.json` files.
* [Import from Postman](/api-client/import-export/import-from-postman)
Upload a Postman collection `.json` file to use it inside Requestly.
* [Import from HAR](/api-client/import-export/import-from-har)
Turn a `.har` capture from your browser's DevTools or a proxy tool into an editable collection of requests.
* [Import OpenAPI Spec](/api-client/import-export/import-openapi-spec)
Import an OpenAPI (Swagger) `.yaml` or `.json` file as a collection, an editable spec, or both.
* [Import from WSDL](/api-client/import-export/import-from-wsdl)
Import SOAP services from a WSDL file or URL.
* Import from SoapUI
Import SOAP requests from a SoapUI project `.xml` file.
# Import / Export Collections
Source: https://docs.requestly.com/api-client/import-export/import-export-api-collections
You can easily **export API collections to a** `.json` **file** and **import them back into Requestly** whenever needed. This makes it simple to back up your work, move between devices, or collaborate with others.
**Need Help First?**\
If you’re new to collections or environments, check out our docs on [creating a collection](/api-client/api-collections#create-api-collection) and managing environments before using import/export.
## Exporting Collections
Exporting a collection generates a `.json` file that contains all the requests, scripts, and metadata inside that collection.
### How to Export a Collection
[Download Requestly](https://requestly.com/downloads) and open app.
In the left sidebar, hover over the collection you want to export.
Click the **three-dot menu (⋯)** next to the collection name and choose **Export**.
A modal will appear showing the collection name.
Click **Export** to download the `.json` file to your device
## Importing Collections
You can re-import previously exported Requestly collections on any device or project to continue working from where you left off.
### How to Import a Collection
[Download Requestly](https://requestly.com/downloads) and open app.
In the top-left corner of the API Client, click the **Import** button. This will open a dropdown with multiple import options.
From the dropdown, choose **Requestly** to open the import modal.
In the import modal, click to browse or drag and drop the `.json` file you want to import. Once selected, the collection will be added to your project.
# Import / Export Environments
Source: https://docs.requestly.com/api-client/import-export/import-export-api-environment
You can easily **export environments to a** `.json` file and **import them back into Requestly** whenever needed. This helps you back up environment variables, move them across devices, or sync with teammates.
## Exporting Environments
Exporting an environment downloads a `.json` file containing all key-value variable pairs in that environment.
## How to Export an Environment
Download Requestly and open app.
In the left sidebar, click on the “Environments” tab to view the list of existing environments.
Hover over the environment you want to export, click the **three-dot menu (⋮)**, and select **Export**.
A modal will appear showing the collection name.
Click **Export** to download the `.json` file to your device
## Importing Environments
You can re-import an exported environment into any project to continue using your environment variables.
### How to Import an Environment
Download Requestly and open app.
In the top-left corner of the client, click **Import**. This opens a dropdown with multiple import options.
Choose **Requestly** to open the import modal.
Click to browse or drag and drop the `.json` file containing your environment.
Once uploaded, the environment will appear in your project under the “Environments” tab.
# Import from cURL
Source: https://docs.requestly.com/api-client/import-export/import-from-curl
Paste any cURL command into Requestly and convert it into a fully editable API request in seconds.
Requestly converts cURL commands into fully editable API requests. This makes it easy to migrate from terminal workflows, import requests from documentation, or grab a request straight from your browser's DevTools network panel.
## How to Import a cURL Command
Download and launch the Requestly Desktop App.
In the top-left corner of the API Client, click the **Import** button. Choose **cURL** from the dropdown.
Paste your raw cURL command into the input box.
Click **Import**. Requestly converts the cURL into an editable API request, ready to send or save to a collection.
## cURL Examples
Paste any of these directly into the import dialog to see how they convert.
**Simple GET request**
```bash theme={null}
curl https://api.example.com/users
```
**GET with headers and query param**
```bash theme={null}
curl "https://api.example.com/users?page=2" \
--header "Authorization: Bearer YOUR_TOKEN" \
--header "Accept: application/json"
```
**POST with JSON body**
```bash theme={null}
curl --request POST \
--url https://api.example.com/users \
--header "Authorization: Bearer YOUR_TOKEN" \
--header "Content-Type: application/json" \
--data '{"name":"Jane Doe","email":"jane@example.com"}'
```
**PUT to update a resource**
```bash theme={null}
curl --request PUT \
--url https://api.example.com/users/42 \
--header "Authorization: Bearer YOUR_TOKEN" \
--header "Content-Type: application/json" \
--data '{"name":"Jane Smith"}'
```
**DELETE request**
```bash theme={null}
curl --request DELETE \
--url https://api.example.com/users/42 \
--header "Authorization: Bearer YOUR_TOKEN"
```
**POST with Basic Auth**
```bash theme={null}
curl --request POST \
--url https://api.example.com/login \
--user "myuser:mypassword" \
--header "Content-Type: application/json" \
--data '{"remember_me": true}'
```
You can copy cURL commands directly from your browser's DevTools. Open DevTools → Network tab → right-click any request → **Copy as cURL**.
## What Gets Imported
When you paste a cURL command, Requestly extracts:
* HTTP method (`-X`, `--request`)
* URL and query parameters
* Headers (`-H`, `--header`)
* Request body (`-d`, `--data`, `--data-raw`, `--data-binary`)
* Basic Auth credentials (`-u`, `--user`)
## What's Next?
Organize imported requests into collections
Replace hardcoded values with reusable variables
Migrate entire Postman collections
# Import from HAR
Source: https://docs.requestly.com/api-client/import-export/import-from-har
Turn a HAR file captured from your browser's DevTools or a proxy tool into an editable Requestly collection.
A HAR (HTTP Archive) file is a JSON-formatted log of a browser session's network traffic. Every modern browser's DevTools, plus proxy tools like Charles, Fiddler, and mitmproxy, can export a HAR. Requestly imports a HAR as a fully editable collection of requests - useful for replaying a captured flow, building an API collection from a real session, or sharing a reproducible bug report.
## How to Import a HAR File
In Chrome or Edge, open **DevTools → Network**, reproduce the flow you want to capture, then right-click any row and choose **Save all as HAR with content**. Firefox and Safari offer the same export from their network panels. Charles Proxy, Fiddler, and mitmproxy all support HAR export from their session menus.
In the API Client, click the **Import** button in the top-left corner and choose **HAR** from the dropdown.
Drag the file onto the upload area or click to browse. HAR files up to **100 MB** are supported. Larger files are rejected before parsing - if your capture is bigger, narrow the recording window in DevTools and re-export.
Requestly parses the file and shows a preview with two options:
* **All Requests** - every captured request, including images, scripts, stylesheets, and fonts.
* **Only API Requests** - JSON and XML APIs, form submissions, mutations, and CORS preflight requests. Static assets (images, CSS, JS, fonts) are skipped.
The count next to each option tells you how many requests will land in the collection. Pick the mode that matches what you want to do with the import.
Requestly creates a collection named `HAR_Import_` containing every imported request. Each request is paired with an **example** holding the captured response, so you can compare the original payload against what you get when you replay.
## How HAR Entries Map to a Collection
* **Root collection.** Every import produces one collection at the root, named `HAR_Import_YYYY-MM-DD_HH-MM-SS`. The timestamp keeps repeated imports distinct in the sidebar.
* **Sub-collections by domain.** Requests are grouped into sub-collections by their owner domain (the registrable domain, e.g. `api.example.com` and `example.com` both group under `example.com`), in the order each domain is first seen. Requests whose domain can't be determined are collected into a single sub-collection named `other`, which is added last and only when such requests exist.
* **Requests and examples.** Every HAR entry produces one request plus one example. The request is editable like any other Requestly request; the example holds the response that was captured (status, headers, body, timing) so you can replay against it without losing the original.
* **Request body.** JSON, form-urlencoded, and multipart bodies are detected from the captured `Content-Type` and opened in the right editor. Other bodies open in the raw editor with the appropriate syntax (HTML, XML, JavaScript, plain text).
* **Cookies.** When the HAR's structured `cookies[]` array is present (Chrome and Firefox exports), it is the source of truth - the imported request gets a single `Cookie` header built from those entries, and any duplicate raw `Cookie` header is dropped. Captures from proxy tools that only carry cookies in the raw header are passed through verbatim.
## What's Skipped, and Why
Some HAR entries can't be imported as Requestly requests. The preview surfaces a warning when this happens:
* **WebSocket connections.** Entries with a `ws://` or `wss://` URL, or marked `_resourceType: "websocket"` by Chrome, are skipped - Requestly's API Client doesn't support WebSocket replay.
* **Binary request bodies.** Some captures (analytics SDKs, gzip-compressed payloads) contain binary POST bodies with embedded null bytes. Requestly strips the null bytes so the body can be stored, and warns you that the imported request may not reproduce the original wire format byte-for-byte. The text-readable portion of the body is preserved.
If the HAR file is empty, isn't valid JSON, or doesn't contain a `log.entries` array, the import fails before the preview step with an error explaining what's wrong.
HAR files often contain sensitive request and response data - auth tokens, cookies, personal information from response bodies. Treat a `.har` like a credential dump: don't share it publicly, and scrub it before attaching to a bug report.
## What's Next?
Organize and rename the imported requests
Replace hardcoded hosts and tokens with reusable variables
Replay every captured request in sequence
# Import from postman
Source: https://docs.requestly.com/api-client/import-export/import-from-postman
Learn how to migrate your Postman collections and environment variables to Requestly.
***
Postman is a popular API development tool widely used for testing and managing APIs. Requestly can import collections and environment files exported from Postman.
### **Export all the workspace data from Postman**
**Step 1**: Click your profile icon in the top-right corner of Postman and select **Settings**.
**Step 2**: Navigate to the **Account** tab and click **Export Data**. It will redirect you to Export data page. Click on **Export data** button.
**Step 3**: Select the data to export (collections, environments, or both) and click **Request Data Export**.
**Step 4**: Check your registered email for exported data, download the ZIP file and extract its contents.
You can also export individual collections and environments from Postman, as explained at the end of this documentation.
Global variables are not automatically exported using this method.\
To use them in Requestly, you need to manually export global variables from Postman and import it into Requestly.
### **Importing into Requestly**
**Step 1**: Open **Requestly Desktop App**.
**Step 2**: Click the **Import** button located in the sidebar header and choose **Postman** from the import options.
**Step 3**: In the upload modal, select and upload the exported Postman **collection** and **environment** files(Multiple files can be imported at once).
**Step 4**: Once the files are processed, click **Import** to finalize the migration.
### **Exporting individual Collections from Postman**
**Step 1**: Open Postman and navigate to the **Collections** tab in the left sidebar to view your collections.
**Step 2**: Click the ellipsis (`...`) next to the collection you wish to export and select **Export** from the dropdown menu.
**Step 3**: In the export dialog, select either **Collection v2** or **Collection v2.1**(Requestly supports both) as the export format. Click **Export** and save the file.
**Step 4**: Import using the same steps as explained in **Import into Requestly** section above.
### **Exporting individual Environments from Postman**
**Step 1**: Open Postman and go to the **Environments** tab in the left sidebar to view your environments.
**Step 2**: Click the ellipsis (`...`) next to the environment you wish to export and select **Export**.
**Step 3**: Choose a location to save the exported environment file and click **Save**.
**Step 4**: Import using the same steps as explained in **Import into Requestly** section above.
### **Known Limitations**
Postman's export format does not include everything in your Postman workspace. Be aware of these gaps before migrating:
* **gRPC collections are not exported.** Postman does not include gRPC requests in its collection export files. There is no workaround - gRPC requests must be recreated manually in Requestly.
* **WebSocket requests are not exported.** Similar to gRPC, Postman does not include WebSocket requests in exported collections.
* **Global variables require a separate export.** Postman's bulk data export does not include global variables. You need to export them manually from the Postman **Environments** sidebar (click the **Globals** entry, then **Export**) and import the resulting file into Requestly alongside your collections.
* **Secret variable values are exported in plaintext.** Postman does not encrypt secret variables in exported files. Review your exported files before sharing them.
* **Binary body and file references are not preserved.** Requests with binary file bodies or form-data file attachments lose the file reference on export. You will need to re-attach files manually after importing into Requestly.
* **Some Postman script APIs have no equivalent.** Postman-specific APIs like `pm.vault`, `pm.visualizer`, and `pm.cookies.jar` do not have Requestly equivalents. Scripts using these APIs will need manual updates. The importer translates `pm.*` calls to `rq.*` automatically, but certain methods (like request header mutation) are read-only in Requestly.
* **Collection-level scripts may need review.** Collection-level pre-request and test scripts are imported, but differences between the Postman and Requestly scripting runtimes may require adjustments.
* **External script references are skipped.** Scripts that reference external URLs (instead of inline code) cannot be imported. Inline the script code before exporting from Postman.
# Import SOAP requests from WSDL
Source: https://docs.requestly.com/api-client/import-export/import-from-wsdl
A WSDL (Web Services Description Language) file defines the structure of a SOAP service, including available operations, request formats, and endpoints. Importing a WSDL helps you quickly get started without building the request from scratch.
Open **Requestly Desktop App** and click the `Import` button.
Select how you want to import your WSDL:
* Paste a **WSDL URL**
* Upload a .**xml** or .**wsdl** file
If the WSDL defines both SOAP 1.1 and 1.2, you can select the **SOAP version** from the dropdown while importing. You can also choose how to organize the generated requests into a **collection** for better management.
Select an options and import the request. The request body, headers, and endpoint will be pre-filled based on the WSDL definition.
# Import / Export OpenAPI Spec
Source: https://docs.requestly.com/api-client/import-export/import-openapi-spec
Learn how to import OpenAPI Specification (Swagger) files to instantly generate API collections and environments.
Import your **OpenAPI Specification** files directly into the **Requestly,** and instantly create organized API collections without any manual setup.
This helps you bring your existing API definitions from Swagger, Postman, or your backend documentation straight into Requestly in just a few clicks.
## What You Can Import
The importer supports both **YAML** and **JSON** OpenAPI files. When you upload a spec, Requestly automatically reads the file and creates API collections and requests based on your defined endpoints.
### How It Imports
Open **Requestly Desktop App**. Make sure you’re in the Project where you want to import your API collection.
Click **Import → OpenAPI** and select your `.yaml` or `.json` file.
OpenAPI import offers three targets:
* **Create a collection** - turn the spec into an API collection of requests (the default).
* **Create a spec** - import the file as an editable API specification you can open and edit.
* **Create a spec + collection** - create the editable specification and a linked collection together.
The two spec options are available only for **OpenAPI 3.x** files that are a single file up to 16 MB. For Swagger 2.0, larger, or multi-file inputs, the import falls back to **Create a collection**.
Requestly will show a preview of what will be imported, including:
* The collections that will be created
* The environments and variables that will be set up
Review the preview and confirm to complete the import.
* Each **path** in your OpenAPI file becomes an individual **request**.
* Requests are grouped under collections named after your API or service.
* Requestly automatically fills in the **method, URL, headers, and body** (if defined in the spec).
* If your spec defines multiple servers (e.g., staging, production), Requestly creates matching environments.
* Each environment includes a `{{base_url}}` variable set to the server URL.
* You can switch environments easily from the environment dropdown.
## What Happens After Import
Once imported, Requestly automatically maps elements from your OpenAPI file to your project structure.
| **OpenAPI Element** | **Where It Appears in Requestly** |
| ------------------------------- | ----------------------------------------------------------------------- |
| **Paths** | Individual requests inside the imported collection |
| **Methods (GET, POST, etc.)** | Reflected automatically in each request |
| **Servers (root level)** | Creates environments with a `{{base_url}}` variable for each server URL |
| **Servers (path level)** | Used as **collection variables in parent** |
| **Schemas / Components** | Used internally for request and response structure |
| **Request bodies & parameters** | Automatically mapped to request body and query params |
## Exporting an OpenAPI Spec
Need an OpenAPI definition for sharing or documentation? You can export any API collection as a standard OpenAPI (Swagger) file directly from Requestly.
### How to Export
Hover over the collection you wish to export and click the **three‑dot menu (⋯)**.
Select **Export → OpenAPI** (or **Export as OpenAPI Spec** in some releases). Requestly will generate the spec based on the requests and variables in the collection.
A modal previews the generated file. Click **Download** to save the `.yaml` (or `.json`) spec to your device.
**Tip**: Make sure the collection’s requests and environment variables are up to date, the exported spec reflects the current state of the collection.
# Import packages into your scripts
Source: https://docs.requestly.com/api-client/import-packages-into-your-scripts
Learn how to import external libraries in Requestly scripts using require to extend functionality with modules like moment, lodash, and uuid.
You can use the `require` method to import preloaded libraries or global helpers directly inside your **Requestly Script Tab** in API Client requests.
The script environment supports JavaScript-based transformations, validations, and dynamic request logic for HTTP and GraphQL APIs.
## **require**
The `require` method lets you import supported modules into your script. Declare the result as a variable to access functions or objects from that module.
### **Syntax**
```javascript theme={null}
const variableName = require('module-name');
```
If the module provides functions or objects, assign it to a variable as shown above.
### **Example**
```javascript theme={null}
// Importing moment for date formatting
const moment = require('moment');
const current = moment().format('YYYY-MM-DD HH:mm:ss');
console.log('Current Time:', current);
// Importing uuid to generate unique IDs
const { v4: uuidv4 } = require('uuid');
console.log('Generated ID:', uuidv4());
```
## **Use Global Objects**
Requestly script sandbox provides several global variables and utilities you can access directly.
### **Available Globals**
| **Global** | **Description** | **Example** |
| :----------- | :--------------------------------------------- | :------------------------------------------- |
| **require** | Import supported libraries into your script. | `const moment = require('moment');` |
| **xml2Json** | Convert XML string to JSON object. | `const data = xml2Json(rq.response.text());` |
| **\_** | Lodash global for data manipulation utilities. | `const result = _.map([1,2,3], n => n * 2);` |
## **Use External Libraries**
The `require` method enables you to use preloaded libraries in the Requestly script environment.
All supported modules are sandboxed for safe execution.
### **Supported Libraries**
The following external libraries are available:
| Library | Description | Documentation |
| :--------------------- | :------------------------------------------------------------- | :-------------------------------------------------- |
| **ajv** | JSON Schema validator for validating API responses. | [Ajv Docs](https://ajv.js.org/) |
| **chai** | Assertion library for adding test-like validations in scripts. | [Chai Docs](https://www.chaijs.com/api/) |
| **cheerio** | Parse and manipulate HTML/XML using a jQuery-like syntax. | [Cheerio Docs](https://cheerio.js.org/) |
| **csv-parse/lib/sync** | Parse CSV data synchronously into objects. | [csv-parse Docs](https://csv.js.org/parse/) |
| **lodash** | Utility library for data manipulation. | [Lodash Docs](https://lodash.com/docs) |
| **moment** | Library for date and time formatting and manipulation. | [Moment.js Docs](https://momentjs.com/docs/) |
| **uuid** | Generate unique identifiers (UUID v4, etc.). | [uuid Docs](https://www.npmjs.com/package/uuid) |
| **xml2Js** | XML parsing and building utilities. | [xml2js Docs](https://www.npmjs.com/package/xml2js) |
**Coming Soon:** We’re adding support to let users import and use libraries directly from ***npm*** and ***jsr***, giving even more flexibility to extend Requestly scripts. \
\
If you need immediate support for any specific library, feel free to comment on our [**GitHub issue**](https://github.com/requestly/requestly/issues/3840) and we’ll prioritize adding it.
**Example**
```javascript theme={null}
const moment = require('moment');
const cheerio = require('cheerio');
const { v4: uuidv4 } = require('uuid');
const id = uuidv4();
const time = moment().format('HH:mm:ss');
const $ = cheerio.load('Hello Requestly
');
console.log('Text:', $('h1').text());
console.log('Request ID:', id, 'Time:', time);
```
## **Use Built-in Globals**
Requestly also provides a few helper functions and contextual variables for working with request and response data.
### **Examples**
```javascript theme={null}
if (rq.response.code === 200) {
const parsed = xml2Json(rq.response.text());
console.log('Converted XML:', parsed);
}
const upper = _.toUpper('requestly');
console.log(upper);
```
## **Notes**
* In addition to the libraries listed above, a set of Node.js built-in modules (such as `crypto`, `buffer`, `path`, `url`, `util`, and `stream`) is available via `require()`.
* No installation or internet access is needed, all libraries are pre-bundled within the Requestly scripting environment.
* The sandbox is isolated for security; access to system-level Node APIs or network calls from `require()` is restricted.
These restrictions apply in **Safe Mode**, the default. If a package needs a native add-on, file-system access, or asymmetric cryptography, switch the request to **Developer Mode**. See [Script execution modes](/api-client/rq-api-reference/overview#script-execution-modes).
# Introduction
Source: https://docs.requestly.com/api-client/mock-server
Create a mock server in the Requestly API Client to serve sample HTTP responses from a hosted URL, with routes, multiple responses, and request-matching rules.
A mock server lets you stand up a fake API in seconds. Instead of waiting for a backend to be built or deployed, you define the routes and the responses yourself, and Requestly serves them from a hosted URL that you can call from your app, your tests, or any HTTP client.
Reach for a mock server when you are developing against an API that does not exist yet, when you need to reproduce an edge case on demand (a `500`, a slow response, a specific error body), or when you want to give your frontend a stable target while the real service is still in flux.
## Prerequisites
Mock Server runs in the cloud, so you need to be signed in and working inside a cloud project (a private or team project synced to your account). It is not available for local projects.
Sign in from the top-right menu, then make sure a cloud project is active in the project switcher before you continue.
## Find the Mock Server
Open the **Mocks** section in the left sidebar of the API Client. This is where every mock server in the active project is listed. A colored dot next to each name shows whether it is currently serving: green and pulsing means active, grey means stopped.
## Quickstart: your first mock in 60 seconds
The fastest way to understand a mock server is to serve one response and call it. This walkthrough creates a `GET /hello` endpoint that returns a small JSON payload.
In the **Mocks** section, click the **+** button (or the **Create mock** button in the empty state), enter a name, and click **Create**. The mock opens in a new editor tab, already scaffolded with one route and one response so you have a working starting point.
Select the scaffolded route and set its **Method** to `GET` and its **Path** to `/hello`. In the response pane, on the **Body** tab set the status to `200` and enter this body:
```json theme={null}
{"message":"Hello, World!"}
```
On the **Headers** tab, add `Content-Type` with the value `application/json` so the caller receives it as JSON. Inline bodies do not get a content type automatically.
Click **Save** in the URL strip to persist your edits, then click **Start** to make the mock live. The status dot in the sidebar turns green.
Copy the endpoint URL for the route, then call it from any HTTP client:
```bash theme={null}
curl https://.mocks.requestly.cloud/hello
```
You get back exactly the status and body you configured:
```json theme={null}
{"message":"Hello, World!"}
```
## The mock URL
Every mock server has its own hosted URL of the form `https://.mocks.requestly.cloud`, shown in the strip at the top of the editor. Each route lives under that base URL at the path you give it, so a route with path `/users` is served at `https://.mocks.requestly.cloud/users`.
To copy a full endpoint URL, hover a route in the routes list and click the copy icon, or use the copy button next to the path field in the response pane. Paste it into your app or another request to call the mock. When you run against a local development build, the base URL uses a `.localhost` host and an explicit port instead (for example `http://.localhost:8091`); the cloud URL above is what you use in production.
A mock only serves traffic while it is running. Click **Start** in the URL strip to begin serving and **Stop** to take it offline. A request to a mock that is stopped returns `503`. The status dot in the sidebar reflects the current state.
## The editor at a glance
The mock editor is a two-pane tab. The left pane lists the routes, and the right pane configures the responses for whichever route is selected. Each response has its own **Body**, **Headers**, and **Rules** sub-tabs.
Edits to routes, responses, and rules are staged until you click **Save** in the URL strip. Navigating away from a mock with unsaved changes prompts you to save or discard.
Once you have the basics working, dig into each part of the editor:
Match requests by method and path, capture path parameters, use wildcards, and control which route wins when two overlap.
Configure the body, status, latency, and headers, insert dynamic values, and choose how the mock picks a response.
Serve a different response depending on the incoming request's query, header, body, cookie, or URL parameter.
# Responses and selection modes
Source: https://docs.requestly.com/api-client/mock-server/responses
Configure a Requestly mock route's responses - body, status, latency, headers, and dynamic values - and choose how the mock picks which response to serve.
A route can have several responses, and you decide how the mock picks between them. This page covers configuring a single response (body, status, latency, headers, dynamic values) and the three selection modes that choose which response to serve on each request.
For how requests are matched to a route in the first place, see [Routes](/api-client/mock-server/routes).
## Multiple responses
Each route's responses are shown as tiles in a horizontal strip in the response pane. Click a tile to edit it, click **Add** to create another, and drag tiles to reorder them. A colored dot on each tile reflects its status code: green for `2xx`, blue for `3xx`, amber for `4xx`, red for `5xx`.
Every route must keep at least one response, so the delete control is disabled when only one remains. In **Rules-based** mode you can mark one response as the **default** with the flag toggle. The default is served when no other response's rules match. The default flag is ignored in the other two modes.
Each response has three sub-tabs: **Body**, **Headers**, and **Rules**. Rules are covered on their own page - see [Matching rules](/api-client/mock-server/rules).
## Body, status, and latency
On the **Body** tab, edit the response body in the editor and set the **Status** code. Use the copy and prettify buttons for JSON and XML bodies. Inline bodies are capped at 5 MB, and the editor warns you as you approach the limit.
Inline bodies do not get a content type automatically. When returning JSON, add a `Content-Type: application/json` header on the **Headers** tab so the caller parses it correctly.
Set a **Latency** delay in milliseconds to simulate a slow endpoint. The mock waits that long before responding. For example, a `GET /slow` route with status `503`, a latency of `1500`, and this body:
```json theme={null}
{"error":"Service Unavailable","simulated":true}
```
returns the configured status after roughly 1.5 seconds:
```bash theme={null}
curl -s -w '[status=%{http_code}] [time=%{time_total}s]' \
https://.mocks.requestly.cloud/slow
```
```json theme={null}
{"error":"Service Unavailable","simulated":true}
[status=503] [time=1.507750s]
```
The hosted mock caps latency at 5000 ms, so any delay up to five seconds is honored in full.
## Headers
On the **Headers** tab, add response headers as key-value pairs, with autocomplete for common header names such as `Content-Type` and `Cache-Control`. Every header you add is returned verbatim to the caller.
For example, a `GET /headers` route with `Content-Type: application/json`, `X-Custom-Header: rq-mock-demo`, and `X-Powered-By: Requestly-Mock`:
```bash theme={null}
curl -i https://.mocks.requestly.cloud/headers
```
```text theme={null}
HTTP/1.1 200 OK
X-Powered-By: Requestly-Mock
Content-Type: application/json
X-Custom-Header: rq-mock-demo
{"ok":true}
```
## Dynamic values
You can insert placeholders into a response body or header value, and the mock replaces them with values from the incoming request each time it serves. Wrap a placeholder in double curly braces.
Request-derived placeholders:
* `{{request.method}}` - the HTTP method of the request.
* `{{request.path}}` - the request path.
* `{{request.urlParam.}}` - a path parameter captured by `:name`, or `{{request.urlParam.0}}` for a `*` wildcard.
* `{{request.queryParam.}}` - a query-string value.
* `{{request.header.}}` - a request header value.
* `{{request.body.}}` - a field from the JSON request body.
* `{{request.cookie.}}` - a request cookie value.
Generated placeholders:
* `{{$randomUUID}}` - a random UUID.
* `{{$timestamp}}` - the current timestamp.
For example, echoing a captured path parameter back in the body:
```json theme={null}
{"userId":"{{request.urlParam.id}}"}
```
served from `GET /users/:id` returns the id from the URL:
```bash theme={null}
curl https://.mocks.requestly.cloud/users/42
```
```json theme={null}
{"userId":"42"}
```
## Selection modes
Once a request matches a route, that route's **selection mode** decides which of its responses to serve. Set it from the mode dropdown at the top of the response pane.
| Mode | What it does | When to use it |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **Rules-based** | Serves the first response whose rules all match. If none match, serves the response marked **default**. If there is no default, returns `404`. | The everyday choice. Branch on request content: a happy-path `200`, a `403` when auth is missing, a premium payload only for `?plan=premium`. |
| **Random** | Picks one of the route's responses uniformly at random. Rules and the default flag are ignored. | Chaos and resilience testing - make the client tolerate a mix of responses (for example a `200` and a `500`) hit unpredictably. |
| **Fallback** | Runs the current route's rules. If none match, it does not use a default - it falls through to the next route that matches the same request. | Layering a specific mock over a broad catch-all route without either route needing to know about the other. |
### Rules-based
Rules-based mode returns the first response whose rules all match, and falls back to the **default** response when none do. For example, a `GET /account` route with a "premium" response gated by a rule (`?plan=premium`) and a "free" response marked default:
```bash theme={null}
curl "https://.mocks.requestly.cloud/account?plan=premium"
```
```json theme={null}
{"plan":"premium","features":["dashboards","sso"]}
```
```bash theme={null}
curl "https://.mocks.requestly.cloud/account?plan=basic"
```
```json theme={null}
{"plan":"free"}
```
The `?plan=basic` request matches no rule, so it falls back to the default. See [Matching rules](/api-client/mock-server/rules) for how to write the rule.
If a rules-based route has no matching rule and no response is marked default, the mock returns `404`.
### Random
Random mode picks one response at random on every request. For example, a `GET /random` route with two responses, `{"pick":"A"}` and `{"pick":"B"}`, returns a mix across identical requests:
```bash theme={null}
for i in $(seq 1 30); do curl -s https://.mocks.requestly.cloud/random; echo; done | sort | uniq -c
```
```text theme={null}
10 {"pick":"A"}
20 {"pick":"B"}
```
### Fallback
Fallback mode tries the current route's rules and, if none match, hands the request to the next route that matches it. For example, a first `GET /fallback` route in fallback mode answers only when `?x=1`, and a following `* /fallback` route answers everything else:
```bash theme={null}
curl "https://.mocks.requestly.cloud/fallback?x=1"
```
```json theme={null}
{"result":"rule-matched-on-first-route (x=1)"}
```
```bash theme={null}
curl "https://.mocks.requestly.cloud/fallback"
```
```json theme={null}
{"result":"fell-through-to-NEXT-matching-route default"}
```
The request without `x=1` matches no rule on the first route, so it falls through and is resolved by the second route. Route order controls which route is tried first - see [route ordering](/api-client/mock-server/routes#ordering-and-shadowing).
# Routes
Source: https://docs.requestly.com/api-client/mock-server/routes
Match incoming requests in a Requestly mock server by method and path, capture path parameters, use wildcards, and control route ordering when two routes overlap.
A route is a method and a path that the mock answers on. When a request arrives, the mock walks its routes from top to bottom and picks the first one whose method and path match. That route then decides which response to serve. This page covers how the matching works.
For the basics of creating a mock and serving your first response, see [Mock Server](/api-client/mock-server).
## Method and path
Add a route with the **+** button above the routes list, then set two things in the response pane at the top:
* **Method**: any standard HTTP verb (`GET`, `POST`, `PUT`, `DELETE`, and so on), plus `*` to match any method.
* **Path**: the path the route answers on, relative to the mock's base URL. It supports path parameters (`:param`) and wildcards (`*`), described below.
Use the filter box above the routes list to find a route by path in a long list, and drag a route up or down to change its order.
## Path parameters
A path segment written as `:name` captures whatever appears in that position and exposes it to your response. The captured value is available both in response templates (as `urlParam.name`) and in [matching rules](/api-client/mock-server/rules) via the URL Param target.
For example, a route `GET /users/:id` with this response body:
```json theme={null}
{"userId":"{{request.urlParam.id}}","note":"the :id path param, echoed"}
```
serves the captured id straight back to the caller:
```bash theme={null}
curl https://.mocks.requestly.cloud/users/42
```
```json theme={null}
{"userId":"42","note":"the :id path param, echoed"}
```
A path parameter matches exactly one segment. `GET /users/:id` matches `/users/42` but does not match `/users` on its own, so a bare `/users` request finds no route and returns `404`:
```bash theme={null}
curl -i https://.mocks.requestly.cloud/users
```
```text theme={null}
HTTP/1.1 404 Not Found
```
## Wildcards
A `*` in the path matches any characters, including slashes, and captures them as `urlParam.0`. Pair it with method `*` to answer every HTTP method on that path.
For example, a route with method `*` and path `/static/*` and this body:
```json theme={null}
{"matchedMethod":"{{request.method}}","matchedPath":"{{request.path}}","wildcard":"{{request.urlParam.0}}"}
```
matches many paths and every method:
```bash theme={null}
curl https://.mocks.requestly.cloud/static/css/app.css
```
```json theme={null}
{"matchedMethod":"GET","matchedPath":"/static/css/app.css","wildcard":"css/app.css"}
```
```bash theme={null}
curl -X POST https://.mocks.requestly.cloud/static/js/x.js
```
```json theme={null}
{"matchedMethod":"POST","matchedPath":"/static/js/x.js","wildcard":"js/x.js"}
```
```bash theme={null}
curl -X DELETE https://.mocks.requestly.cloud/static/a/b/c
```
```json theme={null}
{"matchedMethod":"DELETE","matchedPath":"/static/a/b/c","wildcard":"a/b/c"}
```
The `{{request.method}}`, `{{request.path}}`, and `{{request.urlParam.0}}` placeholders above are dynamic values. See [dynamic values](/api-client/mock-server/responses#dynamic-values) for the full list.
## Ordering and shadowing
Matching is first-match-wins by position: when two routes share the same method and path, the one higher in the list intercepts every request and the one below it is never reached.
For example, with two `GET /shadow` routes where the first returns `200 {"served":"first-route-wins"}` and the second returns `500`, the first always wins:
```bash theme={null}
curl https://.mocks.requestly.cloud/shadow
```
```json theme={null}
{"served":"first-route-wins"}
```
The second route's `500` never appears. The editor flags the shadowed route with a strike-through and a warning icon, with the tooltip "Shadowed by an earlier route with the same method and path - this route is never served", so you can spot and fix the conflict. Drag the route you want to win to the top, or change one route's method or path so they no longer collide.
Ordering also drives the **Fallback** selection mode, where a route that finds no matching response deliberately falls through to the next route that matches the same request. See [selection modes](/api-client/mock-server/responses#selection-modes).
# Matching rules
Source: https://docs.requestly.com/api-client/mock-server/rules
Add request-matching rules to a Requestly mock response so it is served only when the incoming request's query, header, body, cookie, or URL parameter matches.
Rules let one route return different responses depending on the incoming request, without writing any code. On the **Rules** sub-tab of a response, you add one or more conditions; the response is served only when they are satisfied. Rules are how [Rules-based and Fallback selection](/api-client/mock-server/responses#selection-modes) decide which response to pick.
A response with no rules is served unconditionally, which is exactly what you want for the catch-all **default** response.
## Anatomy of a rule
Each rule has five parts:
* A **target**: what part of the request to inspect. Method, Path, Query, Header, Body (matched with a JSONPath expression), Cookie, or URL Param.
* A **property**: which key or path within the target to read, for example a header name, a query key, or a `$.json.path` into the body.
* An **operator**: `equals`, `contains`, `regex`, `>`, `<`, `in`, `exists`, or `jsonpath`.
* A **value** to compare against.
* An **invert** toggle to negate the match (NOT).
When a response has more than one rule, combine them with the **AND / OR** toggle. With AND, every rule must pass; with OR, any one passing is enough. You set one combinator per response.
Body and header matching are on by default, so you can match against request body fields and header values out of the box without any extra setup. The Body target uses a dot-path existence check (for example, does `user.role` exist), not full JSONPath filters.
## Add a rule
In the response pane, select the response you want to gate, then open its **Rules** sub-tab.
Add a rule, then set its target, property, operator, and value. Turn on **invert** if you want the rule to match when the condition is not met.
If you added more than one rule, set the **AND / OR** toggle to decide whether all of them or any of them must pass.
Click **Save**, make sure the mock is running, then call the endpoint with and without the matching condition to confirm the right response is served.
## Worked examples
Each example below gates a response on a real condition and shows the served result.
### Require a header (exists + invert)
To return a `403` only when the `Authorization` header is missing, add a `403` response with one rule: target **Header**, property `authorization`, operator **exists**, invert **on**. Mark the normal `200` response as default.
```bash theme={null}
curl https://.mocks.requestly.cloud/secure
```
```json theme={null}
{"error":"Authorization header required"}
```
```bash theme={null}
curl -H "Authorization: Bearer token123" https://.mocks.requestly.cloud/secure
```
```json theme={null}
{"data":"secret payload"}
```
The missing header matches the inverted `exists` rule and returns `403`; a present header falls through to the default `200`.
### Match on the request body (JSONPath)
To branch on the shape of a JSON body, use the **Body** target with the `jsonpath` operator. Here a `POST /orders` response is gated on `$.user.role` existing, with a `422` default:
```bash theme={null}
curl -X POST -H "Content-Type: application/json" \
-d '{"user":{"role":"admin"}}' https://.mocks.requestly.cloud/orders
```
```json theme={null}
{"matched":"body has user.role (JSONPath)"}
```
```bash theme={null}
curl -X POST -H "Content-Type: application/json" \
-d '{"item":"x"}' https://.mocks.requestly.cloud/orders
```
```json theme={null}
{"error":"missing user.role"}
```
### Read a URL parameter (equals)
A **URL Param** rule reads a value captured by a `:param` in the path. Here `GET /accounts/:id` serves a special response only when `id` equals `42`:
```bash theme={null}
curl https://.mocks.requestly.cloud/accounts/42
```
```json theme={null}
{"you":"account 42 (matched via urlParam rule)"}
```
```bash theme={null}
curl https://.mocks.requestly.cloud/accounts/7
```
```json theme={null}
{"you":"some other account"}
```
### Combine rules with AND
With the combinator set to **AND**, every rule must pass. Here a response on `GET /and` requires both `?a=1` and `?b=2`:
```bash theme={null}
curl "https://.mocks.requestly.cloud/and?a=1&b=2"
```
```json theme={null}
{"combinator":"AND matched (a=1 AND b=2)"}
```
```bash theme={null}
curl "https://.mocks.requestly.cloud/and?a=1"
```
```json theme={null}
{"combinator":"AND default (not both matched)"}
```
### Combine rules with OR
With the combinator set to **OR**, any one rule passing is enough. Here a response on `GET /or` matches when either `?a=1` or `?b=2`:
```bash theme={null}
curl "https://.mocks.requestly.cloud/or?a=1"
```
```json theme={null}
{"combinator":"OR matched (a=1 OR b=2)"}
```
```bash theme={null}
curl "https://.mocks.requestly.cloud/or?c=9"
```
```json theme={null}
{"combinator":"OR default (neither matched)"}
```
# Getting Started
Source: https://docs.requestly.com/api-client/overview
Install the Requestly API Client, send your first request, save it to a collection, and set up environment variables.
Requestly API Client is a lightweight, Git-native tool to design, build, and test APIs. Send requests, organize them into collections, and automate tests with scripts. Your collections live as plain files you can version in Git.
***
## Step 1: Install
The API Client runs as a **desktop app** on macOS, Windows, and Linux.
Download the latest version for [Apple Silicon](https://get.requestly.com/mac-api-client) or [Intel](https://get.requestly.com/mac-intel-api-client).
Download the [Windows installer](https://get.requestly.com/win-api-client).
Download the [Linux AppImage](https://get.requestly.com/linux-api-client).
**What about the browser extension?** The Requestly browser extension is a separate product, an HTTP interceptor for modifying network traffic. The API Client is a standalone desktop app. You do not need the extension to use the API Client.
***
## Step 2: Sign In
Sign in with your Google or email account to get started. Once signed in, your collections and environments sync across devices and you can collaborate with your team.
***
## Step 3: Send Your First Request
Click **+ New** → **Request** in the left sidebar.
Set the method to **GET** and enter:
```text theme={null}
https://app.requestly.io/echo
```
Click **Send**. You’ll see the echo server’s JSON response in the panel below.
You’ve sent your first request. The response panel shows the body, headers, status code, and response time.
***
## Step 4: Save to a Collection
Collections keep related requests organized together.
Click **+ New** → **Collection**. Name it `My APIs`.
Drag the request you just created into the collection, or click the **+** icon next to the collection name to create new requests directly inside it.
You can also create folders inside collections to group requests by feature or endpoint. [Learn more about collections →](/api-client/api-collections)
***
## Step 5: Add an Environment Variable
Environment variables let you switch between dev, staging, and production without editing every request.
Click **+ New** → **Environment**. Name it `Development`.
Add a variable:
* **Key**: `base_url`
* **Value**: `https://app.requestly.io`
Click **Save**.
Replace the URL in your request with:
```text theme={null}
{{base_url}}/echo
```
Variables use double curly braces: `{{variable_name}}`
Now you can create a `Production` environment with a different `base_url` and switch between them using the environment dropdown. [Learn more about variables →](/api-client/environments-and-variables)
***
## What’s Next
Add API Key, Bearer Token, Basic Auth, or OAuth to your requests.
Run JavaScript before requests or after responses for automation.
Write assertions to validate API responses automatically.
Execute an entire collection of requests in sequence.
Bring your existing Postman collections into Requestly.
Paste a cURL command and convert it to a request instantly.
# Overview
Source: https://docs.requestly.com/api-client/rq-api-reference/overview
Overview of the Requestly scripting reference: the rq object, pre-request and post-response scripts, and the Safe and Developer sandbox modes.
Requestly scripts let you add logic to your API requests using JavaScript. You write scripts in two places:
* **Pre-request scripts** run before a request is sent. Use them to set variables, build a signature, fetch a token, or skip the request.
* **Post-response scripts** run after the response arrives. Use them to validate the response, extract values, and write tests.
Inside both, everything you need is on the global **`rq`** object. This reference documents every part of it.
## The rq object
`rq` is the entry point for reading request and response data, managing variables, sending requests, and writing tests. The cards below link to the reference page for each part.
Read and modify the request: method, URL, headers, body, query parameters.
Read the response: status, headers, body, and parsed JSON.
Send an HTTP request from a script and read its response.
Skip a request, control collection-run order, and run another saved request.
Read and write environment variables.
Read and write variables scoped to a collection.
Read and write variables available everywhere.
Read secrets stored securely in your vault.
Define tests that pass or fail based on the response.
Write assertions inside your tests.
Read the current row of data during a collection run.
Read information about the current execution.
## Script execution modes
Requestly can run your scripts in one of two modes: Safe Mode and Developer Mode.
**Availability:** The Safe/Developer mode menu is a desktop-app feature that is rolling out gradually. When it is enabled for your build, Safe Mode is the default and you pick the mode per request from the mode menu in the **Scripts** editor toolbar, next to the pre-request and post-response toggle. If you don't see the mode menu, your scripts run in Developer Mode.
### Safe Mode
**When enabled, Safe Mode is the default.** Scripts run in an isolated sandbox with no access to your system. This is the right choice for almost every script: reading and writing variables, building requests, sending requests with `rq.sendRequest`, and writing tests all work in Safe Mode.
For security, Safe Mode does not allow a script to:
* load a package that needs a native add-on,
* read or write your file system, or
* use asymmetric cryptography such as RS256, ES, or PS (use HS256 instead).
If a script tries to use a package that needs one of these, Requestly shows a message that names the package and explains how to proceed, for example: `Package 'some-package' cannot be used in Safe mode`.
### Developer Mode
Developer Mode runs scripts with full access to your system, including files, the network, and processes. Use it only for scripts you trust, and only when a script needs a capability that Safe Mode does not allow (for example a package with a native add-on).
To switch a request to Developer Mode, open the mode menu in the Scripts toolbar and select **Developer**. Requestly asks you to confirm, because Developer Mode gives scripts full system access. Switching back to Safe Mode takes effect immediately.
Only use Developer Mode for scripts you trust. A script in Developer Mode can read your files, make network connections, and run processes on your machine.
The mode you pick applies to that request for your current session and is not saved with the request.
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [Import Packages into Your Scripts](/api-client/import-packages-into-your-scripts)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
# rq.collectionVariables (Collection variables)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-collection-variables
Complete reference for the rq.collectionVariables object in Requestly scripts to manage collection-scoped variables dynamically.
The `rq.collectionVariables` object provides methods to manage collection variables during script execution. Collection variables are scoped to a specific collection and are only accessible within the requests that belong to that collection. Unlike environment variables (scoped to a specific environment), collection variables persist across all environments within the same collection.
## Methods
### `rq.collectionVariables.set(key, value)`
Creates or updates a collection variable with the given key and value. If the variable already exists, it will be updated with the new value.
**Parameters:**
* `key` (string): The name of the collection variable
* `value` (any): The value to store. Scalar values are stored as strings; passing an array stores a real array, so a later `get` returns the array unchanged. Passing `null` or `undefined` clears the variable, which is equivalent to `unset(key)`, so a later `get` returns `undefined` (not the string `"null"`).
**Example:**
```javascript theme={null}
rq.collectionVariables.set("basePath", "/v1/users");
```
Passing an array to `set` stores a real array, and `get` returns it as a real array with `.first()` and `.last()` helpers. See [rq.environment](/api-client/rq-api-reference/rq-environment#working-with-array-variables) for examples.
### `rq.collectionVariables.get(key)`
Retrieves the value of the specified collection variable.
**Parameters:**
* `key` (string): The name of the collection variable to retrieve
**Returns:** The value of the collection variable, or `undefined` if it doesn't exist.
**Example:**
```javascript theme={null}
const path = rq.collectionVariables.get("basePath");
console.log("Collection Variable basePath:", path);
```
### `rq.collectionVariables.unset(key)`
Removes the specified collection variable.
**Parameters:**
* `key` (string): The name of the collection variable to remove
**Example:**
```javascript theme={null}
rq.collectionVariables.unset("basePath");
```
### `rq.collectionVariables.clear()`
Removes all variables from the current collection.
**Parameters:** none.
**Example:**
```javascript theme={null}
rq.collectionVariables.clear();
console.log("All collection variables cleared");
```
`rq.collectionVariables.clear()` works only when the request belongs to a collection. Calling it from a request that is not in a collection throws an error, the same as `set()` and `unset()`.
## Common Use Cases
### Store API Base Path
Set a base path that all requests in the collection can use:
```javascript theme={null}
// In pre-request script
rq.collectionVariables.set("basePath", "/api/v2");
rq.collectionVariables.set("apiVersion", "v2");
```
Then use it in your request URL:
```text theme={null}
{{baseUrl}}{{basePath}}/users
```
### Share Data Between Collection Requests
Pass data from one request to another within the same collection:
```javascript theme={null}
// In the first request's post-response script
const data = rq.response.json();
rq.collectionVariables.set("createdResourceId", data.id);
rq.collectionVariables.set("resourceName", data.name);
// In the next request's pre-request script
const resourceId = rq.collectionVariables.get("createdResourceId");
console.log("Using resource ID:", resourceId);
```
### Store Default Values
Set default values that can be overridden by environment variables:
```javascript theme={null}
// In pre-request script
const pageSize = rq.environment.get("pageSize") ||
rq.collectionVariables.get("defaultPageSize") ||
"20";
console.log("Using page size:", pageSize);
```
### Track Collection State
Maintain state across requests in a collection:
```javascript theme={null}
// Track if authentication has been completed
const isAuthenticated = rq.collectionVariables.get("isAuthenticated");
if (!isAuthenticated) {
console.log("Need to authenticate first");
rq.collectionVariables.set("isAuthenticated", "true");
}
```
### Store Computed Values
Calculate and store values that multiple requests will use:
```javascript theme={null}
// In pre-request script
const timestamp = Date.now();
const signature = generateSignature(timestamp); // Your custom function
rq.collectionVariables.set("requestTimestamp", timestamp);
rq.collectionVariables.set("requestSignature", signature);
```
## Best Practices
1. **Naming Convention**: Use clear, descriptive names that indicate the variable's purpose
```javascript theme={null}
rq.collectionVariables.set("authBaseEndpoint", "/auth");
rq.collectionVariables.set("apiVersion", "v2");
```
2. **Initialize in Setup Requests**: Create a setup or initialization request that sets default collection variables
3. **Validate Before Use**: Check if a variable exists before using it
```javascript theme={null}
const value = rq.collectionVariables.get("myVar");
if (!value) {
console.error("Collection variable 'myVar' not found");
}
```
4. **Clean Up**: Remove variables that are no longer needed
```javascript theme={null}
rq.collectionVariables.unset("temporaryData");
```
5. **Document Variables**: Add comments in your scripts explaining what each variable is for
```javascript theme={null}
// Store the created user ID for use in subsequent requests
rq.collectionVariables.set("userId", data.id);
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [rq.environment Object](/api-client/rq-api-reference/rq-environment)
* [rq.globals Object](/api-client/rq-api-reference/rq-globals)
* [rq.vault Object](/api-client/rq-api-reference/rq-vault)
* [rq.test Object](/api-client/rq-api-reference/rq-test)
* [rq.expect Object](/api-client/rq-api-reference/rq-expect)
# rq.environment (Environment variables)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-environment
Complete reference for the rq.environment object in Requestly scripts to manage environment variables dynamically during API request execution.
The `rq.environment` object provides methods to dynamically manage environment variables during script execution. Environment variables are scoped to a specific environment and can be used across multiple requests within that environment.
## Methods
### `rq.environment.set(key, value)`
Sets an environment variable with the given key and value. If the variable already exists, it will be updated with the new value.
**Parameters:**
* `key` (string): The name of the environment variable
* `value` (any): The value to store. Scalar values are stored as strings; passing an array stores a real array, so a later `get` returns the array unchanged. Passing `null` or `undefined` clears the variable, which is equivalent to `unset(key)`, so a later `get` returns `undefined` (not the string `"null"`).
**Example:**
```jsx theme={null}
rq.environment.set("authToken", "Bearer ");
```
### `rq.environment.get(key)`
Retrieves the value of the specified environment variable.
**Parameters:**
* `key` (string): The name of the environment variable to retrieve
**Returns:** The value of the environment variable, or `undefined` if it doesn't exist.
**Example:**
```jsx theme={null}
const token = rq.environment.get("authToken");
console.log("Token:", token);
```
### `rq.environment.unset(key)`
Removes the specified environment variable from the current environment.
**Parameters:**
* `key` (string): The name of the environment variable to remove
**Example:**
```jsx theme={null}
rq.environment.unset("authToken");
```
### `rq.environment.clear()`
Removes all variables from the current environment.
**Parameters:** none.
**Example:**
```jsx theme={null}
rq.environment.clear();
console.log("All environment variables cleared");
```
## Common Use Cases
### Store Authentication Token
After receiving a login response, store the auth token for use in subsequent requests:
```jsx theme={null}
// In post-response script
const responseData = rq.response.json();
if (responseData.token) {
rq.environment.set("authToken", "Bearer " + responseData.token);
console.log("Auth token saved to environment");
}
```
### Auto Increment Page Numbers
Automatically increment a page number for pagination:
```jsx theme={null}
// In pre-request script
const currentPage = rq.environment.get("page_number") || 1;
rq.environment.set("page_number", currentPage + 1);
console.log("Next page:", currentPage + 1);
```
### Store API Response Data
Extract and store data from API responses for use in other requests:
```jsx theme={null}
// In post-response script
const data = rq.response.json();
rq.environment.set("user_id", data.id);
rq.environment.set("user_email", data.email);
rq.environment.set("created_at", data.created_at);
```
### Conditional Token Management
Check if a token exists and set it only if needed:
```jsx theme={null}
// In pre-request script
const token = rq.environment.get("authToken");
if (!token) {
console.error("Auth token not found! Please login first.");
} else {
console.log("Using existing auth token");
}
```
### Clean Up Sensitive Data
Remove sensitive information after use:
```jsx theme={null}
// After completing authenticated requests
rq.environment.unset("authToken");
rq.environment.unset("password");
console.log("Sensitive data cleared from environment");
```
### Track Request Counts
Keep track of how many times a request has been made:
```jsx theme={null}
// In post-response script
const requestCount = parseInt(rq.environment.get("request_count") || "0");
rq.environment.set("request_count", requestCount + 1);
console.log("This request has been made", requestCount + 1, "times");
```
## Working with array variables
An [array variable](/api-client/environments-and-variables/environment-variables) stores a list of values. When you `set` an array, Requestly stores it as a real array, and `get` returns it as a real array rather than a comma-joined string:
```jsx theme={null}
rq.environment.set("ids", ["a", "b", "c"]);
const ids = rq.environment.get("ids");
console.log(Array.isArray(ids)); // true
console.log(ids[0]); // "a"
```
You can also read the first or last items with `.first()` and `.last()`:
```jsx theme={null}
const ids = rq.environment.get("ids");
ids.first(); // "a"
ids.last(); // "c"
ids.first(2); // ["a", "b"]
ids.last(2); // ["b", "c"]
```
## Best Practices
1. **Use Descriptive Names**: Choose clear, descriptive names for environment variables (e.g., `authToken` instead of `token`)
2. **Check for Existence**: Always check if a variable exists before using it:
```jsx theme={null}
const value = rq.environment.get("myVar");
if (value) {
// Use the value
} else {
console.error("Variable not found");
}
```
3. **Clean Up**: Remove sensitive data when no longer needed using `unset()`
4. **Type Handling**: Most environment variable values are stored as strings, so convert them when needed. Array-typed variables are the exception and are returned as real arrays:
```jsx theme={null}
const pageNum = parseInt(rq.environment.get("page_number"));
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [rq.collectionVariables Object](/api-client/rq-api-reference/rq-collection-variables)
* [rq.globals Object](/api-client/rq-api-reference/rq-globals)
* [rq.vault Object](/api-client/rq-api-reference/rq-vault)
* [rq.test Object](/api-client/rq-api-reference/rq-test)
* [rq.expect Object](/api-client/rq-api-reference/rq-expect)
# rq.execution (Execution control)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-execution
Reference for the rq.execution namespace in Requestly scripts: read where a request sits, skip it, control collection-run order, and run another saved request.
The `rq.execution` namespace gives your scripts control over how a request runs: where it sits in your collection, whether to skip it, which request the collection runner goes to next, and how to run another saved request on demand.
## rq.execution.location
A read-only array describing where the current request sits. The array lists the path from the top of your collection down to the request itself: `[collection, ...folders, request]`. The last element is always the request's own name.
`rq.execution.location.current` returns the name of the current request (the last element of the array).
Available in both pre-request and post-response scripts.
**Example:**
```jsx theme={null}
console.log("Full path:", rq.execution.location.join(" / "));
console.log("Current request:", rq.execution.location.current);
// Example output for a request named "Get user" inside a "Users" folder:
// Full path: My API / Users / Get user
// Current request: Get user
```
The full folder path is available when a request runs inside a collection (for example during a collection run). In some contexts the array contains only the request name. Always check `rq.execution.location.length` before reading a specific level.
## rq.execution.skipRequest()
Skips the current request. Call it from a **pre-request script** to stop the request from being sent. Everything after the `skipRequest()` call in that pre-request script is also skipped.
Use it to conditionally bypass a request, for example when a required variable is missing.
**Parameters:** none.
**Example:**
```jsx theme={null}
// Pre-request script
if (!rq.environment.get("authToken")) {
console.log("No auth token, skipping this request.");
rq.execution.skipRequest();
}
// Code here does not run if skipRequest() was called.
console.log("This line is skipped when there is no token.");
```
`rq.execution.skipRequest()` is available in pre-request scripts only. It does not exist in post-response scripts, because the request has already been sent by then. Calling it from a post-response script throws an error.
## rq.execution.setNextRequest(nameOrNull)
Tells the **collection runner** which request to run next. This only has an effect during a collection run; it is ignored when you send a single request on its own.
**Parameters:**
* `nameOrNull` (string or null): The name of the request to run next, or `null` to stop the run.
It supports three behaviors:
* **Jump to a request:** pass the name of another request in the run. The runner continues from that request.
* **Repeat the current request:** pass the current request's own name to run it again. (Requestly guards against an endless loop.)
* **Stop the run:** pass `null` to end the current run. If the run uses a data file, the current iteration ends and the next data row still runs.
**Example:**
```jsx theme={null}
// Post-response script
const data = rq.response.json();
if (data.status === "pending") {
// Poll again by re-running this request
rq.execution.setNextRequest(rq.execution.location.current);
} else if (data.status === "error") {
// Abort the rest of the run
rq.execution.setNextRequest(null);
} else {
// Continue with a specific follow-up request
rq.execution.setNextRequest("Fetch report");
}
```
If you name a request that is not part of the current run, the run stops and reports an error. Use the exact request name as it appears in your collection.
## rq.execution.runRequest(id, opts?)
Runs another saved request from inside your script and returns its response. Use it to reuse a saved login request, fetch a dependency, or chain a saved call without leaving the current request.
**Parameters:**
* `id` (string, required): The target request's ID. This is the request's saved ID, not its name. See [Getting a request ID](#getting-a-request-id).
* `opts` (object, optional): `{ variables }`, where `variables` is an object of name/value pairs applied to the request being run. Use it to override variables for that run only.
**Returns:** a `Promise` that resolves to a response object with the same shape as [rq.sendRequest](/api-client/rq-api-reference/rq-send-request#response): `code`, `status`, `headers`, `responseTime`, `json()`, and `text()`.
**Example:**
```jsx theme={null}
// Pre-request script: run a saved "Login" request, then use its token
const res = await rq.execution.runRequest("req_01H8XK2P3Q", {
variables: { username: "ada" },
});
const token = res.json().accessToken;
rq.environment.set("authToken", token);
```
### Getting a request ID
`runRequest` needs the saved ID of the request you want to run, not its name. There are two ways to get it.
**Copy it from the UI:**
1. Open the request you want to run.
2. In the request header, next to **Get client code**, select **Copy request ID**.
3. Paste the copied ID into your `runRequest` call.
**Read it in a script with `rq.info.requestId`:**
[`rq.info.requestId`](/api-client/rq-api-reference/rq-info) returns the saved ID of the request the script is running in. This is the same ID that `runRequest` accepts, so you can capture it in one request and run that request from another. Store it in a variable that outlives the script, such as a global or collection variable.
```jsx theme={null}
// In the request you want to run later, capture its own ID once.
// (For example, in its pre-request script.)
rq.globals.set("loginRequestId", rq.info.requestId);
```
```jsx theme={null}
// In another request, read the saved ID and run it.
const loginId = rq.globals.get("loginRequestId");
const res = await rq.execution.runRequest(loginId);
rq.environment.set("authToken", res.json().token);
```
`runRequest` is run-scoped: during a collection run, the request you run must be part of that same run. Make sure both requests run in the same collection run, or run the target request on its own.
### Things to know
* **The returned response is read-only data.** Variables that the other request sets do not flow back into your current script. Read what you need from the returned response and set your own variables.
* **Run-scoped during a collection run.** When used inside a collection run, the request you run must be part of that same run.
* **No nesting.** A request started with `runRequest` cannot itself call `runRequest`.
* **Up to 10 `runRequest` calls per script.**
* An HTTP error status such as `404` or `500` is not treated as a failure. Inspect `res.code`.
## Common Use Cases
### Skip a request when a precondition is not met
```jsx theme={null}
// Pre-request script
const userId = rq.environment.get("userId");
if (!userId) {
rq.execution.skipRequest();
}
```
### Poll until a job completes
```jsx theme={null}
// Post-response script
const job = rq.response.json();
if (job.state !== "done") {
rq.execution.setNextRequest(rq.execution.location.current);
}
```
### Authenticate by running a saved login request
```jsx theme={null}
// Pre-request script
const res = await rq.execution.runRequest("req_01H8XK2P3Q");
rq.environment.set("authToken", res.json().token);
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [Scripts Reference Overview](/api-client/rq-api-reference/overview)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [Collection Runner](/api-client/collection-runner)
# rq.expect (Expect object)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-expect
Complete reference for the rq.expect object in Requestly scripts to write assertions for API testing using Chai.js assertion library.
The `rq.expect` object provides assertion methods for writing tests in Requestly. It is built on top of the popular [Chai.js](https://www.chaijs.com/) assertion library, giving you access to powerful and expressive assertions for validating API responses.
**Using Chai.js**: Requestly uses the Chai.js BDD assertion library. For the complete list of assertions and advanced features, refer to the [Chai.js official documentation](https://www.chaijs.com/api/bdd/).
## Basic Usage
The `rq.expect` function is used within test functions created by `rq.test` to assert expected conditions:
```jsx theme={null}
rq.test("Status code is 200", function() {
rq.expect(rq.response.code).to.equal(200);
});
```
## Common Assertions
Below are some commonly used Chai.js assertions. For a complete reference, visit the [Chai.js BDD API documentation](https://www.chaijs.com/api/bdd/).
### Equality
```jsx theme={null}
rq.expect(value).to.equal(expected); // Strict equality (===)
rq.expect(obj).to.eql(expected); // Deep equality
rq.expect(value).to.deep.equal(expected); // Deep equality (alias)
```
### Type Checking
```jsx theme={null}
rq.expect(value).to.be.a("string");
rq.expect(value).to.be.an("array");
rq.expect(value).to.be.a("number");
rq.expect(value).to.be.a("boolean");
```
### Properties
```jsx theme={null}
rq.expect(obj).to.have.property("key");
rq.expect(obj).to.have.property("key", value);
```
### Strings
```jsx theme={null}
rq.expect(str).to.include("substring");
rq.expect(str).to.match(/regex/);
```
### Numbers
```jsx theme={null}
rq.expect(num).to.be.above(value);
rq.expect(num).to.be.below(value);
rq.expect(num).to.be.within(min, max);
```
### Arrays & Length
```jsx theme={null}
rq.expect(arr).to.have.lengthOf(value);
rq.expect(arr).to.include(item);
rq.expect(arr).to.be.empty;
```
### Booleans & Existence
```jsx theme={null}
rq.expect(value).to.be.true;
rq.expect(value).to.be.false;
rq.expect(value).to.exist;
rq.expect(value).to.be.null;
rq.expect(value).to.be.undefined;
```
## Negation with `.not`
Negate any assertion using `.not`:
```jsx theme={null}
rq.expect(value).to.not.equal("deleted");
rq.expect(arr).to.not.be.empty;
```
## Chaining Assertions
Chain multiple assertions for better readability:
```jsx theme={null}
rq.expect(data.id).to.be.a("number").and.to.be.above(0);
rq.expect(data.name).to.be.a("string").that.is.not.empty;
```
## Example: Validate Response Structure
```jsx theme={null}
rq.test("Response has correct structure", function() {
const data = rq.response.json();
rq.expect(data).to.be.an("object");
rq.expect(data).to.have.property("status");
rq.expect(data).to.have.property("data");
rq.expect(data.data).to.be.an("array").and.not.be.empty;
});
```
## More Assertions
For the complete list of assertions including:
* Advanced object and array matchers
* Custom assertions with `.satisfy()`
* Key checking with `.have.keys()`
* And many more...
Visit the **[Chai.js BDD API Documentation](https://www.chaijs.com/api/bdd/)**
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.test Object](/api-client/rq-api-reference/rq-test)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [Tests Documentation](/api-client/tests)
* [Chai.js Official Documentation](https://www.chaijs.com/api/bdd/) - For complete assertion reference
# rq.globals (Global variables)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-globals
Complete reference for the rq.globals object in Requestly scripts to manage global variables accessible across all collections and environments.
The `rq.globals` object provides methods to manage global variables during script execution. Global variables work similarly to environment variables, but they are available to all collections and requests across all environments. This makes them ideal for storing truly global configuration or state that needs to be shared everywhere.
## Methods
### `rq.globals.set(key, value)`
Sets a global variable with the given key and value. If the variable already exists, it will be updated with the new value.
**Parameters:**
* `key` (string): The name of the global variable
* `value` (any): The value to store. Scalar values are stored as strings; passing an array stores a real array, so a later `get` returns the array unchanged. Passing `null` or `undefined` clears the variable, which is equivalent to `unset(key)`, so a later `get` returns `undefined` (not the string `"null"`).
**Example:**
```jsx theme={null}
rq.globals.set("appVersion", "1.0.0");
```
Passing an array to `set` stores a real array, and `get` returns it as a real array with `.first()` and `.last()` helpers. See [rq.environment](/api-client/rq-api-reference/rq-environment#working-with-array-variables) for examples.
### `rq.globals.get(key)`
Retrieves the value of the specified global variable.
**Parameters:**
* `key` (string): The name of the global variable to retrieve
**Returns:** The value of the global variable, or `undefined` if it doesn't exist.
**Example:**
```jsx theme={null}
const version = rq.globals.get("appVersion");
console.log("App Version:", version);
```
### `rq.globals.unset(key)`
Removes the specified global variable.
**Parameters:**
* `key` (string): The name of the global variable to remove
**Example:**
```jsx theme={null}
rq.globals.unset("appVersion");
```
### `rq.globals.clear()`
Removes all global variables.
**Parameters:** none.
**Example:**
```jsx theme={null}
rq.globals.clear();
console.log("All global variables cleared");
```
## Common Use Cases
### Store Application Version
Keep track of the application or API version being tested:
```jsx theme={null}
// In setup script
rq.globals.set("appVersion", "1.0.0");
rq.globals.set("apiVersion", "v2");
// In any request
const version = rq.globals.get("appVersion");
console.log("Testing with app version:", version);
```
### Track Global State
Maintain state that needs to be shared across all collections:
```jsx theme={null}
// Track total requests made
const totalRequests = parseInt(rq.globals.get("totalRequests") || "0");
rq.globals.set("totalRequests", totalRequests + 1);
console.log("Total requests made:", totalRequests + 1);
```
### Store User Preferences
Keep user preferences that apply globally:
```jsx theme={null}
rq.globals.set("preferredLanguage", "en");
rq.globals.set("dateFormat", "YYYY-MM-DD");
rq.globals.set("timezone", "UTC");
```
### Global Timestamp
Set a global timestamp that all requests can reference:
```jsx theme={null}
// Set once at the beginning of a test run
rq.globals.set("testRunStartTime", Date.now());
// Reference in any request
const startTime = rq.globals.get("testRunStartTime");
const elapsed = Date.now() - parseInt(startTime);
console.log("Time since test start:", elapsed, "ms");
```
### Feature Flags
Implement global feature flags:
```jsx theme={null}
// Enable/disable features globally
rq.globals.set("enableLogging", "true");
rq.globals.set("enableDebugMode", "false");
rq.globals.set("useNewEndpoint", "true");
// Check flags in any request
const debugMode = rq.globals.get("enableDebugMode") === "true";
if (debugMode) {
console.log("Debug mode is enabled");
}
```
### Store Common Constants
Define constants that are used across all collections:
```jsx theme={null}
rq.globals.set("MAX_PAGE_SIZE", "100");
rq.globals.set("DEFAULT_PAGE_SIZE", "20");
rq.globals.set("API_KEY_HEADER", "X-API-Key");
```
## Variable Scope Hierarchy
Understanding the hierarchy of variables in Requestly:
1. **Global Variables** (`rq.globals`) - Highest level, available everywhere
2. **Collection Variables** (`rq.collectionVariables`) - Available to all requests in a collection
3. **Environment Variables** (`rq.environment`) - Available to all collections in a specific environment
When a variable with the same name exists at multiple levels, the most specific scope takes precedence:
```text theme={null}
Environment Variables > Collection Variables > Global Variables
```
## Best Practices
1. **Use Sparingly**: Reserve global variables for truly global data. Prefer collection or environment variables when possible.
2. **Naming Convention**: Use clear, uppercase names for global constants
```jsx theme={null}
rq.globals.set("MAX_RETRY_ATTEMPTS", "5");
rq.globals.set("DEFAULT_TIMEOUT_MS", "30000");
```
3. **Document Purpose**: Comment your global variable usage
```jsx theme={null}
// Global feature flag for new API version
rq.globals.set("useV2Api", "true");
```
4. **Check Existence**: Always verify a variable exists before using it
```jsx theme={null}
const value = rq.globals.get("myGlobalVar");
if (!value) {
console.error("Global variable 'myGlobalVar' not set");
}
```
5. **Initialize Early**: Set global variables in a dedicated setup script or request
6. **Clean Up**: Remove globals that are no longer needed
```jsx theme={null}
rq.globals.unset("temporaryFlag");
```
7. **Type Conversion**: Most values are stored as strings, so convert them when needed. Array-typed variables are the exception and are returned as real arrays.
```jsx theme={null}
const maxRetries = parseInt(rq.globals.get("maxRetries") || "3");
const enableFeature = rq.globals.get("enableFeature") === "true";
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [rq.environment Object](/api-client/rq-api-reference/rq-environment)
* [rq.collectionVariables Object](/api-client/rq-api-reference/rq-collection-variables)
* [rq.vault Object](/api-client/rq-api-reference/rq-vault)
* [rq.test Object](/api-client/rq-api-reference/rq-test)
* [rq.expect Object](/api-client/rq-api-reference/rq-expect)
# rq.info (Execution info)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-info
Access metadata about the current script execution context in Requestly API client.
The `rq.info` object provides metadata about the current script execution context. It contains information about the request being executed, the current iteration (when running collections), and the event type.
## Methods
### `rq.info.requestId`
**Type:** `string`
The unique identifier of the request being executed.
**Example:**
```jsx theme={null}
console.log("Request ID:", rq.info.requestId);
// Output: Request ID: abc123xyz
```
### `rq.info.requestName`
**Type:** `string`
The name of the request being executed.
**Example:**
```jsx theme={null}
console.log("Request Name:", rq.info.requestName);
```
### `rq.info.eventName`
**Type:** `"pre-request" | "post-response"`
The type of script event currently executing. Returns `"pre-request"` for pre-request scripts and `"post-response"` for post-response scripts.
**Example:**
```jsx theme={null}
if (rq.info.eventName === "pre-request") {
console.log("Running pre-request script");
} else {
console.log("Running post-response script");
}
```
### `rq.info.iteration`
**Type:** `number`
The current iteration index when running a collection with the Collection Runner. The index is **0-based**, meaning the first iteration is `0`, the second is `1`, and so on.
For single request executions (not part of a collection run), this value is `0`.
**Example:**
```jsx theme={null}
console.log("Current iteration:", rq.info.iteration);
// Output: Current iteration: 0 (first iteration)
// Output: Current iteration: 2 (third iteration)
```
### `rq.info.iterationCount`
**Type:** `number`
The total number of iterations configured for the collection run. For single request executions, this value is `1`.
**Example:**
```jsx theme={null}
console.log(`Running iteration ${rq.info.iteration + 1} of ${rq.info.iterationCount}`);
// Output: Running iteration 3 of 10
```
# rq.iterationData (Iteration data)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-iteration-data
Access data from CSV or JSON files during collection runs in Requestly API client scripts.
The `rq.iterationData` object provides access to data from CSV or JSON files when running collections with the Collection Runner. Each iteration of the collection run receives a different row (CSV) or object (JSON) from the data file, allowing you to parameterize your requests dynamically.
This feature works only when you run a collection with an attached data file, which is supported exclusively in the **Desktop App**. If you run a single request or a collection without a data file, rq.iterationData remains **undefined**.
## Methods
### `rq.iterationData.get(key)`
Retrieves the value for a specific key from the current iteration's data.
**Parameters:**
* `key` (string): The name of the variable/column to retrieve
**Returns:** The value associated with the key, or `undefined` if the key doesn't exist
**Example:**
```javascript theme={null}
// For a CSV with columns: city, temperature
const city = rq.iterationData.get("city");
const temp = rq.iterationData.get("temperature");
console.log(`Weather in ${city}: ${temp}°C`);
// Output: Weather in Vancouver: 10°C
```
### `rq.iterationData.has(key)`
Checks if a specific key exists in the current iteration's data.
**Parameters:**
* `key` (string): The name of the variable/column to check
**Returns:** `true` if the key exists, `false` otherwise
**Example:**
```javascript theme={null}
if (rq.iterationData.has("userId")) {
const userId = rq.iterationData.get("userId");
console.log("User ID:", userId);
} else {
console.log("No user ID in this iteration");
}
```
### `rq.iterationData.toObject()`
Returns all data from the current iteration as a JavaScript object.
**Returns:** An object containing all key-value pairs from the current iteration
**Example:**
```javascript theme={null}
const allData = rq.iterationData.toObject();
console.log("Current iteration data:", allData);
// Output: Current iteration data: { city: "Vancouver", temperature: 10 }
```
## Use Cases
### Conditional Logic Based on Data
```javascript theme={null}
// Pre-request script
const userType = rq.iterationData.get("userType");
if (userType === "admin") {
rq.request.headers.add({
key: "X-Admin-Token",
value: "admin-secret-token"
});
} else {
rq.request.headers.add({
key: "X-User-Token",
value: "user-token"
});
}
```
### Validating Response Against Expected Data
```javascript theme={null}
// Post-response script
const expectedStatus = rq.iterationData.get("expectedStatus");
const actualStatus = rq.response.code;
rq.test(`Status code matches expected (${expectedStatus})`, function() {
rq.expect(actualStatus).to.equal(parseInt(expectedStatus));
});
```
## Data File Format Examples
### CSV Format
```csv theme={null}
city,temperature,humidity
Vancouver,10,75
Austin,24,60
London,12,80
```
**Accessing in script:**
```javascript theme={null}
const city = rq.iterationData.get("city"); // "Vancouver"
const temp = rq.iterationData.get("temperature"); // 10
const humidity = rq.iterationData.get("humidity"); // 75
```
# rq.request (Request object)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-request
Complete reference for the rq.request object in Requestly scripts, including properties and methods to access.
The `rq.request` object provides access to all details of the API request in your Requestly scripts. You can use these properties and methods in both pre-request and post-response scripts to read data.
## Properties and Methods
### `rq.request.method`
Use this property to get the Request's method. The HTTP method of the request (e.g. `GET`, `POST`, `PUT`, `OPTION`, `DELETE`, `PATCH`, `HEAD`).
**Example:**
```jsx theme={null}
console.log("Request Method: ", rq.request.method);
```
### `rq.request.headers`
An object that holds the request headers. Read them with `rq.request.headers.get(name)`, `rq.request.headers.has(name)`, or `rq.request.headers.all()`, which returns a plain `{ name: value }` object. `JSON.stringify(rq.request.headers)` returns `{}` because the object exposes only methods (which `JSON.stringify` omits), so use `.all()` when you want to serialize the headers.
**Example:**
```jsx theme={null}
console.log("Headers: ", JSON.stringify(rq.request.headers.all()));
```
You can also modify request headers from a **pre-request script**. The methods below change the headers that are sent with the request. Use them in pre-request scripts; in post-response scripts the request has already been sent, so header changes have no effect. Header changes apply to HTTP and GraphQL requests.
#### `rq.request.headers.add(header)`
Adds a header. If a header with the same name already exists, this adds a second one (it does not replace the existing header).
**Parameters:**
* `header` (object): `{ key, value }` - the header name and value.
**Example:**
```jsx theme={null}
rq.request.headers.add({ key: "X-Trace-Id", value: "abc-123" });
```
#### `rq.request.headers.upsert(header)`
Adds a header, or replaces it if a header with the same name already exists. Header names are matched case-insensitively.
**Parameters:**
* `header` (object): `{ key, value }` - the header name and value.
**Example:**
```jsx theme={null}
rq.request.headers.upsert({ key: "Authorization", value: "Bearer " + rq.environment.get("authToken") });
```
#### `rq.request.headers.remove(name)`
Removes every header with the given name (case-insensitive).
**Parameters:**
* `name` (string): The header name to remove.
**Example:**
```jsx theme={null}
rq.request.headers.remove("X-Debug");
```
#### `rq.request.headers.clear()`
Removes all request headers.
**Parameters:** none. Any argument passed is ignored. `clear()` always removes every header, so to remove a single header use `remove(name)` instead.
**Example:**
```jsx theme={null}
rq.request.headers.clear();
```
The same operations are available directly on `rq.request` as `rq.request.addHeader({ key, value })`, `rq.request.upsertHeader({ key, value })`, and `rq.request.removeHeader(name)`.
### `rq.request.body`
The body of the request, accessible as a string. It is always a string, or `undefined` when the request has no body.
**Example:**
```jsx theme={null}
console.log("Body:", JSON.stringify(rq.request.body));
```
### `rq.request.url`
The full URL of the API request.
**Example:**
```jsx theme={null}
console.log("Request URL:", rq.request.url);
```
### `rq.request.queryParams`
A read-only object mapping each query parameter name to its value (`{ name: value }`). Iterate it with `Object.entries()`.
**Example:**
```jsx theme={null}
console.log("Query Params:", JSON.stringify(rq.request.queryParams));
```
## Common Use Cases
### Logging Request Details
```jsx theme={null}
console.log("Making " + rq.request.method + " request to " + rq.request.url);
console.log("Request headers:", JSON.stringify(rq.request.headers.all()));
console.log("Request body:", JSON.stringify(rq.request.body));
```
### Conditional Logic Based on Request Method
```jsx theme={null}
if (rq.request.method === "POST" || rq.request.method === "PUT") {
console.log("Sending data:", rq.request.body);
}
```
### Accessing Query Parameters
```jsx theme={null}
Object.entries(rq.request.queryParams).forEach(([key, value]) => {
console.log(`Query param ${key}: ${value}`);
});
```
### Adding an Authentication Header
```jsx theme={null}
// In a pre-request script
const token = rq.environment.get("authToken");
if (token) {
rq.request.headers.upsert({ key: "Authorization", value: "Bearer " + token });
}
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [rq.environment Object](/api-client/rq-api-reference/rq-environment)
* [rq.collectionVariables Object](/api-client/rq-api-reference/rq-collection-variables)
* [rq.globals Object](/api-client/rq-api-reference/rq-globals)
* [rq.vault Object](/api-client/rq-api-reference/rq-vault)
* [rq.test Object](/api-client/rq-api-reference/rq-test)
* [rq.expect Object](/api-client/rq-api-reference/rq-expect)
# rq.response (Response object)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-response
Complete reference for the rq.response object in Requestly scripts, including properties and methods to access and process API response data.
The `rq.response` object provides access to all details of the API response in your Requestly scripts. You can use these properties and methods primarily in post-response scripts to process, validate, and extract data from API responses.
## Properties and Methods
### `rq.response.body`
The body of the response as a string.
**Example:**
```jsx theme={null}
console.log("Response Body:", rq.response.body);
```
### `rq.response.bodyEncoding`
Tells you how `rq.response.body` encodes the original response bytes:
* `'utf8'` - the body is the decoded text. This is the case for JSON, XML, HTML, and other text responses.
* `'base64'` - the body is Base64-encoded raw bytes, used for binary responses such as images, PDFs, and archives.
The property is absent on responses saved before this field existed. Treat an absent value as `'utf8'`.
**Example:**
```jsx theme={null}
if (rq.response.bodyEncoding === "base64") {
const { Buffer } = require("buffer");
const bytes = Buffer.from(rq.response.body, "base64");
console.log("Binary response, byte length:", bytes.length);
} else {
console.log("Text response:", rq.response.body);
}
```
### `rq.response.responseTime`
The time taken by the request to complete, in milliseconds.
**Example:**
```jsx theme={null}
console.log("Response Time:", rq.response.responseTime);
```
### `rq.response.headers`
An object holding the response headers. Access a single header with `rq.response.headers.get(name)` or `rq.response.headers.has(name)` (both case-insensitive), or get them all as a plain `{ name: value }` object with `rq.response.headers.all()`.
**Example:**
```jsx theme={null}
console.log("Content-Type:", rq.response.headers.get("content-type"));
console.log("Response Headers:", JSON.stringify(rq.response.headers.all()));
```
### `rq.response.code`
The HTTP status code of the response.
**Example:**
```jsx theme={null}
console.log("Response Code:", rq.response.code);
```
```jsx theme={null}
rq.test("Status is 200", () => {
rq.response.to.have.status(200);
});
```
### `rq.response.json()`
Parses the response body as JSON and returns it as a JavaScript object.
**Example:**
```jsx theme={null}
console.log("Response JSON:", JSON.stringify(rq.response.json()));
```
### `rq.response.text()`
Returns the response body as a plain string.
**Example:**
```jsx theme={null}
console.log("Response Body as String:", rq.response.text());
```
## Common Use Cases
### Validate Response Code
Check if the API returned the expected status code:
```jsx theme={null}
if (rq.response.code !== 200) {
console.error("Unexpected Response Code:", rq.response.code);
} else {
console.log("Request successful!");
}
```
### Extract Data from JSON Response
Parse the response and extract specific fields:
```jsx theme={null}
const responseData = rq.response.json();
const userId = responseData.id;
const userName = responseData.name;
console.log("User ID:", userId);
console.log("User Name:", userName);
// Store extracted data for use in other requests
rq.environment.set("user_id", userId);
```
### Check Response Time
Monitor API performance:
```jsx theme={null}
if (rq.response.responseTime > 1000) {
console.warn("Slow response detected:", rq.response.responseTime + "ms");
} else {
console.log("Response time OK:", rq.response.responseTime + "ms");
}
```
### Extract Authentication Token
Get auth token from response and save it:
```jsx theme={null}
const responseData = rq.response.json();
if (responseData.token) {
rq.environment.set("authToken", responseData.token);
console.log("Auth token saved successfully");
}
```
### Access Response Headers
```jsx theme={null}
Object.entries(rq.response.headers.all()).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
```
### Validate Response Structure
```jsx theme={null}
const data = rq.response.json();
if (data.error) {
console.error("API Error:", data.error);
} else if (!data.id) {
console.error("Missing expected field: id");
} else {
console.log("Response validation passed");
}
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.environment Object](/api-client/rq-api-reference/rq-environment)
* [rq.collectionVariables Object](/api-client/rq-api-reference/rq-collection-variables)
* [rq.globals Object](/api-client/rq-api-reference/rq-globals)
* [rq.vault Object](/api-client/rq-api-reference/rq-vault)
* [rq.test Object](/api-client/rq-api-reference/rq-test)
* [rq.expect Object](/api-client/rq-api-reference/rq-expect)
# rq.sendRequest (Send a request)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-send-request
Reference for rq.sendRequest in Requestly scripts: send an HTTP request from a pre-request or post-response script and read the response.
The `rq.sendRequest` method lets you send an HTTP request from inside a script and read its response. Use it to fetch a token before the main request runs, call a second endpoint after a response arrives, or poll a status URL. It is available in both pre-request and post-response scripts.
## Calling rq.sendRequest
You can call `rq.sendRequest` in two styles. Both send the same request.
**Promise style (recommended):**
```jsx theme={null}
const res = await rq.sendRequest("https://api.example.com/health");
console.log("Status:", res.code);
```
**Callback style:**
```jsx theme={null}
rq.sendRequest("https://api.example.com/health", (err, res) => {
if (err) {
console.error("Request failed:", err);
return;
}
console.log("Status:", res.code);
});
```
The callback follows the Node convention: the first argument is the error (or `null` on success), the second is the response.
## Request input
The first argument is either a URL string or a request configuration object.
### URL string
```jsx theme={null}
const res = await rq.sendRequest("https://api.example.com/users");
```
A bare string is sent as a `GET` request.
### Configuration object
```jsx theme={null}
const res = await rq.sendRequest({
url: "https://api.example.com/users",
method: "POST",
header: {
"Content-Type": "application/json",
"Authorization": "Bearer " + rq.environment.get("authToken"),
},
body: {
mode: "raw",
raw: JSON.stringify({ name: "Ada" }),
},
});
```
**Fields:**
* `url` (string, required): The request URL.
* `method` (string, optional): The HTTP method. Defaults to `GET`.
* `header` (object or array, optional): Request headers. Use a plain object (`{ "Header-Name": "value" }`) or an array of rows (`[{ key, value, disabled }]`). The field name is `header`, singular.
* `body` (object, optional): The request body. See [Body modes](#body-modes).
## Body modes
The `body` object has a `mode` that selects how the body is sent. Two modes are supported.
### Raw
Sends the body exactly as you provide it. Set the `Content-Type` header yourself.
```jsx theme={null}
const res = await rq.sendRequest({
url: "https://api.example.com/users",
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({ name: "Ada", role: "admin" }),
},
});
```
### URL-encoded
Sends form fields as `application/x-www-form-urlencoded`. Requestly sets that `Content-Type` for you unless you set one yourself. Rows marked `disabled: true` are skipped.
```jsx theme={null}
const res = await rq.sendRequest({
url: "https://api.example.com/login",
method: "POST",
body: {
mode: "urlencoded",
urlencoded: [
{ key: "username", value: "ada" },
{ key: "password", value: rq.environment.get("password") },
],
},
});
```
Multipart form-data and file-upload bodies are not supported by `rq.sendRequest`. Scripts run in a sandbox with no access to your file system, so a body cannot read a file from disk.
## Response
The response object passed to your callback (and resolved by the promise) has these members:
* `code` (number): The numeric HTTP status, for example `200`.
* `status` (string): The HTTP status text, for example `"OK"`.
* `headers`: The response headers. Read one with `headers.get("content-type")` (case-insensitive) or `headers["content-type"]`.
* `responseTime` (number): The round-trip time in milliseconds.
* `json()`: Parses the response body as JSON and returns it. Throws if the body is not valid JSON.
* `text()`: Returns the raw response body as a string.
**Example:**
```jsx theme={null}
const res = await rq.sendRequest("https://api.example.com/users/1");
console.log("Status:", res.code, res.status);
console.log("Content-Type:", res.headers.get("content-type"));
console.log("Took:", res.responseTime, "ms");
const user = res.json();
console.log("User name:", user.name);
```
## Error handling
An error is reported two ways at once: the promise rejects, and the callback receives it as the first argument. Handle whichever style you are using.
```jsx theme={null}
try {
const res = await rq.sendRequest("https://does-not-resolve.example");
console.log(res.code);
} catch (err) {
console.error("Could not send the request:", err);
}
```
Two situations produce an error:
* **Invalid arguments:** the configuration has no usable `url`. The request is never sent.
* **Network error:** the request could not reach the server (for example DNS failure, connection refused, or a TLS problem).
An HTTP error status such as `404` or `500` is **not** treated as an error. The promise resolves and the callback receives the response normally. Inspect `res.code` to decide how to handle the status:
```jsx theme={null}
const res = await rq.sendRequest("https://api.example.com/users/999");
if (res.code === 404) {
console.log("User not found");
} else if (res.code >= 500) {
console.error("Server error:", res.code);
}
```
Always `await` the promise or attach a `.catch()` (or pass a callback). A request that is never awaited may have its error go unreported if the script finishes first.
## Common Use Cases
### Fetch a token before the main request
```jsx theme={null}
// Pre-request script
const res = await rq.sendRequest({
url: "https://api.example.com/auth/login",
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({ user: "ada", pass: rq.environment.get("password") }),
},
});
const token = res.json().accessToken;
rq.environment.set("authToken", token);
```
### Call a second endpoint after the response
```jsx theme={null}
// Post-response script
const created = rq.response.json();
const res = await rq.sendRequest("https://api.example.com/audit/" + created.id);
console.log("Audit record:", res.json());
```
### Read a response header
```jsx theme={null}
const res = await rq.sendRequest("https://api.example.com/data");
const rateLimit = res.headers.get("x-ratelimit-remaining");
console.log("Requests remaining:", rateLimit);
```
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [Scripts Reference Overview](/api-client/rq-api-reference/overview)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [rq.environment Object](/api-client/rq-api-reference/rq-environment)
# rq.test (Test object)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-test
Complete reference for the rq.test object in Requestly scripts to write and execute tests for your API requests and responses.
The `rq.test` object allows you to write tests in your post-response scripts to validate API responses and ensure your APIs are working as expected. Tests help you automate quality assurance and catch issues early in development.
## Properties and Methods
### `rq.test(name, function)`
Creates a test with a given name and a test function. The test function should contain assertions using `rq.expect`.
**Parameters:**
* `name` (string): The name of the test (will be displayed in test results)
* `function` (function): A function containing test assertions
**Example:**
```jsx theme={null}
rq.test("Status code is 200", function() {
rq.expect(rq.response.code).to.equal(200);
});
```
## Writing Tests
Tests are typically written in post-response scripts to validate the API response after it's received.
### Basic Test Example
```jsx theme={null}
// Test that the response status is 200
rq.test("Response is successful", function() {
rq.expect(rq.response.code).to.equal(200);
});
// Test that response contains expected data
rq.test("Response has user data", function() {
const data = rq.response.json();
rq.expect(data).to.have.property("id");
rq.expect(data).to.have.property("name");
});
```
### Multiple Assertions in One Test
You can include multiple assertions within a single test:
```jsx theme={null}
rq.test("User object is valid", function() {
const user = rq.response.json();
rq.expect(user).to.have.property("id");
rq.expect(user.id).to.be.a("number");
rq.expect(user.name).to.be.a("string");
rq.expect(user.email).to.include("@");
});
```
## Common Test Patterns
### Validate Status Code
```jsx theme={null}
rq.test("Status code is 200", function() {
rq.expect(rq.response.code).to.equal(200);
});
```
### Validate Response Structure
```jsx theme={null}
rq.test("Response has correct structure", function() {
const data = rq.response.json();
rq.expect(data).to.be.an("object");
rq.expect(data).to.have.property("status");
rq.expect(data).to.have.property("data");
});
```
### Validate Response Time
```jsx theme={null}
rq.test("Response time is acceptable", function() {
rq.expect(rq.response.responseTime).to.be.below(1000);
});
```
### Conditional Tests
```jsx theme={null}
if (rq.response.code === 200) {
rq.test("Successful response has data", function() {
const data = rq.response.json();
rq.expect(data).to.have.property("result");
});
}
```
For more assertion examples and patterns, see the [rq.expect documentation](/api-client/rq-api-reference/rq-expect) and [Chai.js official documentation](https://www.chaijs.com/api/bdd/).
## Best Practices
1. **Use Descriptive Test Names**: Make test names clear and specific
2. **One Concept Per Test**: Each test should validate one logical concept
3. **Test Expected Behavior**: Focus on what should happen
4. **Handle Different Response Codes**: Write tests for both success and error scenarios
5. **Store Values for Later Use**: Combine tests with variable storage
**Example:**
```jsx theme={null}
rq.test("Response contains user ID", function() {
const data = rq.response.json();
rq.expect(data).to.have.property("id");
// Store for use in subsequent requests
rq.environment.set("userId", data.id);
});
```
## Test Results
Test results are displayed in the Requestly interface, showing:
* ✅ Passed tests (green)
* ❌ Failed tests (red)
* Test execution time
* Assertion details for failed tests
## Related Documentation
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.expect Object](/api-client/rq-api-reference/rq-expect)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [Tests Documentation](/api-client/tests)
# rq.vault (Vault object)
Source: https://docs.requestly.com/api-client/rq-api-reference/rq-vault
Complete reference for the rq.vault object in Requestly scripts to read encrypted secrets from the local vault and AWS Secrets Manager.
The `rq.vault` object provides read access to encrypted secrets stored in the Requestly [Vault](/api-client/vault) during script execution. Vault secrets are kept out of collections, exports, and cloud sync. Only `{{vault:key}}` references travel with your project, while the resolved values stay on the user's machine.
`rq.vault` is only available in the **Requestly desktop app**, and Vault is rolling out behind a feature flag. If the Vault surface is not visible in your build, contact support to confirm it is enabled for your account. Vault features are disabled in the web-only mode.
`rq.vault` is **read-only from scripts**. You can read and check secrets, but you cannot create, update, or delete them from a script. Manage secrets from the [Vault page](/api-client/vault). To store a derived value at request time, write it to a variable with `rq.variables.set()` instead.
## Methods
### `rq.vault.get(key)`
Retrieves the value of a vault secret. Works for both **local** secrets and external provider secrets, such as **AWS Secrets Manager** and **Azure Key Vault**, that have been fetched into the vault.
**Parameters:**
* `key` (string): The name of the vault secret to retrieve
**Returns:** The secret's string value, or `undefined` if the key doesn't exist. This call is **synchronous** (no `await` needed).
**Example:**
```jsx theme={null}
const apiKey = rq.vault.get("my-api-key");
console.log("Key loaded:", Boolean(apiKey));
```
### `rq.vault.has(key)`
Checks whether a vault secret with the given key exists. Works for both local secrets and external provider secrets fetched into the vault.
**Parameters:**
* `key` (string): The name of the vault secret to check
**Returns:** `true` if the secret exists, `false` otherwise. This call is **synchronous**.
**Example:**
```jsx theme={null}
if (rq.vault.has("signing-key")) {
const key = rq.vault.get("signing-key");
// generate JWT...
}
```
### `rq.vault.toObject()`
Returns all available vault secrets as a plain object of key/value pairs. Useful for iterating over or inspecting the secrets your script can see.
**Returns:** An object mapping each secret's key to its string value.
**Example:**
```jsx theme={null}
const secrets = rq.vault.toObject();
console.log("Available keys:", Object.keys(secrets));
```
## Common Use Cases
### Generate a JWT Without Exposing the Signing Key
Keep the signing key inside the vault and expose only the generated token to the request:
```jsx theme={null}
// Pre-request script
const signingKey = rq.vault.get("signing-key");
const jwt = generateJwt(payload, signingKey);
rq.variables.set("auth-token", jwt);
```
Then reference `{{auth-token}}` in the Authorization header. The signing key never leaves the vault.
### Cache a Short-Lived Token for the Current Run
Fetch a token once, store it in a variable, and reuse it across subsequent requests until it expires. Use a variable (not the vault) because the vault is read-only from scripts:
```jsx theme={null}
let token = rq.variables.get("session-token");
if (!token) {
const res = await fetch("https://auth.example.com/token", { /* ... */ });
const body = await res.json();
token = body.access_token;
rq.variables.set("session-token", token);
}
rq.request.headers.add({ key: "Authorization", value: `Bearer ${token}` });
```
### Guard Optional Secrets
Only apply a signing step when the signing key is configured:
```jsx theme={null}
if (rq.vault.has("hmac-secret")) {
const secret = rq.vault.get("hmac-secret");
const signature = signRequest(rq.request.body, secret);
rq.request.headers.add({ key: "X-Signature", value: signature });
}
```
## Behavior Notes
* **All methods are synchronous.** `get()`, `has()`, and `toObject()` return their values directly. You do not need to `await` them.
* **Read-only from scripts.** There is no `set()` or `unset()` on `rq.vault`. To create, update, or delete a secret, use the [Vault page](/api-client/vault). To keep a derived value for the current run, use `rq.variables.set()`.
* **Values are strings.** `get()` always returns a string (or `undefined`).
* **JSON secrets from AWS auto-expand.** For a secret named `dbCredentials` storing `{ "username": "admin" }`, use `rq.vault.get("dbCredentials.username")` to read the nested value.
* **Masked in console.** Values returned from `rq.vault.get()` are masked in the Requestly console output. They resolve correctly at request time, but never appear in plaintext in logs.
* **No cloud sync.** Vault values stay on the current machine and are never included in collection exports or project sync.
## Related Documentation
* [Vault Overview](/api-client/vault)
* [Pre-request & Post-response Scripts](/api-client/scripts)
* [rq.sendRequest Object](/api-client/rq-api-reference/rq-send-request)
* [rq.execution Object](/api-client/rq-api-reference/rq-execution)
* [rq.request Object](/api-client/rq-api-reference/rq-request)
* [rq.response Object](/api-client/rq-api-reference/rq-response)
* [rq.environment Object](/api-client/rq-api-reference/rq-environment)
* [rq.globals Object](/api-client/rq-api-reference/rq-globals)
# Scheduled Runs
Source: https://docs.requestly.com/api-client/scheduled-runs
Run a collection automatically on a recurring schedule in the cloud, then review run history and per-request results.
A **Scheduled Run** executes a collection automatically on a recurring schedule in the cloud, so your requests keep running without anyone pressing a button. Where the [Collection Runner](/api-client/collection-runner) runs a collection on demand, a Scheduled Run runs it on a cadence you choose (for example every hour, or once a day) and keeps a history of every run so you can catch regressions over time.
Each Scheduled Run belongs to a single collection. You create and manage Scheduled Runs from that collection's **Runner** tab, review a full run history, and drill into any individual run to see per-request results, assertions, and console output.
## Prerequisites
Scheduled Runs are available on **team projects** only. Local projects and personal cloud projects show an explanatory screen with a link to switch to a team project instead.
Only **HTTP** and **GraphQL** requests run on a schedule. WebSocket, Socket.IO, MQTT, and gRPC requests cannot run on a schedule and are skipped. In the request selection list they appear locked, and a note reminds you which requests will not run.
## Finding Scheduled Runs
Open the collection you want to schedule, then select the **Runner** tab.
The Runner tab has two sub-tabs: **Manual** and **Scheduled**. **Manual** is the on-demand [Collection Runner](/api-client/collection-runner). Select **Scheduled** to see the Scheduled Runs for this collection.
Each Scheduled Run appears as a row showing its name, schedule, the outcome of its most recent run, and a strip of colored squares summarizing recent runs. If the collection has no Scheduled Runs yet, you see an empty state with a **Create Scheduled Run** button.
## Creating a scheduled run
Select **Create Scheduled Run** to open the configuration pane. It has two areas: a request-selection list on the left, and the schedule settings on the right.
Give the Scheduled Run a name that describes its purpose, such as "Nightly smoke run".
Pick the environment the run should use, or leave it as **No environment**.
One scheduled run targets one environment. To run another environment, create a separate scheduled run.
Choose a frequency (**Hour**, **Day**, **Week**, or **Month**) and how often it should run under **Run every**. For example, a frequency of **Hour** with an interval of `6` runs the collection every six hours. Use the **Start active** toggle to decide whether the run begins firing immediately after you create it, or starts paused.
In the left panel, choose which requests to include and drag to reorder them. Requests that cannot run on a schedule are shown locked and are skipped. By default the whole collection runs in its natural order.
Under **Retry on failure**, set **Retries per request** (0 to 10) and a **Backoff** strategy (None, Fixed, Linear, or Exponential). The backoff option is only enabled once you set at least one retry.
Each retry counts as a separate request-attempt against your quota.
Select **Create scheduled run**. The new run appears in the inventory and begins firing on its schedule (unless you started it paused). Scheduled Runs execute in Requestly's cloud region, not on your machine, so they keep running when the app is closed.
### Redaction
Scheduled Runs always redact a fixed set of sensitive headers from the results they capture, so credentials are never stored in run history. This set is shown read-only in the config pane and cannot be changed.
These request and response headers are always redacted in captured results: `Authorization`, `Cookie`, `Set-Cookie`, `X-Api-Key`, and `Proxy-Authorization`.
## Managing scheduled runs
Each row in the inventory has an **Edit** button, a **View runs** button, and an overflow (`⋮`) menu with lifecycle actions:
* **Run now** triggers an immediate on-demand run without changing the schedule. The run is dispatched to the cloud and appears in the run history shortly after it finishes, not instantly.
* **Pause** stops a run from firing on its schedule; **Resume** starts it again. A paused run shows a **Paused** badge in its row.
* **Delete** removes the Scheduled Run after an explicit confirmation. Deleting stops the schedule and removes the run definition, but past run history is retained.
* **Edit** reopens the configuration pane so you can change the name, environment, schedule, request selection, or retry settings.
## Viewing run history
Select **View runs** on any row to open its run history: a list of every run the schedule has produced, newest first. Each entry shows the outcome, when the run started, what triggered it, and how long it took, along with a short failure summary when a run did not succeed.
Use the **search** box to filter by run ID, run status, failure text, or trigger source, and the outcome filter to narrow the list to one of: **Succeeded**, **Failed**, **Timeout**, **Infra error**, or **Skipped**. Use **Load more** to page through older runs.
Run history lists finalized runs only and refreshes on its own periodically. A run you just triggered with **Run now** appears once it finishes, so give it a moment and the list will update. A run that is still in progress is shown but cannot be opened until it completes.
## Inspecting a run
Select any finished run to open its drill-down view. The header shows the run's overall outcome, a **Re-run** button that dispatches a fresh on-demand run, and a failure summary when the run failed.
The body is a two-pane layout:
* The **left pane** lists every request attempt in the run, in order. Each row shows the method, name, and URL, the response status and time, and markers for failed requests, failed assertions, and retry attempts (attempts past the first are labeled).
* The **right pane** shows metrics for the run (when it ran, its duration, the number of tests, the average response time, and what triggered it) and, for the request you select, a tabbed detail view:
* **Headers** - the request and response headers.
* **Payload** - the request body.
* **Response** - the response body. A marker appears when a large body was truncated.
* **Tests** - the assertions for that request, with pass, fail, and error counts.
Below the panes, the **Console** section shows the console output captured for the selected request. Headers, bodies, and console output are fetched on demand as you open each request, and reflect the redaction described above.
## Running as a deploy gate
Scheduled Runs are built for recurring, unattended monitoring. To run a collection as a pass or fail gate inside a CI pipeline instead, use the [Requestly CLI](/api-client/cli), which runs the same collection from your terminal and returns a non-zero exit code when an assertion fails.
## What's Next?
Run a collection on demand and inspect the results before you schedule it.
Add assertions so each scheduled run validates status, body, and headers.
Run collections from your terminal or CI pipeline as a deploy gate.
# Code Snippets in Scripts
Source: https://docs.requestly.com/api-client/script-snippets
Use built-in code snippets to quickly insert common patterns into your pre-request and post-response scripts in Requestly.
The script editor includes a library of ready-to-use code snippets for common scripting tasks - writing tests, reading and setting variables, and logging request or response details. Instead of typing these patterns from scratch, you can browse, search, and insert them with a single click.
## Opening the snippets panel
In any pre-request or post-response script editor, click the **Snippets** button in the toolbar above the editor. A panel opens with a search box at the top and a categorized list of snippets below.
The snippets shown adapt to the active script phase. For example, response assertions only appear when you are editing a post-response script - they are hidden in the pre-request editor where `rq.response` is not available.
## Searching for a snippet
Type in the search box to filter snippets by name. The list narrows to matches as you type. Clear the search to return to the full list.
## Inserting a snippet
Click any snippet name to insert its code at the current cursor position in the editor. The panel stays open so you can insert multiple snippets in one session.
***
## Available snippets
### Tests
These snippets are available in **post-response scripts only**.
#### Status code
| Snippet | Code inserted |
| :----------------------------------- | :--------------------------------------------------------------------------- |
| Status code: Code is 200 | `rq.test("Status code is 200", () => { rq.response.to.have.status(200); });` |
| Status code: Code name has string | Checks `rq.response.statusText` includes `"OK"` |
| Status code: Successful POST request | Asserts `rq.response.status` is one of `[201, 202]` |
#### Response body
| Snippet | What it tests |
| :------------------------------------ | :--------------------------------------------- |
| Response body: Contains string | Body includes a given string |
| Response body: JSON value check | A specific JSON field equals an expected value |
| Response body: Is equal to a string | Entire body equals an exact string |
| Response body: Is valid JSON | Body is parseable JSON |
| Response body: JSON schema validation | Body matches a JSON Schema object you define |
| Response body: Is an array | Body is an array |
| Response body: Has property | Body object has a specific property key |
Example - JSON schema validation:
```javascript theme={null}
const schema = {
type: "object",
properties: {
id: { type: "number" },
name: { type: "string" },
},
required: ["id", "name"],
};
rq.test("Response matches schema", () => {
rq.response.to.have.jsonSchema(schema);
});
```
#### Response headers
| Snippet | What it tests |
| :----------------------------------- | :---------------------------------------- |
| Response headers: Content-Type check | Response includes a `content-type` header |
#### Response time
| Snippet | What it tests |
| :------------------------------- | :-------------------------------------- |
| Response time is less than 200ms | `rq.response.responseTime` is below 200 |
***
### Variables
These snippets are available in **both pre-request and post-response scripts**.
#### Get a variable
| Snippet | Code inserted |
| :-------------------------- | :-------------------------------------------- |
| Get a variable | `rq.variables.get("variable_key");` |
| Get a global variable | `rq.globals.get("variable_key");` |
| Get an environment variable | `rq.environment.get("variable_key");` |
| Get a collection variable | `rq.collectionVariables.get("variable_key");` |
#### Set a variable
| Snippet | Code inserted |
| :-------------------------- | :-------------------------------------------------------------- |
| Set a variable | `rq.variables.set("variable_key", "variable_value");` |
| Set a global variable | `rq.globals.set("variable_key", "variable_value");` |
| Set an environment variable | `rq.environment.set("variable_key", "variable_value");` |
| Set a collection variable | `rq.collectionVariables.set("variable_key", "variable_value");` |
A common pattern is to extract a token from a response and store it for use in subsequent requests:
```javascript theme={null}
// Post-response script on your login endpoint
const body = rq.response.json();
rq.environment.set("authToken", body.token);
```
For a worked example of chaining two requests where the second depends on data from the first, see [Chaining API requests](/api-client/scripts#chaining-api-requests).
#### Clear a variable
| Snippet | Code inserted |
| :---------------------------- | :---------------------------------------------- |
| Clear a global variable | `rq.globals.unset("variable_key");` |
| Clear an environment variable | `rq.environment.unset("variable_key");` |
| Clear a collection variable | `rq.collectionVariables.unset("variable_key");` |
***
### Request / Other
These snippets are available in both phases unless noted.
| Snippet | Phase | Code inserted |
| :------------------ | :----------------- | :------------------------------------------------------------ |
| Log request details | Both | `console.log("Request:", rq.request.method, rq.request.url);` |
| Log response body | Post-response only | Logs `rq.response.status` and `rq.response.body` |
Logs appear in the **DevTools** console tab, tagged with `#script`. See [DevTools](/api-client/devtools) for details.
***
## Related pages
* [Pre-request and Post-response Scripts](/api-client/scripts) - overview of the scripting system and the `rq` API
* [Tests](/api-client/tests) - running and viewing test results after a request
* [Import packages into your scripts](/api-client/import-packages-into-your-scripts) - use external libraries like `moment` and `uuid` in scripts
# Pre-request & Post-response Scripts
Source: https://docs.requestly.com/api-client/scripts
Learn how to use JavaScript in Requestly to customize API requests, process responses, and interact with variables, with examples.
***
Scripts in Requestly allow you to extend and customize your API requests and responses dynamically using JavaScript. These scripts enable you to manipulate requests before they are sent (Pre-request scripts) or process responses after they are received (Post-response scripts). With access to the full request and response objects, you can achieve advanced automation, validations, and transformations.
## **Pre-Request Scripts**
**Pre-Request Scripts** run before the API request is sent to the server. They allow you to modify request attributes, such as headers, body, query parameters, or even the URL. Pre Scripts are useful for adding authentication tokens, generating timestamps, or altering the request dynamically based on certain conditions.
Let’s try to understand the workings of pre-script using easy-to-follow examples.
**Auto Increment Page Numbers**
Let’s assume you have an endpoint that takes page number as query parameter, we use environment variable `{{page_number}}` to get value of page number.
```json theme={null}
https://app.requestly.io/echo?page={{page_number}}
```
We can get current page number from environment variables and set it back with an increment.
```json theme={null}
rq.environment.set("page_number", rq.environment.get("page_number")+1);
```
Now every time you click the Send button of this request it would send incremented page number.
**Test APIs by Randomising Values**
During development hitting an API with new data every time can be a pain, we can use Pre-Script to randomise the values and call the same API without getting duplicate entry error.
Let’s setup our request with body as follows:
```json theme={null}
POST:
```
```json theme={null}
{
"name": "{{name}}",
"email": "{{email}}",
"phone_number": "{{phone_number}}"
}
```
We will use below pre-script to create random values and update them in environment variables.
```jsx theme={null}
var name = (+new Date).toString(36).slice(-5);
var phone = Math.round((Math.random())*(10**10));
rq.environment.set("name", name);
rq.environment.set("email", name+"@example.com");
rq.environment.set("phone_number", phone);
```
You can also use pre-script to generate access tokens, validate the requests, generate some random data for the request.
You can also access elements of the request, collection variables and environment variables, checkout Requestly’s JavaScript API.
## **Post-Response Scripts**
**Post-Response Scripts** run after the API response is received. They allow you to process response data, validate outputs, or log details for debugging. Post Scripts are useful for transforming the response body, validating response codes, or storing results for further use.
Let’s try to understand the working of post script using easy to follow examples.
**Validate Response Code**
```jsx theme={null}
if (rq.response.code !== 200) {
console.error("Unexpected Response Code:", rq.response.code);
}
```
We can also fetch and set API Keys or auth tokens, id, and other data from response of an API and use it in other APIs.
You can access elements of the request, response, collection variables and environment variables, checkout Requestly's JavaScript API.
***
## Viewing Console Logs from Scripts
You can use `console.log()` or `console.error()` in your Pre-Request and Post-Response Scripts to debug your logic and inspect values at runtime. The logs appear in Requestly's built-in **DevTools** panel and are tagged with **#script** so you can filter them quickly.
Click the **DevTools** button in the application footer at the bottom of the window. The panel docks to the bottom of the workspace with a **Console** tab selected by default.
To see logs for just one request, send the request and open the **Debug** tab in the response area instead. It shows DevTools scoped to that request's most recent execution.
In the Console tab's search box, type **#script** to show only logs produced by your Pre-Request and Post-Response Scripts and hide system events and network summaries.
For everything DevTools can show you, including the Network tab and per-request inspection, see the [DevTools page](/api-client/devtools).
## Requestly JavaScript API `rq`
Requestly provides a robust set of JavaScript properties and methods to interact with API requests, responses, environments, and global variables. The `rq` object is available in all pre-request and post-response scripts, giving you full control over your API workflow.
### Available Objects
The Requestly JavaScript API consists of the following main objects:
#### `rq.request`
Access and manipulate API request details including method, headers, body, URL, and query parameters. Use this in both pre-request and post-response scripts to read or modify request data.
**Quick Example:**
```jsx theme={null}
console.log("Request Method:", rq.request.method);
console.log("Request URL:", rq.request.url);
```
[View complete rq.request documentation →](/api-client/rq-api-reference/rq-request)
***
#### `rq.response`
Access API response details including body, headers, status code, and response time. Primarily used in post-response scripts to process and validate API responses.
**Quick Example:**
```jsx theme={null}
console.log("Response Code:", rq.response.code);
const data = rq.response.json();
```
[View complete rq.response documentation →](/api-client/rq-api-reference/rq-response)
***
#### `rq.sendRequest`
Send an HTTP request from inside a script and read its response. Use it to fetch a token before the main request runs, call a second endpoint, or poll a status URL. Available in both pre-request and post-response scripts.
**Quick Example:**
```jsx theme={null}
const res = await rq.sendRequest("https://api.example.com/health");
console.log("Status:", res.code);
```
[View complete rq.sendRequest documentation →](/api-client/rq-api-reference/rq-send-request)
***
#### `rq.execution`
Control how a request runs: read where it sits in your collection, skip it, set which request the collection runner goes to next, and run another saved request.
**Quick Example:**
```jsx theme={null}
if (!rq.environment.get("authToken")) {
rq.execution.skipRequest();
}
```
[View complete rq.execution documentation →](/api-client/rq-api-reference/rq-execution)
***
#### `rq.environment`
Manage environment-specific variables dynamically. Environment variables are scoped to a specific environment (dev, staging, production) and can be used across multiple requests.
**Quick Example:**
```jsx theme={null}
rq.environment.set("authToken", "Bearer ");
const token = rq.environment.get("authToken");
```
[View complete rq.environment documentation →](/api-client/rq-api-reference/rq-environment)
***
#### `rq.collectionVariables`
Manage collection-scoped variables. Collection variables are only accessible within requests that belong to a specific collection and persist across all environments.
**Quick Example:**
```jsx theme={null}
rq.collectionVariables.set("basePath", "/v1/users");
const path = rq.collectionVariables.get("basePath");
```
[View complete rq.collectionVariables documentation →](/api-client/rq-api-reference/rq-collection-variables)
***
#### `rq.globals`
Manage global variables accessible across all collections and environments. Use for truly universal configuration and state.
**Quick Example:**
```jsx theme={null}
rq.globals.set("appVersion", "1.0.0");
const version = rq.globals.get("appVersion");
```
[View complete rq.globals documentation →](/api-client/rq-api-reference/rq-globals)
***
#### `rq.test`
Write tests to validate API responses and ensure your APIs work as expected. Tests help automate quality assurance in post-response scripts.
**Quick Example:**
```jsx theme={null}
rq.test("Status code is 200", function() {
rq.expect(rq.response.code).to.equal(200);
});
```
[View complete rq.test documentation →](/api-client/rq-api-reference/rq-test)
***
#### `rq.expect`
Write assertions for API testing using the powerful Chai.js assertion library. Use with `rq.test` to validate response data.
**Quick Example:**
```jsx theme={null}
rq.test("Response has user data", function() {
const data = rq.response.json();
rq.expect(data).to.have.property("id");
rq.expect(data.name).to.be.a("string");
});
```
[View complete rq.expect documentation →](/api-client/rq-api-reference/rq-expect)
#### `rq.info`
Access execution metadata including request name, iteration index, and event name. Useful for tracking progress in collection runs and implementing iteration-specific logic.
**Quick Example:**
```jsx theme={null}
console.log(`Running ${rq.info.requestName}`);
console.log(`Iteration ${rq.info.iteration + 1} of ${rq.info.iterationCount}`);
```
[View complete rq.info documentation →](/api-client/rq-api-reference/rq-info)
***
#### `rq.iterationData`
Access data from CSV or JSON files during collection runs. Each iteration receives different data from the file, enabling data-driven testing.
**Quick Example:**
```jsx theme={null}
const city = rq.iterationData.get("city");
const temp = rq.iterationData.get("temperature");
console.log(`Weather in ${city}: ${temp}°C`);
```
[View complete rq.iterationData documentation →](/api-client/rq-api-reference/rq-iteration-data)
***
### Using Dynamic Variables in Scripts
Requestly provides dynamic variables, which are built in values that automatically generate common data such as timestamps, UUIDs, and random values. You can access them in scripts using the rq.\$variableName() syntax.
**Quick Example:**
```jsx theme={null}
const uniqueId = rq.$randomUUID();
const timestamp = rq.$timestamp();
const email = rq.$randomEmail();
console.log("Generated User ID:", uniqueId);
console.log("Request Timestamp:", timestamp);
```
**Common Dynamic Variables:**
* `rq.$randomUUID()` - Generate unique identifiers
* `rq.$timestamp()` - Current Unix timestamp
* `rq.$isoTimestamp()` - ISO 8601 timestamp
* `rq.$randomInt()` - Random integer
* `rq.$randomEmail()` - Random email address
* `rq.$randomFirstName()` - Random first name
* `rq.$randomCompanyName()` - Random company name
**With Arguments:**
```jsx theme={null}
// Generate random integer between 1-100
const age = rq.$randomInt(1, 100);
// Generate alphanumeric string of length 10
const code = rq.$randomAlphaNumeric(10);
// Generate password with specific length
const password = rq.$randomPassword("20");
// Generate email with custom name
const email = rq.$randomEmail("John", "Doe");
```
[View complete Dynamic Variables documentation →](/api-client/environments-and-variables/dynamic-variables)
***
## Chaining API requests
When one request depends on the output of another, use a post-response script on the first request to extract the values you need, then reference them from the second request using `{{variable_name}}` placeholders. The same pattern covers auth-token flows, "create then update" sequences, and conditional logic that decides what the next call should send.
The flow has three pieces:
1. **Post-response script on the prerequisite request.** Parse the response and write the values into a variable scope.
2. **Reference the variables** from the next request's URL, headers, query params, or body using `{{variable_name}}` syntax. See [Using variables in API requests](/api-client/environments-and-variables/using-variables-in-api-requests).
3. **Run the requests in order**, either manually or by adding them to a collection and using the [Collection Runner](/api-client/collection-runner).
### Example: pass dynamic data from one request to the next
A collection with two requests: `Get Users` followed by `Add User`. The post-response script on `Get Users` checks whether the target user already exists. If they don't, it stages fresh data for the second request to consume.
**Post-response script on `Get Users`:**
```javascript theme={null}
const body = rq.response.json();
const users = Array.isArray(body) ? body : body.users;
const targetEmail = rq.environment.get("new_user_email");
const existing = users.find(user => user.email === targetEmail);
if (existing) {
rq.variables.set("user_exists", "true");
rq.variables.set("existing_user_id", existing.id);
} else {
rq.variables.set("user_exists", "false");
rq.variables.set("new_user_name", "User_" + Date.now());
}
```
**Request body on `Add User`:**
```json theme={null}
{
"name": "{{new_user_name}}",
"email": "{{new_user_email}}"
}
```
When the collection runs, Requestly substitutes `{{new_user_name}}` and `{{new_user_email}}` with whatever the post-response script wrote. Anything the next request needs (an id from a `POST` to feed a follow-up `PATCH`, an auth token from a login call, an order number returned by a checkout step) follows the same shape.
### Picking a variable scope
| Scope | Setter | Lives for |
| :---------- | :--------------------------- | :-------------------------------------------------------------------------------------------------------- |
| Runtime | `rq.variables.set` | The current session. Available across all projects, local-only, optionally persisted across app restarts. |
| Environment | `rq.environment.set` | The active environment. Persists across runs. |
| Collection | `rq.collectionVariables.set` | The collection. Persists across runs. |
| Global | `rq.globals.set` | Everywhere. Persists across runs. |
For values that exist only to bridge one request to the next, prefer **runtime** scope. It stays local to your device and does not pollute your saved environment with one-off state. Reach for environment or collection scope when the value (an auth token, a tenant id) is meaningful beyond the immediate chain.
For the full per-scope reference, see [Runtime variables](/api-client/environments-and-variables/runtime-variables), [rq.environment](/api-client/rq-api-reference/rq-environment), [rq.collectionVariables](/api-client/rq-api-reference/rq-collection-variables), and [rq.globals](/api-client/rq-api-reference/rq-globals).
***
## Encoding request payloads
Some APIs require the body to be transformed before it goes on the wire, for example Base64-encoding a JSON envelope or signing it with an HMAC. The request body is read-only inside scripts, so you compute the transformed value in a pre-request script, store it in a variable, and reference that variable as the body. Requestly resolves the variable just before the request is sent. (Request headers, unlike the body, can be changed directly from a pre-request script. See [rq.request](/api-client/rq-api-reference/rq-request).)
### Base64 encoding with `Buffer`
`require('buffer')` is available in scripts. It is the recommended path because it handles non-ASCII characters correctly.
**Pre-request script:**
```javascript theme={null}
const { Buffer } = require('buffer');
const payload = {
username: rq.environment.get("username"),
password: rq.environment.get("password"),
};
const encoded = Buffer.from(JSON.stringify(payload), 'utf8').toString('base64');
rq.variables.set("encoded_body", encoded);
```
**Request body:**
```text theme={null}
{{encoded_body}}
```
Set `Content-Type` to whatever the server expects, typically `text/plain` or `application/octet-stream` when the body is a raw Base64 string, or `application/json` if the encoded value is wrapped inside a JSON envelope.
### Base64 encoding with `btoa`
`btoa` and `atob` are available as globals. They are convenient when the payload is plain ASCII:
```javascript theme={null}
const jsonString = JSON.stringify({ token: rq.environment.get("token") });
rq.variables.set("encoded_body", btoa(jsonString));
```
Prefer `Buffer` over `btoa` when the payload may contain non-ASCII characters. `btoa` throws on anything outside the Latin-1 range.
### Decoding a Base64 response
Mirror the encoding pattern in a post-response script:
```javascript theme={null}
const { Buffer } = require('buffer');
const decoded = Buffer.from(rq.response.body, 'base64').toString('utf8');
const data = JSON.parse(decoded);
rq.test("Decoded response contains an access token", () => {
rq.expect(data).to.have.property("access_token");
});
```
When the response itself is binary (an image, PDF, or archive), Requestly already hands you the body as Base64. Check [`rq.response.bodyEncoding`](/api-client/rq-api-reference/rq-response) to tell binary from text before decoding:
```javascript theme={null}
const { Buffer } = require('buffer');
if (rq.response.bodyEncoding === 'base64') {
const bytes = Buffer.from(rq.response.body, 'base64');
rq.test("Response is a non-empty binary payload", () => {
rq.expect(bytes.length).to.be.above(0);
});
}
```
### Signing and hashing with `crypto`
For HMAC signatures, hashes, or AES, Node's `crypto` module is available via `require('crypto')`:
```javascript theme={null}
const crypto = require('crypto');
const body = JSON.stringify({ amount: 100, currency: "USD" });
const signature = crypto
.createHmac('sha256', rq.environment.get("api_secret"))
.update(body)
.digest('hex');
rq.variables.set("body", body);
rq.variables.set("signature", signature);
```
Reference `{{body}}` in the request body and `{{signature}}` in a header such as `X-Signature`. See [Import packages into your scripts](/api-client/import-packages-into-your-scripts) for the full list of built-in packages available to `require()`, including `crypto`, `buffer`, `uuid`, `lodash`, `moment`, `chai`, `ajv`, `cheerio`, `xml2js`, and `csv-parse`.
***
## Code Snippets
The script editor includes a built-in snippets library with ready-to-use patterns for tests, variable operations, and logging. Click **Snippets** in the editor toolbar to browse and insert them.
[View all available snippets →](/api-client/script-snippets)
# Authorization
Source: https://docs.requestly.com/api-client/send-api-request/authorization
Learn how to set up and use various API Authorization methods in Requestly, including API Key, Bearer Token, Basic Auth, OAuth 1.0, and OAuth 2.0, for secure API interactions.
Requestly allows you to send authorization data along with your API requests. Authorization data confirms that the sender has permission to access the API.
Authorization details can be configured in the Authorization tab at either the **collection level** or the **request level**. When authentication is set at the collection level, it applies to all APIs within that collection unless a specific request defines its own authorization settings or selects **NO-AUTH.** Requestly automatically inserts the appropriate authorization information into the necessary sections of the request based on the chosen authentication type.
**OAuth availability:** OAuth 1.0 and OAuth 2.0 are available in the desktop app and are rolling out gradually. If they do not appear in the auth-type dropdown, update to the latest version. The other auth types listed below are unaffected.
Beyond the types below, Requestly also supports **Digest**, **JWT Bearer**, **NTLM**, **Hawk**, and **AWS Signature v4** from the same Auth Type dropdown. Some of these are rolling out gradually in the desktop app.
## Steps to Add Authorization
Click on any request or collection to begin setting up authorization.
1. Go to the **Authorization** tab.
2. Choose the appropriate authorization type from the dropdown menu.
Each authorization type has specific fields that must be filled. Below are the details for each type:
#### No Auth
Requestly won’t send authorization details with a request unless you specify an auth type. If your request doesn’t require authorization, leave the type unset (the dropdown shows "Authorization type" as a placeholder), or use **Clear** to remove a type you set earlier.
#### Inherit Auth from Parent
Requestly uses the auth applied at the parent level. The inherited properties are populated when the request is sent. This works for API requests and sub-collections.
#### API Key
Requestly allows you to send key-value pairs along with the request data. These can be added to either Headers or Query Params. Select "API Key" from the Auth Type list, then enter your key name and value. Choose "Header" or "Query Params" from the "Add to" dropdown list for their inclusion. Variable storage enhances security.
#### Bearer Tokens
Bearer tokens enable requests to authenticate using an access key such as a JSON Web Token (JWT). Tokens are included in the request header. Select "Bearer Token" from the Auth Type dropdown and enter the token value. For additional security, store the token in a variable and reference it by name.
Requestly appends the token value to the text "Bearer" in the required format in the Authorization header.
#### Basic Auth
Basic authentication involves sending a verified username and password with your request. Select "Basic Auth" from the Auth Type dropdown. Enter your API username and password in the respective fields. For extra security, store these in variables.
In the request headers, the Authorization header passes the API a Base64 encoded string representing the username and password, appended to the text "Basic."
#### OAuth 1.0
Sign requests using OAuth 1.0 with HMAC, RSA, or Plaintext signature methods. Pick **OAuth 1.0** from the Auth Type dropdown and fill in the consumer key, consumer secret, access token, and token secret. Requestly generates the nonce, timestamp, and signature on every send.
See the [OAuth 1.0 page](/api-client/send-api-request/authorization/oauth1) for the full field reference and signature method options.
#### OAuth 2.0
Use OAuth 2.0 for modern token-based flows. Pick **OAuth 2.0** from the Auth Type dropdown, then choose a grant type (Authorization Code, Authorization Code with PKCE, Client Credentials, Implicit, Password Credentials, or Manual). Requestly runs the flow, caches the access token, and refreshes it before it expires.
See the [OAuth 2.0 page](/api-client/send-api-request/authorization/oauth2) for each grant type, callback modes, and token lifecycle details.
Click "Send" to ensure that the authorization data is sent along with the API request.
## Variable Support and Export
Requestly supports the use of variables in Authorization Values, allowing flexibility and reuse across multiple requests or collections. Variables can store sensitive data securely and simplify updates when values change. For instance, you can define API tokens or credentials as variables and reference them in authorization fields.
While authorization data can be exported alongside requests or collections, note that variable values themselves are not exported. This ensures the security of sensitive data and prevents accidental sharing of confidential information. Users need to define variable values locally when importing shared requests or collections.
## What's Next?
Store and manage auth tokens securely with variables
Learn how authorization headers are added to requests
Apply authorization to multiple requests at once
# OAuth 1.0
Source: https://docs.requestly.com/api-client/send-api-request/authorization/oauth1
Sign API requests with OAuth 1.0 using HMAC, RSA, or Plaintext signature methods.
OAuth 1.0 is a signature-based authorization scheme. Each request is signed with credentials you hold (a consumer key and access token, plus secrets) using a signature method you pick. The signature, signing parameters, and your credentials are sent in the `Authorization` header or in the request body.
Use OAuth 1.0 when an API explicitly requires it (Twitter API v1.1, older Atlassian and Yahoo APIs, parts of Magento, and various RFC 5849 implementations). Most modern APIs use OAuth 2.0 instead.
**Availability:** OAuth authorization is available in the Requestly desktop app and is rolling out gradually. If **OAuth 1.0** does not appear in the auth-type dropdown, update to the latest version.
## Choose OAuth 1.0 as the auth type
Open any request or collection, then go to the **Authorization** tab.
Pick **OAuth 1.0** from the **Authorization type** dropdown. The OAuth 1.0 fields appear below the dropdown.
See the field reference below.
Click **Send**. Requestly computes the signature and attaches it to the request automatically.
## Field reference
### Credentials
| Field | Purpose |
| ------------------- | ------------------------------------------------------------------------------------------------------- |
| **Consumer Key** | Public identifier the provider issued for your application. |
| **Consumer Secret** | Shared secret paired with the consumer key. Used to sign the request. |
| **Access Token** | Token that represents the resource owner's grant to your application. |
| **Token Secret** | Shared secret paired with the access token. Used together with the consumer secret to sign the request. |
All four fields accept Requestly [variables](../../environments-and-variables) and [vault](../../vault/vault) references. Reference secrets by name (for example `{{vault:twitter_consumer_secret}}`) rather than pasting them inline.
### Signature Method
Pick the algorithm used to sign the request. Requestly supports seven methods:
| Method | What it uses |
| --------------- | ------------------------------------------------------------------------------ |
| **HMAC-SHA1** | HMAC keyed by your consumer and token secrets. Most widely supported. |
| **HMAC-SHA256** | HMAC variant using SHA-256. Stronger than SHA-1; supported by newer providers. |
| **HMAC-SHA512** | HMAC variant using SHA-512. |
| **PLAINTEXT** | Sends the secrets directly, with no signing. Only safe over HTTPS. |
| **RSA-SHA1** | RSA signature using your private key and SHA-1 digest. |
| **RSA-SHA256** | RSA signature with SHA-256 digest. |
| **RSA-SHA512** | RSA signature with SHA-512 digest. |
When you pick an `RSA-*` method, an **RSA Private Key** field appears. Paste the PEM-encoded private key (the block that starts with `-----BEGIN RSA PRIVATE KEY-----` or `-----BEGIN PRIVATE KEY-----`). The consumer secret and token secret fields are still used to populate the standard OAuth parameters, but the signature itself is computed from the RSA key.
### Realm
Optional. If the provider expects a `realm` parameter inside the `Authorization` header (RFC 5849 §3.5.1), set it here. Leave blank when the provider does not require it.
### Add params to
Where to put the OAuth parameters. Two choices:
* **Header** (default): Requestly sends them in the `Authorization` header as `OAuth oauth_consumer_key="…", oauth_token="…", …`.
* **Body**: Requestly sends them as `application/x-www-form-urlencoded` fields in the request body. Only valid when the request has a form body and uses a method that carries one (`POST`, `PUT`, `PATCH`).
Header is correct for the vast majority of providers. Use **Body** only if the API documentation specifies it.
### Include body hash
When on, Requestly adds the `oauth_body_hash` extension parameter (OAuth Request Body Hash spec) to the signature for requests whose body is not `application/x-www-form-urlencoded`. Some providers (notably parts of the Yahoo and Google legacy APIs) require this; most do not.
### Add empty parameters
When on, query parameters and form fields that have a name but an empty value are included in the signature base string. Some providers require empty parameters to be signed; the default is off because most do not.
### Encode OAuth params in header
When on, the `oauth_*` values inside the `Authorization` header are percent-encoded a second time. This matches a stricter reading of RFC 5849 §3.5.1 that some providers enforce. If signature verification keeps failing for no obvious reason, try toggling this.
## What Requestly does for you automatically
You do **not** need to fill in these OAuth parameters manually:
* `oauth_nonce` (a fresh random nonce per request)
* `oauth_timestamp` (current Unix time)
* `oauth_signature_method` (driven by the Signature Method dropdown)
* `oauth_version` (always `1.0`)
* `oauth_signature` (computed from the signature base string and your secrets / private key)
Requestly generates all five on every send, so the same configuration produces a fresh, valid signature each time.
## Troubleshooting
Recompute the signature manually using the provider's debugger (most large providers have one) and compare against Requestly's signature base string. The most common causes:
* A required parameter is missing from the request (the API expects it, the signature base string excludes it).
* The clock on your machine is skewed by more than a few minutes - some providers reject stale timestamps.
* **Encode OAuth params in header** does not match the provider's expectation. Try toggling it.
Check that **Consumer Secret** and **Token Secret** have not been accidentally URL-encoded before you pasted them in. Requestly performs the OAuth encoding itself; double-encoding produces an invalid signature.
Confirm the key is PEM-encoded (begins with `-----BEGIN`). Encrypted PEM keys with a passphrase are not supported - decrypt the key first, or generate an unencrypted copy for use here.
## What's Next?
Set up grant-type-driven OAuth 2.0 flows.
Store OAuth secrets securely outside your collection.
Reference OAuth credentials by name across requests.
# OAuth 2.0
Source: https://docs.requestly.com/api-client/send-api-request/authorization/oauth2
Acquire and attach OAuth 2.0 tokens across all six standard grant types, with built-in token caching and refresh.
OAuth 2.0 is the dominant authorization framework for modern APIs. Requestly handles the entire flow: it opens the provider's consent screen when needed, exchanges the response for an access token, caches the token, refreshes it before it expires, and attaches it to every request.
You pick a **grant type** that matches how the API issues tokens; Requestly shows the right fields for the grant you choose.
**Availability:** OAuth authorization is available in the Requestly desktop app and is rolling out gradually. If **OAuth 2.0** does not appear in the auth-type dropdown, update to the latest version.
## Choose OAuth 2.0 as the auth type
Open any request or collection, then go to the **Authorization** tab.
Pick **OAuth 2.0** from the **Authorization type** dropdown.
Use the **Grant type** dropdown at the top of the OAuth 2.0 form. Requestly swaps the field set to match. See [Grant types](#grant-types) below for which to pick.
The **Get token** button at the bottom of the form is enabled once all required fields are filled. Requestly runs the flow (opening the browser for grants that need user consent), stores the resulting token, and shows its status.
Click **Send**. Requestly attaches the cached token as `Authorization: Bearer ` (the prefix is configurable - see [Token settings](#token-settings) below).
## Grant types
Pick the grant that matches how the API issues tokens. If you are unsure, the provider's documentation will tell you.
| Grant type | When to use |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Authorization code** | Server-to-server apps where the API has a confidential client secret. Most common for first-party integrations. |
| **Authorization code (PKCE)** | Public clients (mobile, SPA, CLI) where you cannot keep a client secret. Adds a code challenge for binding the auth request to the token exchange. |
| **Client credentials** | Service-to-service calls with no user involved. Authenticates the application itself. |
| **Implicit** | Legacy browser-only flow. New integrations should use PKCE instead. Still required by a handful of older providers. |
| **Password credentials** | Resource owner password grant. Only use with first-party apps where you control both ends and only when no other grant fits. |
| **Manual token** | Paste an access token you obtained elsewhere. Useful for one-off testing or when the provider does not implement any standard grant. |
### Authorization code
The standard three-legged flow. Requestly opens the provider's authorization page, the user signs in and consents, the provider redirects back with a code, and Requestly exchanges the code for a token at the token endpoint.
| Field | Required | Purpose |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| **Auth URL** | Yes | Provider's authorization endpoint, e.g. `https://provider.example.com/oauth/authorize`. |
| **Token URL** | Yes | Provider's token endpoint, e.g. `https://provider.example.com/oauth/token`. |
| **Callback URL** | Yes | Redirect URI registered with the provider. See [Callback mode](#callback-mode-hosted-vs-embedded) below. |
| **Client ID** | Yes | OAuth client identifier issued by the provider. |
| **Client Secret** | Yes | OAuth client secret. Store in the [vault](../../vault/vault) rather than pasting it inline. |
| **Scope** | Optional | Space-separated scopes you are requesting, for example `read:user write:user`. |
| **State** | Optional | CSRF nonce. Requestly verifies it on the callback when set. |
### Authorization code (PKCE)
Same as Authorization code, plus a code-challenge / code-verifier pair. Requestly generates and tracks both for you.
Additional field:
| Field | Required | Purpose |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Challenge method** | Yes | `SHA-256` (recommended) or `Plain`. SHA-256 is what RFC 7636 mandates for confidentiality; `Plain` exists only for legacy providers. |
The **Client Secret** field is optional for PKCE - public clients omit it.
### Client credentials
Two-legged flow. No user, no browser.
| Field | Required | Purpose |
| ----------------- | -------- | -------------------------- |
| **Token URL** | Yes | Provider's token endpoint. |
| **Client ID** | Yes | OAuth client identifier. |
| **Client Secret** | Yes | OAuth client secret. |
| **Scope** | Optional | Space-separated scopes. |
### Implicit
The provider returns the token directly in the redirect URL fragment. Avoid in new integrations.
| Field | Required | Purpose |
| ---------------- | -------- | ------------------------------------------ |
| **Auth URL** | Yes | Provider's authorization endpoint. |
| **Callback URL** | Yes | Redirect URI registered with the provider. |
| **Client ID** | Yes | OAuth client identifier. |
| **Scope** | Optional | Space-separated scopes. |
| **State** | Optional | CSRF nonce. |
### Password credentials
The user's username and password are exchanged directly at the token endpoint. Use only when you trust the client with the user's password.
| Field | Required | Purpose |
| ----------------- | -------- | ------------------------------------------------------------------- |
| **Token URL** | Yes | Provider's token endpoint. |
| **Client ID** | Yes | OAuth client identifier. |
| **Client Secret** | Optional | OAuth client secret, when the provider expects one. |
| **Username** | Yes | Resource owner's username. |
| **Password** | Yes | Resource owner's password. Store in the [vault](../../vault/vault). |
| **Scope** | Optional | Space-separated scopes. |
### Manual token
For when you already have an access token from somewhere else and just want Requestly to attach it. No flow, no refresh.
| Field | Required | Purpose |
| --------- | -------- | ------------------------------------------------------ |
| **Token** | Yes | The token to attach. Click **Save token** to store it. |
## Callback mode (hosted vs. embedded)
Grants that involve a browser redirect (Authorization code, Authorization code with PKCE, Implicit) expose a **Use embedded browser** toggle.
* **Hosted callback** (default): the OAuth handshake happens in your system browser, with Requestly's hosted callback URL (`https://oauth.requestly.com/callback`) catching the redirect and handing the code back to the app. The **Callback URL** field is auto-populated and read-only.
Use this when you can register `https://oauth.requestly.com/callback` (or the staging equivalent) with the provider.
* **Embedded browser**: the OAuth handshake happens inside an in-app browser window. The **Callback URL** field becomes editable - set it to any redirect URI you have already registered with the provider. The URL is never fetched; Requestly intercepts the navigation as soon as the provider redirects to it.
Use this when the provider restricts redirect URIs to URLs you control.
Some enterprise identity providers detect embedded webviews and refuse to load the consent page (commonly seen with strict conditional-access, advanced-protection, or anti-phishing policies). When that happens, switch back to **Hosted callback** and register Requestly's callback URL with the provider.
Whichever mode you pick, the redirect URI shown in the **Callback URL** field must be listed in your OAuth app's allowed redirect URIs on the provider side. Most "invalid redirect URI" errors during the consent flow come from forgetting this step. Register the URL once in the provider's developer console before clicking **Get token**.
## Token settings
These cross-grant fields appear below the grant-specific fields (everywhere except **Manual token**).
### Header prefix
The scheme Requestly puts in front of the token in the `Authorization` header. Defaults to `Bearer`, which is what almost every provider expects. Override only if the provider documents a different prefix (for example `Token` or an empty string).
### Token selection
For providers that return both an access token and an OpenID Connect ID token in the same response. Pick which one to attach to outgoing requests:
* **Access token** (default): the standard OAuth 2.0 access token.
* **ID token**: the OIDC ID token. Pick this when you are calling an endpoint that authenticates the user identity rather than authorizing API access.
### Custom auth, token, and refresh parameters
Three collapsible tables for additional parameters most providers do not need:
* **Custom auth parameters**: extra query parameters appended to the authorization URL. Use for vendor-specific extensions like `audience`, `prompt`, or `login_hint`.
* **Custom token parameters**: extra form fields appended to the token-exchange request body.
* **Custom refresh parameters**: extra form fields appended to refresh-token requests.
Each row has a name, a value, and an enable toggle. Disabled rows are kept in the configuration but skipped at send time.
## Token lifecycle
Once you click **Get token**, the panel at the bottom of the form shows the token's status. The panel updates without you having to refresh the form.
| Status | What it means |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| **No token acquired yet** | The flow has not been run yet. Click **Get token**. |
| **Acquiring token…** | The flow is running. Cancel it, or click **Restart** to start over. |
| **Bearer** badge with countdown | A valid token is cached. The countdown shows time until expiry. Click **Clear token** to invalidate it. |
| **Token expired** | The cached token's lifetime is up and there is no refresh token. Click **Get token** to start a new flow. |
| **Refreshing token…** | The cached token expired but a refresh token is available; Requestly is exchanging it for a fresh access token. |
| **Failed** with detail | The flow failed - the panel shows the headline and detail from the provider. Click **Retry** to run it again. |
Tokens are cached per authorization configuration. If you change a field that affects the token (Client ID, Auth URL, Scope, etc.), clear the existing token first to avoid stale cache hits.
### How refreshes happen
Requestly refreshes tokens **lazily, at send time**. There is no background timer that pre-refreshes before expiry. Instead:
* When you click **Send** and the cached token is still valid, Requestly attaches it as-is.
* When the cached token has expired and the provider returned a refresh token, Requestly exchanges the refresh token for a new access token before sending the request. Concurrent sends share a single refresh, so you do not end up with parallel refresh calls hitting the provider.
* When the cached token has expired and there is no refresh token, the request fails with a refresh error and the panel switches back to **Token expired**. Click **Get token** to run the grant flow again.
To force a fresh token before expiry (for example, after rotating client credentials on the provider side), click **Clear token** and then **Get token**.
The **Custom refresh parameters** table under [Token settings](#custom-auth-token-and-refresh-parameters) appends extra fields to the refresh request body when your provider needs them (some providers expect a repeated `scope` or `audience` parameter on refresh).
## Variables and the vault
All OAuth 2.0 fields accept Requestly [variables](../../environments-and-variables) and [vault](../../vault/vault) references. For long-lived credentials (client secrets, RSA keys, user passwords), store the value once in the vault and reference it by name in the form. The reference is what gets exported when you share a collection; the underlying secret stays on your machine.
## What's Next?
Sign requests with the older signature-based OAuth scheme.
Store OAuth client secrets and passwords securely.
Reference OAuth credentials by name across requests.
# Cookies
Source: https://docs.requestly.com/api-client/send-api-request/cookies
Manage cookies for your API requests in Requestly. Cookies captured from responses are stored in a shared cookie jar and automatically attached to matching outgoing requests.
Requestly keeps a built-in cookie jar that captures cookies from API responses and replays them on later requests. This mirrors how a browser handles cookies, so you can reproduce session-based flows (login, then call protected endpoints) without copying values around by hand.
The cookie jar is shared across all your projects on this device. It is stored locally and never synced to the cloud, so session tokens stay on the machine that captured them. Switching projects or environments does not switch the jar.
**Availability:** The cookie jar is a desktop-app feature and is rolling out gradually. If you don't see the **Cookies** entry in the app footer, update to the latest version.
## Open the Cookie manager
The **Cookies** button is in the application footer at the bottom of the window. Clicking it opens the **Cookie manager** modal.
The **Cookies** tab lists every cookie in the jar, grouped by host. Click a host row to expand it and see the cookies stored for that domain.
## How cookies are captured
When a response includes one or more `Set-Cookie` headers, Requestly parses each cookie and stores it in the jar. Once the cookie jar is available for your build, this capture happens automatically. The next time you send a request whose URL matches the cookie's domain and path, Requestly attaches the cookie to that request as a `Cookie` header.
Matching follows standard browser rules (RFC 6265):
* Cookies are matched on the request URL's hostname and path.
* A cookie with `Domain=.example.com` is sent to `api.example.com`, `www.example.com`, and any other subdomain.
* A cookie with no `Domain` attribute is scoped to the exact host that set it.
* Path scoping is enforced. A cookie with `Path=/api` is not sent to `/`.
If you set a `Cookie` header manually on a request, your value wins. The jar will not overwrite a header you wrote yourself.
## Add a cookie manually
You can plant cookies in the jar without sending a request first. This is useful when you want to seed a session token from another tool, or when you are testing how an endpoint behaves under a specific cookie.
In the **Cookies** tab, click the **+** button next to the search field. The tooltip reads **Add cookie (any domain)**.
To add a cookie scoped to a specific host that already appears in the list, click the **+** button on that host's row instead. The modal title shows the host so you know which domain the cookie will land on.
The modal accepts a single `Set-Cookie` header value, the same string a server would send. For example:
```
sessionId=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
```
Supported attributes: `Domain`, `Path`, `Expires`, `Max-Age`, `Secure`, `HttpOnly`, `SameSite`, `Partitioned`. Hover the help icon next to the modal title for a quick reference.
When `Domain=` is omitted, the cookie is scoped to the host shown in the modal title.
Click **Save**. The cookie appears under its host in the **Cookies** tab and will be attached to matching requests from now on.
## Edit, delete, or clear cookies
Hover any cookie row to reveal its action buttons:
* **Edit cookie** opens the same modal pre-filled with the existing `Set-Cookie` string. Change anything, then save.
* **Delete cookie** removes a single cookie immediately.
To clear cookies in bulk:
* **Clear cookies for this domain** is the trash icon on a host row. It removes every cookie under that host after a confirmation prompt.
* **Clear all cookies** is the sweep icon next to the search field. It empties the entire jar after a confirmation prompt.
Clearing cookies is local and immediate. There is no undo. If you cleared cookies you needed, the only way to recover them is to send the request that originally set them.
## Find a cookie quickly
The search input at the top of the **Cookies** tab filters the list as you type. Search matches across host, name, and path, so you can locate a single cookie even when the jar holds hundreds of entries across many domains.
## Cookie row indicators
Each cookie row shows badges and icons that summarize its attributes:
* An **Expires** date or **Session** label. Expired cookies show a red **Expired** badge but stay in the jar until you remove them.
* A **lock** icon means `Secure` is set: the cookie is only sent over HTTPS.
* A **shield** icon means `HttpOnly` is set: the cookie is hidden from scripts.
* A **SameSite** badge (`Lax`, `Strict`, or `None`) reflects the cookie's `SameSite` attribute.
## Allow scripts to read cookies
Pre and post-request scripts can read and write cookies, but only for domains you have explicitly allowed. This keeps a third-party request you import from accidentally exfiltrating cookies for an unrelated host.
In the **Cookie manager**, switch to the **Domains allowlist** tab.
Type a host (for example `api.example.com`) into the input and click **Add**. The host appears in the list below.
Hover a host in the list and click **Revoke** to remove it from the allowlist. Scripts can no longer access cookies for that host until you add it back.
The allowlist only governs script access to the jar. Cookies are still captured from responses and attached to requests automatically regardless of whether their host is allowlisted.
## What's Next?
Configure auth alongside cookies for full session reproduction
Override jar-attached cookies with a manual `Cookie` header
Read and write cookies from pre and post-request scripts
# Configure Request
Source: https://docs.requestly.com/api-client/send-api-request/create-requests/configure-request
Learn how to configure HTTP methods, URLs, and send API requests in Requestly.
This guide covers how to set up HTTP methods, URLs, and send requests effectively.
## HTTP Methods
Requestly supports all standard HTTP methods for API requests:
**GET** retrieves data from a server. It's the most common method for fetching resources.
**Use cases:**
* Fetch user data
* Get list of items
* Retrieve resource details
**POST** sends data to create a new resource on the server.
**Use cases:**
* Create new user
* Submit form data
* Upload content
**PUT** updates an existing resource by replacing it entirely.
**Use cases:**
* Update user profile
* Replace document
* Modify configuration
**PATCH** partially updates an existing resource.
**Use cases:**
* Update specific fields
* Modify user settings
* Change status
**DELETE** removes a resource from the server.
**Use cases:**
* Delete user account
* Remove item
* Clear cache
**HEAD** retrieves only the headers of a resource without the body. It's identical to GET but without the response body.
**Use cases:**
* Check if resource exists
* Get content length before downloading
* Verify last modified date
**OPTIONS** retrieves the communication options available for a resource or server.
**Use cases:**
* Check supported HTTP methods
* Verify CORS configuration
* Discover API capabilities
## Setting Up Your Request URL
The request URL specifies where your API request should be sent. It consists of several components:
## Naming Your Request
Give your request a clear, descriptive name to easily identify it later:
**Good naming examples:**
* `Get User Profile`
* `Create New Order`
* `Update Product Inventory`
* `Delete Customer Account`
**Avoid:**
* `Test`
* `Request 1`
* `API Call`
Use action verbs and specific resource names to make your requests self-documenting. This helps when sharing with team members or revisiting later.
## Sending Your Request
Once you've configured your request:
Click the **Save** button to preserve your request settings. This allows you to reuse it later without reconfiguring.
Press the **Send** button to execute the request. It will display the response in the panel below.
Check the response `status code`, `body`, and `headers` to verify the request was successful.
**Common status codes:**
* `200 OK` - Success
* `201 Created` - Resource created
* `400 Bad Request` - Invalid request
* `401 Unauthorized` - Authentication required
* `404 Not Found` - Resource doesn't exist
* `500 Server Error` - Server-side issue
## What's Next?
Learn how to add query params, path variables, and request body
Set up authentication and custom headers
# Generate Client Code
Source: https://docs.requestly.com/api-client/send-api-request/create-requests/generate-client-code
Export any API request as ready-to-run code in cURL, Python, JavaScript, Go, Java, C#, Swift, PHP, and 20+ other language/library combinations.
Requestly can convert any configured API request into a ready-to-paste code snippet. Use this to move from manual testing to implementation without rewriting the request from scratch.
## How to Generate Client Code
Navigate to the API request for which you want to generate code.
Click the **Get client code** button in the request editor header (next to the request actions).
A modal opens with the generated code. Use the dropdown at the top left to switch languages.
Click **Copy** in the top right corner to copy the snippet to your clipboard.
## Example Output
For a `POST https://api.example.com/users` request with a JSON body and a Bearer token, here is what the generated code looks like per language:
```bash theme={null}
curl --request POST \
--url https://api.example.com/users \
--header 'Authorization: Bearer YOUR_TOKEN' \
--header 'Content-Type: application/json' \
--data '{"name":"Jane Doe","email":"jane@example.com"}'
```
```javascript theme={null}
const response = await fetch("https://api.example.com/users", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "Jane Doe", email: "jane@example.com" })
});
const data = await response.json();
console.log(data);
```
```python theme={null}
import requests
url = "https://api.example.com/users"
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
}
payload = {"name": "Jane Doe", "email": "jane@example.com"}
response = requests.post(url, json=payload, headers=headers)
print(response.status_code, response.json())
```
```go theme={null}
package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
body := bytes.NewBufferString(`{"name":"Jane Doe","email":"jane@example.com"}`)
req, _ := http.NewRequest("POST", "https://api.example.com/users", body)
req.Header.Set("Authorization", "Bearer YOUR_TOKEN")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
fmt.Println(string(data))
}
```
```java theme={null}
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType,
"{\"name\":\"Jane Doe\",\"email\":\"jane@example.com\"}");
Request request = new Request.Builder()
.url("https://api.example.com/users")
.post(body)
.addHeader("Authorization", "Bearer YOUR_TOKEN")
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
```
```csharp theme={null}
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_TOKEN");
var content = new StringContent(
"{\"name\":\"Jane Doe\",\"email\":\"jane@example.com\"}",
System.Text.Encoding.UTF8, "application/json");
var response = await client.PostAsync("https://api.example.com/users", content);
Console.WriteLine(await response.Content.ReadAsStringAsync());
```
```swift theme={null}
var request = URLRequest(url: URL(string: "https://api.example.com/users")!)
request.httpMethod = "POST"
request.setValue("Bearer YOUR_TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = #"{"name":"Jane Doe","email":"jane@example.com"}"#.data(using: .utf8)
let (data, response) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)
```
```php theme={null}
```powershell theme={null}
$headers = @{
"Authorization" = "Bearer YOUR_TOKEN"
"Content-Type" = "application/json"
}
$body = '{"name":"Jane Doe","email":"jane@example.com"}'
Invoke-RestMethod -Method Post `
-Uri "https://api.example.com/users" `
-Headers $headers `
-Body $body
```
```ruby theme={null}
require 'net/http'
require 'json'
uri = URI('https://api.example.com/users')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer YOUR_TOKEN'
request['Content-Type'] = 'application/json'
request.body = { name: 'Jane Doe', email: 'jane@example.com' }.to_json
response = http.request(request)
puts response.code, response.body
```
## Supported Languages
| Language | Library / Variant |
| ----------- | ------------------------------------ |
| C | libcurl |
| C# | HttpClient, RestSharp |
| Clojure | clj-http |
| Go | Native |
| HTTP | Raw HTTP message |
| Java | AsyncHttp, NetHttp, OkHttp, Unirest |
| JavaScript | Axios, Fetch, jQuery, XHR |
| Kotlin | OkHttp |
| Node.js | Axios, Fetch, HTTP, Request, Unirest |
| Objective-C | NSURLSession |
| OCaml | CoHTTP |
| PHP | cURL, Guzzle, HTTP v1, HTTP v2 |
| PowerShell | Invoke-WebRequest, Invoke-RestMethod |
| Python | Requests |
| R | httr |
| Ruby | net::http |
| Shell | cURL, HTTPie, Wget |
| Swift | URLSession |
# Overview
Source: https://docs.requestly.com/api-client/send-api-request/create-requests/overview
Learn how to create and send API requests in Requestly. Test APIs, configure requests, and view responses without writing code.
Requestly allows you to easily send API requests, without the need for writing code or using a terminal. It lets you test APIs, retrieve data, and explore how they work by simply creating a request, clicking Send, and viewing the response.
This is useful for developers testing API endpoints during development, QA engineers validating API responses for edge cases, and support engineers debugging API issues in real-time.
## Quick Start
Follow these steps to send your first API request:
Open **Requestly Desktop App**, then click the `+ New` button to create a new request and select **Request** from the menu.
Choose a descriptive title for your request to make it easy to identify later.
Pick the HTTP method (e.g., `GET`, `POST`) and type the URL of the API you want to test.
Click the **Save** & **Send** button to execute your request.
## Understanding the Response
Once you send a request, you'll see the response displayed in the bottom panel with the following information:
### View the Response Body
Check the response body in the **Response Body** section. You can switch between formatted (pretty) and raw views.
Requestly renders the response based on its content type:
* **Text and structured data** (JSON, XML, HTML, plain text) shows in the editor. JSON and XML are pretty-printed in Preview, and the **Raw** toggle shows the response exactly as it came off the wire. For JSON, you can also [filter the response](/api-client/send-api-request/filter-json-response) to just the values you need using a JSONPath expression.
* **Images** (PNG, JPEG, WebP, GIF, SVG) render as the actual picture in Preview. Switch to **Raw** to see the underlying transported text.
* **Other binary content** (PDF, ZIP, audio, video, fonts, and similar) shows a **Binary response** placeholder with the response size, rather than unreadable characters. Switch to **Raw** to view the Base64-encoded body.
The **Size** shown for the response reflects the true byte count of the body, so it stays accurate for images and other binary responses.
### Download the Response Body
To save a response to a file, click the **Download** button in the response pane header, next to **Save as example**.
Download works for both text and binary responses. Binary content (images, PDFs, fonts, and similar) is saved byte-for-byte, so the file you get is identical to what the server sent - the same response shown in the [preview above](#view-the-response-body).
### Check the Response Headers
Review the headers sent back by the server in the **Headers** tab.
## Next Steps
Now that you understand the basics, explore these guides to master API request creation:
Set up HTTP methods, URLs, and send your first request
Add query parameters, path variables, and request body data
Configure headers for authentication and content types
# Parameters and Body Data
Source: https://docs.requestly.com/api-client/send-api-request/create-requests/parameters-and-body
Learn how to add query parameters, path variables, and request body data to your API requests in Requestly.
Parameters and request bodies allow you to send data with your API requests. This guide covers query parameters, path variables, and different request body formats.
## Path Variables
Path variables allow you to define dynamic segments in your API URL using the **:variableName** syntax. This is useful for RESTful APIs where resource identifiers are part of the URL path.
For example, if your API endpoint is:
```
https://api.example.com/users/:userId/posts/:postId
```
Requestly automatically detects the path variables (`:userId` and `:postId`) from the URL and displays them in the **Params** tab under **Path Variables**. You can then set values for each variable:
| Key | Value | Description |
| ------ | ----- | ---------------------------- |
| userId | 123 | The user's unique identifier |
| postId | 456 | The post's unique identifier |
When you send the request, Requestly compiles the URL with your provided values:
```
https://api.example.com/users/123/posts/456
```
Path variables are automatically extracted from your URL. Simply type a URL with `:variableName` segments, and they'll appear in the Path Variables table for you to fill in.
## Query Parameters
In the **Query Params** section, you can add query parameters as **key-value pairs** to send extra information with the URL. To add more parameters, click on the `+ Add More` button.
Each query parameter consists of:
* **Key**: The parameter name
* **Value**: The parameter value
* **Type**: An enum to enforce the value type
* **Description** (optional): Internal documentation explaining the purpose of the parameter
For example:
* Adding `uid=123` to `https://app.requestly.io/echo` results in: `https://app.requestly.io/echo?uid=123`
The checkboxes next to each parameter let you include or exclude them without deleting them. For instance, if you uncheck a parameter, the final URL will not include it.
### Bulk Edit Query Parameters
You can also manage query parameters using **Bulk Edit**. This allows you to add or update multiple parameters at once in a key:value format.
* Add one parameter per line
* Separate keys and values using a colon `:`
* Prefix any line with `//` to disable that parameter
Bulk Edit is useful when working with a large number of query parameters or when making quick mass updates.
**Example:**
```
page:1
limit:50
sort:desc
// filter:active
```
## Request Body
For POST, PUT, or PATCH requests, use the **Body** tab to send data to the server. Requestly supports multiple body formats to accommodate different API requirements.
### Supported Body Types
Send raw data as plain **text** or structured **JSON**.
**When to use:**
* Sending JSON data to REST APIs
* Posting XML or plain text
* Sending custom formatted data
You can select the language format:
* **JSON** – for structured data like API payloads
* **Text** – for plain string or unstructured data
* **XML** – for XML-based APIs
* **HTML** – for HTML content
* **JavaScript**: for JavaScript payloads
**Example JSON:**
```json theme={null}
{
"name": "John Doe",
"email": "john@example.com",
"age": 30,
"active": true
}
```
Sends data as URL-encoded key-value pairs. This format is commonly used for HTML form submissions.
**When to use:**
* Traditional web form submissions
* Simple key-value data
* APIs that expect form data
Each field consists of:
* **Key**: Field name
* **Value**: Field value
* **Description**: Optional documentation
**Example:**
```
username=johndoe
password=secret123
remember=true
```
Used when uploading files along with form fields. Each field is sent as a separate part of the request body.
**When to use:**
* Uploading images, documents, or files
* Sending files with metadata
* Form submissions with file attachments
Each field can be either:
* **Text field**: Regular key-value pair
* **File field**: File upload with browse button
**Example use case:** Uploading a user profile picture with name and bio
For GraphQL APIs, use the dedicated GraphQL request type which provides:
* Query/Mutation editor with syntax highlighting
* Variables panel
* Schema introspection
Learn more in our [GraphQL Request guide](/api-client/graphql-request).
## Autogenerated Headers
Requestly will automatically add certain headers to your requests based on your request body selections. When you add a request body, Requestly automatically sets the appropriate `Content-Type` header:
| Body Type | Content-Type Header |
| --------------------- | ----------------------------------- |
| RAW (JSON) | `application/json` |
| RAW (Text) | `text/plain` |
| RAW (XML) | `application/xml` |
| RAW (HTML) | `text/html` |
| RAW (JavaScript) | `application/javascript` |
| x-www-form-urlencoded | `application/x-www-form-urlencoded` |
| multipart/form-data | `multipart/form-data` |
You can view and override the autogenerated headers in the Headers tab. These headers are automatically managed by Requestly to ensure your requests are properly formatted.
## What's Next?
Add authentication and custom headers to your requests
Set up API authentication methods
Make your requests dynamic with variables
# Request Headers
Source: https://docs.requestly.com/api-client/send-api-request/create-requests/request-headers
Learn how to configure HTTP headers for authentication, content types, and custom metadata in your API requests.
HTTP headers are key-value pairs that provide additional information about your request. They're essential for authentication, specifying content types, and sending custom metadata to the API.
## Understanding Headers
Headers serve multiple purposes in HTTP requests:
Pass tokens, API keys, or credentials to authenticate with the API
Tell the server what format your data is in (JSON, XML, etc.)
Specify what response format you expect from the server
Send additional information like user agent, tracking IDs, or custom flags
***
## Adding Headers
The **Headers** tab allows you to add Request Headers in your API request.
Each header consists of:
* **Key**: The header name (e.g., `Authorization`, `Content-Type`)
* **Value**: The header value
* **Description** (optional): Internal documentation to explain the purpose of this header
The checkboxes next to each header let you include or exclude them without deleting them. This is useful for testing with and without certain headers.
### Bulk Edit Headers
You can also manage headers using **Bulk Edit**. This allows you to add or update multiple headers at once in a `key:value` format.
**How to use:**
1. Click the **Bulk Edit** button in the Headers tab
2. Add one header per line
3. Separate keys and values using a colon `:`
4. Prefix any line with `//` to disable that header
**Example:**
```
Content-Type:application/json
Authorization:Bearer {{token}}
X-API-Version:v2
// X-Debug:true
```
Bulk Edit is especially useful when copying headers from documentation or sharing with team members.
## Using Variables in Headers
You can use variables in header values to make them dynamic:
```
Key: Authorization
Value: Bearer {{authToken}}
```
Learn more about using variables in [Variables and Environments](/api-client/environments-and-variables).
## Header Inheritance
Headers can be inherited from collections, making it easy to apply common headers across multiple requests:
**Collection-Level Headers** → **Request-Level Headers** → **Authorization Tab**
* **Collection-Level Headers**: Set headers at the collection level to apply them to all requests in that collection.
* **Request-Level Headers**: Override collection-level headers with the same key. Request-level headers have the highest priority.
* **Authorization Tab**: Headers set in the Authorization tab are applied in addition to manual headers and do not override them.
Headers are resolved from most-specific to least-specific. Request-level headers always win over collection-level headers when both define the same key.
## What's Next?
Use the Authorization tab for easier authentication setup
Dynamically generate headers with pre-request scripts
Learn how to use variables in headers
# Filter a JSON Response
Source: https://docs.requestly.com/api-client/send-api-request/filter-json-response
Narrow a JSON response in Requestly to just the values you care about using a JSONPath expression in the Preview view.
When an endpoint returns a large JSON response, scrolling to the few fields you actually care about is slow. The **Preview** view of the response body lets you type a JSONPath expression and narrow the displayed JSON to only the matching values, the same way Postman does.
## Open the filter bar
The filter is available in the **Preview** view when the response is JSON.
Send any request whose response is JSON. The body opens in the **Preview** view, formatted and syntax-highlighted.
In the response body toolbar, click the funnel icon on the right. A full-width filter bar appears below the toolbar.
Enter an expression such as `$.store.book[*].author`. The displayed JSON narrows to the matched values as you type.
## Write the expression
The filter uses standard JSONPath. A few common patterns:
| Expression | Selects |
| -------------------------- | ----------------------------------------------- |
| `$.store.book[*].author` | The `author` of every book under `store.book` |
| `$.items[?(@.price < 10)]` | Every item in `items` whose `price` is below 10 |
| `$.headers` | The whole `headers` object |
| `$.results[0]` | The first element of the `results` array |
# GraphQL Request
Source: https://docs.requestly.com/api-client/send-api-request/graphql-request
Requestly supports GraphQL requests, allowing you to send queries, mutations, and define variables
GraphQL requests work over HTTP just like REST, but instead of defining multiple endpoints, you typically interact with a **single endpoint** (e.g., `/graphql`) and specify the exact data you want. This gives you flexibility, reduces over-fetching, and makes debugging APIs much simpler.
## Create your first GraphQL request
Open **Requestly Desktop App**, then click the `+ New` button to create a new request and select **GraphQL request** from the menu.
Give a descriptive title for your request to make it easy to identify later
Add your GraphQL endpoint.
It will automatically perform **schema introspection** so you can explore available queries, mutations, and types.
Under the **Query** tab, you’ll see three panels:
* **Query/Mutation editor**: where you write or generate queries.
* **Variables editor**: where you define variables in JSON format.
* **Schema**: where you explore your API’s schema (Queries, Mutations, Subscriptions).
In the schema explorer, select a field and expand its arguments. A query will automatically appear in the **Query editor**.\
Alternatively, you can write your query manually
In the **Variables editor**, provide values in JSON format.
Click **Send** to execute your query and view the response.
### Create a GraphQL request with multiple queries
Open **Requestly Desktop App**, then click the `+ New` button to create a new request and select **GraphQL request** from the menu.
From the schema explorer, select more than one field. Both queries will appear in the **Query editor**. Alternatively, you can manually add a new query / mutation.
Only one query runs at a time. First, click the **Send** button, then select the query you want to run from the dropdown.
To execute another query, click the Send button again and select the other query from the dropdown.
## What's Next?
Secure your GraphQL requests with API keys, tokens, or OAuth flows
Make your GraphQL queries dynamic with environment variables
Group related GraphQL requests together
# gRPC Request
Source: https://docs.requestly.com/api-client/send-api-request/grpc-request
Learn how to create and invoke gRPC requests in Requestly using server reflection or a proto file, with support for unary and streaming methods.
gRPC is a high-performance RPC framework that uses Protocol Buffers to define services and messages. Instead of hitting REST-style URLs, you connect to a gRPC server, pick a service method, and invoke it with a structured message. Requestly discovers your services automatically through server reflection or from a `.proto` file, and supports unary as well as all three streaming method types.
**Availability:** gRPC is a desktop-app feature and is rolling out gradually. If you don't see **gRPC request** in the `+ New` menu, update to the latest version.
## Create your first gRPC request
Open the **Requestly Desktop App**, click the `+ New` button, and select **gRPC request** from the menu.
Give your request a clear, descriptive name so it's easy to identify later.
In the address bar, enter your gRPC server address in `host:port` format, for example `localhost:50051`.
As soon as you enter a reachable address, Requestly performs **server reflection** to discover the services and methods the server exposes. No extra setup is required if your server has reflection enabled.
Open the **Select method** dropdown and choose the service method you want to call. Each method shows an icon indicating its type:
* **Unary**: a single request, a single response.
* **Server streaming**: a single request, a stream of responses.
* **Client streaming**: a stream of requests, a single response.
* **Bidirectional**: streams of requests and responses at the same time.
Go to the **Message** tab and enter your request message as JSON. To start from a ready-made template, click **Generate example message** (see below).
Click **Invoke** to call the method. The response panel opens with the received messages, response metadata, and trailers.
## Generate an example message
Writing a request message by hand means knowing every field, its type, and its nesting. The **Generate example message** button, at the bottom of the **Message** tab, does this for you. It reads the selected method's input message definition and writes a complete, correctly shaped JSON skeleton into the editor, so you only have to replace the placeholder values.
The generated message includes every field in the request type, with a placeholder value chosen to match each field's type:
* **Strings** get a sample word, **numbers** get a small sample number, and **booleans** get `true` or `false`.
* **Nested messages** are expanded into nested objects, and **repeated fields** become single-element arrays so you can see the shape.
* **Enums** use one of the defined values, and well-known types are filled with valid examples (for instance, a `google.protobuf.Timestamp` becomes an ISO date such as `2024-01-01T00:00:00Z`).
Generating an example replaces the current contents of the Message editor. Generate first, then edit the values.
## Discover services with a proto file
If your server does not support reflection, or you want to work against a local contract, you can load services from a `.proto` file instead.
Open the schema source control next to the address bar and switch from **Server reflection** to **Proto file**.
Click **Choose .proto file** and select the file on disk. Requestly parses it and lists the discovered services and methods in the **Select method** dropdown.
If your `.proto` file imports other definitions, use **Add import path** to point Requestly at the directories that contain them. Well-known types such as `google.protobuf` are resolved automatically.
## Add metadata
gRPC metadata works like request headers. Open the **Metadata** tab and add key/value pairs. You can enable or disable individual entries with the checkbox, and use `{{variables}}` for dynamic values.
## Handle streaming methods
For server-streaming, client-streaming, and bidirectional methods, the call stays open after you invoke it instead of returning a single response. While a stream is active you have three controls:
* **Invoke** starts the call. Once connected, the address bar's button changes to **Cancel**, which closes the connection immediately in both directions.
* **Send** pushes the message currently in the editor onto the stream without closing it. Available on client-streaming and bidirectional methods, where the client can send more than one message.
* **End streaming** closes the request (client) side of the stream while leaving it open for the server to finish responding. Available on client-streaming and bidirectional methods.
The response panel lists every message in order. Each row shows a direction indicator (an up arrow for messages you sent, a down arrow for messages the server sent back), a sequence number, the timestamp, and a preview you can expand to the full JSON body. Filter by **Sent** or **Received**, or search across all messages.
### Bidirectional streaming
A bidirectional method keeps both sides open at once: you can keep sending messages while the server keeps responding. Invoke the method to open the stream, use **Send** to push each new message, watch responses arrive in the panel, and click **End streaming** when you are done sending.
## Read the response
The response panel shows:
* **Responses**: each message sent and received, with timestamps and an expandable JSON body. Filter by direction or search across messages.
* **Metadata**: the response headers returned by the server.
* **Trailers**: the trailing metadata, including the final gRPC status code and message (for example, `0 OK` or `12 UNIMPLEMENTED`).
The panel header shows the status code, the response time, and the number of messages exchanged.
## Get client code
Click **Get client code** to generate a ready-to-use code snippet for the current request in several languages.
## What's Next?
Secure your gRPC requests with API keys, tokens, or OAuth flows
Make your gRPC messages and metadata dynamic with variables
Group related gRPC requests together
# API Call History
Source: https://docs.requestly.com/api-client/send-api-request/replay-request-from-history
Track and manage API requests with a clear, editable history view in the API Client.
The API Call History feature allows users to track and manage all requests triggered from the API Client. The most recent request is displayed at the top of the history panel, providing a clear chronological view of interactions.
History is stored locally and is not synced to the cloud.
### Viewing API Call History
All API calls made from the client are listed in the left sidebar. Each entry can be clicked to load the request details back into the API Client. This enables users to quickly replay a request after editing some fields.
By default, cached responses are session-only: if you refresh the page, response data is cleared and requests must be re-sent to see their responses again. To keep responses across refreshes, enable **Save responses** from the history menu.
Additionally, the response for any request made during the current session is cached and can be revisited without making a new call, provided the page has not been refreshed.
### Clearing History
Open the history menu and select **Clear all history**. This will permanently remove all recorded requests.
## What's Next?
Permanently save frequently used requests in collections
Make requests reusable across different environments
Configure authentication for your API requests
# SOAP Requests
Source: https://docs.requestly.com/api-client/send-api-request/send-soap
Learn how to create and send SOAP requests in Requestly using XML bodies, endpoints, and variables.
SOAP (Simple Object Access Protocol) is a protocol for exchanging structured information using XML. Unlike REST, SOAP requests require a strict envelope structure and often rely on predefined contracts (WSDL).
You can also import SOAP requests directly using the WSDL. See the [import guide](/api-client/import-export/import-from-wsdl) to get started.
## Create your first SOAP request
Open **Requestly Desktop App**, then click the `+ New` button to create a new request. Select a standard **HTTP request** since SOAP works over HTTP.
Give your request a clear and descriptive name so it’s easy to identify later.
Add your SOAP service endpoint URL and set the method to **POST**:
```http theme={null}
http://www.dneonline.com/calculator.asmx
```
Go to the **Body** tab, select **raw**, and choose **XML** format. Paste your SOAP request body:
```xml theme={null}
{{intA}}
{{intB}}
```
Your request must include the required SOAP structure such as **Envelope** and **Body**, along with proper namespaces.
Click **Send** to execute the request and view the response.
## What's Next?
Secure your SOAP requests with API keys, tokens, or OAuth flows
Make your SOAP requests dynamic with variables
Group related SOAP requests together
# SSL Certificates
Source: https://docs.requestly.com/api-client/send-api-request/ssl-certificates
Add custom CA certificates and per-host client certificates to authenticate against internal or mTLS-protected APIs in the Requestly desktop app.
Many internal APIs use a private certificate authority (CA) instead of a public one, or require a client certificate to prove the caller's identity (mutual TLS / mTLS). Requestly lets you add both kinds of certificate from App Settings so every request to the right host automatically picks them up, with no changes needed to individual requests or collections.
Certificates stay on this device. They are not synced to the Requestly cloud, so each device must add its own copy.
These settings apply across every request type the API client sends: REST/HTTP, GraphQL queries and mutations, and GraphQL subscriptions over WebSocket (`wss://`). The same CA trust set and client-certificate matching rules apply uniformly.
## Prerequisites
* Requestly desktop app version 2605.12.2 or later.
* For CA certificates: a PEM-encoded CA certificate file (`.pem` or `.crt`).
* For client certificates: either a PEM pair (certificate file `.crt` / `.pem` + private key file `.key`) or a PFX bundle (`.pfx` / `.p12`). Optional passphrase if the key or bundle is encrypted.
**Availability:** SSL certificates are a desktop-app feature and are rolling out gradually. If you don't see the **Certificates** section in App settings, update to the latest version.
## Open the Certificates settings
Click the **Settings** icon in the application footer, or navigate to **App Settings** from the menu.
Scroll to the **Certificates** section. It contains two panels: **CA Certificate** and **Client Certificates**.
## CA certificates
A CA certificate tells Requestly to trust servers whose certificate chain is signed by that CA. Use it when your internal API returns a certificate signed by your company's own CA and requests fail with an SSL error.
Requestly merges your uploaded CA with the system and Node built-in trust roots, so public HTTPS sites continue to work normally. You do not need to replace the default trust set.
### Add a CA certificate
In the **CA Certificate** section, click **Add CA Certificate**. An OS file picker opens.
Choose your PEM-encoded CA certificate file (`.pem` or `.crt`). The certificate appears in the list and is enabled by default.
Only one CA certificate is supported at a time. The **Add CA Certificate** button stays disabled while a certificate is already listed, so delete the existing one before switching to a different CA.
### Enable or disable a CA certificate
Each CA certificate row has an **Enabled** toggle. Turn it off to stop trusting that CA without deleting the certificate.
Toggle the CA off to quickly check whether it is the cause of a trust error, without losing your reference to the certificate file.
### Delete a CA certificate
Click the delete icon on the row. A confirmation dialog explains that the cert file on disk is not deleted, only the reference inside Requestly is removed.
## Client certificates
A client certificate lets Requestly prove the caller's identity during a TLS handshake. The certificate is attached only to requests whose host and port match the rule you configure.
### Add a client certificate
In the **Client Certificates** section, click **Add Client Certificate**.
Enter a specific hostname (`api.internal.example.com`) or a single-label wildcard (`*.example.com`) in the **Host** field.
The wildcard matches one subdomain level only: `*.example.com` matches `api.example.com` but not `a.api.example.com` and not `example.com` itself.
The default is 443. Change it if your API runs on a non-standard port.
Pick the format that matches your certificate bundle:
* **Certificate (PEM)**: select your certificate file and your private key file separately.
* **PFX**: select a single `.pfx` or `.p12` bundle that contains both.
If the key or bundle is protected by a passphrase, enter it in the **Passphrase** field. The passphrase is stored encrypted at rest on this device.
Switch to the **PFX** tab if you have a single bundle file instead:
Click **Add**. The new rule appears in the Client Certificates list.
Only one client certificate rule is allowed per host-and-port pair. If a rule already exists for the same host and port, Requestly asks you to confirm before replacing it.
### Delete a client certificate
Click the delete icon on the row. The confirmation dialog shows the host and port the rule covered. As with CA certificates, the cert files on disk are not deleted.
Client certificate rows do not have an individual enable toggle. To stop attaching a certificate to a host, delete the row.
## How certificate matching works
When you send a request, Requestly checks the request URL against your client certificate rules in this order:
1. Exact host match (case-insensitive) takes priority over wildcard matches.
2. Ports must match exactly. If the URL has no explicit port and uses `https`, port 443 is assumed.
3. The first matching rule is used. At most one client certificate is attached per request.
If no rule matches, no client certificate is sent.
CA certificates that are enabled are always merged in for every HTTPS request. Disabled CA certificates are ignored.
## TLS errors in the response panel
When a request fails because of a TLS or certificate problem, the response panel shows an **SSL Error** message describing what went wrong (for example, `SSL Error: UNABLE_TO_VERIFY_LEAF_SIGNATURE`). A **Manage certificates** button appears next to the error to jump directly to the Certificates settings.
Common errors and what they usually mean:
| Error code | Likely cause |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `UNABLE_TO_VERIFY_LEAF_SIGNATURE` | The server's certificate chain is incomplete or signed by a CA Requestly does not trust. Add the CA certificate. |
| `ERR_TLS_CERT_ALTNAME_INVALID` | The hostname in the request does not match any name on the server's certificate. Check that the URL is correct. |
| `CERT_HAS_EXPIRED` | The server's certificate has passed its expiry date. This is a server-side issue. |
| `ERR_SSL_WRONG_VERSION_NUMBER` | TLS version mismatch between Requestly and the server. |
If a cert file referenced in your settings cannot be read from disk (for example, the file was moved), the error reads `SSL Error: Certificate file not found` and includes the path. Re-add the certificate from its new location to fix it.
## Inspect TLS details after a successful request
For HTTPS requests that succeed, you can see the full handshake details in DevTools.
Click **DevTools** in the application footer.
Go to the **Network** tab and click the request whose TLS details you want to inspect.
Select the **Info** tab in the detail panel. It shows the TLS version, cipher suite, server certificate (subject, issuer, and expiry date), and, when a client certificate was sent, the matched rule (host pattern and port), the certificate subject, and the SHA-256 fingerprint.
## What's Next
Set API keys, Bearer tokens, and other auth schemes on requests or collections
Inspect TLS handshake details, headers, and script logs in one panel
# Writing Tests
Source: https://docs.requestly.com/api-client/tests
Learn to write and execute API tests in Requestly using JavaScript, including validations like status code checks and JSON body tests.
Automated API testing ensures endpoints function as expected. Requestly allows you to write tests using JavaScript with the [`rq`](/api-client/scripts#requestly-javascript-api-rq) object enabling validations, schema checks, and automated workflows.
Common testing approaches include:
* **Contract Testing**: Validate responses against JSON schemas.
* **Unit Testing**: Test individual endpoints in isolation.
* **Error Handling**: Verify API behavior for invalid inputs.
You can execute tests using either [Pre-request scripts](/api-client/scripts#pre-request-scripts) (run before a request is sent) or [Post-response scripts](/api-client/scripts#post-response-scripts) (run after a response is received).
The Pre-request and Post-response tabs provide a scripting environment that allows dynamic behavior for API requests.
* The **Scripts → Pre-request tab** enables processing before sending a request, such as setting variable values or modifying headers.
* The **Scripts → Post-response tab** runs after receiving the response and allows for test assertions, logging, and response validation. This tab includes the [Chai.js library](https://www.chaijs.com/api/bdd/), supporting behavior-driven development (BDD) syntax for test assertions.
## Scripting Environment
Requestly provides a JavaScript runtime with built-in utilities. Here’s a quick reference table for key methods:
| **Method/Interface** | **Description** |
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [`rq.test`](/api-client/rq-api-reference/rq-test) | Define a test with a name and callback for assertions. |
| [`rq.expect`](/api-client/rq-api-reference/rq-expect) | Use [Chai.js BDD ](https://www.chaijs.com/api/bdd/)style assertions to compare values. |
| [`rq.environment`](/api-client/rq-api-reference/rq-environment) | Access and manage environment variables. |
| [`rq.globals`](/api-client/rq-api-reference/rq-globals) | Access and manage global variables. |
| [`rq.response`](/api-client/rq-api-reference/rq-response) | Access response details (status, body, headers, etc.). |
| [`rq.request`](/api-client/rq-api-reference/rq-request) | Access request details (method, headers, body, URL, etc.). |
## Writing Tests
To create a test, use the following syntax:
Requestly tests use **Chai.js for assertions**. For more details and examples, visit the official ***Chai.js documentation***.
```javascript theme={null}
rq.test("Test name", () => {
rq.expect(actualValue).to.equal(expectedValue);
});
```
## Example Tests
### Status Code Check
```javascript theme={null}
rq.test("Status is 200", () => {
rq.response.to.have.status(200);
});
```
### JSON Body Validation
```javascript theme={null}
rq.test("User exists", () => {
rq.response.to.have.jsonBody("user.name", "John");
});
```
### Header Check
```javascript theme={null}
rq.test("Has auth header", () => {
rq.response.to.have.header("Authorization");
});
```
### Schema Validation
```javascript theme={null}
rq.test("Valid schema", () => {
rq.response.to.have.jsonSchema({
type: "object",
required: ["id"],
properties: { id: { type: "number" } }
});
});
```
### Skipping Tests
```javascript theme={null}
rq.test.skip("Temporarily disabled test", () => {
// This test won't run
});
```
## Response specific assertions
The `.to` API is supported only for response data in Post-response scripts.
**Status code assertions**
```javascript theme={null}
// Success responses
rq.response.to.be.ok // 2XX
rq.response.to.be.success // 200
rq.response.to.be.accepted // 202
// Client error responses
rq.response.to.be.badRequest // 400
rq.response.to.be.unauthorized // 401
rq.response.to.be.forbidden // 403
rq.response.to.be.notFound // 404
rq.response.to.be.rateLimited // 429
rq.response.to.be.clientError // 4XX
// Server error responses
rq.response.to.be.serverError // 5XX
// Other status categories
rq.response.to.be.error // 4XX or 5XX
rq.response.to.be.info // 1XX
rq.response.to.be.redirection // 3XX
```
`.to.have` **assertions**
```javascript theme={null}
// Checks if response body exactly matches expected value.
rq.response.to.have.body(expectedValue: string)
// Checks response status code or text.
rq.response.to.have.status(expectedValue: number | string)
rq.response.to.have.status(200);
rq.response.to.have.status("OK");
// Checks if response has specified header (case-insensitive)
rq.response.to.have.header(headerName: string)
// Validates that response body is valid JSON.
rq.response.to.have.jsonBody();
// Checks if a path exists in the response.
rq.response.to.have.jsonBody(path: string)
rq.response.to.have.jsonBody("user.name");
// Checks if a JSON path has a specific value.
rq.response.to.have.jsonBody(path: string, value: any)
rq.response.to.have.jsonBody("user.name", "John");
// Validates the response body against a JSON schema. Accepts optional Ajv configuration.
rq.response.to.have.jsonSchema(schema: object, ajvOptions?: AjvOptions)
rq.response.to.have.jsonSchema({
type: "object",
required: ["id", "name"],
properties: {
id: { type: "number" },
name: { type: "string" },
email: { type: "string", format: "email" }
}
}, { allErrors: true });
```
**Negation with** `.to.not`
All the above assertions can be negated by inserting `.not` after `.to`:
```javascript theme={null}
rq.response.to.not.be.error;
rq.response.to.not.have.header("X-Custom");
rq.response.to.not.have.jsonBody("error");
```
# AWS Secrets Manager
Source: https://docs.requestly.com/api-client/vault/aws-secrets-manager
Connect your AWS account to fetch centrally managed secrets into the Requestly vault and reference them in API requests with the {{vault:key}} syntax.
Connect your AWS account to pull centrally managed secrets into the [Vault](/api-client/vault). AWS secrets share the same `{{vault:key}}` namespace as local secrets, so your requests don't need to know where a secret comes from.
**Availability:** External secret providers, including AWS Secrets Manager, require the desktop app, a signed-in Cloud project, and an eligible plan, and are rolling out gradually. If you don't see the option to add a provider, update to the latest version or contact support. Local vault remains fully functional without signing in.
***
## Setting up an AWS provider
Click **Vault** in the app footer.
Click **Connect provider** below the Local Secrets section.
Fill in the configuration form:
| Field | Required | Description |
| ---------------------------- | -------- | -------------------------------------------------------------- |
| **Instance name** | Yes | A label for this configuration (e.g., "Production", "Staging") |
| **Access key** | Yes | Your AWS IAM access key |
| **Secret key** | Yes | Your AWS IAM secret key |
| **Region** | Yes | AWS region (e.g., `us-east-1`) |
| **Session token (optional)** | No | Required only for STS temporary credentials |
Click **Test connection** to validate your credentials against AWS. You can still save even if the test fails and fix credentials later.
Click **Add provider**. The AWS Secrets Manager section appears on the Vault page.
***
## Required AWS IAM permissions
Your IAM user or role needs the following permissions:
```json theme={null}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": "arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:*"
}
]
}
```
Scope the `Resource` to specific secret ARNs for least-privilege access instead of using `*`.
***
## Adding and fetching secrets
In the AWS Secrets Manager section, click **Add secret**. Enter:
* **Alias**: the key you'll use in `{{vault:alias}}`
* **Secret Name or ARN**: the AWS secret identifier
* **Mode**: `Plaintext` or `JSON`
Click **Fetch secrets** to pull the values. Requestly calls the AWS `GetSecretValue` API and stores the result encrypted locally.
Reference the secret using `{{vault:alias}}` in any request field. It resolves on send just like a local secret.
***
## JSON secrets
When an AWS secret contains a JSON object, Requestly auto-expands it into dot-separated keys:
```
AWS Secret "dbCredentials":
{
"username": "admin",
"password": "s3cret",
"host": "db.example.com"
}
```
This creates three vault entries:
* `{{vault:dbCredentials.username}}` resolves to `admin`
* `{{vault:dbCredentials.password}}` resolves to `s3cret`
* `{{vault:dbCredentials.host}}` resolves to `db.example.com`
Nested JSON objects expand recursively with dot notation.
***
## Refreshing secrets after rotation
Fetched values are cached locally and survive app restarts. Requestly also re-fetches every secret of the active configuration automatically when the app starts, so a secret rotated in AWS overnight is usually current before you send your first request. While that startup fetch runs, the Secret Provider section shows a "Loading secrets from provider at startup" banner.
If the startup fetch fails, a warning banner names the affected configuration and offers a **Fetch secrets** button to retry. You can click **Fetch secrets** at any time to pull the current values for every row in the section. The **Last fetched** label next to the configuration selector helps you judge staleness.
There is no scheduled refresh. Fetching always refreshes the whole section, not a single row.
***
## Multiple AWS configurations
You can store multiple AWS configurations (e.g., Production, Staging, EU region) and switch between them:
1. Click the **config selector** in the AWS section header
2. Select a different configuration. The secrets table swaps to that config's secrets.
3. `{{vault:key}}` references resolve from the **active** configuration only
Each configuration maintains its own independent set of secrets and cached values. Switching configs preserves all caches, so no re-fetching is needed.
To add a new configuration, select **+ Add new configuration** from the config selector dropdown.
***
## Credential errors
When AWS credentials expire or become invalid:
* The affected secret row shows an error message
* The provider config section shows an error indicator
* The failed secret's cached value is **cleared** from disk and memory, so `{{vault:alias}}` stops resolving until a fetch succeeds. Only the rows that failed are affected.
To fix: edit your credentials in the same provider config form (no separate reauthentication flow), save, and retry the fetch.
***
## Move to local
You can convert any AWS secret to a local vault secret:
1. Select **Move to local** on an AWS secret
2. The secret moves to the Local Secrets section with the last fetched value preserved
3. It becomes fully editable and is no longer linked to AWS
***
## FAQ
You can store multiple AWS configurations, but only one is active at a time. The active config's secrets are the ones that resolve via `{{vault:key}}`. Switch between configs using the config selector in the AWS section header.
No. Fetched values are cached locally and persist until you refresh them. Click **Fetch secrets** to pull the latest values from AWS.
No. `rq.vault` is read-only from scripts. Only `rq.vault.get()`, `rq.vault.has()`, and `rq.vault.toObject()` are available. Manage AWS secrets from the Vault page or in AWS directly.
***
## Related Documentation
* [Vault Overview](/api-client/vault)
* [`rq.vault` Scripting API](/api-client/rq-api-reference/rq-vault)
# Azure Key Vault
Source: https://docs.requestly.com/api-client/vault/azure-key-vault
Connect an Azure service principal to pull secrets from one or more Azure key vaults into the Requestly vault and reference them in API requests with the {{vault:key}} syntax.
Connect an Azure service principal to pull secrets from your Azure key vaults into the [Vault](/api-client/vault). Azure secrets share the same `{{vault:key}}` namespace as local secrets, so your requests don't need to know where a secret comes from.
Each secret row carries its own vault name, so a single connection can read from several key vaults in the same Azure tenant.
**Availability:** External secret providers, including Azure Key Vault, require the desktop app, a signed-in Cloud project, and an eligible plan, and are rolling out gradually. If you don't see the option to add a provider, update to the latest version or contact support. Local vault remains fully functional without signing in.
***
## What you need from Azure
Requestly signs in to Azure with the service principal client credentials flow, so you need an app registration and a client secret before you configure anything in the app.
In the Azure portal, open the key vault holding your secrets and note its **name** (the first label of its URI, for example `my-vault` in `https://my-vault.vault.azure.net/`). You enter this name per secret in Requestly, not once per connection.
Requestly connects to the global Azure cloud only. Sovereign clouds such as Azure Government and Azure China are not supported.
In **Microsoft Entra ID** (formerly Azure Active Directory), go to **App registrations** and register a new application. From its overview page, copy:
1. The **Directory (tenant) ID**.
2. The **Application (client) ID**.
Under **Certificates & secrets** for that app registration, create a new client secret and copy its **value** immediately. Azure only shows the value once.
Client secrets expire. When yours expires, secret fetches start failing until you create a new one and update the credentials in Requestly.
On the key vault, assign the app registration the **Key Vault Secrets User** role so it can read secret values.
If the vault still uses the legacy access policy permission model instead of Azure role-based access control, add an access policy granting the app the **Get** secret permission instead.
***
## Setting up an Azure provider
Click **Vault** in the app footer.
Click **Connect provider** below the Local Secrets section, or click **Add provider** in the Secret Provider section header if you already have another provider configured.
Set **Provider type** to **Azure Key Vault**, then fill in the form:
| Field | Required | Description |
| ----------------- | -------- | -------------------------------------------------------------- |
| **Instance name** | Yes | A label for this configuration (e.g., "Production", "Staging") |
| **Tenant ID** | Yes | The Directory (tenant) ID of your Microsoft Entra ID directory |
| **Client ID** | Yes | The Application (client) ID of your app registration |
| **Client secret** | Yes | The client secret value you created for that app registration |
Click **Test connection**. Requestly exchanges your credentials for an Azure access token and reports **Connected successfully** or the error Azure returned. You can still save if the test fails and fix the credentials later.
The test only proves the tenant ID, client ID, and client secret are valid. It cannot check whether the app can read a specific vault, because vault names live on individual secrets.
Click **Add provider**. The Secret Provider section appears on the Vault page with your configuration selected.
***
## Adding and fetching secrets
In the Secret Provider section, click **Add secret** and fill the row:
* **Alias**: the key you'll use in `{{vault:alias}}`
* **Vault name**: the key vault to read from, for example `my-vault`
* **Secret name**: the name of the secret inside that vault
Click **Fetch secrets**. Requestly reads every row that has an alias, a vault name, and a secret name, and stores the values encrypted locally. Rows with a missing field are skipped.
Each row lands in one of three states:
* **Never fetched**: the **Secret** column shows **Not fetched**.
* **Fetched**: the **Secret** column shows a masked value. Hover the value and click the eye icon to reveal it.
* **Failed**: the **Secret** column shows **Error** in red, with the error message on a line beneath the row. Any value the row showed before is cleared.
Reference the secret using `{{vault:alias}}` in any request field. It resolves on send just like a local secret.
***
## Remove a secret mapping
To remove a mapping, open the row menu and select **Delete**. This removes the mapping and its cached value from Requestly. Nothing changes in Azure.
***
## Vault and secret name rules
Requestly checks both names before calling Azure, so most typos fail immediately with a clear message:
* **Vault name**: 3 to 24 characters, letters, numbers, and hyphens only, starting with a letter and ending with a letter or number.
* **Secret name**: 1 to 127 characters, letters, numbers, and hyphens only.
A name that breaks these rules shows an `Invalid vaultName` or `Invalid secretName` error on the row.
***
## Reading from multiple key vaults
Because the vault name lives on each secret row rather than on the connection, one Azure provider configuration can read from any number of key vaults, as long as the same app registration has access to each of them:
| Alias | Vault name | Secret name |
| ------------- | --------------------- | ----------------- |
| `DB_PASSWORD` | `prod-data-vault` | `db-password` |
| `STRIPE_KEY` | `prod-payments-vault` | `stripe-live-key` |
If one vault denies access, only that row fails. The rest still fetch.
***
## Refreshing secrets after rotation
Fetched values are cached locally and survive app restarts. Requestly also re-fetches every secret of the active configuration automatically when the app starts, so a secret rotated in Azure overnight is usually current before you send your first request. While that startup fetch runs, the Secret Provider section shows a "Loading secrets from provider at startup" banner.
If the startup fetch fails, a warning banner names the affected configuration and offers a **Fetch secrets** button to retry. You can click **Fetch secrets** at any time to pull the current values for every row in the section. The **Last fetched** label next to the configuration selector helps you judge staleness.
There is no scheduled refresh and no per-row refresh for Azure secrets. Fetching always refreshes the whole section.
***
## Multiple Azure configurations
You can store several Azure configurations (for example, one per Entra ID tenant) and switch between them:
1. Click the **configuration selector** in the Secret Provider section header. Azure entries are labeled ` (Azure)`.
2. Select a different configuration. The secret table swaps to that configuration's secrets.
3. One Azure configuration is active at a time, and `{{vault:key}}` resolves from that one. Secrets from an active configuration of a different provider, such as AWS Secrets Manager, keep resolving alongside it.
To edit or remove a configuration, click **Manage providers**. Editing the credentials discards the cached Azure access token, so the next fetch signs in again with the new values.
***
## Errors and what they mean
Fetch errors appear beneath the affected row. A failed fetch also clears that secret's cached value from disk and memory, so `{{vault:alias}}` stops resolving until a fetch succeeds. Only the rows that failed are affected: every other row keeps its value.
| Message | Cause | Fix |
| ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `Access denied - check that the Service Principal has Key Vault Secrets User role, and that the secret is not disabled` | The app registration cannot read the secret, or the secret is disabled in Azure | Assign the **Key Vault Secrets User** role on that vault, and check that the secret is enabled |
| `Secret not found - check the vault name and secret name` | The vault name or the secret name doesn't match anything in Azure | Correct the **Vault name** and **Secret name** cells |
| `Azure Key Vault returned 401 - token may have been revoked` | The access token was rejected, usually because the client secret was rotated or revoked | Update the **Client secret** in the provider configuration |
| `Connection timed out - check your network connection` | Azure did not respond within 10 seconds | Check your network connection, VPN, or proxy |
| `Cannot reach Azure - check your network connection` | The Azure host could not be resolved, or it refused the connection | Check your DNS settings, network connection, VPN, or proxy |
| `Network error - check your connection` | Any other network failure while contacting Azure | Check your network connection, then fetch again |
| An Azure sign-in error on **Test connection** | The tenant ID, client ID, or client secret is wrong | Re-copy the values from the app registration |
A 401 is retried once with a fresh token before the row is marked as failed, so a token that simply aged out never surfaces as an error.
***
## FAQ
No. An Azure secret is fetched as a single string value and stored under its alias. The JSON auto-expansion available for [AWS Secrets Manager](/api-client/vault/aws-secrets-manager) secrets does not apply to Azure secrets.
You can store multiple Azure configurations, but only one Azure configuration is active at a time. Its secrets are the Azure ones that resolve via `{{vault:key}}`, and an active configuration of a different provider, such as AWS Secrets Manager, keeps resolving alongside it. Switch between Azure configurations using the configuration selector in the Secret Provider section header.
No. Requestly always reads the current version of an Azure secret. There is no version pinning for Azure secrets.
Not directly. The Azure row menu offers **Delete** only. To keep a value locally, reveal it in the Secret column, then add it as a new secret in the Local Secrets section.
Provider credentials are encrypted alongside your vault data using your operating system's keychain. They never sync to Requestly servers and never appear in collection exports.
No. `rq.vault` is read-only from scripts. Only `rq.vault.get()`, `rq.vault.has()`, and `rq.vault.toObject()` are available. Manage Azure secrets from the Vault page or in Azure directly.
***
## Related Documentation
* [Vault Overview](/api-client/vault)
* [AWS Secrets Manager](/api-client/vault/aws-secrets-manager)
* [`rq.vault` Scripting API](/api-client/rq-api-reference/rq-vault)
# Overview
Source: https://docs.requestly.com/api-client/vault/vault
Store sensitive values locally, pull secrets from external providers like AWS Secrets Manager, and reference them in your API requests without ever exposing credentials in collections, exports, or cloud sync.
## What is Vault ?
Vault is a local-first encrypted secrets store built into the Requestly desktop app. It lets you:
* **Store secrets locally**: API keys, tokens, and passwords encrypted on your machine via OS keychain.
* **Pull secrets from external providers**: connect services like [AWS Secrets Manager](/api-client/vault/aws-secrets-manager) and [Azure Key Vault](/api-client/vault/azure-key-vault) to fetch centrally managed credentials.
* **Reference secrets in requests**: use `{{vault:key}}` syntax in URLs, headers, auth fields, and body.
* **Share collections safely**: secret references travel with collections, but values stay on each user's machine.
Vault requires the **Requestly desktop app** (Electron) for OS-level encryption via `safeStorage`. Vault features are not available in the web-only mode.
***
## Local Vault
The local vault is available to **all users**. No sign-in or paid plan is required. Secrets are encrypted at rest using your operating system's keychain (macOS Keychain, Windows Credential Manager, or Linux Secret Service).
### Creating a local secret
Click the **Vault** button in the app footer to open the Vault page.
Click **Add Secret** at the bottom of the Local Secrets table. A new row appears with editable Key and Value cells.
Type a key name (e.g., `my-api-key`) and a value (e.g., `sk-abc123`). Press **Enter** to save. The value masks immediately.
### Using a vault secret in a request
Reference any vault secret using the `{{vault:key}}` syntax in any request field:
```
Authorization: Bearer {{vault:my-api-key}}
```
When you send the request, `{{vault:my-api-key}}` resolves to the actual value. The resolved value **never** appears in the editor, console output, collection exports, or cloud sync. Only the `{{vault:key}}` reference is visible.
Vault secrets appear in the standard `{{` autocomplete dropdown alongside environment and collection variables, labeled with a **Vault** scope badge.
### Inline editing
Click any key or value cell in the vault table to edit it in place. No modals or separate forms are needed. Changes save automatically on blur or Enter.
### Deleting a secret
Delete a vault secret from the table. Any `{{vault:key}}` references to the deleted secret become unresolved immediately.
***
## External secret providers
Connect centrally managed secret managers to pull secrets into the vault. External provider secrets share the same `{{vault:key}}` namespace as local secrets, so your requests don't need to know where a secret comes from.
* [**AWS Secrets Manager**](/api-client/vault/aws-secrets-manager): connect an AWS account to fetch and cache secrets, with support for JSON expansion, multiple configurations, and rotation refresh.
* [**Azure Key Vault**](/api-client/vault/azure-key-vault): connect an Azure service principal to fetch secrets, with a vault name per secret so one connection can read from several key vaults.
* **HashiCorp Vault** and **1Password** (SDK and Connect) are also supported as providers and are rolling out gradually.
External provider integrations require the desktop app, a signed-in Cloud project, and an eligible plan, and are rolling out gradually. Local vault remains fully functional without signing in.
***
## Scripting API
Access vault secrets programmatically in pre-request and post-response scripts using the `rq.vault` API:
```javascript theme={null}
// Pre-request script
const signingKey = rq.vault.get('signing-key');
const jwt = generateJwt(payload, signingKey);
rq.variables.set('auth-token', jwt);
```
Then use `{{auth-token}}` in the Authorization header. The signing key never leaves the vault.
See the full [`rq.vault` reference](/api-client/rq-api-reference/rq-vault) for the read-only `get`, `has`, and `toObject` methods.
***
## Importing from Postman
Requestly preserves `{{vault:key}}` references when importing Postman collections. No syntax translation is needed.
### What happens on import
1. `{{vault:key}}` references in URLs, headers, auth fields, and body are **preserved as-is**.
2. `pm.vault.get/set/unset/has` calls in scripts are **automatically translated** to `rq.vault.get/set/unset/has`.
3. For each detected `{{vault:key}}` reference, a **local secret is pre-created** with an empty value.
4. A post-import summary lists the pre-created secrets.
### After import
Open the Vault page. You'll see the pre-created secret keys with empty values. Fill in the values, and your imported requests will resolve immediately.
Postman collection exports never include vault secret values, only the `{{vault:key}}` references. You'll need to re-enter the actual values in your Requestly vault.
***
## Namespace and resolution
### Resolution priority
If the same key exists in both Local Secrets and an external provider (e.g., AWS), the **external secret wins**. The local secret shows an amber "overridden by duplicate key" warning.
### Variable hover
Hovering over a `{{vault:key}}` reference in any editor field shows:
* The masked value (`••••••••`)
* The scope: **Vault**
* The source: **Local** or the external provider name
Unresolved references show an "Unresolved" diagnostic with guidance.
### Console masking
Vault secret values are **always masked** in the console and response viewer. You'll see the `{{vault:key}}` reference or `••••••••`, never the plaintext value.
***
## Security model
| Property | Behavior |
| ------------------------ | -------------------------------------------------------------------------------------------------------------- |
| **Encryption at rest** | All vault data encrypted via Electron `safeStorage` (OS keychain). Files on disk are not human-readable. |
| **Device isolation** | Each OS user account has a separate vault. A different OS user on the same machine cannot access your secrets. |
| **No cloud sync** | Vault values are never sent to Requestly servers, never included in cloud project sync. |
| **No export inclusion** | Collection exports contain `{{vault:key}}` references, never resolved values. |
| **Provider credentials** | Stored encrypted alongside vault secrets. Never appear in logs or plaintext files. |
| **Session independence** | Local vault works regardless of sign-in state. External provider features require authentication. |
**Linux users:** Vault requires a D-Bus Secret Service implementation (GNOME Keyring, KWallet, or equivalent). If no keyring is configured, vault features are disabled but the rest of the app works normally.
***
## FAQ
No. Vault requires the desktop app (Electron) for OS-level encryption. This matches how Postman's vault requires the Desktop Agent.
Local vault secrets persist and continue resolving. They're tied to your OS user session, not your Requestly account. Previously fetched external provider secrets also remain cached and resolvable. However, you cannot configure new providers or fetch new secrets until you sign back in.
Vault is desktop-only and does not work in CI/CD pipelines. For automated runs, use environment variables or your CI platform's native secret injection.
No. `rq.vault` is read-only from scripts for both local and external provider secrets. Only `rq.vault.get()`, `rq.vault.has()`, and `rq.vault.toObject()` are available. To create, update, or delete a secret, use the Vault page. To keep a derived value for the current run, use `rq.variables.set()`.
# Changelogs
Source: https://docs.requestly.com/changelogs
What's new in the Requestly API Client, grouped by desktop release.
Updates to the Requestly API Client, newest first. Each entry is anchored to a
desktop release and collects everything that shipped under it.
### 🚀 New
* You can now use `xml2Json` as a bare global in request scripts to parse XML responses, matching the scripting environment you may know from Postman. ([#4072](https://github.com/requestly/requestly-api-client/pull/4072))
* You can now write an On Message script for gRPC server-streaming and bidirectional calls - the script runs once per received message and its assertions appear individually in the collection runner. ([#4042](https://github.com/requestly/requestly-api-client/pull/4042))
* You can now import a gRPC request by pasting a grpcurl command, the same way HTTP requests can be imported from a cURL command. ([#3738](https://github.com/requestly/requestly-api-client/pull/3738))
### 🐛 Fixes
* gRPC server reflection now uses the authentication credentials you have configured on the request, so reflection works correctly against servers that require auth. ([#3704](https://github.com/requestly/requestly-api-client/pull/3704))
### 🚀 New
* Your pre- and post-request scripts now have access to CryptoJS (crypto-js) as a built-in global, with no require call needed. ([#4049](https://github.com/requestly/requestly-api-client/pull/4049))
* Lodash is now available as \_ in your pre- and post-request scripts without requiring it first. ([#4066](https://github.com/requestly/requestly-api-client/pull/4066))
* Importing an OpenAPI spec now lets you create both a collection and a mock server in one step. ([#4010](https://github.com/requestly/requestly-api-client/pull/4010))
* When you save a request example, its endpoint is now automatically added as a route in your mock server. ([#4034](https://github.com/requestly/requestly-api-client/pull/4034))
### ✨ Improvements
* You can now reach App Settings from a dedicated button that is always visible in the header, without needing to open a menu. ([#3974](https://github.com/requestly/requestly-api-client/pull/3974))
* When importing a Postman collection that contains some malformed entries, Requestly now imports everything it can parse and shows you a list of items that were skipped, instead of rejecting the whole file. ([#4013](https://github.com/requestly/requestly-api-client/pull/4013))
* cURL imports now correctly handle digest and NTLM auth, multipart form data, and no longer include curl's automatic Accept and User-Agent headers in your imported request. ([#3985](https://github.com/requestly/requestly-api-client/pull/3985))
* Duplicating a request now copies its advanced settings alongside it, and WebSocket and Socket.IO handshake header values now support variable and vault references. ([#3987](https://github.com/requestly/requestly-api-client/pull/3987))
* The Visualize button now shows a highlighted state when the visualization panel is open, so you can tell at a glance whether it is active. ([#4025](https://github.com/requestly/requestly-api-client/pull/4025))
* The desktop app now keeps its theme in sync with your OS color scheme, so system dark and light mode preferences are reflected consistently across the app. ([#3972](https://github.com/requestly/requestly-api-client/pull/3972))
### 🐛 Fixes
* Importing a large local project no longer fails silently with no error or progress shown. ([#4019](https://github.com/requestly/requestly-api-client/pull/4019))
* gRPC requests on desktop now respect your OS certificate store, and disabling TLS verification correctly skips the full certificate chain check. ([#3975](https://github.com/requestly/requestly-api-client/pull/3975))
* Calling rq.visualizer.clear() in a post-response script now correctly clears any visualization that a pre-request script set. ([#4039](https://github.com/requestly/requestly-api-client/pull/4039))
* The desktop app now recovers automatically if the main window fails to load at startup, instead of appearing stuck. ([#4038](https://github.com/requestly/requestly-api-client/pull/4038))
* Visualizations now render with the correct colors for your current light or dark theme. ([#4028](https://github.com/requestly/requestly-api-client/pull/4028))
* Saving a request on Windows with OneDrive-synchronized project folders no longer fails with a directory error. ([#4018](https://github.com/requestly/requestly-api-client/pull/4018))
* The AI assistant no longer repeats the same lookup in a loop when you ask a question from a collection tab. ([#3991](https://github.com/requestly/requestly-api-client/pull/3991))
### 🚀 New
* You can now generate a cloud mock server from any collection in one click - every request becomes a route and each saved example becomes a served response. ([#3811](https://github.com/requestly/requestly-api-client/pull/3811))
* Scripts can now use `rq.visualizer.set()` in pre-request scripts, and `rq.response.stream` gives you the raw response body as a Buffer for reading binary data, both matching Postman behavior. ([#3971](https://github.com/requestly/requestly-api-client/pull/3971))
* When you upload a file using the wrong importer, the app now detects the actual format and lets you switch to the correct importer in one click without re-uploading the file. ([#3962](https://github.com/requestly/requestly-api-client/pull/3962))
### ✨ Improvements
* Import warnings are now shown only on the result step and grouped by type, so each kind of issue appears once instead of repeating across multiple steps. ([#3963](https://github.com/requestly/requestly-api-client/pull/3963))
* The scheduled run creation form no longer shows a pre-flight run count estimate, keeping the configuration focused on just the schedule settings. ([#3977](https://github.com/requestly/requestly-api-client/pull/3977))
### 🐛 Fixes
* Fixed an issue where scripts using `rq.sendRequest` or `fetch` would silently drop query strings, ignore your proxy and SSL settings, and return corrupted binary response bodies. ([#3945](https://github.com/requestly/requestly-api-client/pull/3945))
* Fixed three issues: exporting an environment with secret values now prompts for confirmation before downloading, a single over-long name no longer causes an entire Postman collection import to fail, and saving collection-scoped variables from example tabs now works correctly. ([#3973](https://github.com/requestly/requestly-api-client/pull/3973))
* When an import fails to save, you now see the actual HTTP status code and server response details instead of a generic 'Unknown error' message. ([#3947](https://github.com/requestly/requestly-api-client/pull/3947))
* The AI assistant now shows a specific error message based on what went wrong, instead of a single generic failure notice. ([#3960](https://github.com/requestly/requestly-api-client/pull/3960))
* Fixed the AI assistant's chat input so that Enter sends your message and Mod+Enter inserts a new line. ([#3989](https://github.com/requestly/requestly-api-client/pull/3989))
* The AI assistant now shows a loading indicator when you switch to a conversation thread that is still loading its messages. ([#3990](https://github.com/requestly/requestly-api-client/pull/3990))
* Fixed an issue where the AI assistant could get stuck if a tool action was interrupted mid-session. ([#3938](https://github.com/requestly/requestly-api-client/pull/3938))
### ✨ Improvements
* The desktop app now installs custom script packages through a safer channel, closing a potential security gap without changing how packages work. ([#3916](https://github.com/requestly/requestly-api-client/pull/3916))
* The AI chat assistant now limits messages to 10,000 characters and shows a clear message when you send requests too quickly. ([#3898](https://github.com/requestly/requestly-api-client/pull/3898))
* When a project search finds no results, the message now names which team and local projects were searched, so you know exactly where to look. ([#3915](https://github.com/requestly/requestly-api-client/pull/3915))
### 🐛 Fixes
* Single-team accounts now appear correctly in the team switcher, and team memberships are cleaned up when a user is removed from a team. ([#3917](https://github.com/requestly/requestly-api-client/pull/3917))
### 🐛 Fixes
* Fixed a bug where the embedded terminal could show ghost tabs or connection errors on recently released desktop versions. ([#3900](https://github.com/requestly/requestly-api-client/pull/3900))
* Fixed an issue where importing certain valid OpenAPI specifications would fail; the importer now succeeds on any spec that passes initial parsing, extracting what it recognizes rather than rejecting the whole file. ([#3896](https://github.com/requestly/requestly-api-client/pull/3896))
### 🚀 New
* You can now render a custom HTML visualization of response data by calling `rq.visualizer.set(template, data)` in a post-response script, then selecting Visualize in the response panel. Use `Mod+Shift+Enter` to send and visualize in one step. ([#3840](https://github.com/requestly/requestly-api-client/pull/3840))
### ✨ Improvements
* The Sharing tab now displays a note clarifying exactly what your documentation share links include (read-only docs) and exclude (scripts and auth), so you know what recipients will see before you share. ([#3861](https://github.com/requestly/requestly-api-client/pull/3861))
### 🐛 Fixes
* The desktop app now blocks secondary listeners from attaching to the background bridge, closing a gap where injected scripts could silently read all background service traffic, including stored secrets and credentials. ([#3888](https://github.com/requestly/requestly-api-client/pull/3888))
* Deleting all requests from a collection while the runner is open now correctly shows the empty state and disables the Run button instead of displaying stale entries from the deleted requests. ([#3872](https://github.com/requestly/requestly-api-client/pull/3872))
### 🐛 Fixes
* Importing a collection exported from the old Requestly app no longer rejects the entire file when individual requests are missing header or auth fields - valid requests are imported and any unrecoverable ones are reported by name. ([#3881](https://github.com/requestly/requestly-api-client/pull/3881))
* Script `rq.sendRequest` calls on desktop now honor your system certificate store, custom CA certificates, SSL verification toggle, and proxy settings, fixing silent failures on corporate or TLS-intercepting networks. ([#3880](https://github.com/requestly/requestly-api-client/pull/3880))
* Starting to rename a chat history thread and then dismissing the popover without saving no longer leaves that thread stuck in its rename input the next time you open chat history. ([#3870](https://github.com/requestly/requestly-api-client/pull/3870))
* Pressing the save shortcut immediately after editing a request body, query parameters, or script field now reliably saves your latest content instead of silently reverting to the previous value. ([#3863](https://github.com/requestly/requestly-api-client/pull/3863))
* Changing a query parameter's type annotation (for example from "string" to "integer") is now saved correctly and no longer reverts to the original type on reload. ([#3631](https://github.com/requestly/requestly-api-client/pull/3631))
* Running the Requestly CLI on Windows no longer fails with a JSON parse error caused by an incorrectly formatted internal build file. ([#3851](https://github.com/requestly/requestly-api-client/pull/3851))
### 🐛 Fixes
* The desktop terminal now supports multiple tabs again, restoring the ability to run separate terminal sessions side by side. ([#3841](https://github.com/requestly/requestly-api-client/pull/3841))
### 🐛 Fixes
* When you restore a tab for a request, collection, or environment that was deleted on another device or by a teammate, you now see a clear not-found message with a Close tab button instead of an infinite loading spinner. ([#3822](https://github.com/requestly/requestly-api-client/pull/3822))
### 🐛 Fixes
* Scripts using `rq.sendRequest` with a callback now correctly wait for the callback to complete, so environment variables set inside the callback are applied and test assertions run as expected. ([#3746](https://github.com/requestly/requestly-api-client/pull/3746))
### 🐛 Fixes
* You can now import OpenAPI specs that previously failed due to non-standard but commonly produced field formats, such as boolean required fields or shorthand type strings generated by real conversion tools. ([#3731](https://github.com/requestly/requestly-api-client/pull/3731))
* The desktop app no longer freezes or becomes unresponsive when you open or create a local project with a large amount of saved data. ([#3715](https://github.com/requestly/requestly-api-client/pull/3715))
* The CLI no longer crashes on startup when running under Node 18, restoring all commands including collection run. ([#3708](https://github.com/requestly/requestly-api-client/pull/3708))
* The scheduled run form no longer shows requests from a previously viewed collection when you open it in a different collection. ([#3705](https://github.com/requestly/requestly-api-client/pull/3705))
* Sending a request immediately after editing the body now correctly uses your latest edits instead of the version saved a moment before. ([#3686](https://github.com/requestly/requestly-api-client/pull/3686))
### 🚀 New
* The AI Assistant now has an auto mode that skips individual approval prompts for tool actions; you can toggle it with Shift+Tab or by clicking the status indicator in the chat panel. ([#3661](https://github.com/requestly/requestly-api-client/pull/3661))
* You can now open the AI Assistant directly from the app footer. ([#3647](https://github.com/requestly/requestly-api-client/pull/3647))
* A read-only keyboard shortcuts reference overlay is back, showing all your shortcuts at a glance. ([#3642](https://github.com/requestly/requestly-api-client/pull/3642))
### ✨ Improvements
* Scheduled Runs now shows an Active/Paused badge on each schedule in the list, lets you search run history by run ID, and opens the Tests tab first when a run finishes with failures. ([#3665](https://github.com/requestly/requestly-api-client/pull/3665))
* The request Settings tab now shows an indicator dot when you have active overrides, offers an inline retry button when a request fails due to an SSL or parsing error, and displays a settings summary in the collection runner before you start a run. ([#3639](https://github.com/requestly/requestly-api-client/pull/3639))
* Your desktop login session is now encrypted when stored on disk, so it cannot be read if someone accesses your local files. ([#3646](https://github.com/requestly/requestly-api-client/pull/3646))
* For teams using TestHub, member and access management is now under Project Settings in a Members and access section and opens in your system browser. ([#3555](https://github.com/requestly/requestly-api-client/pull/3555))
### 🐛 Fixes
* The auto-generated Content-Type header is no longer added when you have already set one explicitly on the request. ([#3681](https://github.com/requestly/requestly-api-client/pull/3681))
* Saving a request as new now carries over the description and clears leftover data from body tabs you are not actively using; requests skipped by a pre-request script now show a dedicated skipped panel instead of a blank response. ([#3668](https://github.com/requestly/requestly-api-client/pull/3668))
* Variable names are now trimmed of surrounding whitespace when you save them. ([#3676](https://github.com/requestly/requestly-api-client/pull/3676))
* Editing the URL bar no longer duplicates existing query parameters; matching parameters are now updated in place. ([#3670](https://github.com/requestly/requestly-api-client/pull/3670))
* MQTT connections now work when the broker URL is a single variable placeholder such as . ([#3660](https://github.com/requestly/requestly-api-client/pull/3660))
* Message editors in WebSocket and Socket.IO requests now scroll correctly when working with large payloads. ([#3643](https://github.com/requestly/requestly-api-client/pull/3643))
* The AI Assistant panel no longer flickers or reloads your conversation when you close and reopen it. ([#3622](https://github.com/requestly/requestly-api-client/pull/3622))
* The duplicate variable name warning now correctly treats names that differ only by letter case as distinct. ([#3667](https://github.com/requestly/requestly-api-client/pull/3667))
* Cmd/Ctrl+0 (Reset Zoom) is now correctly treated as a reserved shortcut and cannot be rebound in keyboard settings. ([#3663](https://github.com/requestly/requestly-api-client/pull/3663))
* The Git panel now shows the correct branch name on empty repositories, auto-fetches in the background to keep the behind counter accurate, and hides the Push button until the repository has at least one commit. ([#3285](https://github.com/requestly/requestly-api-client/pull/3285))
* Importing an OpenAPI collection no longer fails on long example names, and validation errors now include the field names needed to identify the problem. ([#3619](https://github.com/requestly/requestly-api-client/pull/3619))
### ✨ Improvements
* The desktop app's initial load is now up to 76% smaller on the wire, making startup noticeably faster. ([#3566](https://github.com/requestly/requestly-api-client/pull/3566))
* Scheduled run results now show the actual headers that were sent, including values resolved by pre-request scripts and auth, instead of unresolved template placeholders. ([#3496](https://github.com/requestly/requestly-api-client/pull/3496))
### 🐛 Fixes
* Collapsing and re-expanding the sidebar no longer resets your open editors, response panels, or tab state. ([#3613](https://github.com/requestly/requestly-api-client/pull/3613))
* In scripts, setting a variable to null or undefined now clears it instead of storing the literal string, matching Postman's behavior. ([#3585](https://github.com/requestly/requestly-api-client/pull/3585))
* The light, dark, and system theme options now work correctly on the sign-in screen. ([#3591](https://github.com/requestly/requestly-api-client/pull/3591))
* Pressing Cmd+F (or Ctrl+F) while editing in the request body or a scripts editor no longer steals focus to the sidebar search. ([#3583](https://github.com/requestly/requestly-api-client/pull/3583))
### 🚀 New
* The AI assistant can now read and edit your requests, collections, and environments - when it suggests a change, you see an inline diff to accept or reject before anything is saved. ([#3055](https://github.com/requestly/requestly-api-client/pull/3055))
### 🐛 Fixes
* Fixed several WebSocket and Socket.IO reliability issues, including a freeze when receiving large payloads, query params no longer syncing with the URL bar, vague connection failure messages, and a missing Cancel button during connection. ([#3549](https://github.com/requestly/requestly-api-client/pull/3549))
### 🚀 New
* Signing up is now required to use the app, and the onboarding experience has been redesigned to guide you through initial setup more clearly. ([#3416](https://github.com/requestly/requestly-api-client/pull/3416))
* You can now switch between your teams directly from within the app using the new in-product team switcher. ([#3478](https://github.com/requestly/requestly-api-client/pull/3478))
* A new Scheduled Runs tab in the Collection Runner lets you discover and manage scheduled runs per collection alongside a Manual run sub-tab. ([#2786](https://github.com/requestly/requestly-api-client/pull/2786))
* You can now create and configure scheduled runs directly from the app, with settings for schedule frequency, retry policy, and request selection. ([#2814](https://github.com/requestly/requestly-api-client/pull/2814))
* Scheduled runs now include a history list showing past executions and a drill-down view with per-request results. ([#2837](https://github.com/requestly/requestly-api-client/pull/2837))
* You can pause, resume, delete, or immediately trigger a scheduled run directly from the run list. ([#2847](https://github.com/requestly/requestly-api-client/pull/2847))
* A re-run button lets you re-execute a previous scheduled run, and an inline config pane lets you adjust settings without navigating away. ([#2885](https://github.com/requestly/requestly-api-client/pull/2885))
* Scheduled runs can now automatically retry failed requests based on a configurable retry policy and attempt limit. ([#2953](https://github.com/requestly/requestly-api-client/pull/2953))
* The scheduled run detail view now shows per-request results in a two-pane layout with headers, payload, response, and test tabs, and the create form has been reorganized with clearer sections. ([#3035](https://github.com/requestly/requestly-api-client/pull/3035))
* Scheduled run results are automatically uploaded to BrowserStack Test Hub for centralized test tracking. ([#2762](https://github.com/requestly/requestly-api-client/pull/2762))
* Each `rq.test` assertion in a scheduled collection run now appears as its own result in BrowserStack Test Hub instead of being grouped under a single request. ([#2780](https://github.com/requestly/requestly-api-client/pull/2780))
* You can now export and import scheduled run configurations using the REST API or the CLI. ([#2823](https://github.com/requestly/requestly-api-client/pull/2823))
* You can now manage scheduled runs from the command line using the new `rq scheduled-run` subcommands. ([#2764](https://github.com/requestly/requestly-api-client/pull/2764))
* When publishing a release in API Design, the version is now automatically derived from the `info.version` field in your OpenAPI spec. ([#3443](https://github.com/requestly/requestly-api-client/pull/3443))
### ✨ Improvements
* The team-switching overlay has been polished and is now hidden when you are working in a local project. ([#3525](https://github.com/requestly/requestly-api-client/pull/3525))
* Vault access from scripts is now disabled by default and can be re-enabled from the Vault settings page. ([#3479](https://github.com/requestly/requestly-api-client/pull/3479))
* Import warnings are now cleaner, with redundant low-value notices removed and the remaining ones made more actionable. ([#3411](https://github.com/requestly/requestly-api-client/pull/3411))
* In-progress scheduled runs now appear in the run history, and runs are ordered by when they actually ran rather than when they were created. ([#3373](https://github.com/requestly/requestly-api-client/pull/3373))
* Realtime and gRPC requests are now excluded from scheduled run request selection, preventing unsupported configurations from being saved. ([#3104](https://github.com/requestly/requestly-api-client/pull/3104))
### 🐛 Fixes
* A tooltip was covering the create-project button in the project switcher settings area, making it impossible to click. ([#3548](https://github.com/requestly/requestly-api-client/pull/3548))
* Switching the body type in an HTTP request no longer leaves behind stale values from the previous type. ([#3395](https://github.com/requestly/requestly-api-client/pull/3395))
* OpenAPI collections with XML request bodies now import correctly with the proper content type applied. ([#3418](https://github.com/requestly/requestly-api-client/pull/3418))
* The collection runner now correctly records and displays results from WebSocket, Socket.IO, and gRPC requests. ([#3476](https://github.com/requestly/requestly-api-client/pull/3476))
* Clicking 'Try it' on an example multiple times in quick succession no longer opens duplicate draft tabs. ([#3500](https://github.com/requestly/requestly-api-client/pull/3500))
* Adding a request to a scheduled run and saving it now works correctly, and the run detail view no longer renders broken components. ([#3053](https://github.com/requestly/requestly-api-client/pull/3053))
### 🐛 Fixes
* The sidebar toggle button now correctly reports its open or closed state to screen readers and other assistive technologies. ([#3456](https://github.com/requestly/requestly-api-client/pull/3456))
* The array variable type now only appears in the type picker when your installed desktop version supports it, preventing silent data corruption when scripts read or write array variables on older builds. ([#3460](https://github.com/requestly/requestly-api-client/pull/3460))
### 🚀 New
* You can now choose how a response body is displayed using the new format selector in the response toolbar, with options for JSON, XML, HTML, YAML, JavaScript, Markdown, Raw, Hex, and Base64. ([#3312](https://github.com/requestly/requestly-api-client/pull/3312))
* Variables now support an array data type, so scripts can store and retrieve real arrays with `.first()` and `.last()` instead of having them flattened to comma-joined strings. ([#3444](https://github.com/requestly/requestly-api-client/pull/3444))
### ✨ Improvements
* The API Docs publishing flow now shows Copy link and View actions in the success toast, the empty-state primary button highlights the most useful next step, and the Components Library in the API Design sidebar is collapsed by default. ([#3435](https://github.com/requestly/requestly-api-client/pull/3435))
### 🐛 Fixes
* Secret vault references in OAuth 2.0 and JWT Bearer auth fields now resolve correctly when sending requests, instead of being passed as literal template strings to the token endpoint. ([#3434](https://github.com/requestly/requestly-api-client/pull/3434))
* The Run via CLI command generated by the collection runner now uses the environment name instead of its internal ID for local projects, so the copied command works when you run it. ([#3419](https://github.com/requestly/requestly-api-client/pull/3419))
* Keyboard shortcuts rebound to punctuation keys such as semicolons, periods, slashes, and brackets now fire correctly after being configured in the desktop app's shortcut settings. ([#3396](https://github.com/requestly/requestly-api-client/pull/3396))
* A security vulnerability in the desktop app's git integration has been patched, and remote URLs are now validated to allow only standard schemes such as https, http, and ssh. ([#3383](https://github.com/requestly/requestly-api-client/pull/3383))
### 🚀 New
* You can now collapse the Collections sidebar to give your request editor more room, and restore it with a click or Cmd/Ctrl+B. ([#3313](https://github.com/requestly/requestly-api-client/pull/3313))
* A new Keyboard Shortcuts page in Settings on desktop lets you view all available shortcuts, reassign any of them directly in the list, and reset everything to defaults. ([#3098](https://github.com/requestly/requestly-api-client/pull/3098))
### ✨ Improvements
* Script errors in pre- and post-request scripts now show line numbers and column positions in the Response panel, DevTools console, and Collection Runner, so you can pinpoint mistakes faster. ([#3310](https://github.com/requestly/requestly-api-client/pull/3310))
### 🐛 Fixes
* Changing a team member's role no longer fails with an error when the member has been invited but has not yet logged in. ([#3346](https://github.com/requestly/requestly-api-client/pull/3346))
### 🚀 New
* You can now delete all variables at once from the Environment, Global, and Collection variable tables using the new Delete All button, which asks for confirmation before clearing. ([#2985](https://github.com/requestly/requestly-api-client/pull/2985))
* Users who are not signed in now see a notification banner with a Sign in option, giving advance notice that a free account will soon be required. ([#3303](https://github.com/requestly/requestly-api-client/pull/3303))
### ✨ Improvements
* When a mandatory update is detected while the desktop app is running, the download now starts automatically so you can install it without any extra steps. ([#3319](https://github.com/requestly/requestly-api-client/pull/3319))
### 🐛 Fixes
* Fixed a bug where the Clone repository modal immediately closed after clicking Clone from the project switcher. ([#3188](https://github.com/requestly/requestly-api-client/pull/3188))
* The collection runner now executes requests in the same order they appear in the sidebar, including reorders made by dragging. ([#3301](https://github.com/requestly/requestly-api-client/pull/3301))
* Fixed a regression on desktop where the sign-in notification banner remained visible after logging in. ([#3338](https://github.com/requestly/requestly-api-client/pull/3338))
* Fixed the embedded terminal on desktop appearing as a blank panel, so it now correctly renders text using the app's current light or dark theme. ([#3282](https://github.com/requestly/requestly-api-client/pull/3282))
* Fixed Quick Share links returning errors for visitors - shared links now load reliably. ([#3278](https://github.com/requestly/requestly-api-client/pull/3278))
* Fixed three Postman scripting issues: skipped tests no longer silently discard their function body, response body assertions now require an exact match instead of a substring match, and false warnings about unsupported Postman APIs have been removed. ([#3028](https://github.com/requestly/requestly-api-client/pull/3028))
* Fixed the desktop auto-update getting stuck on an error state after a download completed, by adding a verification step between download and success. ([#3328](https://github.com/requestly/requestly-api-client/pull/3328))
### 🐛 Fixes
* Requests with an empty body no longer send a spurious Content-Type header, preventing failures on servers that reject unexpected content types. ([#3270](https://github.com/requestly/requestly-api-client/pull/3270))
### 🐛 Fixes
* Deleted specs, components, and linked specs in API Design no longer reappear in the sidebar after a page reload. ([#3239](https://github.com/requestly/requestly-api-client/pull/3239))
* Using 'Save as new' on an HTTP or GraphQL request now carries all Settings overrides, including SSL verification, redirect policy, and timeout, over to the duplicate. ([#3221](https://github.com/requestly/requestly-api-client/pull/3221))
* Pre-request scripts that call rq.collectionVariables.set(), unset(), or clear() on a standalone request no longer abort the send with an error - the call is silently skipped and the request proceeds normally. ([#3197](https://github.com/requestly/requestly-api-client/pull/3197))
* Collection variables defined on a parent or ancestor folder are now visible to pre-request and post-response scripts, matching what you already see in the URL and header preview. ([#3225](https://github.com/requestly/requestly-api-client/pull/3225))
* Importing Postman collections now correctly infers the raw body content type from the Content-Type header when Postman's format hint is missing, and the Body tab shows a warning when your selected body language and Content-Type header disagree. ([#3219](https://github.com/requestly/requestly-api-client/pull/3219))
### 🚀 New
* You can now sign in to your Git provider with an OAuth device-code flow, in addition to a personal access token. ([#3154](https://github.com/requestly/requestly-api-client/pull/3154))
### ✨ Improvements
* The API Client sidebar now shows a Git status indicator for Git-backed projects. ([#3158](https://github.com/requestly/requestly-api-client/pull/3158))
* Improved keyboard navigation across the app. ([#3072](https://github.com/requestly/requestly-api-client/pull/3072))
* Extended the scripting API with `rq.response.headers` accessors, and brought Safe-mode scripts to parity for `rq.response.to.have.jsonSchema` and the JSON body helpers. ([#3170](https://github.com/requestly/requestly-api-client/pull/3170), [#3175](https://github.com/requestly/requestly-api-client/pull/3175), [#3177](https://github.com/requestly/requestly-api-client/pull/3177))
### 🐛 Fixes
* Example "Try it" now resolves collection-level variables. ([#3169](https://github.com/requestly/requestly-api-client/pull/3169))
* Collection variable default values are now applied when exporting a collection to OpenAPI. ([#3180](https://github.com/requestly/requestly-api-client/pull/3180))
* Older Requestly exports that omitted query parameters, headers, or enabled flags now import correctly. ([#3167](https://github.com/requestly/requestly-api-client/pull/3167))
* Fixed an error when using "Go to source" after the source specification had been deleted. ([#3168](https://github.com/requestly/requestly-api-client/pull/3168))
* AI requests are now rate-limited per user to keep the service responsive. ([#3198](https://github.com/requestly/requestly-api-client/pull/3198))
### 🚀 New
* You can now create private, scoped share links for a single endpoint or folder in your published API docs, with optional password protection and an expiry, and revoke them at any time. ([#3082](https://github.com/requestly/requestly-api-client/pull/3082))
* You can now connect a GitLab account with a personal access token for Git-backed projects. ([#3074](https://github.com/requestly/requestly-api-client/pull/3074))
### ✨ Improvements
* Large collection trees that span multiple projects now scroll smoothly. ([#3124](https://github.com/requestly/requestly-api-client/pull/3124))
### 🐛 Fixes
* Fixed a freeze in single-line fields when a value containing line breaks was entered. ([#3103](https://github.com/requestly/requestly-api-client/pull/3103))
* Fixed Requestly-format imports that could fail to save, and the app now shows the actual reason when an import fails. ([#3117](https://github.com/requestly/requestly-api-client/pull/3117))
* Generated code snippets now render multipart file fields as file uploads. ([#3109](https://github.com/requestly/requestly-api-client/pull/3109))
* Fixed local projects occasionally reporting data as corrupted after a transient read failure; these reads are now retried. ([#3116](https://github.com/requestly/requestly-api-client/pull/3116))
* AI features now redact request and response bodies before any data leaves your machine for quality evaluation. ([#3119](https://github.com/requestly/requestly-api-client/pull/3119))
### 🚀 New
* You can now right-click items in the sidebar tree and open tabs to rename, duplicate, delete, and run other actions from a context menu. ([#2966](https://github.com/requestly/requestly-api-client/pull/2966))
* You can now copy, cut, and paste requests and folders, within a collection or across collections, using the right-click menu and the usual keyboard shortcuts. ([#2983](https://github.com/requestly/requestly-api-client/pull/2983))
* You can now add descriptions to requests and examples across every protocol, and they render in your published API docs. ([#3010](https://github.com/requestly/requestly-api-client/pull/3010))
### ✨ Improvements
* The request history list now loads and scrolls smoothly even with thousands of entries, and history search no longer stutters as you type. ([#2972](https://github.com/requestly/requestly-api-client/pull/2972), [#2961](https://github.com/requestly/requestly-api-client/pull/2961))
* The Collection Runner and large request lists feel more responsive thanks to reduced re-rendering. ([#2969](https://github.com/requestly/requestly-api-client/pull/2969), [#2962](https://github.com/requestly/requestly-api-client/pull/2962))
### 🐛 Fixes
* The desktop app now opens external links only over secure HTTPS connections and restricts in-app navigation to trusted origins, protecting you against malicious links. ([#3089](https://github.com/requestly/requestly-api-client/pull/3089))
* Desktop vault files are now readable only by their owner, so your stored secrets stay private on shared machines. ([#3001](https://github.com/requestly/requestly-api-client/pull/3001))
* Fixed a freeze in the API specification editor caused by an infinite render loop in the governance flow. ([#3065](https://github.com/requestly/requestly-api-client/pull/3065))
* The desktop terminal now closes its sessions when you delete a project, and new terminal sessions are limited to local projects. ([#3031](https://github.com/requestly/requestly-api-client/pull/3031))
* Fixed a server-side issue where saving role or permission changes at the same time could fail. ([#3018](https://github.com/requestly/requestly-api-client/pull/3018))
* Added safeguards that limit the number of concurrent import tasks per user and project, keeping imports reliable under load. ([#3046](https://github.com/requestly/requestly-api-client/pull/3046))
### 🚀 New
* When importing an OpenAPI file, you can now choose to create a collection, an API specification, or both together in a single step. ([#2973](https://github.com/requestly/requestly-api-client/pull/2973))
### 🐛 Fixes
* On Windows, the sign-in dialog now stays open and offers a "Copy the URL" option when your default browser fails to launch, so you can complete the login without getting stuck. ([#2894](https://github.com/requestly/requestly-api-client/pull/2894))
* Pasting a cURL command whose URL contains unencoded spaces now imports correctly instead of being rejected. ([#3027](https://github.com/requestly/requestly-api-client/pull/3027))
* Importing a Postman collection now correctly preserves query parameters defined in request examples. ([#2899](https://github.com/requestly/requestly-api-client/pull/2899))
* Signing up with an email and password now requires at least 8 characters, preventing accounts with weak credentials from being created. ([#3016](https://github.com/requestly/requestly-api-client/pull/3016))
* Adding a new route in the Mock Server now automatically selects it so you can start editing immediately, and the rule row controls are visually aligned. ([#2893](https://github.com/requestly/requestly-api-client/pull/2893))
### 🚀 New
* If your organization is subject to data-residency restrictions, you now see a clear compliance notice on sign-in with a sign-out option, instead of hitting an unexpected error. ([#2963](https://github.com/requestly/requestly-api-client/pull/2963))
### 🐛 Fixes
* Importing a Postman data-export ZIP no longer shows a false error for the archive metadata file bundled by Postman, and imports that finish with warnings now display a 'What needs attention' summary instead of a generic success message. ([#2931](https://github.com/requestly/requestly-api-client/pull/2931))
* Fixed a server-side issue that caused login failures and widespread errors when multiple users signed in at the same time. ([#2991](https://github.com/requestly/requestly-api-client/pull/2991))
### 🚀 New
* You can now click 'View changelog' in the desktop update notification to read what changed before restarting to install the update. ([#2904](https://github.com/requestly/requestly-api-client/pull/2904))
### 🐛 Fixes
* Fixed security issues in the desktop vault where a crash during startup could erase your stored secrets, vault folders were readable by other users on shared machines, and crafted symbolic links could affect files outside the vault. ([#2891](https://github.com/requestly/requestly-api-client/pull/2891))
* When adding a team member or resending an invitation fails, you now see the specific reason from the server instead of a generic error message. ([#2956](https://github.com/requestly/requestly-api-client/pull/2956))
* Fixed a bug in the desktop terminal where commands installed via login-profile tools (such as Homebrew, nvm, or Volta) were not found, and fixed a separate issue where the cursor would jump unexpectedly when resizing the terminal panel. ([#2958](https://github.com/requestly/requestly-api-client/pull/2958))
* Fixed an error that prevented 'Update Collections' from applying content changes when syncing a collection from an API specification. ([#2949](https://github.com/requestly/requestly-api-client/pull/2949))
### 🚀 New
* You can now open an embedded terminal in the Dev Tools panel of the desktop app, with support for multiple concurrent sessions in tabs. ([#2863](https://github.com/requestly/requestly-api-client/pull/2863))
* Each operation in the published API docs reader now has its own shareable URL, so you can link teammates directly to a specific endpoint. ([#2922](https://github.com/requestly/requestly-api-client/pull/2922))
### ✨ Improvements
* Press Mod+K while viewing published API docs to jump straight to the outline search field. ([#2940](https://github.com/requestly/requestly-api-client/pull/2940))
* Published API docs now render oneOf and anyOf schema compositions with clearly labeled sections, making complex request and response shapes easier to read. ([#2934](https://github.com/requestly/requestly-api-client/pull/2934))
* Schema property descriptions in published API docs now render markdown formatting, so code snippets, bold text, and links display as intended instead of as raw markup. ([#2928](https://github.com/requestly/requestly-api-client/pull/2928))
* Published API docs now correctly display response headers and link sections, and resolve schemas that are defined at the top level of your spec. ([#2927](https://github.com/requestly/requestly-api-client/pull/2927))
### 🐛 Fixes
* Proxy settings now show a clear validation error for out-of-range port numbers, automatically remove any http\:// or https\:// prefix you type in the host field, and require both username and password when authentication is turned on. ([#2846](https://github.com/requestly/requestly-api-client/pull/2846))
* Fixed an issue where triggering a scheduled run returned a permissions error immediately after signing in. ([#2918](https://github.com/requestly/requestly-api-client/pull/2918))
### ✨ Improvements
* Collection imports now show a real progress bar with live status instead of a bare spinner. ([#2787](https://github.com/requestly/requestly-api-client/pull/2787))
* Invalid project names are now flagged with a clear message before you create or rename a project, instead of failing afterward. ([#2892](https://github.com/requestly/requestly-api-client/pull/2892))
* Legacy Postman scripts that use deprecated variables now keep working in the default safe sandbox, with a deprecation warning instead of a silent error. ([#2912](https://github.com/requestly/requestly-api-client/pull/2912))
* In published API docs, the outline now highlights and follows the section you are reading as you scroll. ([#2917](https://github.com/requestly/requestly-api-client/pull/2917))
### 🐛 Fixes
* Markdown editing is now readable in light mode, with syntax markers that match your theme. ([#2859](https://github.com/requestly/requestly-api-client/pull/2859))
### ✨ Improvements
* Published docs render OpenAPI schemas more faithfully. ([#2878](https://github.com/requestly/requestly-api-client/pull/2878))
### 🐛 Fixes
* You can now unstage files in a brand-new repository that has no commits yet. ([#2879](https://github.com/requestly/requestly-api-client/pull/2879))
### 🚀 New
* View specs from multiple projects together in the Specs sidebar. ([#2860](https://github.com/requestly/requestly-api-client/pull/2860))
### ✨ Improvements
* Published docs now group endpoints by tag for easier navigation. ([#2873](https://github.com/requestly/requestly-api-client/pull/2873))
### 🐛 Fixes
* Viewer-role users no longer see create and edit actions they cannot perform. ([#2758](https://github.com/requestly/requestly-api-client/pull/2758))
* GraphQL request variables now keep their typed values intact when saved. ([#2867](https://github.com/requestly/requestly-api-client/pull/2867))
### 🚀 New
* Scripts gain a full request-execution namespace with setNextRequest, skipRequest, runRequest, and location. ([#2849](https://github.com/requestly/requestly-api-client/pull/2849))
* Scripts can now clear request headers for Postman parity. ([#2832](https://github.com/requestly/requestly-api-client/pull/2832))
* Scripts can now clear environment, global, and collection variables for Postman parity. ([#2854](https://github.com/requestly/requestly-api-client/pull/2854))
* Bulk-delete mock routes by path prefix. ([#2811](https://github.com/requestly/requestly-api-client/pull/2811))
### ✨ Improvements
* The API Design versions pane now shows documentation status and has a collapsible header. ([#2818](https://github.com/requestly/requestly-api-client/pull/2818))
* The Specs and Components sidebar is now collapsible and resizable. ([#2845](https://github.com/requestly/requestly-api-client/pull/2845))
### 🚀 New
* Configure proxy settings in the desktop app. ([#2726](https://github.com/requestly/requestly-api-client/pull/2726))
* Run a collection from the command line with a new Run via CLI option on the Collection Runner. ([#2795](https://github.com/requestly/requestly-api-client/pull/2795))
* Copy a request's ID with a new Copy Request ID button in every protocol editor. ([#2856](https://github.com/requestly/requestly-api-client/pull/2856))
### 🐛 Fixes
* Fixed the URL field freezing when you switch tabs quickly. ([#2785](https://github.com/requestly/requestly-api-client/pull/2785))
* Fixed collection variables being incorrectly read-only in safe mode. ([#2819](https://github.com/requestly/requestly-api-client/pull/2819))
### 🚀 New
* Request capture now follows redirect hops and handles Digest/NTLM challenges and GraphQL introspection. ([#2746](https://github.com/requestly/requestly-api-client/pull/2746))
* Create multiple mock routes at once, including their nested responses and rules. ([#2759](https://github.com/requestly/requestly-api-client/pull/2759))
* Stash your Git changes from a new stash view, with indicators shown across the app. ([#2774](https://github.com/requestly/requestly-api-client/pull/2774))
### ✨ Improvements
* Scripts can now modify request headers in both scripting engines. ([#2783](https://github.com/requestly/requestly-api-client/pull/2783))
* The Git sidebar panel is tidier with collapsible sections, a change-count badge, and clearer error messages. ([#2775](https://github.com/requestly/requestly-api-client/pull/2775))
### 🐛 Fixes
* Importing a partial Requestly export now re-parents orphaned items so nothing goes missing. ([#2782](https://github.com/requestly/requestly-api-client/pull/2782))
### 🚀 New
* Cloning a repository now discovers and sets up any Requestly project it contains automatically. ([#2768](https://github.com/requestly/requestly-api-client/pull/2768))
* Resolve merge conflicts with a new two-way conflict resolution view. ([#2769](https://github.com/requestly/requestly-api-client/pull/2769))
### ✨ Improvements
* Scripts now run on a faster, more reliable safe-mode engine, including full support on Windows. ([#2731](https://github.com/requestly/requestly-api-client/pull/2731))
### 🐛 Fixes
* Fixed duplicate key-value row identifiers that could appear when loading a request. ([#2756](https://github.com/requestly/requestly-api-client/pull/2756))
* Fixed a false Body-tab indicator dot and corrected the skipped-request count in Run History. ([#2766](https://github.com/requestly/requestly-api-client/pull/2766))
### 🚀 New
* DevTools now captures OAuth token fetches that the app makes on your behalf. ([#2697](https://github.com/requestly/requestly-api-client/pull/2697))
* A new Git Providers settings page lets you connect accounts, and you can enter or update a personal access token mid-operation when authentication is needed. ([#2735](https://github.com/requestly/requestly-api-client/pull/2735))
* Create, switch, and pick Git branches directly from a branch picker. ([#2736](https://github.com/requestly/requestly-api-client/pull/2736))
* Browse and select GitHub repositories from a built-in repo picker. ([#2737](https://github.com/requestly/requestly-api-client/pull/2737))
### ✨ Improvements
* Search your projects and see them sorted alphabetically. ([#2739](https://github.com/requestly/requestly-api-client/pull/2739))
### 🚀 New
* You can now publish collection documentation and share it via a public reader page with public, internal, or password access. ([#2649](https://github.com/requestly/requestly-api-client/pull/2649))
### ✨ Improvements
* Scripts now show a deprecation warning when using old Postman-style identifiers. ([#2699](https://github.com/requestly/requestly-api-client/pull/2699))
### 🐛 Fixes
* Fixed four API client bugs across request and collection workflows. ([#2730](https://github.com/requestly/requestly-api-client/pull/2730))
* Fixed JSONPath navigation for bracketed keys and a missing duplicate-example notification. ([#2728](https://github.com/requestly/requestly-api-client/pull/2728))
* Local file moves now report all naming conflicts instead of failing silently. ([#2724](https://github.com/requestly/requestly-api-client/pull/2724))
### 🚀 New
* You can now download a response body directly to a file. ([#2567](https://github.com/requestly/requestly-api-client/pull/2567))
* Added Postman-like JSONPath filtering to the response Pretty view. ([#2661](https://github.com/requestly/requestly-api-client/pull/2661))
* Added a line-wrap toggle to the JSON Pretty view in the response viewer. ([#2647](https://github.com/requestly/requestly-api-client/pull/2647))
### 🐛 Fixes
* JWT auth now shows the signed preview token in auto-generated headers and query params. ([#2648](https://github.com/requestly/requestly-api-client/pull/2648))
* Long lists such as projects, mocks, and specifications now load every page instead of stopping short. ([#2688](https://github.com/requestly/requestly-api-client/pull/2688))
* Fixed key-value rows that could share an id and behave incorrectly. ([#2629](https://github.com/requestly/requestly-api-client/pull/2629))
### 🚀 New
* Binary response bodies are now preserved losslessly, with image previews in the response viewer. ([#2596](https://github.com/requestly/requestly-api-client/pull/2596))
* Added a Commits view with a commit-graph rail for Git-backed projects. ([#2404](https://github.com/requestly/requestly-api-client/pull/2404))
### 🐛 Fixes
* OAuth2 now shows the fetched token in the panel and the auto-generated Authorization header. ([#2617](https://github.com/requestly/requestly-api-client/pull/2617))
* Fixed several MQTT issues including auth on connect, a tab-close leak, and publishing with embedded variables. ([#2598](https://github.com/requestly/requestly-api-client/pull/2598))
### 🚀 New
* Added App Settings rows to configure eight default behaviors for HTTP and GraphQL requests. ([#2390](https://github.com/requestly/requestly-api-client/pull/2390))
* Added rq.sendRequest in scripts for parity with Postman's pm.sendRequest. ([#2582](https://github.com/requestly/requestly-api-client/pull/2582))
* Added several quality-of-life improvements to the WebSocket and Socket.IO editors. ([#2531](https://github.com/requestly/requestly-api-client/pull/2531))
### ✨ Improvements
* Importers now show clearer, more accurate reasons when an import fails. ([#2227](https://github.com/requestly/requestly-api-client/pull/2227))
### 🐛 Fixes
* Imports no longer fail on partial legacy auth objects, placeholder cookies, or null key names. ([#2523](https://github.com/requestly/requestly-api-client/pull/2523))
* Fixed drag-and-drop reordering of collections reverting when items had tied ranks. ([#2590](https://github.com/requestly/requestly-api-client/pull/2590))
### ✨ Improvements
* Hardened sign-in and mock server handling against abuse. ([#2510](https://github.com/requestly/requestly-api-client/pull/2510))
### 🐛 Fixes
* Duplicate request headers that differ only in letter case are now collapsed correctly. ([#2501](https://github.com/requestly/requestly-api-client/pull/2501))
### 🚀 New
* The Tests tab now shows how many tests passed out of the total, with pass and fail color coding. ([#2461](https://github.com/requestly/requestly-api-client/pull/2461))
### ✨ Improvements
* Projects now open faster by deferring background data loading until it is actually needed. ([#2475](https://github.com/requestly/requestly-api-client/pull/2475))
### 🐛 Fixes
* Fixed several desktop app crashes during startup, shell loading, and when a config file was corrupt. ([#2369](https://github.com/requestly/requestly-api-client/pull/2369))
* Re-imported global variables now correctly merge instead of losing their global scope. ([#2456](https://github.com/requestly/requestly-api-client/pull/2456))
* Searching collections now shows a clear empty state when no results match. ([#2476](https://github.com/requestly/requestly-api-client/pull/2476))
### ✨ Improvements
* You now get a success toast when switching environments. ([#2425](https://github.com/requestly/requestly-api-client/pull/2425))
* The active history entry is now highlighted and its font matches collections. ([#2421](https://github.com/requestly/requestly-api-client/pull/2421))
* Template variables are now highlighted in HTTP and GraphQL examples. ([#2435](https://github.com/requestly/requestly-api-client/pull/2435))
* MQTT expanded timeline messages now show the retain flag. ([#2433](https://github.com/requestly/requestly-api-client/pull/2433))
### 🐛 Fixes
* GraphQL variables editor now accepts template tokens. ([#2400](https://github.com/requestly/requestly-api-client/pull/2400))
* Switching an MQTT request from v5 to v3 now correctly removes the Properties tab from the URL. ([#2401](https://github.com/requestly/requestly-api-client/pull/2401))
### 🚀 New
* HTTP and GraphQL requests now have a per-request Settings tab with values that can inherit from parent levels. ([#2379](https://github.com/requestly/requestly-api-client/pull/2379))
* Manage reusable message-body templates in a dedicated Message Templates library. ([#2363](https://github.com/requestly/requestly-api-client/pull/2363))
### 🐛 Fixes
* Fixed sending GET requests with a body over HTTP/2. ([#2388](https://github.com/requestly/requestly-api-client/pull/2388))
* Switching authorization type now correctly drops stale fields from the previous type. ([#2377](https://github.com/requestly/requestly-api-client/pull/2377))
* The Vault now surfaces the real reason when an operation fails. ([#2380](https://github.com/requestly/requestly-api-client/pull/2380))
* The WSDL import button now enables only when the URL matches a valid pattern as you type. ([#2355](https://github.com/requestly/requestly-api-client/pull/2355))
### 🚀 New
* Save and reuse WebSocket and Socket.IO examples. ([#2285](https://github.com/requestly/requestly-api-client/pull/2285))
* gRPC proto file content now persists across sessions and syncs to the cloud. ([#2314](https://github.com/requestly/requestly-api-client/pull/2314))
### 🐛 Fixes
* Fixed gRPC stream panel preview, trailer overflow, and reflection method reset issues. ([#2209](https://github.com/requestly/requestly-api-client/pull/2209))
* Saving an HTTP, GraphQL, or gRPC request as new now keeps it in the right collection. ([#2325](https://github.com/requestly/requestly-api-client/pull/2325))
* GraphQL Send is now blocked when the query body is empty. ([#2337](https://github.com/requestly/requestly-api-client/pull/2337))
* URL-bar encoding is preserved when you toggle a query parameter on or off. ([#2333](https://github.com/requestly/requestly-api-client/pull/2333))
### 🚀 New
* Reuse saved message templates, beautify XML, and get clearer connection-state feedback in realtime clients. ([#2277](https://github.com/requestly/requestly-api-client/pull/2277))
### ✨ Improvements
* Added a Skip link to onboarding. ([#2311](https://github.com/requestly/requestly-api-client/pull/2311))
### 🐛 Fixes
* Discarding or saving variable edits no longer leaves phantom rows behind. ([#2292](https://github.com/requestly/requestly-api-client/pull/2292))
* The authorization info banner now shows the correct text when an API key is placed in query params. ([#2293](https://github.com/requestly/requestly-api-client/pull/2293))
* URL fragments are now stripped from query-parameter parsing so they no longer pollute your params. ([#2299](https://github.com/requestly/requestly-api-client/pull/2299))
* Validation errors are now shown verbatim when saving, so you know exactly what went wrong. ([#2305](https://github.com/requestly/requestly-api-client/pull/2305))
### 🚀 New
* Build and send Socket.IO requests with a dedicated editor. ([#2202](https://github.com/requestly/requestly-api-client/pull/2202))
* Import environment variables directly from a .env file. ([#2254](https://github.com/requestly/requestly-api-client/pull/2254))
* Save and reuse MQTT examples on both cloud and local projects. ([#2261](https://github.com/requestly/requestly-api-client/pull/2261))
* Import and export WebSocket and Socket.IO requests in Requestly's native format. ([#2278](https://github.com/requestly/requestly-api-client/pull/2278))
### 🐛 Fixes
* XML responses now keep leaf elements inline for easier reading. ([#2269](https://github.com/requestly/requestly-api-client/pull/2269))
* Scripts now preserve boolean and number types when reading values instead of converting them to strings. ([#2276](https://github.com/requestly/requestly-api-client/pull/2276))
### 🚀 New
* Connect a local project to Git directly inside the desktop app. ([#2194](https://github.com/requestly/requestly-api-client/pull/2194))
* MQTT requests can now be imported and exported in Requestly's native format. ([#2251](https://github.com/requestly/requestly-api-client/pull/2251))
### ✨ Improvements
* MQTT message timelines now display byte-probed formats and MQTT v5 properties more clearly. ([#2230](https://github.com/requestly/requestly-api-client/pull/2230))
### 🐛 Fixes
* MQTT topic subscriptions stay stable and reconcile correctly when you reconnect. ([#2231](https://github.com/requestly/requestly-api-client/pull/2231))
* The JSON editor no longer flags placeholders as syntax errors. ([#2233](https://github.com/requestly/requestly-api-client/pull/2233))
* You can now select multiple files at once in the import drop zone. ([#2239](https://github.com/requestly/requestly-api-client/pull/2239))
### 🚀 New
* Added the WebSocket request editor with a live message timeline and connect/disconnect controls. ([#2181](https://github.com/requestly/requestly-api-client/pull/2181))
* MQTT requests can now be saved to cloud and local projects. ([#2195](https://github.com/requestly/requestly-api-client/pull/2195))
### 🐛 Fixes
* Collections now warn when you try to save an empty name in the overview editor. ([#2190](https://github.com/requestly/requestly-api-client/pull/2190))
* Renaming an item now blocks saving and shows an error when the name is left empty. ([#2192](https://github.com/requestly/requestly-api-client/pull/2192))
* gRPC error responses now preserve trailers and report the correct status. ([#2200](https://github.com/requestly/requestly-api-client/pull/2200))
### 🚀 New
* Added the MQTT request editor with message, topics, authorization, properties, and last will tabs. ([#2047](https://github.com/requestly/requestly-api-client/pull/2047))
* Added a keyboard shortcuts modal you can open from the Help menu or with Cmd+/. ([#2131](https://github.com/requestly/requestly-api-client/pull/2131))
### ✨ Improvements
* gRPC service discovery now supports importing a proto file. ([#2156](https://github.com/requestly/requestly-api-client/pull/2156))
* gRPC requests now support pre and post scripts and per-protocol editor autocompletion. ([#2125](https://github.com/requestly/requestly-api-client/pull/2125))
### 🐛 Fixes
* The collection runner now clamps out-of-range iteration and delay values and warns you. ([#2150](https://github.com/requestly/requestly-api-client/pull/2150))
* Fixed Mock Server showing blank responses and rule errors after editing. ([#2171](https://github.com/requestly/requestly-api-client/pull/2171))
### 🚀 New
* Added the Mock Server with a sidebar, editor, and drag-to-reorder for routes. ([#2066](https://github.com/requestly/requestly-api-client/pull/2066))
* You can now drag to reorder environment variables. ([#2091](https://github.com/requestly/requestly-api-client/pull/2091))
### ✨ Improvements
* Expanded the gRPC client with a config panel, authentication, custom metadata, and message template generation. ([#2087](https://github.com/requestly/requestly-api-client/pull/2087))
* Added grpcurl code generation for gRPC requests. ([#2126](https://github.com/requestly/requestly-api-client/pull/2126))
* Response header details now collapse progressively to fit narrower panels. ([#2102](https://github.com/requestly/requestly-api-client/pull/2102))
### 🚀 New
* Added an MQTT client for connecting to brokers and publishing messages. ([#2013](https://github.com/requestly/requestly-api-client/pull/2013))
### ✨ Improvements
* Exports to Postman and OpenAPI now carry over five additional authentication types. ([#2046](https://github.com/requestly/requestly-api-client/pull/2046))
* gRPC requests now support saved examples, variable interpolation, and persistence. ([#2051](https://github.com/requestly/requestly-api-client/pull/2051))
### 🐛 Fixes
* Inherited OAuth 2.0 authentication now resolves correctly and renders its config variables. ([#2082](https://github.com/requestly/requestly-api-client/pull/2082))
* Fixed a Windows issue where renaming files in a local project produced broken paths. ([#1840](https://github.com/requestly/requestly-api-client/pull/1840))
* Generated client code no longer percent-encodes your template variables incorrectly. ([#2073](https://github.com/requestly/requestly-api-client/pull/2073))
### 🚀 New
* Added AWS Signature v4 authentication with both live and presigned URL modes. ([#1912](https://github.com/requestly/requestly-api-client/pull/1912))
* Added NTLM authentication support on the desktop app. ([#1998](https://github.com/requestly/requestly-api-client/pull/1998))
### ✨ Improvements
* Added a report-issue entry to make it easier to send us feedback. ([#2027](https://github.com/requestly/requestly-api-client/pull/2027))
### 🐛 Fixes
* Importing older Requestly exports now restores environment variables that were missing an identifier. ([#2021](https://github.com/requestly/requestly-api-client/pull/2021))
* Empty or corrupt local project files no longer break loading. ([#1986](https://github.com/requestly/requestly-api-client/pull/1986))
### 🚀 New
* Added app-wide back and forward navigation buttons so you can move through screens you've visited. ([#1974](https://github.com/requestly/requestly-api-client/pull/1974))
* Introduced the gRPC client with support for streaming requests. ([#1951](https://github.com/requestly/requestly-api-client/pull/1951))
### ✨ Improvements
* Opening a specification tab for the first time is now faster. ([#1980](https://github.com/requestly/requestly-api-client/pull/1980))
### 🐛 Fixes
* Creating a custom package with a duplicate name now shows a clear conflict message instead of a server error. ([#1978](https://github.com/requestly/requestly-api-client/pull/1978))
* GraphQL responses that return HTML no longer crash response parsing. ([#1989](https://github.com/requestly/requestly-api-client/pull/1989))
### 🚀 New
* Send and inspect gRPC requests with the new gRPC support. ([#1917](https://github.com/requestly/requestly-api-client/pull/1917))
### ✨ Improvements
* Environments are now sorted alphabetically in the selector. ([#1949](https://github.com/requestly/requestly-api-client/pull/1949))
* Clearer drag-and-drop indicators when reordering collections. ([#1962](https://github.com/requestly/requestly-api-client/pull/1962))
* Bottom panel dock preferences now persist across sessions. ([#1963](https://github.com/requestly/requestly-api-client/pull/1963))
### 🐛 Fixes
* The app now reloads automatically instead of erroring after a new version is deployed. ([#1811](https://github.com/requestly/requestly-api-client/pull/1811))
### 🚀 New
* Added SSL certificate support, including client certificates and custom CA certificates. ([#1797](https://github.com/requestly/requestly-api-client/pull/1797))
* Authenticate requests using HTTP Digest authentication. ([#1945](https://github.com/requestly/requestly-api-client/pull/1945))
* Design and edit OpenAPI specifications with a dedicated editor, issues panel, and governance checks. ([#1884](https://github.com/requestly/requestly-api-client/pull/1884))
### 🚀 New
* The Requestly CLI now supports running cloud collections. ([#1591](https://github.com/requestly/requestly-api-client/pull/1591))
* Added five new authentication types for securing your requests. ([#1784](https://github.com/requestly/requestly-api-client/pull/1784))
* Authenticate requests using JWT Bearer tokens with configurable payload directives. ([#1834](https://github.com/requestly/requestly-api-client/pull/1834))
### ✨ Improvements
* Collection trees now remember expansion state per project and added a collapse-all button. ([#1795](https://github.com/requestly/requestly-api-client/pull/1795))
### 🐛 Fixes
* The desktop window can now be dragged while the app is loading. ([#1809](https://github.com/requestly/requestly-api-client/pull/1809))
* Pasting a cURL command that is not a valid request no longer fails silently. ([#1923](https://github.com/requestly/requestly-api-client/pull/1923))
### 🚀 New
* The desktop app now downloads updates in the background with a progress bar. ([#1587](https://github.com/requestly/requestly-api-client/pull/1587))
* Configure OAuth 2.0 and view the resulting token directly in the Authorization tab. ([#1696](https://github.com/requestly/requestly-api-client/pull/1696))
### 🐛 Fixes
* Requests and environments now appear correctly when viewing multiple projects. ([#1773](https://github.com/requestly/requestly-api-client/pull/1773))
* Variable values are now preserved when migrating local projects from the previous app. ([#1775](https://github.com/requestly/requestly-api-client/pull/1775))
* Aligned the sidebar default sort order with the previous app. ([#1776](https://github.com/requestly/requestly-api-client/pull/1776))
### 🚀 New
* Migrate your local projects from the previous desktop app into Requestly. ([#1630](https://github.com/requestly/requestly-api-client/pull/1630))
* Complete interactive OAuth flows through a hosted callback so login redirects work on desktop. ([#1672](https://github.com/requestly/requestly-api-client/pull/1672))
### 🐛 Fixes
* Fixed imports of older collections and environments that previously failed to load. ([#1748](https://github.com/requestly/requestly-api-client/pull/1748))
* Importing now merges into your existing global environment instead of failing with a conflict. ([#1739](https://github.com/requestly/requestly-api-client/pull/1739))
### 🚀 New
* Run your collections from the command line with the new Requestly CLI. ([#1541](https://github.com/requestly/requestly-api-client/pull/1541))
* Authenticate requests with OAuth 2.0, including a token service and orchestration. ([#1596](https://github.com/requestly/requestly-api-client/pull/1596))
* Use non-interactive OAuth 2.0 grants with automatic token refresh. ([#1648](https://github.com/requestly/requestly-api-client/pull/1648))
* Sign requests with OAuth 1.0 directly from the Authorization tab. ([#1572](https://github.com/requestly/requestly-api-client/pull/1572))
### ✨ Improvements
* Added contextual help hints across the API client. ([#1659](https://github.com/requestly/requestly-api-client/pull/1659))
### 🐛 Fixes
* Older imported records without an explicit type now correctly default to HTTP requests. ([#1674](https://github.com/requestly/requestly-api-client/pull/1674))
### 🚀 New
* An app-wide cookie jar lets you manage cookies with a Postman-style experience. ([#1622](https://github.com/requestly/requestly-api-client/pull/1622))
* Import much larger files, with the limit raised from 30 MB to 100 MB. ([#1550](https://github.com/requestly/requestly-api-client/pull/1550))
* Import API definitions from SoapUI projects. ([#1531](https://github.com/requestly/requestly-api-client/pull/1531))
* Import an exported Requestly project archive directly. ([#1602](https://github.com/requestly/requestly-api-client/pull/1602))
### ✨ Improvements
* Add a description column to the request headers editor. ([#1601](https://github.com/requestly/requestly-api-client/pull/1601))
* Clear the script package cache with a new button to reclaim disk space. ([#1524](https://github.com/requestly/requestly-api-client/pull/1524))
### 🚀 New
* Use npm packages directly in your scripts, with search and one-click install. ([#1467](https://github.com/requestly/requestly-api-client/pull/1467))
### ✨ Improvements
* Postman imports now translate npm and jsr package requires in scripts. ([#1520](https://github.com/requestly/requestly-api-client/pull/1520))
* The package library now always shows its split layout for a steadier view. ([#1502](https://github.com/requestly/requestly-api-client/pull/1502))
### 🐛 Fixes
* The package library Save button now matches the size of other editors. ([#1509](https://github.com/requestly/requestly-api-client/pull/1509))
### 🚀 New
* Run GraphQL subscriptions on the desktop app. ([#1398](https://github.com/requestly/requestly-api-client/pull/1398))
* Create and reuse custom script packages across your requests with a new package library. ([#1451](https://github.com/requestly/requestly-api-client/pull/1451))
* An SSL verification indicator now appears in the footer. ([#1472](https://github.com/requestly/requestly-api-client/pull/1472))
### 🐛 Fixes
* Postman export now preserves template-prefixed URLs. ([#1466](https://github.com/requestly/requestly-api-client/pull/1466))
* Scripts that use a top-level return now have their Postman-style calls transformed correctly. ([#1428](https://github.com/requestly/requestly-api-client/pull/1428))
### 🚀 New
* Import HAR files directly, with captured requests turned into examples. ([#1357](https://github.com/requestly/requestly-api-client/pull/1357))
* Local filesystem projects now detect and sync changes made outside the app. ([#1386](https://github.com/requestly/requestly-api-client/pull/1386))
### 🐛 Fixes
* The Debug tab stays accessible even when a response returns an error. ([#1450](https://github.com/requestly/requestly-api-client/pull/1450))
* HTTP/2 pseudo-headers are now filtered out of requests imported from HAR. ([#1446](https://github.com/requestly/requestly-api-client/pull/1446))
* Postman export no longer wraps the collection in a duplicate root entry. ([#1456](https://github.com/requestly/requestly-api-client/pull/1456))
### 🚀 New
* Inspect outgoing requests with new DevTools Console and Network panels. ([#1362](https://github.com/requestly/requestly-api-client/pull/1362))
* Toggle SSL certificate verification on or off per request. ([#1390](https://github.com/requestly/requestly-api-client/pull/1390))
### ✨ Improvements
* Empty projects now show helpful call-to-action prompts, and project creation is simpler. ([#1343](https://github.com/requestly/requestly-api-client/pull/1343))
### 🐛 Fixes
* Template variables in the URL bar are now preserved, and dynamic variables resolve in code snippets. ([#1377](https://github.com/requestly/requestly-api-client/pull/1377))
* Postman imports with array-based form-data file sources now parse correctly. ([#1401](https://github.com/requestly/requestly-api-client/pull/1401))
* Root collection descriptions now import from Postman, and the overview scrollbar is hidden. ([#1410](https://github.com/requestly/requestly-api-client/pull/1410))
### 🚀 New
* Run bulk operations on examples and import them from supported formats. ([#1296](https://github.com/requestly/requestly-api-client/pull/1296))
* Create examples instantly from the sidebar and save them from a new dropdown. ([#1348](https://github.com/requestly/requestly-api-client/pull/1348))
### ✨ Improvements
* Persisted example tabs now show a "Try it" button in place of Send. ([#1358](https://github.com/requestly/requestly-api-client/pull/1358))
* Redesigned confirmation dialogs for clearer, more readable prompts. ([#1316](https://github.com/requestly/requestly-api-client/pull/1316))
### 🐛 Fixes
* Variables now resolve correctly in generated code snippets, and request body content type is set properly. ([#1361](https://github.com/requestly/requestly-api-client/pull/1361))
* Invalid GraphQL variables now show an inline validation error instead of failing silently. ([#1373](https://github.com/requestly/requestly-api-client/pull/1373))
* Importing from cURL no longer carries over a stale Content-Length header. ([#1366](https://github.com/requestly/requestly-api-client/pull/1366))
# Team projects
Source: https://docs.requestly.com/collaboration/how-to-get-started-with-shared-workspace
Learn how to set up a team project in Requestly
Requestly’s **team and shared projects** make collaboration easy by **syncing** all **project data** so members can work together on **HTTP rules, mock APIs, the API client, and sessions**. Whether you're debugging, testing, or managing API workflows, a shared project keeps your team in sync and productive.
### Setting up a shared project
Let's create a shared project and invite teammates to collaborate in real time. Follow these simple steps to get started.
### Create a project
In the top-left corner of the sidebar, find the project dropdown (you start in a project named **Default Project**).
Click the project dropdown. The switcher lists your **Local projects** and **Team projects**, each with a create option.
Click **Create a team project** to make a shared project (or **Create a local project** for a device-only project). Enter a name for your project in the provided field and click **Create project**.
You can also check the checkbox at the bottom of this popup to invite your entire team while creating the project.
## Managing team members
If your account is managed through a **BrowserStack organization**, project creation and member management happen on the **BrowserStack projects dashboard** instead of in the app. In that case the create and member controls open the BrowserStack dashboard, and your changes sync back into Requestly automatically.
To effectively manage access, admins can add team members, update their roles, or remove team members within a project. Below are the steps to perform these actions.
### Adding new members
Navigate to the Requestly dashboard and switch to the project where you want to add members.
In the project switcher, hover the project row and click the **Project settings** gear (or **Add members**).
From here you can open the **Members** tab to see the current members before inviting.
In the **Members** tab, use the **Add member** form.
Enter your teammates email addresses and assign them specific roles.
Invited members will receive an email to join the project. Once they accept, they will appear in the members list.
### Removing members
Navigate to the Requestly dashboard and switch to the project where you want to remove members.
In the project switcher, hover the project row and click the **Project settings** gear (or **Add members**).
Locate the member you want to remove from the members’ list. Click the 3-dot menu next to their role and select **Remove user from project**.
A confirmation prompt will appear. Confirm the action to remove the member successfully.
If a member has been invited but not yet joined, you can revoke their invite from the same dropdown.
# Managing your project
Source: https://docs.requestly.com/collaboration/how-to-get-started-with-shared-workspace/managing-workspace
Learn how to manage projects in Requestly
### Renaming a project
Projects can be renamed by following these steps
In the Requestly dashboard, locate and click on your project name at the top.
From the dropdown or navigation menu, select **Project Settings**.
In the **Project Settings** section, find the **Project Name** field and enter the new name
Click the **Save Changes** button to apply the new project name.
### Delete a project
Projects can be deleted using the **Delete Project** button in the project settings
Deleted projects and their contents are retained for 7 days before being permanently removed. See the [Data Recovery Policy](../../account/data-recovery) if you need to restore a deleted project.
# User Roles and Permissions
Source: https://docs.requestly.com/collaboration/how-to-get-started-with-shared-workspace/user-roles
Learn how to manage team collaboration securely in Requestly with Role-Based Access Control (RBAC) by defining roles and setting permissions.
***
Requestly enhances collaboration and security by allowing project admins to assign specific roles to users. This role-based access control (RBAC) ensures that only authorized members can access sensitive configurations, such as API keys and authentication tokens, and helps prevent unauthorised modifications.
In this doc, you'll learn how Requestly's RBAC works, the specific roles available, the permissions associated with each role, and how to change user roles within your project
## How RBAC Works in Requestly
Requestly uses role-based access control (RBAC) to ensure that every team member only gets access to what they need. It has three roles, **Admin**, **User**, and **Viewer**, each with permissions that protect sensitive data like API keys and tokens and reduce mistakes or unauthorised changes, making teamwork smoother and more efficient.
## User Roles and Their Permissions
Each project has three roles, each with distinct permissions:
#### **Admin**
* Full control over **project settings, member management, and permissions**.
* Can **create, edit, delete, and execute** API requests, collections, and environments.
#### **User**
* Can **create, edit, delete, and execute** API requests, collections, and environments.
* **Cannot** manage team settings, members, or project-wide configurations.
#### **Viewer**
Viewers cannot edit API requests, but they can **execute** them.
* **Read-only access**.
* Can **view and execute** API requests, collections, and environments but **cannot make any changes** or access sensitive project settings.
### Permissions Table
Below is a table that outlines key permissions for each role:
| **Permission** | **Admin** | **User** | **Viewer** |
| -------------- | --------- | ----------------- | ---------- |
| Add a new user | ✅ | ✅ (Add as a user) | ❌ |
| Remove a user | ✅ | ❌ | ❌ |
| **Permission** | **Admin** | **User** | **Viewer** |
| --------------------------------------------------------- | --------- | -------- | ---------- |
| Send a request | ✅ | ✅ | ✅ |
| Save, update, or delete a request | ✅ | ✅ | ❌ |
| Create, update, or delete a collection | ✅ | ✅ | ❌ |
| Switch an environment | ✅ | ✅ | ✅ |
| Create, update, or delete a Environment variable | ✅ | ✅ | ❌ |
| Define current/local values in a Environment variable | ✅ | ✅ | ✅ |
| View secrets | ✅ | ✅ | ❌ |
| Export Requests, Collections and Environment | ✅ | ✅ | ❌ |
| Create new draft requests | ✅ | ✅ | ❌ |
| Import collection/environments from Requestly and Postman | ✅ | ✅ | ❌ |
| Import cURL | ✅ | ✅ | ❌ |
## Changing Roles
At times, you may need to update a team member’s role. Follow these steps to change roles within your project:
Navigate to the Requestly dashboard and switch to the project where you want to add members.
In the project switcher, hover the project row and click the **Project settings** gear.
Find the member whose role you want to change in the members list.
Use the dropdown next to their name to select the new role (e.g. Admin, User, or Viewer) and confirm the change.
# Local project
Source: https://docs.requestly.com/collaboration/local-workspace
Learn how to set up local projects in Requestly
**Local project** in Requestly, like [team projects](https://docs.requestly.com/collaboration/how-to-get-started-with-shared-workspace), is a way to isolate your work. The key difference is that it stores all your data on your local system, ensuring full privacy. Your collections, requests, and environment data stay on your device and can’t be accessed by anyone else
Local project data lives entirely on your device, so it is not backed up by Requestly and cannot be restored by our team if deleted. See the [Data Recovery Policy](../account/data-recovery) for details.
## **How to create a local project**
Click on the **current project name** at the top-left corner of the app to open the project dropdown.
In the project switcher, click **Create a local project** to start the setup.
Select **“Local project”** as the project type. Enter a **project name** and choose a **folder** where all configurations and API data will be stored.
Once all details are entered, click **“Create”** to finalize the setup. Your local project is now ready to use!
## **How to delete a local project**
Click the **current project name** in the top left to open the project dropdown.
Select the local project you want to remove and open its **Settings**.
You can also delete any related files or folders stored on your device if you want to clean up everything linked to that project
Click **Delete Project** and confirm the action by entering the project name. Then click the **Delete Project** button to complete the removal.
# Working with multiple projects
Source: https://docs.requestly.com/collaboration/multiple-workspaces
Requestly allows you to **work with multiple local projects at once**. This makes it easier to collaborate across services (Auth, Payments, Orders, etc.) without merging everything into a single project.
**Note:** Multi-project view works only with **local projects** at this time.
## How to use multiple projects
Follow these steps to open multiple local projects in one view:
Open Requestly and navigate to the **API tab** from the sidebar.
In the top-left corner, click on your current project name to open the **project selector** dropdown.
Check the boxes next to the local projects you want to load together.
Your chosen projects will appear grouped in the selector.
That’s it! You can now test APIs across multiple projects in one seamless view.
## Using environments in multi-project view
When working with multiple projects, each project keeps its own **separate environment**. This ensures that variables from one project do not interfere with another.
### **Switching environments**
You can switch environments using the **dropdown below the project name** in the sidebar. This lets you quickly toggle between different setups for the same project.
### **Editing environment variables**
To edit variables for a project:
1. Go to the **Environments tab**.
2. Select the project whose environment you want to edit.
3. You’ll see all variables for that project listed, and you can add, update, or remove them as needed.
## Moving requests across projects
You can easily move or share requests between different projects in multi-project view. There are two ways to do this:
### **Method 1: Drag and drop**
### **Method 2: Move via menu**
Click on the **three dots** menu next to the request you want to move.
Choose the **Move to Collection** option from the menu.
Select the target project and the collection within it where you want to move the request.
Click **Move** to complete the action. The request will now appear in the selected project and collection.
## Sharing data across projects
To share values (like tokens) across different projects, you can use [**Runtime Variables**](/api-client/environments-and-variables/runtime-variables). These act as **super-global variables** that are accessible across all projects. They can be created as temporary values for quick testing or persisted for longer use. You can view, edit, or clear them anytime from the **Runtime Variables tab** on the left.
# Introduction
Source: https://docs.requestly.com/collaboration/workspaces
Learn about projects and workspaces in Requestly, how to organize your rules, mocks, and API requests and collaborate with your team.
A **project** in Requestly (also called a **workspace** in the HTTP Interception section) is where you store all related rules, mock APIs, API requests, and collections in one place. It helps keep everything organized and easily accessible for better management and collaboration.
The API Client refers to these as **projects**. The HTTP Interception section refers to the same concept as **workspaces**. They are the same thing.
### Understanding projects
A Requestly project contains HTTP rules, API requests, collections, and mocks. By default, you start in a **private project**, where no other user can view or access your rules.
This setup is ideal for personal work or testing. However, you can create additional **team projects** and invite other users to collaborate in real time, sharing rules, APIs, and mocks effortlessly, or create a **local project** to keep all your data on your machine.
### Types of projects
Requestly offers two main types of projects:
**Team project**, A team project is cloud-based: all your data is securely stored and synced across teams and devices. This is ideal when you work with a team and need everyone to stay in sync.
**Local project (beta)**, A local project stores all your data on your computer, giving you complete control and privacy. It is designed for individual use rather than team collaboration. Choose this option if you prefer local storage over the cloud.
## Explore
Create and manage a local project that stores data on your device.
Work with several local projects side by side and move requests between them.
Invite teammates and collaborate in real time with a shared cloud project.
Understand the Admin, User, and Viewer roles within a shared project.