Design and Test an API with Postman

Write an OpenAPI spec, build a tested collection, and chain requests in Postman.

Introduction

30 Second Summary

Every time you check the weather, scroll a social feed, or pay for something online, an API is working behind the scenes. When those APIs break or misbehave, the apps they power break too.

In this project, you will design an API contract using an OpenAPI specification, then test a real API with automated scripts inside Postman. You will write test assertions, chain requests together with variables, and run everything as a single automated test suite.

What You'll Build

You will send live HTTP requests to a real API, see JSON responses come back, and run a full test suite with every assertion passing in one automated sweep.

By the end of this project, you'll have:

  • An OpenAPI 3.0 specification in Postman's Spec Hub with paths, schemas, and a live documentation preview you can browse.
  • A hand-built Postman Collection with GET, POST, and PUT requests against JSONPlaceholder, each carrying automated test scripts that validate status codes, response times, and JSON structure.
  • A working request chain that captures data from one response and feeds it into the next request automatically using environment variables.
  • Secret Mission: Generate an OpenAPI specification back from your tested collection, completing the full design-to-test-to-spec API lifecycle.

Are there any prerequisites?

No. This project walks you through installing Postman and creating a free account. No prior API experience is needed.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters.

Professional API developers use a two-sided workflow: they design the contract first with an OpenAPI specification, then test the real thing with scripting tools.

In this project, you'll learn both sides. You'll write an OpenAPI spec that defines a Task Manager API, then build a hands-on Postman collection against JSONPlaceholder (a free public REST API) with automated tests and request chaining.

Set Up Postman and Create Your Workspace

Everything you build in this project lives inside Postman. Your OpenAPI specification, your test collection, your environment variables, and your automated test runs all happen in one place.

A dedicated workspace keeps your project files organized and separate from everything else in your Postman account. In this step, you will install Postman, sign in, and create that workspace.

In this step, get ready to:
  • Install and open the Postman desktop app.
  • Sign in to a free Postman account.
  • Create a dedicated workspace called API Testing Lab.
Install and open Postman

Postman is a desktop app available for macOS, Windows, and Linux. Check whether you already have it installed.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Postman and look for the app in the results.

✔️ I see Postman in my search results

  • Press Enter to open Postman.
  • Postman auto-updates, so you are already on the latest version. You are ready to move on.

ⓧ I don't see Postman

  • Open your browser and go to the Postman download page by visiting this link:

https://www.postman.com/downloads/

  • Click the download button for your operating system (macOS, Windows, or Linux).
  • Once the download finishes, open the installer and follow the on-screen instructions.
  • After installation, Postman opens automatically.

Postman not opening after install?

  • On macOS, you may need to drag the Postman icon into your Applications folder first.
  • On Windows, try running the installer as an administrator by right-clicking the file and selecting Run as administrator.
  • If Postman still does not launch, restart your computer and try opening it again.

Still stuck? Help me troubleshoot my Postman installation.

You should now see the Postman app open on your screen.

Sign in to your Postman account

You need a Postman account to use Spec Hub and save your work. A free account gives you everything this project needs.

✔️ I'm already signed in

If you see your avatar or profile icon in the upper-right corner of Postman, you are already signed in. Skip ahead to the next substep.

ⓧ I need to sign in or create an account

  • Click Sign In in the upper-right corner of Postman. If you do not have an account yet, click Create Account instead.
  • Postman opens your default browser for sign-in. Enter your credentials (or sign up with your email, Google, or GitHub).
  • After signing in, you are redirected back to the Postman desktop app.

Why does the browser open?

Postman handles sign-in through your browser for security. Once you complete sign-in there, the desktop app picks it up automatically. You must finish signing in within five minutes or the process times out and you will need to restart it from the app.

Browser not opening for sign-in?

If your browser does not open within a few seconds, look for a link in Postman that says open it manually or copy the URL. Click either option to complete sign-in.

Need more help? Help me sign in to Postman.

You should now see your profile icon in the upper-right corner of Postman, confirming you are signed in.

Create your API Testing Lab workspace

A workspace in Postman is a container for your specs, collections, and environments. Creating a dedicated one for this project keeps everything in one place.

  • Click Workspaces in the header at the top of Postman.
  • Click Create Workspace.
  • Enter API Testing Lab in the Name field.
  • Select Blank workspace so you start with an empty workspace.
  • Leave the remaining options as their defaults.
  • Click Create Workspace to finalize.

What is a workspace?

Think of a workspace as a folder for your entire API project. It holds your specifications, collections, environments, and test results. Keeping a separate workspace for each project prevents your work from getting mixed together.

Postman opens your new workspace. You should see API Testing Lab displayed in the header and in the sidebar on the left.

Don't see your workspace?

  • Make sure you clicked Create Workspace at the end. If the dialog closed without creating anything, repeat the steps above.
  • Click Workspaces in the header again to see a list of all your workspaces. API Testing Lab should appear in the list. Click it to open it.

Still stuck? Help me find or create my workspace in Postman.

Your workspace is ready. Next up, you will design your API by writing an OpenAPI specification from scratch inside Postman's Spec Hub.

Design Your API with an OpenAPI Specification

Before writing a single test, you need to define what your API should look like. This is API-first design: you write the contract before building or testing anything.

In this step, you will write an OpenAPI 3.0 specification that describes a Task Manager API. Postman's Spec Hub gives you a live documentation preview as you type, so you can see your API taking shape in real time.

What is API-first design?

In API-first design, you write a specification that defines your endpoints, request bodies, and response shapes before writing any code or tests. The specification acts as a contract that everyone (frontend developers, backend developers, testers) agrees on.

This is the opposite of building an API first and documenting it later. With the contract in place, teams can work in parallel because everyone knows exactly what to expect.

In this step, get ready to:
  • Create a new OpenAPI 3.0 specification in Spec Hub.
  • Define paths, operations, and a reusable schema for a Task Manager API.
  • Preview the live API documentation in the right sidebar.
Create a new specification in Spec Hub

Spec Hub is where Postman stores and manages API specifications. You will create a new spec here and choose the OpenAPI 3.0 format.

  • In the sidebar, click the + icon and select Spec.
  • Select OpenAPI 3.0 as the specification type.
  • Postman creates a new specification with boilerplate content in the editor.

The boilerplate is a starting point you will replace shortly. First, rename the specification.

  • In the sidebar, click More actions (the three-dot icon) next to your new specification and select Rename.
  • Type Task Manager API and press Return or Enter.

You should see "Task Manager API" as the specification name in the sidebar.

Don't see the Spec option?

Make sure your API Testing Lab workspace is the active workspace. The + icon appears in the left sidebar. If you still cannot see it, confirm you are signed into your Postman account.

Help me find the Spec option in the sidebar.

Write the spec foundation and Task schema

Every OpenAPI spec starts with a header that declares the format version and basic info. You will also define a reusable Task schema up front so your path definitions can reference it.

  • Select all the boilerplate content in the editor (Cmd+A on macOS, Ctrl+A on Windows) and replace it with this YAML:
openapi: 3.0.0
info:
  title: Task Manager API
  version: 1.0.0
# Paths define the API endpoints
paths: {}
# Components hold reusable schemas
components:
  schemas:
    Task:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        completed:
          type: boolean

What does this code do?

  • openapi: 3.0.0 declares this spec uses the OpenAPI 3.0 format.
  • info provides the API title and version number. These appear in the generated documentation.
  • paths: {} is a placeholder you will fill in next. It tells OpenAPI you have no endpoints defined yet.
  • The Task schema under components/schemas defines a reusable data shape with three properties: id (integer), title (string), and completed (boolean).
  • Click Save in the upper right of the editor.

The editor should show your spec without any red error indicators. The Task schema is defined at the bottom, and paths: {} is ready for your endpoints.

Add the /tasks endpoints

The /tasks path handles listing all tasks (GET) and creating a new task (POST). Both operations reference the Task schema you just defined.

  • In the editor, find the line that says paths: {} and replace it with the following:
paths:
  # List and create tasks
  /tasks:
    get:
      summary: Get all tasks
      responses:
        '200':
          description: A list of tasks
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Task'
    post:
      summary: Create a new task
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Task'
      responses:
        '201':
          description: Task created

What does this code do?

  • The get operation on /tasks returns a 200 response containing a JSON array of Task objects.
  • The post operation accepts a Task object in the request body and returns 201 when the task is created.
  • $ref: '#/components/schemas/Task' points back to the Task schema you defined in the foundation chunk. This keeps your spec DRY (Don't Repeat Yourself).
  • Click Save.

The editor now shows the /tasks path with both GET and POST operations. No red error indicators should appear.

Seeing a red error indicator?

YAML is sensitive to indentation. Make sure /tasks: is indented with exactly two spaces under paths:. Each nested level adds two more spaces.

Also check that paths: {} was fully replaced (no leftover {} characters on the same line).

Help me fix YAML indentation errors in my OpenAPI spec.

  • Now add the single-task endpoints. Place the following YAML directly below the post operation's last line (description: Task created), and above the components: line:
  /tasks/{taskId}:
    parameters:
      - name: taskId
        in: path
        required: true
        schema:
          type: integer
    get:
      summary: Get a task by ID
      responses:
        '200':
          description: A single task
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Task'
    put:
      summary: Update a task
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Task'
      responses:
        '200':
          description: Task updated
    delete:
      summary: Delete a task
      responses:
        '204':
          description: Task deleted

What does this code do?

  • /tasks/{taskId} uses a path parameter so each operation targets a specific task by its ID.
  • The parameters block defines taskId as a required integer in the URL path. This applies to all operations under this path.
  • Three operations are defined: get retrieves a single task, put updates it, and delete removes it. The delete operation returns a 204 (no content) because there is nothing to send back.
  • Click Save.

Your spec now has both paths: /tasks and /tasks/{taskId}. The editor should be free of error indicators.

✔️ Awesome, I've got everything!

Great. Double check you have saved the spec by looking for the spec name "Task Manager API" in the sidebar with no unsaved-changes indicator.

ⓧ I'd like to double check the full code

Your spec is split across three sections. Scroll up and confirm each one is present, in this order:

  • Spec foundation: openapi: 3.0.0, info with title and version, and components/schemas/Task with id, title, and completed properties.
  • /tasks path: get returning a 200 array of Tasks, and post returning 201.
  • /tasks/{taskId} path: a taskId parameter, get returning 200, put returning 200, and delete returning 204.

Make sure the components: section sits below both paths, not between them.

Preview your API documentation

Postman can render your spec as browsable documentation while you edit. Before you open the preview, think about what you expect to see. How many paths should appear?

  • Click Live preview in the right sidebar.

The documentation preview opens and shows your two paths: /tasks and /tasks/{taskId}. Each path lists its operations with their summaries and response codes.

  • Scroll down in the preview to find the Schemas section.
  • Confirm you see the Task schema listed with its three properties: id, title, and completed.

This is the API contract you have designed. Every endpoint, request body, and response shape is defined in one place.

What is OpenAPI doing for you here?

The live preview turns your YAML specification into human-readable documentation automatically. Anyone on your team can read these docs and know exactly what endpoints exist, what data they accept, and what they return.

If you change the spec (add a field, rename a path), the documentation updates immediately. No separate docs to maintain.

Live preview is empty or not showing paths?

Make sure you clicked Save after your last edit. The preview renders the saved version of the spec.

If the preview shows errors, check that /tasks and /tasks/{taskId} are both nested under paths: with correct indentation (two spaces per level).

Help me get the live preview working for my OpenAPI spec.

Your API contract is locked in. You have a complete OpenAPI specification that defines every endpoint, parameter, and data shape for a Task Manager API. Next up, you will build real requests against a live API and see actual data come back.

Build and Send Your First Requests

Your OpenAPI spec defines what the Task Manager API should look like. Now it's time to talk to a real API and see if the design actually holds up.

You'll build requests against JSONPlaceholder, a free public API that behaves like a real REST API. This step gets you your first visible win: sending a request and seeing real JSON data come back.

In this step, get ready to:
  • Generate a Postman Collection from your OpenAPI spec.
  • Build and send a GET request to a live public API.
  • Send a POST request to create a new resource.
Generate a collection from your spec

One of the benefits of writing an OpenAPI spec first is that Postman can automatically generate a collection from it. This gives you a set of pre-built request stubs based on your API design.

  • Switch back to your Task Manager API spec in the sidebar under Specs.
  • Click Generate Collection in the upper right of the workbench.
  • Enter Task Manager Tests as the collection name.
  • Click Generate collection.

You should see Task Manager Tests appear under Collections in the sidebar. Click it to expand its contents and see the generated request stubs.

Why build a collection by hand?

The generated collection is a useful starting point, but it points at placeholder URLs. It does not connect to a real API you can test against.

You'll build a separate collection by hand against a live API so you learn how Postman requests actually work. Understanding request construction from scratch is a skill that matters far more than generating stubs.

Create a collection and send your first GET request

JSONPlaceholder is a free fake REST API that returns realistic data for testing. It supports all standard HTTP methods with zero setup required.

  • In the sidebar, click the + icon and select Collection.
  • Click the collection name in the workbench and rename it to JSONPlaceholder Tests.
  • Hover over the new collection in the sidebar and click Add request.

A new request tab opens in the workbench. This is where you configure what Postman sends to the API.

  • Click the request name at the top and rename it to Get Todo.
  • Make sure the method dropdown to the left of the URL field is set to GET.
  • Enter https://jsonplaceholder.typicode.com/todos/1 in the URL field.

Before you click Send, what do you think the response will contain? This URL asks for a single to-do item with an ID of 1.

  • Click Send.

You should see a 200 OK status in the response panel. The response body is a JSON object with four fields: userId, id, title, and completed.

What is a GET request?

A GET request asks the API to retrieve data without changing anything. Think of it like looking up a contact in your phone. You get the information back, but nothing is added or removed.

The 200 OK status code means the server found the resource and returned it successfully.

Not seeing a 200 OK response?

Make sure the URL is exactly https://jsonplaceholder.typicode.com/todos/1 with no trailing spaces or typos.

Check that your internet connection is active. JSONPlaceholder is a public API, so no API key or authentication is needed.

Why isn't my GET request returning data from JSONPlaceholder?

Send a POST request to create a resource

GET retrieves existing data, but APIs also need to create new resources. A POST request sends data to the server and gets back the newly created resource.

  • Hover over the JSONPlaceholder Tests collection in the sidebar and click Add request.
  • Click the request name at the top and rename it to Create Post.
  • Change the method dropdown from GET to POST.
  • Enter https://jsonplaceholder.typicode.com/posts in the URL field.

A POST request needs a body: the data you are sending to the API. You'll configure this in the Body tab.

  • Select the Body tab below the URL field.
  • Choose raw from the format options.
  • In the dropdown to the right of raw, select JSON.
  • Paste this JSON body into the text area:
{
  "title": "My test post",
  "body": "This is a test",
  "userId": 1
}

What does this JSON body do?

Each field tells the API what to create. title and body are the content of the new post. userId links it to a specific user.

JSONPlaceholder simulates the creation. It accepts your data and returns it back with a new id field, just like a real API would.

What status code do you expect from a request that creates a new resource? It will not be 200 OK this time.

  • Click Send.

You should see a 201 Created status. The response body is a JSON object containing your data plus a new id field that the API assigned to the newly created resource.

Why 201 instead of 200?

HTTP uses different status codes to communicate exactly what happened. 200 OK means the request succeeded. 201 Created means the request succeeded and a new resource was created as a result.

This distinction helps API consumers know whether a resource already existed or was just born.

Seeing a 400 or 500 error?

Check that the Body tab shows raw selected with the format dropdown set to JSON. If the format is set to Text, the API will not parse your data correctly.

Make sure your JSON has matching curly braces and all keys are wrapped in double quotes.

Why is my POST request to JSONPlaceholder failing?

You now have two working requests that can read and create data. Next up, you'll add automated test scripts so Postman can verify these responses for you instead of checking them manually every time.

Write Automated Test Scripts

Your GET and POST requests are working and returning real data from JSONPlaceholder. Right now, though, you are scanning the response by eye every time to check if it looks correct.

That works for one-off checks, but it falls apart when you have dozens of endpoints to validate. Postman's scripting engine lets you write JavaScript assertions that run automatically after every request and tell you pass or fail instantly.

In this step, get ready to:
  • Add three automated test scripts to your GET request.
  • Add two automated test scripts to your POST request.
  • Verify all five tests pass in the Test Results tab.
Add test scripts to the GET request

Each request in Postman has a Scripts tab where you can write JavaScript that runs after the response comes back. These post-response scripts check things like the status code and the shape of the JSON body for you.

  • In the sidebar, expand the JSONPlaceholder Tests collection.
  • Click the GET request (https://jsonplaceholder.typicode.com/todos/1) to open it.
  • Click the Scripts tab in the request editor.
  • Click Post-response to open the post-response script editor.
  • Paste the following three test scripts into the editor:
// Check that the API returns a 200 OK status
pm.test("Status code is 200", function () {
    pm.expect(pm.response.code).to.eql(200);
});

// Check that the response arrives within 2 seconds
pm.test("Response time is below 2000ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(2000);
});

// Check that the response body has the expected fields
pm.test("Response has expected properties", function () {
    const responseJson = pm.response.json();
    pm.expect(responseJson).to.have.property("userId");
    pm.expect(responseJson).to.have.property("id");
    pm.expect(responseJson).to.have.property("title");
    pm.expect(responseJson).to.have.property("completed");
});

What do these tests check?

Each pm.test block defines one named test. Inside each test, pm.expect makes an assertion using Chai.js syntax.

  • pm.expect(pm.response.code).to.eql(200) confirms the server returned a 200 OK status.
  • pm.expect(pm.response.responseTime).to.be.below(2000) checks the response arrived in under 2 seconds.
  • pm.response.json() parses the response body as JSON, and .to.have.property() confirms each expected field exists.
  • Click Send to run the GET request.
  • Click the Test Results tab in the response pane at the bottom.

You should see 3 passing tests listed: Status code is 200, Response time is below 2000ms, and Response has expected properties. The tab header shows how many tests passed out of the total.

Tests not showing up?

  • Make sure you pasted the scripts into the Post-response section under the Scripts tab, not the Pre-request section.
  • Check for any red error highlights in the script editor. A missing closing bracket or parenthesis will prevent all tests from running.
  • If the Test Results tab shows 0 tests, click Send again. Tests only run when a fresh response comes in.

Why aren't my Postman post-response test scripts running?

Add test scripts to the POST request

The POST request needs its own tests. A successful POST should return a different status code than a GET, and the response body should include the ID of the newly created resource.

  • In the sidebar, click your POST request (https://jsonplaceholder.typicode.com/posts) to open it.
  • Click the Scripts tab, then click Post-response.
  • Paste the following two test scripts into the editor:
// Check that the API returns a 201 Created status
pm.test("Status code is 201", function () {
    pm.expect(pm.response.code).to.eql(201);
});

// Check that the response body includes an id for the new resource
pm.test("Response has id property", function () {
    pm.expect(pm.response.json()).to.have.property("id");
});

What do these tests check?

  • The first test checks for a 201 status code instead of 200. A 201 Created response is the standard for successful resource creation.
  • The second test calls pm.response.json() directly inside pm.expect and checks that the returned object has an id property. This confirms the server assigned an ID to your new resource.

Before you send this request, take a guess. How many total tests do you think should pass across both your GET and POST requests?

  • Click Send to run the POST request.
  • Click the Test Results tab in the response pane.

You should see 2 passing tests: Status code is 201 and Response has id property. Combined with the 3 from your GET request, that gives you 5 automated assertions that will catch any API misbehavior.

Seeing a failing test?

  • If the status code test fails, confirm your request method is set to POST (not GET) in the method dropdown next to the URL.
  • If the id property test fails, make sure the Body tab is set to raw and JSON. A missing body means the server has nothing to create.
  • Double check that you pasted into the correct request. Open the GET request and confirm its Test Results still show 3 passing tests from the previous substep.

My Postman POST request test is failing. Help me debug.

✔️ Awesome, all 5 tests are passing!

Confirm that your GET request shows 3 passing tests and your POST request shows 2 passing tests. You are good to go.

ⓧ I'd like to double check my test scripts

Here is the full post-response script for the GET request (Scripts > Post-response):

// Check that the API returns a 200 OK status
pm.test("Status code is 200", function () {
    pm.expect(pm.response.code).to.eql(200);
});

// Check that the response arrives within 2 seconds
pm.test("Response time is below 2000ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(2000);
});

// Check that the response body has the expected fields
pm.test("Response has expected properties", function () {
    const responseJson = pm.response.json();
    pm.expect(responseJson).to.have.property("userId");
    pm.expect(responseJson).to.have.property("id");
    pm.expect(responseJson).to.have.property("title");
    pm.expect(responseJson).to.have.property("completed");
});

And here is the full post-response script for the POST request (Scripts > Post-response):

// Check that the API returns a 201 Created status
pm.test("Status code is 201", function () {
    pm.expect(pm.response.code).to.eql(201);
});

// Check that the response body includes an id for the new resource
pm.test("Response has id property", function () {
    pm.expect(pm.response.json()).to.have.property("id");
});

You now have 5 automated tests that verify your API behaves correctly without you lifting a finger to read the response. Next up, you will chain your requests together using environment variables and run the entire collection as an automated test suite.

Chain Requests with Variables and Run the Collection

Your automated tests now catch misbehaving responses the moment you click Send. That is a huge step up from manually eyeballing JSON.

There is a gap, though. Your requests are isolated from each other. In a real API workflow, you create a resource and then update or delete it using the ID that came back. If you hardcode that ID, your tests break as soon as the data changes. Environment variables solve this by capturing values from one response and feeding them into the next request automatically. Then the Collection Runner executes everything as a single automated test suite.

In this step, get ready to:
  • Create an environment with reusable variables.
  • Chain requests so the POST response feeds into a PUT request.
  • Run the full collection as an automated test suite with the Collection Runner.
Create an environment with variables

Right now, every request in your collection has the full JSONPlaceholder URL hardcoded. If you ever needed to point at a different server, you would have to update every single request by hand. Postman environments let you store a value once and reference it everywhere with {{variableName}} syntax.

  • Click Environments in the sidebar.
  • Click the + icon to create a new environment.
  • Name it JSONPlaceholder Env.
  • In the variable table, enter baseUrl in the first row under the Variable column.
  • Enter https://jsonplaceholder.typicode.com under the Value column.
  • Press Cmd+S (macOS) or Ctrl+S (Windows) to save.
  • Select JSONPlaceholder Env from the environment dropdown at the top right of the workbench.

You should see JSONPlaceholder Env displayed in the environment dropdown. This means all requests in this workspace can now reference your variables.

What is an environment in Postman?

An environment is a set of key-value pairs that you can swap in and out. Professional teams use them to switch between development, staging, and production servers without editing any request URLs.

Now update your existing requests to use the new variable instead of the hardcoded URL.

  • Open the GET request in your JSONPlaceholder Tests collection.
  • In the URL field, select the full URL and replace it with {{baseUrl}}/todos/1.
  • Click Send.

You should still see a 200 OK response with the same JSON data. The {{baseUrl}} variable resolved to the full URL behind the scenes.

  • Open the POST request.
  • Replace the URL with {{baseUrl}}/posts.
  • Click Send.

You should still see a 201 Created response. All your existing tests still pass, and both requests now use the environment variable.

Seeing an error after changing the URL?

  • Make sure you selected JSONPlaceholder Env from the environment dropdown at the top right. Without an active environment, Postman cannot resolve {{baseUrl}}.
  • Check that the variable name in your URL matches exactly. {{baseUrl}} is case-sensitive and must match what you typed in the environment table.
  • Make sure there are no extra spaces inside the curly braces.

Still stuck? Help me fix my Postman environment variable not resolving in my request URL.

Chain the POST response and add a PUT request

Your POST request creates a new resource and JSONPlaceholder returns the new id in the response. You need to capture that id so a follow-up PUT request can use it to update the same resource.

  • Open the POST request in JSONPlaceholder Tests.
  • Go to the Scripts tab, then click Post-response.
  • After your existing test scripts, add this line to capture the returned id into an environment variable:
pm.environment.set("postId", pm.response.json().id);

What does this script do?

  • pm.response.json().id pulls the id field from the JSON response that JSONPlaceholder returned.
  • pm.environment.set("postId", ...) saves that value into your active environment under the name postId. Any request that references {{postId}} will automatically use this captured value.
  • Click Send.
  • Click the eye icon at the top right of the workbench to open the environment quick look.

You should see postId listed with a numeric value. That value was captured from the POST response and is now available to any subsequent request.

PostId not appearing in the environment?

  • Make sure you added the pm.environment.set line after your existing test scripts, not inside one of the pm.test blocks. It should be a standalone line at the bottom.
  • Confirm your environment is still selected in the dropdown. If no environment is active, pm.environment.set has nowhere to save the value.
  • Check that all your existing tests still pass in the Test Results tab. A syntax error in your script can prevent the capture line from running.

Still stuck? Help me debug why pm.environment.set is not saving my postId variable in Postman.

✔️ Awesome, I've got everything!

Great. Make sure you have saved the POST request before continuing.

ⓧ I'd like to double check the full code

Your POST request's complete Post-response script should look like this:

// Check status code is 201
pm.test("Status code is 201", function () {
    pm.expect(pm.response.code).to.eql(201);
});

// Check response has id property
pm.test("Response has id property", function () {
    pm.expect(pm.response.json()).to.have.property("id");
});

// Capture the returned id for the next request
pm.environment.set("postId", pm.response.json().id);

Now add the PUT request that uses the captured postId to update the resource.

  • Hover over the JSONPlaceholder Tests collection name in the sidebar and click the three-dot menu icon.
  • Select Add request.
  • Name the new request Update Post.
  • Change the method dropdown from GET to PUT.
  • Set the URL to:
{{baseUrl}}/posts/{{postId}}

Why two variables in one URL?

{{baseUrl}} resolves to the server address you stored in the environment. {{postId}} resolves to the id your POST request captured. Together, they build a URL like https://jsonplaceholder.typicode.com/posts/101 without you ever hardcoding a number.

  • Select the Body tab, choose raw, and select JSON from the format dropdown.
  • Enter the following JSON body:
{
  "id": {{postId}},
  "title": "Updated title",
  "body": "Updated body",
  "userId": 1
}

What does this body do?

This sends an updated version of the post back to JSONPlaceholder. The {{postId}} in the body tells the server which resource you are updating. Postman resolves the variable before sending, so the server receives a plain number.

  • Go to the Scripts tab, then click Post-response.
  • Add the following test scripts to verify the update worked:
// Check status code is 200
pm.test("Status code is 200", function () {
    pm.expect(pm.response.code).to.eql(200);
});

// Verify the title was updated
pm.test("Title is updated", function () {
    pm.expect(pm.response.json().title).to.eql("Updated title");
});

What do these tests check?

  • The first test confirms JSONPlaceholder returned 200 OK, meaning the update was accepted.
  • The second test parses the response body and checks that title equals "Updated title". This proves the server echoed back the data you sent.
  • Click Send.

You should see a 200 OK response. Open the Test Results tab at the bottom of the response panel and confirm both tests pass.

PUT request failing or tests not passing?

  • Make sure you sent the POST request first in this session. The postId variable only exists after the POST script runs and captures it.
  • Check that the URL uses double curly braces: {{baseUrl}} and {{postId}}. Single braces will not resolve.
  • If the title test fails, confirm the title value in your JSON body is exactly "Updated title" with a lowercase t in title. It must match the string in your test assertion.

Still stuck? Help me debug why my PUT request or its tests are failing in Postman.

Run the full collection with the Collection Runner

Each request works on its own, but you have not yet proven they work as a connected sequence. The Collection Runner executes every request in your collection in order, running all test scripts automatically.

Before you run it, think about this: you have a GET, a POST that captures postId, and a PUT that depends on postId. What do you expect to happen if the requests run in order?

  • Click Items in the sidebar.
  • Select the JSONPlaceholder Tests collection.
  • Click Run.
  • On the Functional tab, select Run manually.
  • Select JSONPlaceholder Env from the environment dropdown.
  • Click Start run.

All three requests execute in order. Every test passes. The PUT request's URL shows the postId variable was resolved from the value the POST captured. You just ran an automated test suite.

Why does request order matter?

The Collection Runner executes requests from top to bottom. Your POST request must run before the PUT request because the POST script is what sets the postId variable. If the PUT ran first, {{postId}} would be empty and the request would fail.

You can drag requests in the sidebar to reorder them. Make sure your collection stays in the order: GET, POST, PUT.

Some tests failing in the Collection Runner?

  • Check that the requests are in the correct order: GET first, then POST, then PUT. The PUT depends on the postId that POST sets.
  • Confirm you selected JSONPlaceholder Env in the Collection Runner's environment dropdown. Without it, none of your {{baseUrl}} references will resolve.
  • If only the PUT request fails, re-send the POST request manually first to make sure postId is captured, then try the runner again.

Still stuck? Help me figure out why some of my Postman Collection Runner tests are failing.

Secret mission

Complete the API Lifecycle with Spec Generation

You have gone from spec to collection. Now reverse the flow: generate an OpenAPI specification directly from your tested collection and compare it to the one you wrote by hand, completing the full design-to-test-to-spec lifecycle.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely in Postman's free tier, so there are no ongoing costs. Decide whether to keep your workspace and collections, pause them for later, or delete everything.

Resources you used:

  • "API Testing Lab" workspace in Postman.
  • "Task Manager API" and "JSONPlaceholder API (Generated)" specs in Spec Hub.
  • "Task Manager Tests" and "JSONPlaceholder Tests" collections.
  • "JSONPlaceholder Env" environment.
  • Postman desktop app.

Keep everything running

No action needed. Choose this if you want to keep experimenting with your specs, collections, and test scripts.

  • Your "API Testing Lab" workspace, all collections, specs, and the environment stay saved in your Postman account at no cost.
  • The Postman desktop app remains installed on your machine.
  • Your free Postman account stays active. You can use it for future API projects.

Pause - I'll come back to this later

Your workspace and all its contents are saved in Postman's cloud automatically. Quit the app to free up system resources on your machine.

  • Quit the Postman desktop app.
  • When you are ready to continue, reopen Postman and sign in. Your "API Testing Lab" workspace and all its collections, specs, and environment will be exactly as you left them.

Delete - I don't want to use this again

Remove all project resources from your Postman account and optionally uninstall the app.

  • Open Postman and switch to the "API Testing Lab" workspace using the Workspaces dropdown at the top.
  • Click the three-dot menu next to the workspace name at the top of Postman.
  • Select Delete workspace.
  • Confirm the deletion when prompted. This removes the workspace and everything inside it, including all specs, collections, and environments.
  • To uninstall Postman on macOS, drag it from your Applications folder to the Trash.
  • To uninstall Postman on Windows, open Settings, select Apps, find Postman in the list, and click Uninstall.

Nice Work!

Nice Work!

Nice work! You just designed, tested, and debugged a complete API workflow inside Postman.

You've learned how to:

  • Written an OpenAPI 3.0 specification from scratch in Spec Hub, defining paths, schemas, and previewing live documentation to design your API contract before writing a single test.
  • Built a hand-crafted Postman Collection with GET, POST, and PUT requests against JSONPlaceholder, each with automated test scripts using pm.test and pm.expect to validate status codes, response times, and JSON structure.
  • Chained requests together using environment variables to capture data from one response and feed it into the next, then ran your entire collection as an automated test suite with the Collection Runner.
  • Secret Mission: Generated an OpenAPI specification back from your tested collection, completing the full design-to-test-to-spec API lifecycle.

Ready to quiz yourself?