Skip to main content
/tayyab/portfolio — zsh
tayyab
TA
// dispatch.read --classified=false --access-level: public

Replacing Postman With Playwright API Tests: A 30-Day Migration Story

March 30, 2026 EST. READ: 12 MIN #Quality Assurance

Late 2024, an e-commerce client had this stack: Playwright for browser tests, Postman + Newman for API contract tests. Two CI pipelines, two reporters, two patterns for handling auth, two places to update test data. The Postman license fees were modest but the cognitive overhead of maintaining two systems was significant.

30 days of focused work later, all 240 API tests had moved to Playwright's request fixture. One CI pipeline. One reporter. One auth pattern. License gone, mental overhead gone, regression risk reduced.

This is the migration story — what mapped, what didn't, and the patterns I'd reuse on the next one.

Table of Contents

Why Migrate at All (It's Not Always Worth It)

Migrate when:

  • You're already running Playwright for browser tests and want to consolidate.
  • Your Postman tests are written by your QA team (not by external partners who depend on the Postman GUI).
  • Your team prefers code-as-tests over GUI-defined tests.
  • You have at least 3 weeks of focused QA capacity.

Don't migrate when:

  • Your Postman tests are documentation that backend engineers reference.
  • Postman Mock Server is critical to your testing workflow.
  • You don't have Playwright in production yet.

The e-commerce client's situation matched the "migrate" criteria. They got value. Half my other clients are running Postman just fine; I haven't pushed migration on them.

What Postman Does Well That Playwright Doesn't

  • GUI-driven exploration. Backend engineers love the request builder. Hard to beat for ad-hoc API exploration.
  • Mock servers. Postman's mock server feature has no direct Playwright equivalent.
  • Collection sharing across non-coders. Product managers can run a collection. They can't run a Playwright test.
  • Pre-request scripts and dynamic variables. Postman's templating is mature.
  • Built-in OAuth flows. Postman has nice OAuth helpers. Playwright is more manual.

What Playwright Does Well That Postman Doesn't

  • Code review. Tests live in your repo, get reviewed, get versioned.
  • Type safety. TypeScript types catch contract drift at edit time, not run time.
  • Real test fixtures. Playwright's fixture system is more powerful than Postman's pre-request scripts.
  • Programmability. Loops, conditionals, retries — natural in code, awkward in Postman.
  • Combined with browser tests. Same fixtures, same auth, same reports. Huge integration win.
  • Free. No license tiers.

Mapping Postman Concepts to Playwright

PostmanPlaywright
Collectiontests/api/feature/*.spec.ts directory
Requestrequest.get/post/put/delete call
Pre-request scripttest.beforeEach or fixture
Tests tab assertionsexpect(...).toBe(...)
Environment variablesprocess.env.X
Collection variablesShared fixture state
Newman runnernpx playwright test
Postman reportersAllure, HTML, JSON reporters
Mock serverSeparate tool (MSW, WireMock)

The 30-Day Plan

Week 1: Discovery and shared fixtures

  • Export the Postman collection as JSON. Read it. Categorize requests by feature.
  • Identify shared concerns: auth, base URLs, common request bodies. Build Playwright fixtures for them.
  • Pick the 5 simplest requests. Migrate them as proof-of-concept.

Week 2: Bulk migration of contract tests

  • Walk through Postman folders systematically. Convert each request to a Playwright spec.
  • Skip anything complex (file upload, OAuth, conditional flows). Park them for week 3.
  • Update CI to run both old (Newman) and new (Playwright) suites in parallel. Verify same coverage.

Week 3: Complex flows

  • OAuth flows. Use Playwright's request fixture with explicit token handling.
  • File upload tests. request.post with multipart form data.
  • Sequential dependent requests. Convert Postman's request chaining to native test sequences.

Week 4: Cutover and cleanup

  • Compare Newman vs Playwright results for a week. Confirm parity.
  • Remove Newman from CI.
  • Archive the Postman collection in case backend devs want to reference it.
  • Update documentation. Drop the license.

Side-by-Side Code: Postman vs Playwright

Postman

// Pre-request Script:
const auth = pm.environment.get('authToken');
pm.request.headers.add({ key: 'Authorization', value: `Bearer ${auth}` });

// Request: POST {{baseUrl}}/orders
// Body: { "items": [{ "sku": "WIDGET-1", "qty": 2 }] }

// Tests:
pm.test('Status 201', () => pm.response.to.have.status(201));
pm.test('Has order ID', () => {
  const json = pm.response.json();
  pm.expect(json.id).to.match(/^ord_/);
  pm.environment.set('lastOrderId', json.id);
});

Playwright

// fixtures/api.ts
import { test as base } from '@playwright/test';

export const test = base.extend({
  authedRequest: async ({ request }, use) => {
    const token = await fetchTestToken();
    await use({
      get: (url: string) => request.get(url, {
        headers: { Authorization: `Bearer ${token}` },
      }),
      post: (url: string, data: any) => request.post(url, {
        data,
        headers: { Authorization: `Bearer ${token}` },
      }),
    });
  },
});

// tests/api/orders/create-order.spec.ts
import { test } from '../../../fixtures/api';
import { expect } from '@playwright/test';

test('POST /orders creates an order', async ({ authedRequest }) => {
  const response = await authedRequest.post('/orders', {
    items: [{ sku: 'WIDGET-1', qty: 2 }],
  });

  expect(response.status()).toBe(201);
  const body = await response.json();
  expect(body.id).toMatch(/^ord_/);
});

The Playwright version is longer but more readable, type-safe, and integrates with the rest of your test infrastructure.

The 5 Gotchas That Cost Me Time

1. Postman's request chaining is implicit; Playwright's is explicit

Postman lets you read pm.environment.get('lastOrderId') in any subsequent request, even across collections. Playwright doesn't. You either pass values explicitly between tests in the same file, or use a fixture-level state object.

2. Postman has more permissive JSON parsing

Postman tolerates trailing commas, comments in JSON, and other non-strict syntax. Playwright (and the underlying fetch) does not. Some test bodies needed reformatting.

3. Postman's environment scoping

Postman has 4 levels of variable scope (global, environment, collection, local). Playwright fixtures are simpler. Map Postman's scopes to module-level constants, fixture-level state, and test-level state. The conversion is mechanical once you understand the mapping.

4. Newman's HTML reporter

Some teams have built dashboards around Newman's reporter output. Playwright's reporter is different. Either: regenerate the dashboard from Playwright's JSON output, or write an adapter. Plan for this in week 4.

5. Postman Mock Servers

If your team uses Postman Mock Servers as part of integration tests, the migration breaks those. Stand up an alternative (MSW, WireMock, or Prism) before retiring the Postman workspace.

FAQs

What about Bruno or Hoppscotch?

Modern Postman alternatives. If your migration goal is mainly cost or open-source, Bruno is a near-drop-in replacement. If your goal is consolidating with browser tests, Playwright wins.

How do I keep API documentation up to date after migration?

Use OpenAPI/Swagger as your API spec source. Generate Postman collections from OpenAPI for backend devs who like the GUI. Generate Playwright tests for QA. Single source of truth.

What about parallel API tests?

Playwright's fullyParallel: true works for API tests too. Same caveats — make sure tests don't share mutable state.

Can I keep Postman for some tests and Playwright for others?

Yes — see my multi-framework post. The cost is real but legitimate when each tool fits a clear slice.

What about contract testing with Pact?

Different category. Pact tests the contract between two services from both sides. Playwright API tests verify your API behaves as expected from the client perspective. They complement each other.

How do I handle GraphQL?

Same as REST. request.post('/graphql', { data: { query, variables } }). Match on operation name in mocks if needed.

What about WebSocket testing?

Different API entirely. Use page.routeWebSocket for browser-driven WebSocket tests, or a Node WebSocket client for direct testing.

How do I migrate Postman environments?

Map to .env.staging, .env.production, etc. Load via dotenv. Standard Node pattern.

What about Postman's monitoring features?

That's an uptime/synthetic-monitoring use case. Playwright can do this too — schedule the test to run periodically against production with a separate config. But dedicated tools (Pingdom, Checkly) are better here.

Should I migrate API tests before browser tests?

If you're starting Playwright fresh and have Postman already, do API last. Browser tests are higher-leverage early. Migrate Postman once your Playwright skills and infrastructure are solid.

Wrap-Up

Postman → Playwright API migration is a 30-day project that pays back in unified tooling, type safety, and reduced licensing. It's not always the right call — Postman has real strengths around exploration and mock servers — but for teams already running Playwright, the consolidation is worth the migration cost.

If your team is evaluating this migration and wants help scoping the work, that's part of framework engagements. Or book a free call.

Related reading:

Tayyab Akmal
// author

Tayyab Akmal

AI & QA Automation Engineer

6 years of catching critical bugs in fintech, e-commerce, and SaaS — then building the Playwright and Selenium automation that prevents them from shipping again.

// related_dispatches

YOU MIGHT ALSO READ

// feedback_channel

FOUND THIS USEFUL?

Share your thoughts or let's discuss automation testing strategies.

→ Start Conversation
Available for hire