← Routing & Handlers

ROUTING & HANDLERS FEATURE

Content Negotiation

One endpoint serves JSON or HTML depending on the Accept header — no branching in handler code.

Feature Guide

A quick orientation block that answers the essential questions: what this feature does, how it works, why it matters, and the key concepts behind it.

What this does

A single endpoint serves JSON, HTML, or other formats depending on the Accept header or ?_format= query parameter.

How it works

The produces array in #[AsPayload] declares which Content-Types the endpoint supports. The framework negotiates the best match against the client Accept header and selects the appropriate response serializer.

Why it matters

Content negotiation lets one route serve both browser and API clients. The handler stays format-agnostic — it populates the resource DTO, and the framework handles serialization.

Key concepts

produces
Declares the Content-Types an endpoint can return, enabling content negotiation.
Accept header
HTTP header the client sends to indicate preferred response formats.

Negotiation

One endpoint, multiple representations

The same handler output can render as HTML for browsers or JSON for API consumers.

GET /demo/routing/content-negotiation Single endpoint
Accept: text/html or Accept: application/json Representation switch

HTML response

Wireless Headphones

Rendered as a normal SSR page fragment for the browser.

$79.99

Mechanical Keyboard

Rendered as a normal SSR page fragment for the browser.

$129.99

Ultra-wide Monitor

Rendered as a normal SSR page fragment for the browser.

$549.99
produces Accept header ?_format= override ContentNegotiator

Verified against Semitexa Ultimate 2026.09.19.1020

Content Negotiation

A single endpoint serves JSON, HTML, or other formats depending on the Accept header or ?_format= query parameter.

How it works

The produces array on the payload's access attribute (#[AsPublicPayload], #[AsProtectedPayload], or #[AsServicePayload]) declares which Content-Types the endpoint supports. The framework negotiates the best match against the client Accept header and selects the appropriate response serializer.

Why this matters

Content negotiation lets one route serve both browser and API clients. The handler stays format-agnostic — it populates the resource DTO, and the framework handles serialization.

© Jeff Sickel: "Deleted code is debugged code."

Payload Trusted input boundary
<?phpdeclare(strict_types=1);namespace App\Application\Payload\Routing;use App\Application\Resource\Page\ProductCollectionPageResource;use Semitexa\Core\Attribute\AsPublicPayload;#[AsPublicPayload(    path: '/products',    methods: ['GET'],    responseWith: ProductCollectionPageResource::class,    produces: ['text/html', 'application/json'],)]final class ContentNegotiationPayload{}

How it works

The produces array in #[AsPayload] declares which Content-Types the endpoint supports. The framework negotiates the best match against the client Accept header and selects the appropriate response serializer.

Why it matters

Content negotiation lets one route serve both browser and API clients. The handler stays format-agnostic — it populates the resource DTO, and the framework handles serialization.

Key concepts

produces
Declares the Content-Types an endpoint can return, enabling content negotiation.
Accept header
HTTP header the client sends to indicate preferred response formats.

Support Semitexa
Built for developers who prefer control over magic. Your support helps keep it fast, open, and evolving.

Donate via PayPal