Skip to main content
Back to Blog
Reference
2026-06-03

Insomnia API Testing: Complete Engineer's Guide 2026

Insomnia API testing for engineers: requests, environments with {{ _.base_url }}, auth, request chaining, test suites, and CI automation with the Inso CLI.

Insomnia API Testing: Complete Engineer's Guide 2026

Insomnia is a cross-platform API client that has earned a permanent place in many engineering toolchains because it does three things exceptionally well: it makes ad-hoc HTTP requests effortless, it organizes those requests into reusable, environment-driven collections, and it pushes the same collections into continuous integration through its command-line companion, the Inso CLI. If you have ever maintained a sprawling set of curl commands in a shared doc, or struggled to keep staging and production base URLs straight across a dozen requests, Insomnia is the tool that replaces that chaos with structure.

This guide is a complete, hands-on reference for using Insomnia as an engineer in 2026 — not just as a request-firing toy, but as a tested, versioned, automatable part of your API workflow. We start from the fundamentals of building a request, then layer in the features that make Insomnia powerful at scale: environments with template tags like {{ _.base_url }}, every common authentication scheme, response-to-request chaining so a login token flows into the next call automatically, unit test suites that assert on responses, and finally running the whole thing headlessly in CI with the Inso CLI. The examples use real JSON request bodies and JavaScript-based test assertions so you can copy them into your own workspace and run them immediately.

By the end you will be able to model an entire API surface in Insomnia, parameterize it across multiple deployment targets, validate it with automated tests, and wire those tests into your pipeline so a broken endpoint fails the build. Whether you are testing a REST API, a GraphQL endpoint, or a gRPC service, the patterns here scale from a single developer's scratchpad to a team-owned, source-controlled test asset.

Insomnia Core Concepts and Workspace Structure

Before firing requests, it helps to understand how Insomnia organizes work, because the structure is what makes everything else maintainable. The hierarchy, from outermost to innermost, is: a workspace (or "project") contains collections; a collection contains folders and requests; environments and authentication can be defined at any level and inherit downward.

ConceptWhat it holdsTypical scope
Workspace / ProjectCollections, design docs, environmentsOne per API or product
CollectionFolders and requestsA logical API surface
FolderRelated requests, shared auth/headersA resource group (e.g. /users)
RequestMethod, URL, headers, body, authA single endpoint call
EnvironmentKey/value variables (base_url, token)Per deployment target

This inheritance model is the key to staying DRY. Authentication set on a folder applies to every request inside it. A header defined at the collection level appears on all requests unless overridden. Environment variables resolve from the active environment down through any sub-environments. Designing your collection so that shared concerns live as high as possible means you change a base URL or a token in one place and every request picks it up.

A practical first step is to create one collection per service and one folder per resource. Inside the users folder you place List users, Get user, Create user, and so on. The folder owns the auth header; the requests own only what is unique to them — the method, the path suffix, and the body. This discipline pays off the moment your collection grows past a handful of requests.

Building Your First Request

A request in Insomnia is the combination of an HTTP method, a URL, headers, an optional body, and optional auth and query parameters. Create one with the new-request button, choose the method, and paste the URL. For a POST that sends JSON, select the JSON body type and Insomnia automatically sets the Content-Type: application/json header for you.

Here is a typical create-user request body. Note the values that reference template tags — we will define those in the next section.

{
  "name": "Grace Hopper",
  "email": "grace@example.com",
  "role": "admin",
  "active": true,
  "metadata": {
    "source": "insomnia-guide",
    "createdBy": "{{ _.current_user }}"
  }
}

The query parameters tab lets you build the query string with a UI instead of hand-encoding it, which avoids subtle encoding bugs. For a list endpoint you might add page=1, limit=20, and sort=createdAt:desc. Insomnia assembles ?page=1&limit=20&sort=createdAt%3Adesc and shows you the final URL.

Once you send a request, the response pane shows the status code, timing breakdown (DNS, TLS, transfer), headers, and a pretty-printed body with a filter box. The timeline view exposes the raw request and response bytes, which is invaluable when debugging why a request behaves differently from curl. Get comfortable with the response pane early, because the test suites you write later assert on exactly these fields.

Environments and Template Tags

Environments are where Insomnia goes from convenient to powerful. An environment is a JSON object of variables you can reference anywhere a value is accepted — URLs, headers, bodies, query params — using the template tag syntax {{ _.variable_name }}. By switching the active environment you re-point every request at a different target without editing a single request.

Define a base environment with the values common to all targets, then sub-environments that override per deployment:

{
  "base_url": "https://api.staging.example.com/v1",
  "current_user": "ci-bot",
  "default_limit": 20
}

A production sub-environment overrides only what differs:

{
  "base_url": "https://api.example.com/v1"
}

Now every request uses {{ _.base_url }}/users as its URL. Selecting "Staging" or "Production" from the environment dropdown swaps the host instantly. This is the single most important habit in Insomnia: never hardcode a host or a secret in a request — always reference an environment variable.

The _. prefix is the modern Insomnia template namespace; older content sometimes shows the bare {{ base_url }} form, but {{ _.base_url }} is the current syntax and is what the Inso CLI expects. Beyond plain variables, Insomnia ships template tags that compute values dynamically. The table below lists the ones you will use most.

Template tagProducesExample use
{{ _.base_url }}An environment variableRequest URL host
{{ $timestamp }}Current Unix timestampCache-busting query param
{{ $uuid }}A random UUID v4Idempotency-Key header
{{ $randomEmail }}A fake email addressUnique test user creation
Response tagA value from another request's responseAuth token reuse (see chaining)

Sensitive values like API keys belong in a private environment, which Insomnia does not export when you share or sync the collection. Keep secrets out of the shared base environment so that exporting the collection for CI never leaks credentials into source control.

Authentication Schemes

Insomnia supports every authentication method you are likely to encounter, configured per request or inherited from a folder. The auth tab handles the mechanics so you do not hand-craft the Authorization header in most cases.

For Bearer token auth, choose Bearer and reference an environment variable so the token is centralized:

Auth type: Bearer Token
Token: {{ _.access_token }}

For Basic auth, supply username and password (again from environment variables) and Insomnia base64-encodes them into the header. For API key auth, you specify the key name and value and whether it goes in a header or the query string. For OAuth 2.0, Insomnia can run the full authorization-code or client-credentials flow, exchange the code for a token, and store the resulting access token so subsequent requests use it automatically.

A clean pattern for token-based APIs is to keep a dedicated Login request that authenticates and returns a token, then reference that token everywhere else. You can store the token in an environment variable manually, but the more elegant approach is response chaining, which pulls the token directly from the login response with no copy-paste. That is the next section, and it is the feature that makes Insomnia feel like an automation tool rather than a manual one.

Chaining Requests with Response References

Response chaining lets one request use a value extracted from another request's response. The canonical example: a Login request returns { "token": "..." }, and every authenticated request references that token automatically. When you send the authenticated request, Insomnia sees the response tag, runs the login request if needed, extracts the token via a JSONPath, and injects it.

Suppose the login response looks like this:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.payload.sig",
  "expiresIn": 3600,
  "user": { "id": "u_123", "role": "admin" }
}

In the Authorization header of a downstream request, you insert a Response template tag configured to pull from the Login request and the JSONPath $.token. The header value becomes:

Authorization: Bearer {{ Response: Login -> $.token }}

Now firing Get current user triggers Login (if its cached response is stale), extracts the fresh token, and sends it. You never copy a token by hand again. The same technique chains created resources: a Create order request returns an order id, and Get order references $.id from the create response to fetch exactly what was just created.

URL: {{ _.base_url }}/orders/{{ Response: Create order -> $.id }}

Response tags can trigger the upstream request automatically, reuse the last response, or use the most recent response within a time window — configurable per tag. For test suites you generally want "always send the request" so each run starts fresh, while for interactive exploration "use the most recent response" avoids hammering the API. Understanding this caching behavior prevents the common confusion of "why is my token stale" — it is the response tag reusing an old response.

Writing Test Suites in Insomnia

Insomnia ships a unit-testing surface where you write JavaScript assertions against requests using a Chai-style expect API. Tests live in the Test tab, are grouped into suites, and each test sends a request (or references a previously sent response) and asserts on the result. This turns your collection from a manual tool into an automated regression suite.

A test that validates the login endpoint:

const response = await insomnia.send();
const body = JSON.parse(response.data);

expect(response.status).to.equal(200);
expect(body).to.have.property('token');
expect(body.token).to.be.a('string');
expect(body.expiresIn).to.be.above(0);
expect(body.user.role).to.equal('admin');

A test that validates the create-user flow and its side effects:

const created = await insomnia.send('Create user');
const createdBody = JSON.parse(created.data);

expect(created.status).to.equal(201);
expect(createdBody).to.have.property('id');
expect(createdBody.email).to.equal('grace@example.com');

// Verify the resource is now retrievable
const fetched = await insomnia.send('Get user');
const fetchedBody = JSON.parse(fetched.data);
expect(fetched.status).to.equal(200);
expect(fetchedBody.id).to.equal(createdBody.id);

The insomnia.send() call with no argument sends the request the test is attached to; passing a request name sends that named request, which is how you compose multi-step assertions. Because the body arrives as a string in response.data, you parse it with JSON.parse before asserting on fields. Group related tests into a suite (for example "Auth", "Users", "Orders") so you can run a focused subset or the whole thing.

Good test suites assert on more than the happy path. Add tests for unauthorized access (expect 401 without a token), validation errors (expect 422 with a bad body), and not-found cases (expect 404 for a missing id). These negative tests catch regressions that happy-path checks miss, and they document the API's contract for the next engineer.

Running Tests in CI with the Inso CLI

The feature that elevates Insomnia from a desktop tool to a CI citizen is Inso, the command-line companion that runs your collections and test suites headlessly. With Inso you export your Insomnia data, commit it to the repository, and run the test suites in your pipeline so a broken endpoint fails the build before it reaches production.

First, export the workspace. Insomnia can sync to Git directly, or you export a .insomnia directory / a single export file. Commit that to your repo. Then install Inso and run the suite:

# Install the Inso CLI
npm install -g insomnia-inso

# List the test suites available in the exported data
inso export spec

# Run a named test suite against the staging environment
inso run test "Smoke Suite" \
  --env "Staging" \
  --reporter spec \
  --workspace-dir ./insomnia

The --env flag selects which environment's variables to use, so the same suite runs against staging in CI and production in a release gate by changing one flag. The --reporter flag controls output format; use spec for human-readable logs and junit to emit a JUnit XML file your CI can parse into a test report.

A minimal GitHub Actions job that runs the suite on every pull request:

name: API Tests
on: [pull_request]
jobs:
  inso:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm install -g insomnia-inso
      - name: Run Insomnia test suite
        run: |
          inso run test "Smoke Suite" \
            --env "Staging" \
            --reporter junit \
            --workspace-dir ./insomnia > results.xml
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: api-test-results
          path: results.xml

Inso exits with a non-zero code when any test fails, which fails the job automatically. Because the collection and tests are version-controlled, code review covers your API tests just like any other code, and the history shows exactly when an endpoint's contract changed. This closes the loop: requests you build interactively in the desktop app become automated guarantees in CI with no rewriting.

Insomnia vs Other API Clients

Engineers often ask how Insomnia compares to Postman and to plain curl or HTTPie. The honest answer is that they overlap heavily and the right choice depends on team needs. The table below summarizes the practical differences as of 2026.

CapabilityInsomniaPostmancurl / HTTPie
Environments + template tagsYes ({{ _.var }})Yes ({{var}})Manual (shell vars)
Response chainingNative template tagsScripts (pm.* )Manual scripting
Test suitesJS + Chai expectJS (pm.test)External (bats, etc.)
CLI for CIInso (clean Git-friendly)NewmanNative (it is the CLI)
Git-native collectionsYesLimitedN/A (plain files)
Offline / local-firstStrongCloud-leaningFully local

Insomnia's differentiators are its Git-native, file-based storage (collections are diffable), its declarative response template tags (chaining without writing imperative scripts for the common case), and the clean Inso CLI. Teams that value source-controlled, reviewable API assets and a lightweight local-first experience tend to prefer it. If you already live in curl, Insomnia is the natural next step that adds structure without forcing you to abandon the request-first mental model.

Frequently Asked Questions

How do I reference an environment variable in Insomnia?

Use the template tag syntax {{ _.variable_name }} anywhere a value is accepted — request URLs, headers, JSON bodies, and query parameters. Define the variable in an environment (for example base_url), then write {{ _.base_url }}/users as the URL. Switching the active environment from the dropdown re-points every request that uses the variable, which is how you move between staging and production without editing any request.

What is the difference between Insomnia and the Inso CLI?

Insomnia is the desktop application where you build and run requests interactively. Inso is its command-line companion that runs the same collections and test suites headlessly, which is what you use in CI. You build and debug in the desktop app, export or Git-sync the workspace, then run inso run test in your pipeline. Inso exits non-zero on test failure so a broken endpoint fails the build automatically.

How do I pass a login token to other requests automatically?

Use response chaining. In the downstream request's Authorization header, insert a Response template tag that points at your Login request and extracts the token with the JSONPath $.token, producing Bearer {{ Response: Login -> $.token }}. When you send the request, Insomnia runs the login request, extracts the fresh token, and injects it, so you never copy a token by hand. Configure the tag to always send the login request for deterministic test runs.

Can I write automated tests in Insomnia?

Yes. The Test tab provides a JavaScript testing surface with a Chai-style expect API. Each test calls insomnia.send() to fire its request (or a named request), parses response.data with JSON.parse, and asserts on the status and body fields. Group tests into suites like Auth or Users, and include negative cases such as 401 unauthorized and 422 validation errors. These suites run both in the app and headlessly via the Inso CLI.

How do I keep API keys and secrets out of source control?

Store sensitive values in a private environment rather than the shared base environment. Insomnia excludes private environments when you export or sync the collection, so secrets never land in the exported files you commit. In CI, inject the secret values as environment variables or repository secrets and map them into the environment Inso uses, keeping credentials out of the version-controlled workspace entirely.

What does the _. prefix mean in template tags?

The _. prefix is Insomnia's current namespace for environment variables, so {{ _.base_url }} reads the base_url key from the active environment. Older tutorials sometimes show the bare {{ base_url }} form, but the _. form is the modern syntax and the one the Inso CLI expects. Built-in dynamic tags use a different prefix, such as {{ $uuid }} and {{ $timestamp }}, which generate values rather than reading the environment.

How do I run the same tests against staging and production?

Define one environment per target (Staging, Production) that overrides only the values that differ, such as base_url, on top of a shared base environment. In CI, run inso run test "Suite" --env "Staging" for pull requests and the same command with --env "Production" as a release gate. Because every request references {{ _.base_url }}, switching the --env flag re-targets the entire suite without changing a single request or test.

Does Insomnia support GraphQL and gRPC?

Yes. Insomnia has a dedicated GraphQL request type with schema introspection and autocomplete for queries and variables, and it supports gRPC requests using your .proto definitions, including unary and streaming calls. Environments, template tags, and authentication work the same way across REST, GraphQL, and gRPC, so the patterns in this guide — variables, chaining, and Inso-driven CI — apply regardless of the protocol your service speaks.

Conclusion

Insomnia rewards engineers who treat it as more than a request launcher. Model your API as collections and folders, parameterize everything through environments and {{ _.base_url }} template tags, eliminate copy-paste with response chaining, assert behavior with JavaScript test suites, and finally run those suites in CI with the Inso CLI so a broken contract fails the build. Each layer builds on the last, turning an interactive tool into a version-controlled, automated guarantee of your API's behavior.

Start small: parameterize one collection with a base-url environment, add a login chain, write three smoke tests, and wire inso run test into a pull-request job. From there the same patterns scale to your whole API surface. For more API-testing guides and ready-to-install testing skills for your AI coding agent, explore the QASkills.sh skills directory and the full collection of tutorials on the QASkills.sh blog.

Insomnia API Testing: Complete Engineer's Guide 2026 | QASkills.sh