API Testing with Postman
Test a real REST API and build a QA portfolio on GitHub.
Introduction
30 Second Summary
When you order food through an app, dozens of API calls happen behind the scenes. If any of those calls return the wrong data or fail silently, your order breaks.
In this project, you will test a real REST API using Postman, write automated test assertions that catch exactly those kinds of failures, and publish your work as a professional portfolio repository on GitHub.
What You'll Build
A complete API testing portfolio targeting the Restful Booker API, with an organized Postman collection containing automated test assertions, environment configuration, and professional documentation hosted on GitHub.
By the end of this project, you'll have:
- A GitHub profile README introducing you as a QA tester and linking to your portfolio projects.
- A Postman collection covering authentication, CRUD operations, and negative test cases, each with automated test assertions.
- A professional GitHub repository containing exported test files, environment configuration, and an API test documentation file.
- Secret Mission: chain requests together with dynamic variables and add response time performance tests.
Are there any prerequisites?
You need a GitHub account and Git installed on your machine. No prior experience with Postman or API testing is required.
Install Postman and Set Up Your GitHub Profile
Every QA testing portfolio needs two foundations: a tool for running your tests and a place to showcase your work. In this project, your testing tool is Postman, and your showcase is GitHub.
In this step, you'll install Postman and set up a GitHub profile README. This README is the first thing hiring managers see when they visit your GitHub profile.
In this step, get ready to:
- Install the Postman desktop app and create a free account.
- Create a GitHub profile README with a professional introduction.
Install and verify Postman
Postman is a desktop application for testing APIs. You send HTTP requests to an API endpoint, and Postman displays the response so you can verify the data is correct.
- Install Postman by running this command in your terminal:
snap install postman
What does this command do?
The snap install command downloads and installs Postman from the Snap store. Postman recommends Snap for Linux because it bundles all the libraries the app needs.
You should see a confirmation message in your terminal once the installation completes.
Seeing a permission error?
Some systems require elevated privileges to install Snap packages. Try running the install with sudo:
sudo snap install postman
If Postman crashes immediately after installing, you may have a library compatibility issue. Download the tarball from postman.com/downloads instead, then extract it with tar zxf and run the Postman binary directly.
Help me troubleshoot my Postman installation on Linux.
- Open your application launcher by pressing the Super key.
- Type Postman and press Enter to open it.
Don't use sudo to launch Postman
Always launch Postman without sudo. Starting it with sudo causes file permission issues in your ~/.config folder where Postman stores its data.
When Postman opens for the first time, it prompts you to sign in or create an account.
- Follow the prompts to create a free Postman account using your email.
Why do I need a Postman account?
Postman requires a free account to save your test collections and sync your work. Without one, you cannot persist the tests you build throughout this project.
You should see the Postman workspace ready for creating new requests and collections.
Create or update your GitHub profile README
GitHub has a special feature for profile pages. If you create a public repository with a name that exactly matches your GitHub username, the README.md in that repository appears at the top of your profile page.
Already have a profile README repository?
If you already have a repository named after your GitHub username, skip the creation steps below and go straight to editing your README.md.
- Go to github.com and click the + icon in the upper-right corner.
- Click New repository.
- In the Repository name field, enter your exact GitHub username. For example, if your username is janedoe, the repository name must be janedoe.
- Select Public for the repository visibility.
- Toggle Add a README file to on.
- Click Create repository.
Why must the name match exactly?
GitHub only recognizes a repository as your profile README when the repository name is a case-sensitive, exact match of your username. A single character difference and it becomes a regular repository.
Now you'll replace the default template with a professional introduction.
- In your new repository, click on README.md to open the file.
- Click the pencil icon on the right side of the file header to edit it.
- Select all existing content and replace it with the following:
# Hi, I'm [[YOURNAME="your name"]]
I'm building my skills in QA and software testing. I enjoy finding bugs and making software more reliable.
## Tools I'm Learning
- Postman
- Git
- API Testing
## Portfolio Projects
*Projects coming soon - check back for updates!*
What do these sections do?
The heading introduces you by name. The opening paragraph tells visitors what you're focused on learning.
The Tools I'm Learning section lists the technologies you're gaining experience with. The Portfolio Projects section is a placeholder where you'll add links to repositories like the one you're building in this project.
- Replace the name placeholder with your actual name.
- Click Commit changes in the top right of the editor.
- GitHub asks you to confirm the commit message. Accept the default and click Commit changes again.
- Visit your GitHub profile page by navigating to github.com/your-username in your browser.
- Your profile README should appear at the top of the page, showing your name, your QA statement, and your tools list.
Don't see the README on your profile?
Make sure the repository name matches your GitHub username exactly, including capitalization. Even a single mismatched character prevents GitHub from recognizing it as a profile README.
Confirm the repository visibility is set to Public. Private repositories do not display on your profile page.
Help me figure out why my GitHub profile README is not showing up.
Your tools are installed and your GitHub profile is ready to impress. Next up, you'll create your API testing repository and set up a Postman environment to start testing.
Create Your Repository and Postman Environment
Your GitHub profile is looking professional and Postman is ready to go. Now you need a place to store all of your testing work where hiring managers can find it.
In this step, you'll create a dedicated GitHub repository for your API testing project. You'll also configure Postman with environment variables so your API requests stay flexible and reusable across every test.
In this step, get ready to:
- Create a public GitHub repository for your API testing project.
- Set up a Postman environment with variables for the Restful Booker API.
Create the GitHub repository
- On GitHub, click the + icon in the top right corner of the page.
- Select New repository.
- Enter api-testing-restful-booker in the Repository name field.
- In the Description field, enter API testing portfolio - Restful Booker API tested with Postman.
- Select Public for the repository visibility.
- Check the Add a README file checkbox.
- Click Create repository.
Your new repository page loads with a README.md file displayed.
- On your new repository page, click the green Code button and copy the HTTPS URL.
- Move to your Desktop by running this command:
cd ~/Desktop
- Clone your repository by running this command, replacing the URL with the one you copied:
git clone [[REPO_URL="https://github.com/your-username/api-testing-restful-booker.git"]]
- Confirm the repository was cloned by running:
ls
You should see api-testing-restful-booker in the output.
Seeing 'repository not found'?
Double-check that the URL you copied matches the repository you just created. The username in the URL must match your GitHub username exactly.
If git prompts you for credentials, make sure you are signed in to GitHub and that your Git credentials are configured on your machine.
Help me troubleshoot my git clone error.
Set up the Postman environment
Before you start sending requests, you need a way to store values that every request will share. Postman environments let you define variables once and reference them across all of your requests with double curly brace syntax like {{base_url}}.
- Switch back to Postman.
- Click Environments in the left sidebar.
- Click the + icon to create a new environment.
- Enter Restful Booker as the environment name.
- Click the Add variable text box and type base_url as the variable name.
- Enter https://restful-booker.herokuapp.com as the value for base_url.
- Click Add variable again in the next row and type token as the variable name. Leave its value empty.
- Click the environment selector dropdown at the top right of the workbench.
- Select Restful Booker from the list to make it the active environment.
What is a Postman environment?
A Postman environment is a reusable set of variables you can swap into your requests. Instead of hardcoding the API URL into every request, you store it once as base_url and reference it with {{base_url}}.
The token variable is empty for now. In the next step, you'll fill it with a real authentication token from the Restful Booker API.
- Verify the environment selector at the top right now shows Restful Booker as the active environment.
- Click Environments in the sidebar, then select Restful Booker. Confirm that base_url shows https://restful-booker.herokuapp.com and token is listed with an empty value.
Don't see your variables?
Make sure you selected the Restful Booker environment from the environment selector at the top right. If the selector still shows No environment, click the dropdown and choose Restful Booker.
If the variables are missing entirely, click Environments in the sidebar, select your environment, and re-add the variables using the Add variable row at the bottom of the table. Changes save automatically.
Help me set up my Postman environment variables.
Your repository is live on GitHub and Postman is configured with the Restful Booker API's base URL. Next up, you'll send your first requests to authenticate and read real booking data.
Authenticate and Read Bookings
Your Postman environment is set up with the Restful Booker base URL ready to go. Now it's time to send your first API requests.
Before you can test most endpoints, you need to authenticate. You'll grab a token from the API first, then start reading booking data and writing automated test assertions.
In this step, get ready to:
- Authenticate against the Restful Booker API and verify you receive a valid token.
- Test reading booking data with GET requests and automated assertions.
Create a Postman collection and authenticate
A Postman collection groups related API requests together. You'll create one collection for the entire Restful Booker project, then organize requests into folders by category.
- In Postman, click Collections in the left sidebar.
- Click the + icon to create a new collection.
- Name the collection Restful Booker API Tests.
What is a Postman collection?
A collection is like a project folder for all the requests you want to test against a single API. You can organize requests into subfolders, add test scripts, and even run the entire collection in sequence.
- Click View more actions (the three-dot menu) next to the Restful Booker API Tests collection name.
- Select Add folder.
- Name the folder Auth.
- Click View more actions next to the Auth folder.
- Select Add request.
- Name the request CreateToken.
- Change the HTTP method dropdown from GET to POST.
- Enter {{base_url}}/auth in the URL field.
What does {{base_url}} mean?
The double curly braces tell Postman to substitute the value from your active environment. Since you set base_url to https://restful-booker.herokuapp.com in the previous step, Postman replaces {{base_url}} with that URL automatically.
- Click the Body tab below the URL field.
- Select raw from the format options.
- Change the dropdown on the right from Text to JSON.
- Paste the following credentials into the body editor:
{
"username": "admin",
"password": "password123"
}
- Click the Headers tab.
- In the first empty row, type Content-Type in the Key column.
- Type application/json in the Value column.
Header may already exist
Postman often auto-adds a Content-Type header when you select JSON as the body format. If you see it already listed in the Headers tab, you can skip this step.
- Click the blue Send button.
You should see a 200 OK status in the response panel. The response body contains a token field with a string value.
The API responded successfully. Now you'll add automated test assertions so Postman can verify this response for you every time you send the request.
- Click the Scripts tab (next to Body and Headers).
- Click Post-response.
- Paste the following test assertions into the script editor:
// Verify the auth endpoint returned a success status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Confirm the response body includes a token string
pm.test("Response has token", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.token).to.be.a("string");
});
What do these tests do?
Each pm.test() call creates a named test case. If the assertion inside the function fails, that test is marked as failed.
- pm.response.to.have.status(200) checks the HTTP status code of the response.
- pm.response.json() parses the response body as JSON so you can inspect individual fields.
- pm.expect(jsonData.token).to.be.a("string") asserts the token field exists and is a string.
- Click Send again.
- Click the Test Results tab in the response panel.
You should see 2 passing tests with green checkmarks.
Tests not passing?
- Make sure you clicked Post-response (not Pre-request) in the Scripts tab.
- Check that your JSON body has the exact username admin and password password123. Typos in credentials cause the API to return a different response.
- Confirm your Restful Booker environment is still selected in the top-right environment dropdown.
Why are my Postman test assertions failing for the CreateToken request?
✔️ Awesome, I've got everything!
Great. Make sure both tests show green checkmarks before moving on.
ⓧ I'd like to double check the full code
Here is the complete post-response script for your CreateToken request:
// Verify the auth endpoint returned a success status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Confirm the response body includes a token string
pm.test("Response has token", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.token).to.be.a("string");
});
Test reading bookings
With authentication confirmed, you can start testing the API's booking endpoints. The Restful Booker API comes pre-loaded with 10 booking records that reset every 10 minutes.
- Click View more actions next to the Restful Booker API Tests collection.
- Select Add folder.
- Name the folder Booking.
- Click View more actions next to the Booking folder.
- Select Add request.
- Name the request GetBookingIds.
- Confirm the method is set to GET.
- Enter {{base_url}}/booking in the URL field.
- Click the Scripts tab, then click Post-response.
- Paste the following test assertions into the script editor:
// Verify the endpoint returned a success status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Confirm the response is a non-empty list of booking IDs
pm.test("Response is an array", function () {
const jsonData = pm.response.json();
pm.expect(jsonData).to.be.an("array");
pm.expect(jsonData.length).to.be.above(0);
});
What do these tests do?
- pm.expect(jsonData).to.be.an("array") confirms the response is a list of items, not a single object.
- pm.expect(jsonData.length).to.be.above(0) confirms the list contains at least one booking. The Restful Booker API always has at least 10 pre-loaded records.
- Click Send.
- Click the Test Results tab in the response panel.
You should see 2 passing tests. The response body shows an array of booking ID objects.
Now you'll add a second GET request that retrieves a single booking's full details.
- Click View more actions next to the Booking folder.
- Select Add request.
- Name the request GetBooking.
- Confirm the method is set to GET.
- Enter {{base_url}}/booking/1 in the URL field.
- Click the Headers tab.
- Add a header with Key set to Accept and Value set to application/json.
Why set the Accept header?
The Accept header tells the API what format you want the response in. Without it, the Restful Booker API may return XML instead of JSON. Setting it to application/json ensures you get a JSON response that your test scripts can parse.
- Click the Scripts tab, then click Post-response.
- Paste the following test assertions into the script editor:
// Verify the endpoint returned a success status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Confirm the response contains all required booking fields
pm.test("Response has required booking fields", function () {
const jsonData = pm.response.json();
pm.expect(jsonData).to.have.property("firstname");
pm.expect(jsonData).to.have.property("lastname");
pm.expect(jsonData).to.have.property("totalprice");
pm.expect(jsonData).to.have.property("depositpaid");
pm.expect(jsonData).to.have.property("bookingdates");
});
What do these tests do?
- Each .to.have.property() call checks that the booking object contains a specific field. If any field is missing, the test fails.
- These five fields (firstname, lastname, totalprice, depositpaid, bookingdates) make up the core booking data structure in the Restful Booker API.
- Click Send.
- Click the Test Results tab in the response panel.
You should see 2 passing tests. The response body shows a full booking object with guest details, pricing, and dates.
Tests not passing for your GET requests?
- If GetBooking returns a 404, the booking with ID 1 may have been deleted by another tester. The API resets every 10 minutes, so wait a moment and try again.
- Make sure you added the Accept header with value application/json to the GetBooking request. Without it, the API may return XML, which causes pm.response.json() to fail.
- Confirm your Restful Booker environment is still selected in the top-right environment dropdown.
Why are my GET booking requests failing in Postman?
✔️ Awesome, I've got everything!
Great. Make sure all tests show green checkmarks for both GetBookingIds and GetBooking before moving on.
ⓧ I'd like to double check the full code
Here are the complete post-response scripts for your Booking folder requests.
GetBookingIds post-response script:
// Verify the endpoint returned a success status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Confirm the response is a non-empty list of booking IDs
pm.test("Response is an array", function () {
const jsonData = pm.response.json();
pm.expect(jsonData).to.be.an("array");
pm.expect(jsonData.length).to.be.above(0);
});
GetBooking post-response script:
// Verify the endpoint returned a success status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Confirm the response contains all required booking fields
pm.test("Response has required booking fields", function () {
const jsonData = pm.response.json();
pm.expect(jsonData).to.have.property("firstname");
pm.expect(jsonData).to.have.property("lastname");
pm.expect(jsonData).to.have.property("totalprice");
pm.expect(jsonData).to.have.property("depositpaid");
pm.expect(jsonData).to.have.property("bookingdates");
});
You've got authentication working and two read endpoints verified with automated assertions. Next up, you'll test creating, updating, and deleting bookings to cover the full range of CRUD operations.
Create, Update, and Delete Bookings
In the previous step, you proved you can read data from the Restful Booker API. Reading is only half the story. Real QA testers also need to verify that an API can create, modify, and remove data correctly.
In this step, you will test the full CRUD lifecycle by sending POST, PUT, and DELETE requests. You will also write test assertions for each one to make sure the API behaves as expected.
In this step, get ready to:
- Create a new booking with a POST request and validate the response data matches what you sent.
- Update an existing booking with a PUT request using token-based authentication.
- Delete a booking with a DELETE request and verify the API confirms removal.
Test creating a booking
A POST request tells the API to create a new resource. For the Restful Booker API, that means creating a new hotel booking with guest details, dates, and pricing.
- In your Restful Booker API Tests collection, expand the Booking folder.
- Click the three dots next to the Booking folder and select Add request.
- Name the request CreateBooking.
- Change the method dropdown from GET to POST.
- Enter {{base_url}}/booking as the URL.
- Click the Headers tab.
- Add a header with key Content-Type and value application/json.
- Add a second header with key Accept and value application/json.
- Click the Body tab, select raw, and choose JSON from the format dropdown.
- Paste the following booking data into the body:
{
"firstname": "Jane",
"lastname": "Tester",
"totalprice": 150,
"depositpaid": true,
"bookingdates": {
"checkin": "2026-07-01",
"checkout": "2026-07-10"
},
"additionalneeds": "Breakfast"
}
What is this JSON body?
This is the booking data you are asking the API to create. It includes a guest name, the total price, whether a deposit was paid, the check-in and check-out dates, and any additional needs like breakfast.
The API will use this data to create a new booking record and send the details back in its response.
Now add test assertions so Postman automatically checks the response every time you send this request.
- Click the Scripts tab, then click Post-response.
- Add the following test script:
// Check the API returned a 200 OK status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Check the response includes a booking ID
pm.test("Response has bookingid", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.bookingid).to.be.a("number");
});
// Verify the returned booking data matches what we sent
pm.test("Booking data matches request", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.booking.firstname).to.eql("Jane");
pm.expect(jsonData.booking.lastname).to.eql("Tester");
pm.expect(jsonData.booking.totalprice).to.eql(150);
});
What do these tests check?
The first test confirms the API returned a 200 status code, meaning the booking was created successfully.
The second test checks that the response contains a bookingid field. The API wraps the booking data inside a booking object and adds a unique bookingid at the top level.
The third test verifies the returned data matches what you sent. This catches bugs where the API saves incorrect values.
- Click Save to save the request.
- Click Send.
- Click the Test Results tab at the bottom of the response panel. You should see 3 passing tests.
Tests not passing?
Make sure the Restful Booker environment is selected in the environment dropdown at the top right of the workbench. Without it, {{base_url}} will not resolve.
Check that you selected raw and JSON in the Body tab. If the format is set to Text, the API may not accept the request body.
If the "Booking data matches request" test fails, double-check you pasted the JSON body exactly as shown, including the correct field names and values.
Help me debug my CreateBooking test failures.
Test updating and deleting bookings
Updating and deleting bookings are write operations that require authentication. The Restful Booker API uses a Cookie header to pass your auth token, which is different from the more common Bearer token pattern.
Before you can send authenticated requests, you need to grab the token from your CreateToken response and store it in your environment.
- In the Auth folder, click on your CreateToken request.
- Click Send to get a fresh token.
- In the response body, select and copy the token value (the string inside the quotes after "token":).
- Click Environments in the left sidebar.
- Click on your Restful Booker environment.
- Paste the token value into the Current value column for the token variable.
- Click Save to save the environment.
Why copy the token manually?
Right now, you are copying the token by hand so you can focus on learning how PUT and DELETE requests work. In the Secret Mission later, you will automate this step so the token is captured and reused automatically.
Now create the UpdateBooking request. A PUT request replaces the entire booking resource with new data.
- Switch back to Collections in the left sidebar.
- Click the three dots next to the Booking folder and select Add request.
- Name the request UpdateBooking.
- Change the method to PUT.
- Enter {{base_url}}/booking/1 as the URL.
- Click the Headers tab.
- Add a header with key Content-Type and value application/json.
- Add a header with key Accept and value application/json.
- Add a header with key Cookie and value token={{token}}.
Why a Cookie header instead of Authorization?
Most APIs use an Authorization: Bearer <token> header for authentication. The Restful Booker API uses a Cookie header instead. This is one of the quirks of the practice API that teaches you to read documentation carefully rather than assuming every API works the same way.
- Click the Body tab, select raw, and choose JSON from the format dropdown.
- Paste the following updated booking data into the body:
{
"firstname": "Jane",
"lastname": "Tester",
"totalprice": 200,
"depositpaid": true,
"bookingdates": {
"checkin": "2026-08-01",
"checkout": "2026-08-15"
},
"additionalneeds": "Lunch"
}
What changed in this body?
Compared to the CreateBooking body, the totalprice changed from 150 to 200, the dates moved to August, and additionalneeds changed from Breakfast to Lunch. A PUT request replaces the entire booking, so you must include all fields even if only some changed.
- Click the Scripts tab, then click Post-response.
- Add the following test script:
// Check the API returned a 200 OK status
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
// Verify the response reflects the updated values
pm.test("Updated values reflected", function () {
const jsonData = pm.response.json();
pm.expect(jsonData.totalprice).to.eql(200);
pm.expect(jsonData.additionalneeds).to.eql("Lunch");
});
Why check the updated values specifically?
The PUT response from the Restful Booker API returns the updated booking data directly. By checking totalprice and additionalneeds, you confirm the API actually saved your changes instead of silently ignoring them.
- Click Save to save the request.
- Click Send.
- Click the Test Results tab. You should see 2 passing tests.
Getting a 403 Forbidden?
A 403 means your token is missing or invalid. Go back to the CreateToken request, click Send to get a fresh token, and paste the new token value into your token environment variable. The API resets every 10 minutes, so tokens can expire.
Also double-check your Cookie header is exactly token={{token}} with no extra spaces.
Help me fix my 403 Forbidden error on UpdateBooking.
Now create the DeleteBooking request to test removing a booking from the system.
- Click the three dots next to the Booking folder and select Add request.
- Name the request DeleteBooking.
- Change the method to DELETE.
- Enter {{base_url}}/booking/1 as the URL.
- Click the Headers tab.
- Add a header with key Cookie and value token={{token}}.
- Click the Scripts tab, then click Post-response.
- Add the following test script:
// Check the API returned a 201 status (Restful Booker's delete confirmation)
pm.test("Status code is 201", function () {
pm.response.to.have.status(201);
});
Why does DELETE return 201 instead of 204?
Most APIs return 204 No Content for a successful delete. The Restful Booker API intentionally returns 201 Created instead. This is one of the practice API's built-in quirks designed for testers to discover and document.
- Click Save to save the request.
- Click Send.
- Click the Test Results tab. You should see 1 passing test.
Getting a 405 Method Not Allowed?
A 405 can appear if you try to delete a booking that does not exist. The API resets its data every 10 minutes, so booking ID 1 may have already been deleted by another user. Try sending the request again. If the API has reset, the booking will be back.
If you still see a 403 Forbidden, refresh your token by re-sending the CreateToken request and pasting the new token into your environment variable.
Help me debug my DeleteBooking request.
Your collection now covers the full CRUD lifecycle. Next up, you will add negative test cases to check how the API handles invalid inputs, then export everything and publish it to your GitHub portfolio.
Add Negative Tests, Document, and Update Your Profile
You've tested the full lifecycle of a booking. Your Postman collection can authenticate, create, read, update, and delete bookings on the Restful Booker API.
Testing what works is only half the job. Hiring managers want to see that you also test what should fail. In this step, you'll add negative test cases, write professional documentation, and push everything to your GitHub portfolio.
In this step, get ready to:
- Add negative test cases for invalid IDs, missing fields, and bad credentials.
- Export your Postman collection and environment to JSON files.
- Create professional API test documentation and push everything to GitHub.
Add negative test cases
Your existing tests verify that the API behaves correctly when given valid inputs. Negative tests flip this around and confirm the API handles bad inputs gracefully.
What is negative testing?
Negative testing sends intentionally invalid data to an API and checks that it responds with the correct error. For example, requesting a booking that does not exist should return a 404 status, not a 200.
This is one of the first things hiring managers look for in a QA portfolio because it shows you think beyond the happy path.
- In your Restful Booker API Tests collection, right-click the collection name and select Add folder.
- Name the folder Negative Tests.
Now you'll add three requests inside this folder, each targeting a different failure scenario.
- Right-click the Negative Tests folder and select Add request.
- Name the request GetBooking - Invalid ID.
- Set the method to GET.
- Set the URL to {{base_url}}/booking/99999.
- Go to the Scripts tab and click Post-response.
- Paste the following test script:
// Verify the API returns 404 for a non-existent booking
pm.test("Status code is 404", function () {
pm.response.to.have.status(404);
});
What does this test do?
Booking ID 99999 does not exist on the server. The test asserts that the API correctly returns a 404 Not Found status instead of silently succeeding.
- Click Send.
- Click the Test Results tab in the response panel. You should see 1 passing test.
- Add another request in the Negative Tests folder.
- Name it CreateBooking - Missing Fields.
- Set the method to POST.
- Set the URL to {{base_url}}/booking.
- In the Headers tab, set Content-Type to application/json.
- In the Body tab, select raw and choose JSON from the dropdown.
- Enter a body with only one field, deliberately missing the required fields:
{"firstname": "Test"}
- Go to the Scripts tab, click Post-response, and paste the following test script:
// Verify the API rejects a booking with incomplete data
pm.test("Status code is not 200", function () {
pm.expect(pm.response.code).to.not.equal(200);
});
What does this test do?
A real booking requires fields like lastname, totalprice, and bookingdates. By sending only firstname, you are testing that the API does not accept incomplete data with a 200 success status.
- Click Send.
- Click the Test Results tab. You should see 1 passing test.
- Add one more request in the Negative Tests folder.
- Name it CreateToken - Bad Credentials.
- Set the method to POST.
- Set the URL to {{base_url}}/auth.
- In the Headers tab, set Content-Type to application/json.
- In the Body tab, select raw and choose JSON.
- Enter the following body with intentionally wrong credentials:
{"username": "wrong", "password": "wrong"}
- Go to the Scripts tab, click Post-response, and paste the following test script:
// Verify invalid credentials do not produce a token
pm.test("Response does not contain a valid token", function () {
const jsonData = pm.response.json();
pm.expect(jsonData).to.not.have.property("token");
});
What does this test do?
When someone sends wrong credentials, the API should refuse to issue an authentication token. This test checks that the response body does not contain a token property, confirming the API properly rejects the login attempt.
- Click Send.
- Click the Test Results tab. You should see 1 passing test.
Your Negative Tests folder now has three requests, each confirming the API handles a different type of bad input correctly.
Test showing as failing?
The Restful Booker API is a practice API with intentional quirks. If a negative test fails, that is actually a valid finding you can document in your test report.
If no tests appear at all, make sure you pasted the script in the Post-response section of the Scripts tab, not in the Pre-request section.
Help me debug why my Postman negative test is failing against the Restful Booker API.
Export, commit, and update your GitHub profile
Your collection and environment live inside Postman right now. To share them as part of a portfolio, you need to export them as JSON files, add documentation, and push everything to your GitHub repository.
- In Postman, click Collections in the left sidebar.
- Click View more actions (the three-dot icon) next to your Restful Booker API Tests collection.
- Select More then Export.
- If prompted to choose a format, select Collection v2.1.
- Click Export JSON and save the file as Restful-Booker.postman_collection.json inside your local api-testing-restful-booker folder.
- Click Environments in the left sidebar.
- Click View more actions (the three-dot icon) next to your Restful Booker environment.
- Select Export. The file downloads automatically.
- Save or move it as Restful-Booker.postman_environment.json inside your local api-testing-restful-booker folder.
Why export as Collection v2.1?
Collection v2.1 is the most widely compatible format. Other tools and team members can import and run your collection without any conversion steps.
- Create a new file called API-Test-Documentation.md in your api-testing-restful-booker folder and paste the following content:
# API Test Documentation - Restful Booker
## Project Overview
This project demonstrates API testing of the Restful Booker REST API using Postman. It covers authentication, CRUD operations on bookings, and negative test scenarios to validate error handling.
## API Under Test
- **Name**: Restful Booker
- **Base URL**: https://restful-booker.herokuapp.com
- **Description**: A practice REST API with authentication features and intentional bugs for testers to explore.
- **Data Reset**: The API resets to its default state every 10 minutes.
## Test Coverage Summary
| Request Name | Method | Endpoint | What Is Tested |
|---|---|---|---|
| CreateToken | POST | /auth | Valid credentials return a token |
| GetBookingIds | GET | /booking | Returns an array of booking IDs |
| GetBooking | GET | /booking/1 | Returns booking details with all expected fields |
| CreateBooking | POST | /booking | Creates a booking and returns a bookingid |
| UpdateBooking | PUT | /booking/1 | Updates a booking with authentication |
| DeleteBooking | DELETE | /booking/1 | Deletes a booking with authentication |
| GetBooking - Invalid ID | GET | /booking/99999 | Returns 404 for a non-existent booking |
| CreateBooking - Missing Fields | POST | /booking | Returns an error for incomplete data |
| CreateToken - Bad Credentials | POST | /auth | Does not return a token for invalid credentials |
## Findings and Bugs Discovered
- The DELETE endpoint returns a 201 status code instead of the more common 204 No Content.
- The API resets its data every 10 minutes, so bookings created during testing are not permanent.
## Tools Used
- **Postman** - API testing and collection management
- **Git and GitHub** - Version control and repository hosting
What is in this documentation file?
This file gives anyone reviewing your repository a clear picture of what you tested, how you tested it, and what you found. The test coverage table maps every request to its method, endpoint, and assertion focus.
The findings section is especially important. It shows you actively analyzed the API's behavior rather than just running scripts.
- Save API-Test-Documentation.md.
- Open README.md in your api-testing-restful-booker folder.
- Replace the existing content with the following:
# API Testing - Restful Booker
API testing portfolio project demonstrating systematic testing of the [Restful Booker](https://restful-booker.herokuapp.com) REST API using Postman.
## Tools Used
- [Postman](https://www.postman.com/) (desktop app)
- Git and GitHub
## How to Import and Run
1. Clone this repository.
2. Open Postman and click **Import**.
3. Select `Restful-Booker.postman_collection.json` to import the collection.
4. Select `Restful-Booker.postman_environment.json` to import the environment.
5. In the top-right corner of Postman, select the **Restful Booker** environment.
6. Open the collection and send requests individually, or use the **Collection Runner** to run all tests.
## Test Coverage
| Request | Method | Endpoint | Tests |
|---|---|---|---|
| CreateToken | POST | /auth | Status 200, token returned |
| GetBookingIds | GET | /booking | Status 200, response is an array |
| GetBooking | GET | /booking/1 | Status 200, body contains required fields |
| CreateBooking | POST | /booking | Status 200, bookingid returned, data matches |
| UpdateBooking | PUT | /booking/1 | Status 200, updated values returned |
| DeleteBooking | DELETE | /booking/1 | Status 201 |
| GetBooking - Invalid ID | GET | /booking/99999 | Status 404 |
| CreateBooking - Missing Fields | POST | /booking | Non-200 status |
| CreateToken - Bad Credentials | POST | /auth | No valid token returned |
What does this README do for your portfolio?
This is the first thing a hiring manager sees when they open your repository. The "How to Import and Run" section proves your work is reproducible. The test coverage table gives them a quick overview without needing to open Postman.
- Save README.md.
- Switch back to your terminal and commit all your files to GitHub by running these commands:
cd api-testing-restful-booker
git add .
git commit -m "Add Restful Booker API test collection with documentation"
git push origin main
What do these commands do?
- cd api-testing-restful-booker navigates into your cloned repository folder.
- git add . stages all four new files for commit.
- git commit saves a snapshot of your changes with a descriptive message.
- git push origin main uploads everything to your GitHub repository.
- Open your api-testing-restful-booker repository on GitHub in your browser.
- You should see all four files listed: Restful-Booker.postman_collection.json, Restful-Booker.postman_environment.json, API-Test-Documentation.md, and your updated README.md.
Files not showing on GitHub?
If git push failed, make sure you are inside the api-testing-restful-booker folder (not its parent). Run pwd to check your current directory.
If you see an authentication error, GitHub now requires a personal access token instead of a password. Follow the prompts to authenticate.
Help me push my API testing files to GitHub.
The last step is to link this new repository from your GitHub profile so visitors can find it.
- Open your GitHub profile README repository (the one named after your username) on GitHub.
- Click Edit README (the pencil icon).
- Find the Portfolio Projects section you created earlier.
- Add a line linking to your new repository. Here is an example you can use:
- [API Testing - Restful Booker](https://github.com/[[GITHUB_USERNAME="your GitHub username"]]/api-testing-restful-booker) - API testing with Postman covering authentication, CRUD operations, and negative tests.
- Click Commit changes to save your profile README.
- Visit your GitHub profile page. You should see your updated profile README with a clickable link to your api-testing-restful-booker repository.
Profile README not showing on your profile?
The repository name must match your GitHub username exactly, including capitalization. Make sure the repository is set to Public.
Help me troubleshoot my GitHub profile README.
Secret mission
Chain Requests and Add Performance Tests
Right now, you copy the auth token by hand and hardcode booking IDs in your request URLs. In this extension, you'll make your requests pass data to each other automatically and add performance checks to every test.
Clean Up Your Resources
Clean Up Your Resources
This project uses only free services and local tools, so there are no ongoing costs to worry about. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- Local clone of the api-testing-restful-booker repository.
- api-testing-restful-booker GitHub repository.
- GitHub profile README repository.
- Restful Booker API Tests Postman collection.
- Restful Booker Postman environment.
- Postman desktop app (installed via Snap).
Keep everything running
No action needed. Choose this if you plan to continue building on your API testing portfolio or want to revisit this project later.
- Your Postman collection and environment stay saved in your Postman workspace.
- Your GitHub repositories remain public and accessible to hiring managers.
- The Postman desktop app stays installed on your machine.
- Your free Postman account remains active at no cost.
Pause - I'll come back to this later
Close Postman to free up system memory. All your data is saved in your Postman workspace and will be there when you reopen the app.
- Close the Postman desktop app.
- Your collection, environment, GitHub repositories, and local files are all preserved automatically.
Delete - I don't want to use this again
Remove all project resources and start fresh. This cannot be undone for your GitHub repositories.
Delete the Postman collection and environment:
- In Postman, click the three dots icon next to the Restful Booker API Tests collection in the left sidebar.
- Select Delete and confirm the deletion.
- Click Environments in the left sidebar, then click the three dots icon next to the Restful Booker environment.
- Select Delete and confirm.
Delete the api-testing-restful-booker GitHub repository:
- Go to your api-testing-restful-booker repository page on GitHub.
- Click the Settings tab.
- Scroll down to the Danger Zone section.
- Click Delete this repository and follow the confirmation prompts.
Delete the GitHub profile README repository (optional):
- Only do this if you do not plan to use your profile README for future portfolio projects.
- Follow the same steps as above for your profile README repository (the one named after your GitHub username).
Delete the local repository clone:
- Navigate to the folder where you cloned api-testing-restful-booker and delete it by running:
rm -rf api-testing-restful-booker
Remove the Postman desktop app:
- Remove Postman from your system by running:
snap remove postman
Nice Work!
Nice Work!
You just built a complete API testing portfolio from scratch. Your GitHub profile now showcases a professional QA repository that proves you can systematically test a real REST API, write meaningful assertions, and document your findings.
You've learned how to:
- Test full CRUD operations on a live REST API using Postman, including token-based authentication, request building, and automated test assertions with pm.test and pm.expect.
- Create negative test cases that validate how an API handles invalid IDs, missing fields, and bad credentials.
- Build a professional QA portfolio repository on GitHub with exported collections, environment configuration, API test documentation, and a polished profile README.
- Secret Mission: chained requests together with dynamic variables and added response time performance tests across your entire collection.
Ready to quiz yourself?