Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>VReq - API Runner (Scenario testing - beta)New to Visual Studio Code? Get it now.
VReq - API Runner (Scenario testing - beta)

VReq - API Runner (Scenario testing - beta)

VenkatY

|
89 installs
| (0) | Free
File-based API testing in VS Code using .vreq/.venv/.vscript/.vscenario
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

VReq - File Based API Testing for VS Code

Run API requests from simple text files with environments, chaining, scripts, and tests directly inside VS Code.

VReq is a lightweight file-based API testing tool designed as a developer-friendly alternative to GUI tools like Postman.

Sample test API repository setup here


Features

• Run HTTP requests directly from .vreq files
• Environment configuration using .venv files
• Request chaining and dependencies
• Pre/Post request scripts
• Multi-request scenario orchestration with .vscenario
• Built-in response viewer (JSON + headers + timing)
• Test assertions for API validation
• CodeLens support for quick execution
• Diagnostics and linting for request files


File Types

File Purpose


.vreq API requests and collections

.venv Environment variables

.vscript Pre/Post scripts

.vtest Optional test definitions

.vscenario Multi-request scenarios and workflows


Quick Start

Create an environment

Create env/dev.venv

host: https://postman-echo.com
headers.Accept: application/json
tenantId: dev
timeoutMs: 30000
debug: false
forceNoProxy: false
useSystemProxy: false
# optional enterprise CA bundle (PEM)
tls.caFile: C:\\certs\\corp-root-ca.pem
# optional local dev bypass for https://localhost only
tls.allowInsecureLocalhost: true
# optional override when useSystemProxy=true
# proxyUrl: http://proxy.company.local:8080

Create a request

Create reqs/echo.vreq

Collection: Echo Demo

---

Name: getEcho
Request:
GET {{host}}/get

Query:
hello: world
tenant: {{tenantId}}
page: 1

Headers:
Accept: application/json

Tests:
- status is 200
- header content-type contains json

Auth examples (with and without Auth)

Create reqs/auth-samples.vreq

Collection: Auth Samples

---

Name: publicEcho
Request:
GET {{host}}/get

Query:
mode: public

Headers:
Accept: application/json

Tests:
- status is 200

---

Name: securedApi
Request:
GET {{apiHost}}/secure/data

Auth:
Use: env

Headers:
Accept: application/json

Tests:
- status is 200

With Auth: Use: env, add these in .venv:

auth.type: oauth2-client-credentials
auth.tokenUrl: https://login.example.com/oauth2/token
auth.clientId: {{clientId}}
auth.clientSecret: {{clientSecret}}
auth.scope: api.read

You can override the OAuth scope per request using the request Auth: section:

Auth:
Use: env
Scope: api.write

You can also override the OAuth cache key per request:

Auth:
Use: env
CacheKey: pricing-uat-forward

For backward compatibility, you can also override the OAuth scope using a request header:

Headers:
Accept: application/json
Scope: api.write

OAuth client-credentials tokens are cached automatically per auth configuration. By default, VReq derives the cache key from tokenUrl, clientId, and scope, so different credentials do not reuse the same token.

Per-request Scope: overrides are included in that cache separation, so two requests or scenario steps using the same client credentials but different scopes will generate different cached tokens automatically.

In .vscenario flow runs, requests with the same OAuth client credentials and the same effective scope will reuse the cached token across steps to avoid unnecessary token requests.

If you want to control token reuse explicitly, set:

auth.cacheKey: pricing-auth

This is useful when you want multiple requests to intentionally share the same cached token, or when you want to force different requests to use separate cache entries.

If a request defines Auth: CacheKey: while using Auth: Use: env, that request-level cache key overrides the environment auth.cacheKey. This is especially useful in .vscenario flows where different requests need different cached tokens even when they share the same selected environment.

Only requests that contain an Auth: section will send Authorization headers.


Select environment

Open Command Palette and run:

VReq: Select Environment


Run the request

Open the .vreq file and click:

▶ Run Request

or

▶ Run File


Swagger/OpenAPI Import

VReq can generate requests directly from a local swagger.json / openapi.json file or a URL to one.

Open Command Palette and run:

VReq: Import Swagger/OpenAPI

Then paste either:

• https://petstore.swagger.io/v2/swagger.json
• /absolute/path/to/swagger.json
• relative/path/to/swagger.json

VReq generates everything under:

imports/swagger/<api-name>/
  manifest.json
  source.json
  env/default.venv
  requests/*.vreq
  scenarios/smoke.vscenario

Notes:

• v1 supports JSON Swagger/OpenAPI documents
• generated request URLs convert path params like {id} to {{id}}
• generated requests include default tests and auth scaffolding where possible
• manifest.json stores the original import source for refresh

To regenerate an existing import, run:

VReq: Refresh Swagger/OpenAPI Imports


Scenarios

Use .vscenario when you need to:

• run multiple .vreq requests in sequence
• reuse one selected environment across all requests
• override request Vars, Query, Headers, or Body
• pass outputs between steps with SaveAs
• run JavaScript calculation or comparison scripts
• persist intermediate artifacts to disk
• trigger follow-up requests conditionally
• evaluate final scenario assertions

Step-by-step setup

1. Create the environment

Create env/dev.venv

host: https://postman-echo.com
tenantId: dev
quoteStartDate: 2026-01-01
quoteEndDate: 2027-12-31
debug: true

2. Create the request files

Create reqs/pricing.vreq

Collection: Pricing

---
Name: GetHistoricalPrices
Request:
GET {{host}}/get

Query:
type: historical
startDate: {{quoteStartDate}}
endDate: 2026-06-24

Headers:
Accept: application/json
X-Tenant: {{tenantId}}

Tests:
- status is 200
- header content-type contains json

---
Name: GetForwardPrices
Request:
GET {{host}}/get

Query:
type: forward
startDate: 2026-06-25
endDate: {{quoteEndDate}}

Headers:
Accept: application/json
X-Tenant: {{tenantId}}

Tests:
- status is 200
- header content-type contains json

Create reqs/integrations.vreq

Collection: Integrations

---
Name: GetSalesforceData
Request:
GET {{host}}/get

Query:
source: salesforce
expectedValue: 4.5

Headers:
Accept: application/json
X-Tenant: {{tenantId}}

Tests:
- status is 200
- header content-type contains json

---
Name: CreateJiraIssue
Request:
POST {{host}}/post

Headers:
Content-Type: application/json
Accept: application/json
X-Tenant: {{tenantId}}

Body:
{
  "summary": "Price mismatch detected",
  "description": "Calculated={{comparison.finalValue}}, Salesforce={{comparison.salesforceValue}}"
}

Tests:
- status is 200
- header content-type contains json

3. Create the scenario scripts

Create scripts/ProfitMargin.vscript

export default function run(inputs, ctx) {
  ctx.log(`quoteStartDate=${inputs.quoteStartDate}`);
  ctx.log(`quoteEndDate=${inputs.quoteEndDate}`);

  const historicalAverage = 100;
  const forwardAverage = 100;
  const combinedAverage = (historicalAverage + forwardAverage) / 2;
  const finalValue = combinedAverage * 0.045;

  ctx.log(`combinedAverage=${combinedAverage}`);
  ctx.log(`finalValue=${finalValue}`);

  return {
    historicalAverage,
    forwardAverage,
    combinedAverage,
    finalValue
  };
}

Create scripts/CompareSalesforce.vscript

export default function run(inputs, ctx) {
  const calculated = Number(inputs.calculated.finalValue);
  const salesforceValue = Number(inputs.salesforce.args.expectedValue);
  const match = calculated === salesforceValue;

  ctx.log(`calculated=${calculated}`);
  ctx.log(`salesforceValue=${salesforceValue}`);
  ctx.log(`match=${match}`);

  return {
    match,
    finalValue: calculated,
    salesforceValue
  };
}

4. Create the scenario file

Create scenarios/price-validation.vscenario

Name: Price Validation

Use Requests:
- Collection: Pricing
  Request: GetHistoricalPrices

- Collection: Pricing
  Request: GetForwardPrices

- Collection: Integrations
  Request: GetSalesforceData

- Collection: Integrations
  Request: CreateJiraIssue

Inputs:
quoteStartDate: 2026-01-01
quoteEndDate: 2027-12-31

Request Overrides:
GetHistoricalPrices.Query:
  startDate: {{quoteStartDate}}
  endDate: 2026-06-24

GetForwardPrices.Query:
  startDate: 2026-06-25
  endDate: {{quoteEndDate}}

CreateJiraIssue.Body:
  {
    "summary": "Price mismatch detected"
  }

Scripts:
- File: scripts/ProfitMargin.vscript
  As: profitMargin

- File: scripts/CompareSalesforce.vscript
  As: compareCalc

Flow:
- Run: GetHistoricalPrices
  SaveAs: historical
  Persist: artifacts/historical.json
  PersistAs: json

- Run: GetForwardPrices
  SaveAs: forward
  Persist: artifacts/forward.json
  PersistAs: json

- Script: profitMargin
  Inputs:
    quoteStartDate: {{quoteStartDate}}
    quoteEndDate: {{quoteEndDate}}
    historicalPrices: {{historical.response.json}}
    forwardPrices: {{forward.response.json}}
  SaveAs: calcResult
  Persist: artifacts/calcResult.json
  PersistAs: full

- Run: GetSalesforceData
  SaveAs: salesforce

- Script: compareCalc
  Inputs:
    calculated: {{calcResult}}
    salesforce: {{salesforce.response.json}}
  SaveAs: comparison
  Persist: artifacts/comparison.json
  PersistAs: json

- If: comparison.match == false
  Then:
    - Run: CreateJiraIssue
      SaveAs: jiraResult
      Persist: artifacts/jiraResult.json
      PersistAs: full

Assertions:
- expr comparison.match equals true

5. Select the environment

Open Command Palette and run:

VReq: Select Environment

Pick dev.

6. Run the scenario

Open the .vscenario file and use:

▶ Run Scenario

or press:

Ctrl+Enter / Cmd+Enter

7. Check outputs

After the run:

• the progress popup shows the current scenario stage
• the VReq response viewer shows scenario steps and assertions
• persisted artifacts are written to the artifacts/ folder
• script logs are written to Output -> VReq

Scenario syntax overview

Supported top-level sections:

Name:
Use Requests:
Inputs:
Request Overrides:
Scripts:
Flow:
Assertions:

Supported request overrides:

Request Overrides:
GetHistoricalPrices.Vars:
  quoteStartDate: {{quoteStartDate}}

GetHistoricalPrices.Query:
  startDate: {{quoteStartDate}}

GetHistoricalPrices.Headers:
  X-Tenant: {{tenantId}}

GetHistoricalPrices.Body:
  {
    "from": "{{quoteStartDate}}"
  }

Supported step types:

- Run: <request-name>
- Script: <script-alias>
- If: <expression>
  Then:
    - Run: <request-name>

Run steps also support step-level overrides. These override both the base .vreq request and any scenario-level Request Overrides: values:

- Run: <request-name>
  Vars:
    key: value
  Query:
    key: value
  Headers:
    key: value
  Body:
    {
      "key": "value"
    }

Scenario Inputs: can be referenced directly inside step-level Run: overrides, and also indirectly through step-level Vars: values. For example:

Inputs:
quoteStartDate: 2026-01-01

Flow:
- Run: GetPrices
  Vars:
    fromDate: {{quoteStartDate}}
  Query:
    startDate: {{fromDate}}
  SaveAs: historical

In this example, {{quoteStartDate}} resolves from Inputs:, and {{fromDate}} then resolves from the step-level Vars: override.

Example: run the same request twice with different step-level overrides

Base request in reqs/pricing.vreq:

Collection: Pricing

Name: GetPrices

Vars:
priceType: historical
fromDate: 2026-01-01
toDate: 2026-06-24

Request:
GET {{host}}/get

Query:
type: {{priceType}}
startDate: {{fromDate}}
endDate: {{toDate}}

Headers:
Accept: application/json
X-Tenant: {{tenantId}}

Tests:
- status is 200
- header content-type contains json

Scenario:

Name: Run Same Request Twice

Use Requests:
- Collection: Pricing
  Request: GetPrices

Request Overrides:
GetPrices.Headers:
  X-Scenario: price-check

Flow:
- Run: GetPrices
  Vars:
    priceType: historical
    fromDate: 2026-01-01
    toDate: 2026-06-24
  Query:
    startDate: 2026-01-01
    endDate: 2026-06-24
  SaveAs: historical

- Run: GetPrices
  Vars:
    priceType: forward
    fromDate: 2026-06-25
    toDate: 2027-12-31
  Query:
    startDate: 2026-06-25
    endDate: 2027-12-31
  Headers:
    X-Mode: forward
  SaveAs: forward

Assertions:
- expr historical.status equals 200
- expr forward.status equals 200

In this example:

• Request Overrides: applies to every GetPrices execution in the scenario
• the first Run: step executes GetPrices with historical values
• the second Run: step executes the same GetPrices request again with different Vars, Query, and Headers
• step-level overrides take precedence over Request Overrides:

Supported persistence modes:

PersistAs: json
PersistAs: raw
PersistAs: full

Scenario validation checks

VReq validates .vscenario files in the editor before execution and shows diagnostics for common issues.

Current checks include:

• missing Use Requests: - File: ... targets
• missing Scripts: - File: ... targets
• unresolved Collection + Request references
• ambiguous Collection + Request matches across multiple .vreq files
• unknown Run: request names
• unknown Script: aliases
• duplicate script aliases
• Request Overrides: targeting unknown requests
• PersistAs used without Persist
• values referenced before a SaveAs step defines them
• warnings when multiple scenario Run: steps inherit the same env auth.cacheKey without a request-level Auth: CacheKey: override
• If: / Assertions: referencing unknown or conditionally-defined values

These checks help catch broken scenario wiring before you run the workflow.


Tests

Example assertions:

Tests:
- status is 200
- json.path code equals {{code}}
- json.path total greaterThan 10
- json.path discount lessThan 0.5
- json.expr subtotal + tax equals 108
- json.expr (subtotal + tax) / itemCount greaterThan 20
- json.expr qty * unitPrice lessThan 1000
- header content-type contains json
- json.path user.id exists
- json.path status equals success
- json.path items any(itemId equals "553")
- json.path items filter(itemId equals "553") count equals 1
- body contains success
- time lessThanMs 500

Scripts

Example pre-script.vscript

log.info("Executing pre request script")

ctx.set("traceId", crypto.randomUUID())

req.headers["X-Trace-Id"] = ctx.get("traceId")

Objects available inside scripts:

Object Purpose


env environment variables ctx shared runtime variables req request object res response object log extension logger

JSON bodies may include comments in Body: sections. VReq ignores // ..., /* ... */, and line-start # ... comments before sending JSON requests.

Scenario scripts use JavaScript too. A .vscenario script should export a default function:

export default function run(inputs, ctx) {
  ctx.log("running scenario script");
  return { ok: true };
}

Objects available inside scenario scripts:

Object Purpose


inputs resolved scenario step inputs ctx script logger and metadata


Commands

Command Description


VReq: Select Environment choose environment

VReq: Run Current Request run request under cursor

VReq: Run File run entire collection

VReq: Run Scenario run current scenario file

VReq: Show Last Response open response viewer


Why VReq?

Most API tools rely heavily on GUI workflows.

VReq focuses on:

• version-controlled API tests
• simple text-based configuration
• automation-friendly workflows
• developer-centric experience

Your API tests live alongside your source code.


License

MIT License

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft