Skip to content

HTTP Headers

Jean-Marc Strauven edited this page Dec 23, 2025 · 1 revision

HTTP Headers

Learn about the RFC-compliant HTTP headers automatically added to API responses.


Overview

Laravel ApiRoute automatically adds version-related headers to all API responses. These headers help clients understand the version they're using and any lifecycle information.

HTTP/1.1 200 OK
X-API-Version: v1
X-API-Version-Status: deprecated
Deprecation: Sun, 01 Jun 2025 00:00:00 GMT
Sunset: Mon, 01 Dec 2025 00:00:00 GMT
Link: </api/v2/users>; rel="successor-version"

Header Configuration

Enable or disable individual headers:

// config/apiroute.php
'headers' => [
    'enabled' => true,
    'include' => [
        'version' => true,           // X-API-Version
        'status' => true,            // X-API-Version-Status
        'deprecation' => true,       // Deprecation (RFC 8594)
        'sunset' => true,            // Sunset (RFC 7231)
        'successor_link' => true,    // Link rel="successor-version"
    ],
],

Standard Headers

X-API-Version

Shows the current API version being used.

X-API-Version: v1

Always present when headers are enabled.


X-API-Version-Status

Shows the lifecycle status of the version.

X-API-Version-Status: active

Possible values:

  • active - Current stable version
  • beta - Beta/preview version
  • deprecated - Deprecated version
  • sunset - End-of-life version

X-API-Version-Fallback

Added when a fallback to a different version occurred.

X-API-Version: v2
X-API-Version-Fallback: v1

This means the request was for v2, but the route was served from v1.


RFC-Compliant Headers

Deprecation Header (RFC 8594)

The Deprecation header indicates when an API version was deprecated.

Deprecation: Sun, 01 Jun 2025 00:00:00 GMT

Format: RFC 7231 HTTP-date format

Reference: RFC 8594 - The Sunset HTTP Header Field

When added: Only for versions marked as deprecated

ApiRoute::version('v1', function () {
    // ...
})->deprecated('2025-06-01'); // Adds Deprecation header

Sunset Header (RFC 7231)

The Sunset header indicates when an API version will be removed.

Sunset: Mon, 01 Dec 2025 00:00:00 GMT

Format: RFC 7231 HTTP-date format

Reference: RFC 7231 - Hypertext Transfer Protocol

When added: Only for versions with a sunset date

ApiRoute::version('v1', function () {
    // ...
})->sunset('2025-12-01'); // Adds Sunset header

Link Header (RFC 8288)

The Link header points to the successor version.

Link: </api/v2/users>; rel="successor-version"

Reference: RFC 8288 - Web Linking

When added: Only when a successor version is defined

ApiRoute::version('v1', function () {
    // ...
})->setSuccessor('v2'); // Adds Link header

Complete Example

For a deprecated version with all information:

ApiRoute::version('v1', function () {
    Route::get('users', [UserController::class, 'index']);
})
->deprecated('2025-06-01')
->sunset('2025-12-01')
->setSuccessor('v2');

Response headers:

HTTP/1.1 200 OK
Content-Type: application/json
X-API-Version: v1
X-API-Version-Status: deprecated
Deprecation: Sun, 01 Jun 2025 00:00:00 GMT
Sunset: Mon, 01 Dec 2025 00:00:00 GMT
Link: </api/v2/users>; rel="successor-version"

Headers by Version Status

Status X-API-Version X-API-Version-Status Deprecation Sunset Link
Active Yes active No No No
Beta Yes beta No No No
Deprecated Yes deprecated Yes (if date set) Yes (if date set) Yes (if successor set)
Sunset Yes sunset Yes Yes Yes

Client-Side Handling

JavaScript Example

async function fetchAPI(endpoint) {
    const response = await fetch(`/api/v1/${endpoint}`);

    // Check for deprecation warning
    const deprecation = response.headers.get('Deprecation');
    if (deprecation) {
        console.warn(`API version is deprecated since ${deprecation}`);
    }

    // Check for sunset date
    const sunset = response.headers.get('Sunset');
    if (sunset) {
        console.warn(`API version will be removed on ${sunset}`);
    }

    // Check for successor
    const link = response.headers.get('Link');
    if (link && link.includes('successor-version')) {
        console.info(`Upgrade available: ${link}`);
    }

    return response.json();
}

PHP Example

$response = Http::get('https://api.example.com/v1/users');

if ($response->header('Deprecation')) {
    Log::warning('Using deprecated API version', [
        'deprecation' => $response->header('Deprecation'),
        'sunset' => $response->header('Sunset'),
    ]);
}

VersionHeaders Class

The VersionHeaders class handles adding headers to responses:

use Grazulex\ApiRoute\Http\Headers\VersionHeaders;

class VersionHeaders
{
    public function addToResponse(Response $response, VersionDefinition $version): Response
    {
        // Adds all configured headers
    }
}

Headers are added automatically by the ResolveApiVersion middleware.


Disabling Headers

Disable All Headers

// config/apiroute.php
'headers' => [
    'enabled' => false,
],

Disable Specific Headers

// config/apiroute.php
'headers' => [
    'enabled' => true,
    'include' => [
        'version' => true,
        'status' => true,
        'deprecation' => false,  // Disable deprecation header
        'sunset' => false,       // Disable sunset header
        'successor_link' => false,
    ],
],

Custom Header Handling

If you need custom header logic, you can extend the middleware:

use Grazulex\ApiRoute\Middleware\ResolveApiVersion;

class CustomApiVersionMiddleware extends ResolveApiVersion
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = parent::handle($request, $next);

        // Add custom headers
        $response->headers->set('X-Custom-Header', 'value');

        return $response;
    }
}

Next Steps

Clone this wiki locally