Content Negotiation: Mastering API Format Handling with Accept Headers
Learn how to implement Content Negotiation in your REST API. Master the Accept header to serve JSON, XML, or other formats based on client preference.

Previously in this course, we covered rate limiting fundamentals to ensure our API remains stable under load. Now that your Task Manager API is protected, we need to make it more flexible by allowing clients to request data in their preferred format through Content Negotiation.
What is Content Negotiation?
Content negotiation is the mechanism in HTTP that allows a client and a server to agree on the best representation of a resource. Instead of forcing every client to parse the same data structure, your API can detect what the client wants—such as application/json or application/xml—and respond accordingly.
This is driven primarily by the Accept request header. When a client sends a request, it includes this header to tell the server: "I am willing to accept these specific media types." If the server can provide one of those types, it does so; otherwise, it should return a 406 Not Acceptable status code.
Implementing Format Handling
In a typical backend implementation, you check the Accept header of the incoming request before serializing your data. While JSON as the Standard Exchange Format is our default, supporting other formats like XML makes your API more versatile for legacy systems or specialized clients.
Worked Example: Handling JSON vs. XML
Imagine our GET /v1/tasks endpoint. We want to check the Accept header and return the appropriate payload.
JAVASCRIPT// Pseudo-code implementation for a Task route app.get(CE9178">'/v1/tasks', (req, res) => { const tasks = getTasksFromDb(); // Our task data const acceptHeader = req.headers[CE9178">'accept']; if (acceptHeader === CE9178">'application/xml') { res.setHeader(CE9178">'Content-Type', CE9178">'application/xml'); return res.send(convertToXml(tasks)); } // Default to JSON res.setHeader(CE9178">'Content-Type', CE9178">'application/json'); res.json(tasks); });
The server sets the Content-Type header in the response so the client knows exactly what format it received. This prevents common issues like MIME-sniffing prevention, which can lead to security vulnerabilities if the browser guesses the file type incorrectly.
Practical Exercise
- Modify your existing
GET /v1/tasksendpoint to inspect theAcceptheader. - If the client sends
application/json, return the standard JSON response. - If the client sends
text/plain, return a simple comma-separated string of task titles. - If the client sends an unsupported format (e.g.,
application/pdf), return a406 Not Acceptableresponse.
Common Pitfalls
- Ignoring the 406 Status: Many developers default to JSON regardless of the
Acceptheader. Always return406 Not Acceptableif the client requests a format you don't support; this is the correct RESTful way to signal a mismatch. - Over-complicating: You do not need to support every possible format. Start with JSON and one other format (like XML) only if your specific requirements demand it.
- Missing Content-Type: Always explicitly set the
Content-Typeheader in your response. Without it, clients may fail to parse your response correctly.
FAQ
Q: Should I use Content Negotiation for API versioning?
A: Yes, it is a valid strategy. Instead of v1/tasks, you can use header-based versioning to keep your URIs clean, as discussed in our guide on mastering header-based versioning for clean evolution.
Q: What is the difference between Accept and Content-Type?
A: Accept is what the client wants to receive, while Content-Type is what the server is actually sending.
Recap
Content negotiation allows your API to evolve alongside client needs. By respecting the Accept header, you provide a better developer experience and ensure your API remains accessible to a wider variety of clients. Remember to explicitly set your Content-Type headers to keep your responses predictable and secure.
Up next: We will begin exploring Resource Relationships and how to link your data models using HATEOAS.
Work with me

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs — the backend engine for your app, mobile client, or SaaS. Built by an API specialist.

Headless WordPress + Next.js Frontend Development
Keep WordPress for content, get a lightning-fast Next.js frontend. The best of both worlds — familiar editing, modern speed.

