Skip to content

RESTful Messages & Status Codes — Request/Response Guide

DodaTech Updated Jun 6, 2026 7 min read

RESTful messages are HTTP request and response structures carrying data between clients and servers using headers, status codes, and bodies.

What You’ll Learn

  • The structure of HTTP requests and responses in REST
  • Common request headers for content type, auth, and caching
  • Response status codes by category (1xx–5xx)
  • Content negotiation and format selection
  • Consistent error response patterns

Why Messages Matter

Every API interaction is a conversation. The client sends a request saying what it wants, and the server responds with the result. How you format these messages determines whether developers understand your API in minutes or struggle for hours. DodaTech’s Durga Antivirus Pro API uses consistent message patterns — every response includes the same error structure, every request uses standard headers, and status codes precisely describe what happened.

    sequenceDiagram
    participant Client
    participant Server
    Client->>Server: GET /api/v1/threats<br/>Accept: application/json<br/>Authorization: Bearer tok
    Server->>Client: 200 OK<br/>Content-Type: application/json<br/>Cache-Control: max-age=300<br/>[{"id":"th-001","name":"Emotet"}]
    Client->>Server: POST /api/v1/threats<br/>Content-Type: application/json<br/>{"name":"NewThreat","hash":"..."}
    Server->>Client: 201 Created<br/>Location: /api/v1/threats/th-003<br/>{"id":"th-003",...}
    Note over Client,Server: Status codes tell the story
  
Prerequisites: Knowledge of REST, RESTful Methods, and RESTful Resources.

HTTP Request Structure

Every HTTP request has three parts:

  1. Request line: Method, URI, HTTP version
  2. Headers: Metadata about the request
  3. Body: Data (for POST, PUT, PATCH only)
POST /api/v1/threats HTTP/1.1
Host: api.durga-antivirus.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
Accept: application/json
User-Agent: Durga-Antivirus/2.1

{"name": "Trojan.Generic", "hash": "a1b2c3d4", "severity": "high"}

Common Request Headers

HeaderPurposeExample
AuthorizationAuthentication credentialsBearer eyJhbGci...
Content-TypeFormat of the request bodyapplication/json
AcceptDesired response formatapplication/json
User-AgentClient identificationDurga-Antivirus/2.1
Cache-ControlCaching preferencesno-cache
If-None-MatchConditional request (ETag)"abc123"

Why Content-Type and Accept are separate: Content-Type tells the server how to parse the body you’re sending. Accept tells the server what format you want the response in. They can be different — you might send form data (application/x-www-form-urlencoded) but want JSON back (application/json).

HTTP Response Structure

Every response also has three parts:

  1. Status line: HTTP version, status code, reason phrase
  2. Headers: Metadata about the response
  3. Body: Response data
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=300
ETag: "abc123"
X-Request-Id: req-789

{"id": "th-001", "name": "Emotet", "severity": "critical"}

Status Codes by Category

Status codes are grouped into five classes. The first digit tells you the category:

2xx — Success

CodeMeaningWhen to Use
200 OKSuccessGET, PUT, PATCH, DELETE (with body)
201 CreatedResource createdPOST — include Location header
202 AcceptedAccepted for processingAsync operations (file scan queued)
204 No ContentSuccess, no bodyDELETE, some PUT operations

3xx — Redirection

CodeMeaningWhen to Use
301 Moved PermanentlyResource movedAPI endpoint changed permanently
304 Not ModifiedUse cached versionConditional GETs with ETag

4xx — Client Error

CodeMeaningWhen to Use
400 Bad RequestMalformed syntaxInvalid JSON, missing required fields
401 UnauthorizedAuthentication requiredMissing or invalid API key
403 ForbiddenInsufficient permissionsValid auth but no access
404 Not FoundResource doesn’t existInvalid ID or URI
405 Method Not AllowedWrong HTTP methodPOST on read-only endpoint
409 ConflictResource state conflictDuplicate creation, stale version
422 Unprocessable EntitySemantic validation errorEmail format invalid
429 Too Many RequestsRate limit exceededToo many requests in time window

5xx — Server Error

CodeMeaningWhen to Use
500 Internal Server ErrorUnexpected errorUnhandled exception
502 Bad GatewayUpstream failureDownstream service unavailable
503 Service UnavailableServer overloadedMaintenance mode, rate limiting at infrastructure

Content Negotiation

Content negotiation is how the client and server agree on the format for data exchange. The client sends an Accept header, and the server responds with the best matching format.

// Client requests JSON
GET /api/v1/threats HTTP/1.1
Accept: application/json

// Server responds with JSON
HTTP/1.1 200 OK
Content-Type: application/json
...

// Client requests XML
GET /api/v1/threats HTTP/1.1
Accept: application/xml

// Server responds with XML (if supported)
HTTP/1.1 200 OK
Content-Type: application/xml
...

Consistent Error Responses

Every error should follow the same structure so clients can parse errors programmatically:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request body contains invalid fields.",
    "details": [
      { "field": "email", "message": "Must be a valid email address" },
      { "field": "age", "message": "Must be a positive integer" }
    ],
    "requestId": "req-789"
  }
}

Why requestId? When something goes wrong, developers need to trace the issue. Including a unique request ID in every response (and logging it server-side) lets you correlate error reports with server logs without exposing internal details.

Common Mistakes

1. Returning 200 for All Successful Requests

Using 200 for everything (creation, deletion, successful GET) loses the semantic meaning of status codes. 201 says “resource created” — it’s more informative than 200.

2. Inconsistent Error Body Formats

One endpoint returns {"error": "not found"}, another returns {"code": 404, "msg": "Resource not found"}. This forces clients to write custom error parsers for each endpoint. Standardize the error format across your entire API.

3. Exposing Stack Traces in 500 Errors

Returning a stack trace or internal error message (database credentials, file paths) in production is a security vulnerability. Always return a generic 500 Internal Server Error with a request ID for tracking.

4. Ignoring the Location Header After POST

The Location header in a 201 Created response tells the client where the new resource lives. Without it, the client must guess the URI or parse the response body. This breaks HATEOAS principles.

5. Using Wrong 4xx Code

400 Bad Request is for malformed syntax (invalid JSON). 422 Unprocessable Entity is for semantic validation failures (email format wrong). Using them interchangeably confuses clients.

Practice Questions

  1. What are the five categories of HTTP status codes?
  2. What does 201 Created include that 200 OK doesn’t?
  3. What is the difference between 400 Bad Request and 422 Unprocessable Entity?
  4. Why should every response include a request ID?
  5. What is the purpose of the Accept header?

Answers:

  1. 1xx (Informational), 2xx (Success), 3xx (Redirection), 4xx (Client Error), 5xx (Server Error).
  2. A Location header pointing to the URI of the newly created resource.
  3. 400 is for malformed syntax (invalid JSON, wrong data type). 422 is for valid syntax but invalid semantics (well-formed JSON with invalid email format).
  4. Request IDs let developers correlate error reports with server logs to diagnose issues without exposing internal details.
  5. The Accept header tells the server what response format the client prefers (JSON, XML, etc.).

Challenge: Write a complete HTTP response for POST /api/v1/devices that fails with a validation error. Include the status code, headers, and a standardized error body with at least two field-level errors.

FAQ

Should I always return JSON for errors?
: Yes — if your API uses JSON for success responses, use JSON for errors too. Consistent formats across all responses reduce cognitive load for developers. The same Content-Type header applies to both success and error responses.
What is the difference between 401 and 403?
: 401 Unauthorized means the client is not authenticated (missing or invalid credentials). 403 Forbidden means the client is authenticated but doesn’t have permission to access the resource. Think: “401 = who are you?” vs “403 = you can’t do that.”
When should I use 202 Accepted?
: Use 202 Accepted when the request will be processed asynchronously. For example, submitting a file to Durga Antivirus Pro for scanning — the scan takes time, so the server accepts the request and returns an ID the client can poll later.
Should I use 409 Conflict or 400 for duplicate resources?
: Use 409 Conflict for duplicate resources. This status code specifically means the request conflicts with the current state of the server. 400 is too generic — it doesn’t tell the client that retrying with different data (unique constraint) would fix it.

Try It Yourself

Create a mock API that returns proper status codes using this Node.js Express server:

const express = require('express');
const app = express();
app.use(express.json());

const threats = [
  { id: 'th-001', name: 'Emotet', severity: 'critical' }
];

// GET — list threats
app.get('/api/v1/threats', (req, res) => {
  res.status(200).json(threats);
});

// POST — create threat (validation example)
app.post('/api/v1/threats', (req, res) => {
  if (!req.body.name) {
    return res.status(422).json({
      error: { code: 'VALIDATION_ERROR', message: 'Name is required' }
    });
  }
  const threat = { id: `th-${Date.now()}`, ...req.body };
  threats.push(threat);
  res.status(201).location(`/api/v1/threats/${threat.id}`).json(threat);
});

app.listen(3000);

Run this with node server.js and test with curl to see proper status codes in action.

What’s Next

TopicDescription
Statelessness & Caching in RESTHow stateless design enables scaling and caching
REST API SecurityAuthentication, authorization, and rate limiting
RESTful APIs OverviewReview the complete REST architecture
GraphQL vs RESTCompare message patterns across API styles

What’s Next

Congratulations on completing this Restful Messages tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro