Postman is still the most convenient way to exercise a Web API by hand — every HTTP method, headers, bodies, and saved collections you can rerun after each change. This walkthrough tests GET, POST, PUT, and DELETE against an ASP.NET Core Web API and reads the status codes you should expect from each.
Install Postman
Download Postman and install it. The free tier does everything this tutorial needs.
Worth knowing alongside Postman:
- Since .NET 9 the Web API template ships an OpenAPI document, and viewers like Scalar give you an in-browser tester with zero setup — see getting started with ASP.NET Core Web API.
- Visual Studio and VS Code understand
.httpfiles (the template creates one), which keep runnable requests in your repository.
Postman remains the tool of choice when you want collections, environments, auth flows, and test scripts.
Create the ASP.NET Core Web API
Any API with CRUD endpoints works. The examples below use a supplier API like the one from CRUD operations using ASP.NET Core; run it with dotnet run and note the port Kestrel prints — requests go to http://localhost:<port>/api/supplier.
Test HTTP GET
In Postman, the left pane holds your history and collections; the right pane builds requests.
Select GET from the method dropdown, enter the API URL (http://localhost:<port>/api/supplier), and click Send. The response appears below — status 200 OK, body in JSON by default (the response viewer can also render XML, HTML, or plain text).

Test HTTP POST
POST creates a new entity; the API binds the JSON request body to the model ([FromBody]).
- Select POST from the dropdown.
- Enter the URL:
http://localhost:<port>/api/supplier - Open the Body tab → choose raw → set the type to JSON.
- Enter the supplier JSON object.
- Click Send.
A successful create returns 201 Created, and the response body carries the created entity — including its server-generated id. Well-behaved APIs also return a Location header pointing at the new resource; check the Headers tab of the response.

Also test the failure path on purpose: remove a required field from the JSON and send again. ASP.NET Core's model validation answers 400 Bad Request with a ProblemDetails body that names each offending field:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"Name": ["The Name field is required."]
}
}
If you get 415 Unsupported Media Type instead, the Body type dropdown isn't set to JSON — Postman then sends Content-Type: text/plain and the API refuses to bind it.
Test HTTP PUT
PUT updates an entity (or, in some API designs, creates it at a known URL). The practical difference between PUT and POST: PUT is idempotent — sending the same PUT five times leaves the same single result, while sending the same POST five times creates five entities. A PUT request carries the complete entity with all attributes set; for partial updates APIs use PATCH.
- Select PUT.
- Enter the URL including the id:
http://localhost:<port>/api/supplier/1 - Body → raw → JSON, with the full updated supplier object.
- Click Send.
A successful update returns 200 OK with content (this API responds "Supplier Updated Successfully."), or 204 No Content when the API returns an empty body. If the id doesn't exist, expect 404 Not Found.

Test HTTP DELETE
DELETE removes the entity addressed by the URL. If a DELETE request has a body, the server ignores it — the id in the URL is what matters.
- Select DELETE.
- Enter the URL with the id:
http://localhost:<port>/api/supplier/1 - Click Send.
Expected status codes:
- 200 OK — deleted, response includes content describing the result (this API's case).
- 204 No Content — deleted, empty response body.
- 404 Not Found — no entity with that id.

Call an endpoint that needs a JWT
Real APIs protect endpoints with [Authorize], and an unauthenticated request answers 401 Unauthorized. Testing those in Postman is a two-request flow:
- Get a token — POST to your login endpoint with credentials in the JSON body. The response carries the token (see JWT authentication in ASP.NET Core for building this side).
- Use it — in the protected request, open the Authorization tab, pick Bearer Token, and paste the token. Postman adds the
Authorization: Bearer <token>header for you.
Set the Authorization on the collection instead of each request and every request in it inherits the token — one place to update when it expires. Expect 401 when the token is missing or expired, and 403 Forbidden when the token is valid but the user lacks the required role.
Chain requests with variables
Retyping ids between requests gets old fast. Postman variables fix both setup and chaining:
- Base URL: create an environment with
baseUrl = http://localhost:5000, then write every URL as{{baseUrl}}/api/supplier. Switching from local to a deployed API becomes a dropdown change. - Pass values between requests: in the POST request's Scripts → Post-response tab, capture the created id:
const supplier = pm.response.json();
pm.collectionVariables.set("supplierId", supplier.id);
Now the PUT and DELETE requests can use {{baseUrl}}/api/supplier/{{supplierId}} — run the collection top to bottom and each request feeds the next, no copy-paste.
Make requests assert: tests
The same Scripts tab turns a request into a test. Assertions run automatically after every send:
pm.test("status is 201 Created", () => pm.response.to.have.status(201));
pm.test("response carries the new id", () => {
const body = pm.response.json();
pm.expect(body.id).to.be.above(0);
});
pm.test("Location header points at the resource", () => {
pm.expect(pm.response.headers.get("Location")).to.include("/api/supplier/");
});
With tests on each request, the Collection Runner (right-click the collection → Run) executes GET → POST → GET → PUT → DELETE in order and shows a green/red report — a real regression suite instead of eyeballing responses.
Run it in CI with Newman
Collections aren't locked inside the app. Export the collection (and environment) as JSON, commit them next to the API code, and run them from any terminal or pipeline with Newman, Postman's CLI runner:
npm install -g newman
newman run supplier-api.postman_collection.json -e local.postman_environment.json
Newman exits non-zero when any test fails, which is exactly what a CI step wants. A GitHub Actions job that starts the API, waits for it, and runs Newman gives you living API documentation that fails the build when behavior drifts.
Status codes cheat sheet
| Code | Meaning | Typical cause in ASP.NET Core |
|---|---|---|
| 200 OK | Success with body | GET, or PUT/DELETE returning content |
| 201 Created | Entity created | POST via CreatedAtAction |
| 204 No Content | Success, empty body | PUT/DELETE returning NoContent() |
| 400 Bad Request | Validation failed | Data annotations / model binding errors |
| 401 Unauthorized | No/invalid token | [Authorize] without a bearer token |
| 403 Forbidden | Token OK, rights missing | Role/policy check failed |
| 404 Not Found | No such resource | Wrong URL or id; routing mismatch |
| 415 Unsupported Media Type | Body type wrong | Missing Content-Type: application/json |
| 500 Internal Server Error | Unhandled exception | Read the API's console/logs |
Tips that pay off quickly
- Watch the status code first, body second — most API bugs announce themselves in the code (400 model validation, 404 routing, 415 missing
Content-Type: application/json, 500 server fault). - If a request works in Postman but fails from a browser app, that is almost always CORS — Postman ignores CORS; browsers enforce it.
Comments (0)
No comments yet — be the first to share your thoughts.