Introduction
Building a high-quality API involves more than transmitting data; it requires adhering to the "language of the web." This guide explores HTTP methods and status codes, detailing the correct actions and responses for various scenarios. Mastering these fundamentals transforms complex code into a professional system that is clear, efficient, and intuitive for integration.
HTTP Methods
The following sections outline the standard implementation of HTTP methods.
1. GET – Retrieve Data
This method is the standard for fetching data without modification. It is "safe" and "idempotent," meaning repeated calls do not alter the server state.
// Fetch the entire list of library members
app.MapGet("/api/members", async (MemberRegistry registry) =>
{
var members = await registry.ListAllAsync();
return Results.Ok(members);
});
// Fetch a specific member by unique ID
app.MapGet("/api/members/{id:int}", async (int id, MemberRegistry registry) =>
{
var member = await registry.FindByIdAsync(id);
return member is null
? Results.NotFound()
: Results.Ok(member);
});
Standard Responses:
2. POST – Create a New Entry
POST is used to submit data to create a new resource. It is "non-idempotent"; multiple identical submissions typically result in multiple resource entries.
// Register a new vehicle
app.MapPost("/api/vehicles", async (RegisterVehicleRequest data, FleetManager manager) =>
{
var vehicle = await manager.AddNewVehicleAsync(data);
// Return 201 Created and include the 'Location' header
return Results.Created($"/api/vehicles/{vehicle.Vin}", vehicle);
});
Key Standards for POST:
201 Created: Confirms the operation succeeded and a new resource was generated.
Location Header: Directs the client to the specific URL of the new resource.
Resource Body: Provides the created object, including server-generated fields like IDs.
3. PUT – Full Resource Replacement
PUT replaces an existing resource entirely. It is "idempotent"; repeating the same request multiple times results in the same state as the initial call.
// Completely update project details
app.MapPut("/api/projects/{code}", async (string code, ProjectUpdate data, PortfolioManager manager) =>
{
var existingProject = await manager.GetByCodeAsync(code);
if (existingProject is null)
return Results.NotFound();
await manager.ReplaceProjectAsync(code, data);
return Results.NoContent();
});
Key Standards for PUT:
4. PATCH – Surgical Updates
PATCH performs partial updates. Unlike PUT, only the specific fields intended for modification are transmitted.
// Update specific parts of a profile
app.MapPatch("/api/subscribers/{id:guid}", async (Guid id, JsonPatchDocument<Subscriber> updates, MembershipService service) =>
{
var subscriber = await service.GetByIdAsync(id);
if (subscriber is null)
return Results.NotFound();
updates.ApplyTo(subscriber);
await service.SaveAsync(subscriber);
return Results.NoContent();
});
Key Standards for PATCH:
5. DELETE – Remove an Entry
DELETE permanently removes a resource. It is considered idempotent; while the first call deletes the data, subsequent identical requests should not cause system errors.
// Remove a specific record
app.MapDelete("/api/employees/{badgeId:int}", async (int badgeId, StaffManager manager) =>
{
var staffMember = await manager.GetByBadgeIdAsync(badgeId);
if (staffMember is null)
return Results.NotFound();
await manager.PermanentlyRemoveAsync(badgeId);
return Results.NoContent();
});
Standard HTTP Status Codes
HTTP status codes serve as universal shorthand, ensuring system predictability and simplifying debugging.
A. Success Codes (2xx)
These indicate that a request was received and accepted.
| Code | Name | Usage |
|---|
| 200 | OK | Successful GET, or a PUT/PATCH returning an updated version. |
| 201 | Created | Successful POST resulting in a new resource. |
| 204 | No Content | Successful DELETE or PUT/PATCH where no body is returned. |
B. Client Error Codes (4xx)
These indicate a failure caused by the request itself.
| Code | Name | Usage |
|---|
| 400 | Bad Request | General validation errors or malformed data. |
| 401 | Unauthorized | Authentication is missing or invalid. |
| 403 | Forbidden | Authenticated, but lacking necessary permissions. |
| 404 | Not Found | The requested resource or endpoint does not exist. |
| 409 | Conflict | Data collision, such as duplicate unique identifiers. |
| 429 | Too Many Requests | Rate limiting due to excessive requests. |
C. Server Error Codes (5xx)
These indicate a failure on the server side.
| Code | Name | Usage |
|---|
| 500 | Internal Error | An unhandled exception or bug within the code. |
| 503 | Service Unavailable | Server overload or temporary maintenance. |
Common Professional Pitfalls to Avoid
Avoid Misleading 200 OK Responses: Never return a success status code if the operation failed.
Distinguish Between 401 and 403: Use 401 Unauthorized when identity is unknown or unverified. Use 403 Forbidden when the identity is known but lacks the required permissions for the action.
Protect Sensitive Data: Do not include raw stack traces or internal code errors in 500 Internal Server Error responses. Log detailed errors privately and return a generic message to the client.
Accurate Error Attribution: Ensure client-side mistakes (such as malformed email formats) result in 400 Bad Request responses rather than server-side 500 errors.
Conclusion
In this article, we have seen how mastering HTTP methods and status codes builds professional, predictable APIs. Correctly applying these standards ensures system scalability and simplifies integration for other developers. Adhering to these patterns provides a robust foundation for building reliable, industry-standard web services. Hope this will useful.