We use cookies to enhance your experience on the site
CodeWorlds
Back to collections
Guide12 min read

Insomnia, an API client where you choose where data lives

Insomnia is Kong's API client with three storage modes: cloud, local disk, and a Git repository. Collections, tests, vault integration, and a Bruno comparison.

Insomnia, an API client where you choose where data lives

API clients today split into those requiring an account with cloud synchronisation and those keeping everything local. Insomnia lets you choose, and at project level, which separates it from most of its competition.

Three modes are available: a cloud with synchronisation across devices, local disk with nothing sent anywhere, and a Git repository as the storage location for collections. The third is the most interesting for teams, since it turns collections into reviewable files.

Three storage modes

Think the mode through when creating a project, since it determines how the team works.

Cloud mode synchronises collections across devices and people. It is the most convenient and means that request content, including internal addresses and interface structure, sits with the vendor. For public interfaces that is immaterial; for internal ones it sometimes becomes a conversation with the security team.

Local mode keeps everything on disk and sends nothing. It suits individual work and compliance requirements, at the cost of no sharing beyond exporting a file.

Repository based mode combines the advantages of both. Collections live as files in your repository, so they go through review, carry change history, and work for everybody with access to the code. A collection change travels the same path as a code change.

The last mode makes the most sense for a team and demands discipline. Secrets must not reach the repository, so environments holding tokens need marking private or pulling values from a vault.

Collections, environments, and variables

The structure resembles other tools in this category: requests group into collections and changing values live in environments.

Code
TEXT
{{ _.baseUrl }}/api/orders/{{ _.orderId }}

Authorization: Bearer {{ _.token }}

Environments can inherit, so shared values are written once at the parent level and differences live in children. That simplifies the situation where four environments differ in two values.

Variables can come from a previous request's response, solving the commonest problem: a token expiring hourly. Rather than copying it by hand, you point at a field in the login request's response and the tool substitutes it automatically.

Set one thing from the start: no hardcoded addresses. A request written for five minutes' use lasts two years, and a collection with addresses baked in stops working at the first environment change.

Vaults and secrets

Version eleven added integration with external vaults, which changes how teams handle tokens.

Previously a secret had to be typed into an environment or fetched by hand. The first approach ended with a token in a file, the second was tiresome. Pulling a value from a vault at send time solves both: the collection holds a reference rather than a value.

That matters particularly in repository based mode. The collection reaches the repository alongside the code, so a vault reference is safe there while a typed token is not.

For individual work, marking a variable private suffices, keeping it out of exports. That distinction matters when sharing a collection, since you want to pass on the request structure rather than your credentials.

Tests and running collections

Beyond sending requests the tool lets you write tests checking responses.

Code
JavaScript
insomnia.test('Order is paid', () => {
  insomnia.expect(insomnia.response.code).to.eql(200)

  const data = insomnia.response.json()
  insomnia.expect(data.status).to.eql('paid')
  insomnia.expect(data.items).to.be.an('array').that.is.not.empty
})

The same after response script suits moving a value into the environment, which solves the problem of a token expiring midway through a collection run.

Code
JavaScript
insomnia.test('Store the token', () => {
  insomnia.expect(insomnia.response.code).to.eql(200)
  insomnia.environment.set('token', insomnia.response.json().access_token)
})

Two write targets are worth distinguishing. Writing to the selected environment affects only that one, while writing to the base environment is visible to every child environment. An access token belongs in the first, a service base address usually in the second.

Running a whole collection walks every request in order, giving a simple post deployment interface test. It catches the commonest class of problem with back end changes: a field that disappeared or was renamed.

A separate command line tool serves the build pipeline, taking a collection name and an environment. Without that step tests stay something run by hand, meaning rarely in practice.

Code
Bash
brew install inso
inso run collection "Orders" --env "Production"
inso run test "Order contract" --env "Production"

Worth knowing: this tool is not installed from the npm registry today. A package under that name exists, but its last release dates from 2022, so installing from there gives you a version several years old. The current routes are a system package manager, a ready executable, or a container image, and the last of those is usually the most convenient in a pipeline. The image sets no working directory, so the mounted path needs the working directory switch as well, otherwise the tool looks for the collection in the container root.

Code
Bash
docker run --rm -v "$PWD:/var/temp" kong/inso:latest \
  run collection "Orders" --env "Production" -w /var/temp

Remember it does not replace tests in code. Checking response shape after deployment is useful, while business logic is tested closer to itself.

Interface design

The tool also supports working with an interface description in the standard format, with preview and validation.

That feature helps in the approach where a description precedes implementation and serves as a contract between teams. The front end can then work against a mock generated from the description before the back end is ready.

A practical note: an interface description has value only while maintained. A file written at project start and abandoned after three months is worse than none, since it misleads. If the team plans to generate neither code nor tests from it, a well maintained collection is a better foundation.

Beyond that the tool handles protocols outside plain HTTP: GraphQL with schema browsing, websockets, server sent events, and calls in the binary format. That last one is sometimes decisive, since few graphical tools support it.

Team work on a repository

Repository based mode needs a few agreements, without which it becomes a source of merge conflicts.

The first concerns splitting into projects. One large project holding every team's requests means each change touches a file others edit too. Splitting by area of responsibility keeps that to a minimum.

The second is naming. Descriptively named requests, "create order with deferred payment" for instance, read clearly in a diff. Names like "test 3" say nothing in the tool or in review.

The third is how a change is made. A collection change travels the same path as a code change: a branch, a pull request, a review. That sounds heavy for adding one request, and it guards against somebody changing the base address and breaking the collection for everyone.

The fourth is tidying. Collections grow, and requests to retired endpoints stay because nobody dares delete them. A quarterly review removing anything nobody has run in six months keeps a collection usable.

Migrating from another tool

A collection built over two years is usually the main reason teams stay with a tool they dislike. It helps to know how large that cost really is.

Import from other clients' formats works and carries requests, headers, and environment variables. That covers most of a typical collection's content, so the move itself is a matter of minutes.

What needs attention is scripts. Syntax differs between tools, so code pulling a token from a response must be rewritten. On a collection with five such places that is an hour's work; on one with fifty it is worth asking whether they are all still needed.

The second thing is secrets. Import will not carry values from environments marked private, and rightly so, so they must be set again. That is a good moment to rotate tokens, since the configuration is being touched anyway.

The third is settling the storage mode before importing. Dropping a collection into a cloud project and then moving it to repository based mode means doing the work twice.

Insomnia against the alternatives

ToolStrengthWeaknessPick it when
InsomniaThree storage modes, vaults, many protocolsAn application to installTeam wanting collections in the repository and many protocols
BrunoCollections as files, works without an external serviceFewer protocolsTeam treating collections as code
HoppscotchBrowser based, self hostingLess elaborate featuresQuick access without installation
PostmanLargest feature and integration setHeavy, requires an accountLarge organisation with an elaborate process

Choosing among the first three rows comes down to three questions. Do you need protocols beyond HTTP, since the first row has the broadest support. Do you want to work entirely without an external service, since the second is built for that. Does browser access without installation matter, since the third serves that.

All three allow keeping collections in a repository, so the differences there are smaller than vendor material suggests. Team habit often decides it, since a tool nobody wants to open helps nothing whatever it can do.

Plugins and extending it

The tool allows writing your own plugins, which helps with things specific to your back end.

The commonest use is a custom request signing scheme. Interfaces requiring a signature built from a key and a timestamp cannot be handled with headers alone, and a plugin computing the signature before sending solves it once for the whole team.

The second is custom response formats. A back end returning data in a binary or compressed format needs transforming before it can be read, and that fits in a plugin too.

The third is generating values. Identifiers in a particular format, test data matching validation rules, timestamps in an unusual shape: anything recurring on every request.

Keep it in proportion, though. A plugin is code without tests, running on team machines, and its maintenance falls to whoever wrote it. For things a variable or a per request script can handle, a plugin is disproportionate to the problem.

Common mistakes

The first is hardcoded addresses instead of environment variables. The collection stops working after an environment change, and fixing requests by hand takes longer than setting a variable at the start.

The second is tokens in a collection heading for the repository. A value written into an environment stays in the change history and needs rotating once discovered.

The third is choosing cloud mode without checking requirements. For internal interfaces settle that before creating the project, since changing mode later means moving the collection.

The fourth is a collection testing only the happy path. A change in error handling then passes unnoticed, and that is where most surprises hide.

The fifth is an interface description nobody maintains. An outdated file misleads more effectively than no file at all.

The sixth is tests run only by hand. Without wiring into the build pipeline they stop being used within a month.

When a graphical client is unnecessary

It is worth saying plainly that not every task needs such a tool, since installing an application to check one endpoint is excessive.

A single request is checked faster with a terminal command, particularly when only the status and a few fields interest you. The same goes for a quick check on whether a service responds at all.

Repeatable tasks belong in scripts. A daily check across a dozen endpoints is a file run on a schedule rather than a collection somebody must open and click through.

Business logic tests belong in code, closer to that logic. Checking whether a discount calculated correctly is a unit test rather than a request in an API client.

A graphical client earns its keep on three things: reading long responses, working with a collection the team maintains, and exploring somebody else's interface you do not yet know. On those the difference from a terminal registers, and that is when having one is worthwhile.

FAQ

Is Insomnia free?

Basic use is free, and paid plans add team collaboration, higher limits, and organisational features. Check the current tiers on the vendor's site, since the billing model changes from time to time.

Can I work without an account and without a cloud?

Yes, local mode keeps everything on disk and sends nothing. Repository based mode stores collections as files in your repository, which for team work is usually a better choice than a vendor cloud.

How does it differ from Bruno?

Bruno is built around one idea: collections as repository files with no server side service. Insomnia offers a choice of three modes and supports more protocols, binary format calls included, at the cost of a larger application.

Does it support gRPC and GraphQL?

Yes, both have dedicated views. GraphQL pulls the schema from the endpoint and suggests fields, and for binary calls the tool reads service definitions, which is rare among graphical clients.

Can a collection run in a build pipeline?

Yes, through a command line tool taking a collection and an environment. That lets you check after deployment whether the interface's key paths answer as before.

Documentation sits on the Kong site, and the source code in the GitHub repository.