Skip to main content

How to Migrate from Postman to Bruno 2026

·OSSAlt Team
postmanbrunomigrationapi-testingguide
Share:

How to Migrate from Postman to Bruno 2026

Bruno is the Git-native alternative to Postman. Instead of syncing to a cloud account, API collections live as plain text files in your Git repository. Version-controlled, offline-first, and open source with a MIT license. The migration is among the simplest in the developer tool space: export, import, and commit.

TL;DR

Export your Postman collection as Collection v2.1 JSON, import it into Bruno, and Bruno converts everything to .bru files stored on your local filesystem. Add the collection to Git, push, and your entire API test suite is version-controlled alongside your code. No cloud account needed, no syncing required.

Key Takeaways

  • Bruno stores API collections as plain text .bru files — readable, diffable, and greppable
  • Import from Postman Collection v2.1 JSON is built-in and handles most collections accurately
  • Variables use the same {{variable}} syntax as Postman — environment references don't change
  • Bruno CLI (@usebruno/cli) enables running collections in CI/CD pipelines without extra tooling
  • The biggest gaps vs Postman: no cloud sync (Git instead), no mock servers, no API monitoring
  • Bruno's scripting uses JavaScript with full access to the request and response context

Why Developers Switch from Postman

Postman has shifted from a developer tool toward an enterprise collaboration platform. Cloud sync is now mandatory for sharing collections — meaning API requests, including any embedded credentials or endpoint details, leave your machine. The free tier limits collaboration, pushing teams toward $12-19/user/month plans for basic sharing functionality that used to be free.

Practically, Postman's collection format is an opaque JSON blob that doesn't diff well in pull requests. When a teammate adds a request or changes an endpoint, reviewing that change in GitHub requires parsing nested JSON structures, not reading recognizable request definitions.

Bruno solves both problems. Collections are stored in your repository as .bru files — one file per request, using a clean domain-specific language that's immediately readable in a code review. Sharing happens via Git: push to main, and every team member pulls the latest requests with their next git pull. There's no cloud service involved at any point.

Step 1: Export from Postman

  1. Open Postman → navigate to your collection
  2. Click (three dots) next to the collection name → Export
  3. Select Collection v2.1 (not v1 — Bruno's importer requires v2.1)
  4. Save the JSON file to a known location

For workspace-level exports, you can export multiple collections at once. If you have environment files in Postman, export those separately: EnvironmentsExport.

Step 2: Install Bruno

Download from usebruno.com for Mac, Windows, or Linux.

Or via package manager:

# macOS
brew install bruno

# npm (cross-platform)
npm install -g @usebruno/cli

The desktop app provides the GUI for building and running requests. The CLI (bru) enables running collections in terminal and CI/CD environments.

Step 3: Import Postman Collection

  1. Open Bruno
  2. Click Import Collection
  3. Select Postman Collection
  4. Choose your exported JSON file
  5. Select a folder in your project to store the collection

Bruno converts Postman's JSON into .bru files — plain text, one file per request:

# get-users.bru
meta {
  name: Get Users
  type: http
  seq: 1
}

get {
  url: {{baseUrl}}/api/users
  body: none
  auth: bearer
}

auth:bearer {
  token: {{authToken}}
}

headers {
  Content-Type: application/json
}

The .bru format is readable to anyone familiar with HTTP. Method, URL, auth type, and headers are all immediately visible — far more review-friendly than Postman's nested JSON collection format.

Step 4: Set Up Environments

Create environment files in your collection folder:

# environments/development.bru
vars {
  baseUrl: http://localhost:3000
  authToken: dev-token-here
}

# environments/staging.bru
vars {
  baseUrl: https://api-staging.example.com
  authToken: staging-token-here
}

# environments/production.bru
vars {
  baseUrl: https://api.example.com
  authToken: {{SECRET_AUTH_TOKEN}}
}

For secrets, use Bruno's secret variable feature. Secret variables are stored in a .env file that you add to .gitignore — they're never committed to version control. This is fundamentally more secure than Postman's cloud-synced environment variables.

Step 5: Commit to Git

# Your API collection is now plain text files
git add api-collection/
git commit -m "chore: import API collection from Postman"

This is Bruno's killer feature — your entire API test suite is version-controlled alongside your code. Every team member has the same requests, synced via Git. API changes appear in pull request diffs, get code-reviewed, and land in the main branch alongside the corresponding code changes. The API contract is part of the codebase, not a separate cloud account.

No cloud account needed. No subscription required. The entire sharing model is Git.

Step 6: Run Collections in CI/CD

# Install Bruno CLI
npm install -g @usebruno/cli

# Run entire collection against staging environment
bru run --env staging api-collection/

# Run a specific subfolder
bru run --env staging api-collection/auth/

# Generate JUnit XML for CI reporting
bru run --env staging api-collection/ --reporter-junit output.xml

GitHub Actions example:

name: API Tests
on: [push, pull_request]
jobs:
  api-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install -g @usebruno/cli
      - run: bru run --env staging api-collection/
        env:
          SECRET_AUTH_TOKEN: ${{ secrets.API_TOKEN }}

This replaces Postman's Newman runner. The same collection developers use in the GUI runs in CI without any conversion or additional tooling. Secrets are injected via environment variables, keeping credentials out of both the collection files and the CI logs.

Scripting in Bruno

Bruno supports pre-request and post-request scripts using JavaScript:

// Pre-request script — runs before the request
const timestamp = Date.now();
bru.setVar('requestTimestamp', timestamp);

// Post-response script — runs after the response
const data = bru.response.getBody();
bru.setVar('userId', data.id);

// Test assertions
test("Status is 200", function() {
  expect(bru.response.getStatus()).to.equal(200);
});

test("Response has users array", function() {
  const data = bru.response.getBody();
  expect(data.users).to.be.an('array');
  expect(data.users.length).to.be.greaterThan(0);
});

Scripts live inside .bru files or in separate pre-request.js and post-response.js files in the request directory. This makes scripts version-controlled alongside request definitions — when a script changes to handle a new API response format, that change appears in your PR diff.

Key Differences From Postman

PostmanBruno
Cloud-synced collectionsGit-native file-based
JSON format (opaque).bru format (human-readable)
Account requiredNo account needed
{{variable}}{{variable}} (identical syntax)
Pre-request scripts✅ JavaScript scripting
Test scripts✅ Assertions
Mock servers
Team collaborationVia Git (push/pull)
Environments in cloudEnvironment files in repo
Newman CLI runnerBruno CLI (bru run)
API monitoring

What You'll Gain

  • Full version control — requests in Git, reviewable in PRs, full audit history
  • Team sync via Git — no cloud account or subscription required
  • Offline-first — works completely without internet
  • Security — credentials stored in .env files (gitignored), never synced to any cloud
  • Plain text — readable, diffable, and greppable with standard tools
  • CI/CD integration — Bruno CLI runs collections natively in pipelines

What You'll Lose

  • Cloud sync (replaced by Git — often better for developer teams)
  • Mock servers (use Mockoon, WireMock, or msw as alternatives)
  • API monitoring (use self-hosted uptime tools)
  • Postman's collaboration UI with inline comments and changelog

Team Adoption: Getting Everyone Off Postman

The hardest part of migrating from Postman to Bruno is often cultural, not technical. Developers who have used Postman for years have muscle memory around the GUI, cloud sync, and collection sharing via Postman's workspace model. The Git-based sharing model requires a mindset shift.

The most effective rollout strategy is to migrate one team or project first, run Bruno alongside Postman for a few weeks, and let the convenience differences become apparent. When developers see API changes reviewed in PRs — with request body changes right next to the corresponding code change — and when they notice collections always match the current branch they're working on, the advantages sell themselves. The credential security story is also compelling for security-conscious teams: no API keys or tokens ever leave the developer's machine or hit Postman's servers.

For teams on Postman's paid plan, the cost comparison is simple. Postman Basic costs $12/user/month; Postman Professional costs $19/user/month. A 5-person team on Professional pays $1,140/year for collaboration features. Bruno is free and MIT-licensed. For context on how this fits into a broader developer tool cost audit, the SaaS subscription audit framework provides a structured approach to calculating total tooling ROI.

The best open source alternatives to Postman covers Bruno alongside other options — Insomnia, Hoppscotch, and HTTPie — for teams that want to compare before committing to a specific tool. For teams evaluating more comprehensive API development platforms, the best open source API management tools roundup covers tools that add documentation, mocking, and gateway features on top of basic request testing.

The Bottom Line

Bruno is the right choice for developer teams who want API collections to live in their repository rather than a cloud account. The migration is fast — typically under an hour for a substantial Postman collection. After the migration, API testing integrates naturally into the Git workflow your team already uses: request changes in PRs, reviews in the diff, deployment via standard CI/CD.


Compare API testing tools on OSSAlt — workflow, collaboration, and data ownership side by side.

See open source alternatives to Postman on OSSAlt.

Why Migrate from Postman?

Postman started as a lightweight Chrome extension in 2012 and grew into a full platform. That growth came with trade-offs that have frustrated developers over the past few years. The most significant concern is cloud sync. Every API collection you create in Postman is uploaded to Postman's servers. That means your endpoint URLs, authentication tokens, environment variables, and request headers all live in a third-party cloud. For teams working with internal APIs, staging credentials, or proprietary service architectures, this is a real security risk. Several organizations have had API keys accidentally leaked when developers used personal Postman accounts and then left the company, leaving collections in a shared workspace that nobody remembered to clean up.

Pricing has also shifted dramatically. Postman's free tier used to cover most development needs, but the team plan now runs $149 per user per year to unlock features like Git sync, custom domains, and more than three active environments. For a team of five, that's $745 per year just for an HTTP client. The collaboration features that justify this cost — shared workspaces, role-based access, audit logs — are things you get for free when your collections are just files in a Git repository.

The deeper problem with Postman's cloud model is that it creates a divergence between where your API tests live and where your code lives. Your codebase is version-controlled in Git, but your API tests are siloed in a separate cloud tool with its own versioning system. This means API changes are not reviewed in pull requests, there's no easy way to tie a specific collection state to a specific code release, and onboarding a new developer means they need to be added to the Postman workspace rather than just cloning the repo.

Bruno solves all of this by treating API collections the same way developers treat code. Collections are directories of plain text files. You commit them, branch them, diff them, and review them in pull requests. The entire workflow fits naturally into the development process you already use.

Bruno's File Format Explained

The .bru file format is Bruno's plain-text representation of an HTTP request. Each request becomes a single file with a structured syntax that is both human-readable and machine-parseable. A typical .bru file has several sections: meta (name, type, sequence), the HTTP method and URL block, optional authentication configuration, headers, and a body or query parameters section.

Because .bru files are plain text, they behave like any other source code file. You can open them in a text editor, search across them with grep, and see meaningful diffs when requests change. When a teammate updates a header or changes an endpoint path, the pull request diff shows exactly what changed — not a JSON blob with shuffled keys that's impossible to review.

Secret management works differently from Postman. In Bruno, the convention is to use environment variable references in your request files, but the actual values are never stored in the .bru files themselves. Environment files are split into two types: those that can be committed to Git (containing non-sensitive defaults) and those that should be gitignored (containing real credentials). This gives you a clean separation between the structure of your environment (version-controlled) and the secrets (which stay local or in a secrets manager). This is the opposite of what often happens with Postman, where developers inadvertently commit collection exports that contain real token values embedded in the JSON.

The format also supports scripting. You can write JavaScript pre-request scripts and post-response tests using a Chai-style assertion API. The scripts are embedded directly in the .bru file, so they're visible in code review alongside the rest of the request definition. There's no separate hidden tab burying logic that's hard to discover during a pull request review.

Common Pitfalls

The transition from Postman to Bruno is generally smooth, but there are a few friction points to be aware of before you start.

Pre-request script syntax has some differences. While Bruno supports JavaScript scripting, the API surface is not identical to Postman's scripting model. Postman scripts access environment and response data through methods on a global pm object. Bruno uses a bru object with slightly different method names and a somewhat different API surface. If you have complex pre-request scripts — especially ones that fetch auth tokens or compute HMAC signatures — you'll need to port them. Most scripts translate in under an hour, but it's worth auditing your collection for scripting complexity before you commit to the migration timeline.

Environment variable management requires adjusting your mental model. Postman has a global environment and collection-level environments that can be toggled in the UI. Bruno uses environment files in the collection directory. If you have many environments (development, staging, production, per-developer locals), you'll need to decide which environment files should be committed and which should be gitignored. The general rule is to commit environment files that contain only variable names and safe defaults, and gitignore files that contain real credentials or environment-specific secrets.

The biggest feature gap is monitoring. Postman has a built-in monitors feature that runs collections on a schedule and alerts you when requests fail. Bruno has no equivalent. If you rely on Postman monitors for uptime checks or API health validation, you'll need a separate solution — most teams use a dedicated uptime monitor like Checkly, Grafana synthetic monitoring, or a simple cron job running the Bruno CLI against a staging environment. This is not necessarily a disadvantage (purpose-built monitoring tools are better at alerting, on-call workflows, and status pages), but it is work you'll need to account for separately from the Bruno migration itself.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.