← API

API FEATURE

Structured Errors

API failures should stay operationally useful. This page shows the exact error body a client would parse, not just the fact that the request failed.

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

Structured Errors demonstrates that Semitexa API failures stay machine-readable even when the route throws domain exceptions.

How it works

The route throws typed domain exceptions, and ExternalApiExceptionMapper turns them into one JSON envelope with a stable `error.code`, human message, structured context, and optional retry metadata.

Why it matters

API clients need more than a string message. A stable envelope lets SDKs, dashboards, and background jobs branch on error semantics without scraping text.

Key concepts

ExternalApiExceptionMapper
Maps domain exceptions on external API routes into stable JSON error envelopes.
error.context
Structured machine-readable metadata that explains the failure without parsing the message.
request_id
Correlation id slot for tracing a failing API request across logs and support channels.

Failure Contract

Not-found envelope

The route throws a domain exception, but the external API pipeline still returns one predictable error envelope.

Route GET /demo/api/structured-errors?type=not-found
Response 404 application/json
CLI curl -H "Accept: application/json" "http://localhost:9502/demo/api/structured-errors?type=not-found"
Header Value
Content-Type application/json

Machine-readable error body

{
    "error": {
        "code": "not_found",
        "message": "Demo API product #missing-product not found.",
        "context": {
            "resource": "Demo API product",
            "identifier": "missing-product"
        },
        "request_id": null,
        "docs_url": null
    }
}
ExternalApiExceptionMapper DomainException error.context request_id

Verified against Semitexa Ultimate 2026.09.19.1020

Structured Errors

API failures should stay operationally useful. The ExternalApiExceptionMapper intercepts any DomainException thrown from an #[ExternalApi] route and transforms it into a predictable JSON error envelope before the response leaves the framework.

How it works

Domain exceptions carry typed context — field errors for validation failures, retry_after for rate limits, resource identifiers for not-found cases. The mapper reads that context and places it under error.context in the response body. The HTTP status code maps directly from the exception type. The outer envelope shape is always { error: { code, message, context, request_id, docs_url } }.

Why this matters

Clients can rely on error structure even when the business path fails. Validation problems stay nested under error.context.fields, auth failures keep the same outer shape with only the status changing, and retry guidance appears in both the Retry-After header and the machine-readable body. SDKs and dashboards can branch on error.code with one parser instead of two.

© Edsger W. Dijkstra: "Simplicity is prerequisite for reliability."

Structured Errors Handler Application entry point
<?phpdeclare(strict_types=1);namespace App\Application\Handler\Api;use App\Application\Exception\Api\DemoApiNotFoundException;use App\Application\Payload\Api\ApiErrorTriggerPayload;use App\Application\Resource\Api\ErrorEnvelopeResource;use Semitexa\Core\Attribute\AsPayloadHandler;use Semitexa\Core\Contract\TypedHandlerInterface;#[AsPayloadHandler(payload: ApiErrorTriggerPayload::class, resource: ErrorEnvelopeResource::class)]final class ApiErrorTriggerHandler implements TypedHandlerInterface{    public function handle(ApiErrorTriggerPayload $payload, ErrorEnvelopeResource $resource): ErrorEnvelopeResource    {        throw new DemoApiNotFoundException('Product', 'demo-product');    }}

Envelope Notes

What this endpoint is proving

Concern Behavior Why it matters
Exception mapping A typed domain exception becomes `{ error: { code, message, context, request_id } }`. Clients can rely on error structure even when the business path fails.
Context preservation Resource name and identifier stay in `error.context` instead of being buried in text. Support tooling can diagnose failures without brittle string parsing.

How it works

The route throws typed domain exceptions, and ExternalApiExceptionMapper turns them into one JSON envelope with a stable `error.code`, human message, structured context, and optional retry metadata.

Why it matters

API clients need more than a string message. A stable envelope lets SDKs, dashboards, and background jobs branch on error semantics without scraping text.

Key concepts

ExternalApiExceptionMapper
Maps domain exceptions on external API routes into stable JSON error envelopes.
error.context
Structured machine-readable metadata that explains the failure without parsing the message.
request_id
Correlation id slot for tracing a failing API request across logs and support channels.

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

Donate via PayPal