Back to all articles
API Best Practices

Understanding The HTTP Deprecation Header

October 25, 2024

The HTTP Deprecation header is used to inform clients that an API endpoint is or will be deprecated. According to the recently released RFC 9745, the field should be an RFC 9651 Date, which is expressed in Unix time. The date can either be in the past (the API has already been deprecated) or can be in the future (the API will be deprecated at this date). Here's an example for an API that was deprecated Friday, June 30, 2023 at 23:59:59 UTC:

YAMLyaml
Deprecation: @1688169599

Benefits of Implementing the Deprecation Header

  • Additional Warning: Your API consumers may not read the deprecation warning you send out via email/other comms so this is another way for them to become aware of the impending deprecation
  • Maintain in Code: In comparison to docs (which are often decoupled from your API code) the deprecation header is sent by the API at runtime and can be updated directly by the developers.
  • Tooling Support: API clients can eventually adopt a pattern of inspecting network responses for the deprecation header and logging a warning in non-production environments

Other Deprecation Header Formats

This convention has not always been the case, and many API providers stray from the format. Some prefer to use the RFC 7231 HTTP-date format (often expressed in GMT) instead, which looks like this:

YAMLyaml
Deprecation: Wed, 11 Oct 2023 23:59:59 GMT

The obvious benefit of this format is that it's much more easily readable by an API developer inspecting network responses. Some tooling (ex. API clients) might find this format more difficult to parse than unix time however.

Even simpler still is using a boolean instead of a date:

YAMLyaml
Deprecation: true

As a binary answer to the question "is this API deprecated?". The drawback of the boolean is that is necessitates communicating the API's deprecation ahead of time through other means than the headers. Given that the deprecation header is not widely adopted, this process is usually necessary anyways. The other drawback is that it limits API client libraries' ability to warn you of an upcoming deprecation.

Extending the HTTP Deprecation Header

Although the deprecation header is useful on its own, you can actually couple it with other headers as a part of a holistic API deprecation process.

The Deprecation Link Relation Type

You can use the link relation type to communicate more information about the deprecation of the API. For example, you can link to documentation or a blog post about the deprecation like this:

YAMLyaml
Link:
  <https://developer.example.com/deprecation>; rel="deprecation";
  type="text/html"

This can be particularly useful if more than just a single endpoint is being deprecated. One limitation of the HTTP deprecation header is that it doesn't provide context on the scope of the deprecation - is the whole API being deprecated, or just this endpoint? Using a link should help with filling in that gap.

The HTTP Sunset Header

Sunsetting is the point in time in which the deprecated API becomes unresponsive. The HTTP sunset header (RFC 8594) is typically used to convey when the sunset will occur. This is often coupled with the deprecation header to give a full picture of the API's end-of-life.

YAMLyaml
Deprecation: @1688169599
Sunset: Sun, 30 Jun 2024 23:59:59 UTC

Note that the sunset header uses a different date format than the deprecation header due to "historical reasons".

Implementing the HTTP Deprecation Header

Below are some code samples on how to implement the deprecation header in various popular API frameworks.

Node.js with Express

TypeScripttypescript
const express = require("express");
const app = express();

app.get("/v1/old-endpoint", (req, res) => {
  const deprecationDate = Math.floor(Date.now() / 1000); // Unix time
  res.set("Deprecation", `@${deprecationDate}`);
  res.json({ message: "This endpoint is deprecated." });
});

app.listen(3000, () => console.log("Server running on port 3000"));

Python with Flask

python
from flask import Flask, make_response
from datetime import datetime

app = Flask(__name__)

@app.route('/v1/old-endpoint')
def old_endpoint():
    response = make_response({'message': 'This endpoint is deprecated.'})
    deprecation_date = int(datetime(2023, 10, 11, 23, 59, 59).timestamp())
    response.headers['Deprecation'] = deprecation_date
    return response

if __name__ == '__main__':
    app.run(port=3000)

Java with Spring Boot

Javajava

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.temporal.*;

@RestController
public class ApiController {

    @GetMapping("/v1/old-endpoint")
    public ResponseEntity<String> oldEndpoint() {
        String deprecationDate = Instant.now().getEpochSecond()
        return ResponseEntity.ok()
                .header("Deprecation", deprecationDate)
                .body("This endpoint is deprecated.");
    }
}

Go with net/http

Gogo
package main

import (
    "fmt"
    "net/http"
    "time"
)

func oldEndpoint(w http.ResponseWriter, r *http.Request) {
    deprecationDate := time.Now().Unix()
    w.Header().Set("Deprecation", deprecationDate)
    w.Header().Set("Sunset", "Wed, 11 Nov 2023 23:59:59 GMT")
    fmt.Fprintln(w, `{"message": "This endpoint is deprecated."}`)
}

func main() {
    http.HandleFunc("/v1/old-endpoint", oldEndpoint)
    http.ListenAndServe(":3000", nil)
}

PHP with Laravel

PHPphp
<?php

use Illuminate\Support\Facades\Route;

Route::get('/v1/old-endpoint', function () {
    $deprecationDate = time();
    return response()->json(['message' => 'This endpoint is deprecated.'])
        ->header('Deprecation', $deprecationDate);
});

Parsing the Deprecation Header Client Side

There's no use in sending the header if you don't use it client-side. Here's a simple javascript example:

TypeScripttypescript
fetch("/v1/old-endpoint")
  .then((response) => {
    const deprecationHeader = response.headers.get("Deprecation");
    if (deprecationHeader) {
      const deprecationDate = new Date(parseInt(deprecationHeader) * 1000);
      console.warn(
        `This API was deprecated on ${deprecationDate.toUTCString()}`,
      );
    }
    return response.json();
  })
  .then((data) => {
    console.log(data);
  });

Implementing the HTTP Deprecation Header with Zuplo

You can add Deprecation headers in your application code (as in the examples above), or by using an API Gateway such as Zuplo.

Doing it at the gateway often works better: deprecation stays in one place instead of scattered across services, you can change dates or add a Sunset or Link header without a backend redeploy, and it works the same whether your backend is Node, Go, or something else.

If your API runs behind Zuplo, you can add these headers on the outgoing response using the Set Headers (outbound) policy on any route that serves a deprecated endpoint.

  1. In the Zuplo dashboard, open your project and go to Policies.
  2. Add a new policy of type Set Headers (outbound), i.e. set-headers-outbound.
  3. Configure the headers you want on the response. The policy takes an array of name/value pairs:
JSONjson
{
  "name": "deprecation-headers",
  "policyType": "set-headers-outbound",
  "handler": {
    "export": "SetHeadersOutboundPolicy",
    "module": "$import(@zuplo/runtime)",
    "options": {
      "headers": [
        { "name": "Deprecation", "value": "@1688169599" },
        { "name": "Sunset", "value": "Sun, 30 Jun 2024 23:59:59 GMT" },
        {
          "name": "Link",
          "value": "<https://developer.example.com/deprecation>; rel=\"deprecation\"; type=\"text/html\""
        }
      ]
    }
  }
}
  1. Attach this policy to the route(s) for your deprecated endpoint. Every response from that route will then include these headers. You can use different policies per route if deprecation dates or links vary.

This keeps deprecation in one place (the gateway), works with any backend language, and makes it easy to add or remove deprecation without redeploying your service. For full lifecycle support, including brownouts and sunset windows, combine this with Zuplo’s Brown Out policy and our guide on sunsetting APIs.

HTTP Deprecation Policy

Set Deprecation, Sunset, and Link headers on outgoing responses following the IETF HTTP Deprecation Header standard. No backend changes required.

Try It Yourself

Try it yourself

HTTP Deprecation Example

A complete working example that adds Deprecation, Sunset, and Link headers to API responses. Deploy directly to your Zuplo account or run locally.

Deploy

Alternatives to the HTTP Deprecation Header

There are only a handful of alternatives in terms of runtime indication of deprecation status.

Legacy: Using the HTTP Warning Header

The HTTP Warning header is a general-purpose header that carries additional information about the status or transformation of a message. It's primarily used to warn clients about potential issues that might not be reflected in the status code.

The Warning header uses a three-digit warning code, an optional agent (usually the hostname), and a warning text enclosed in double quotes. The 299 warning code is ideal for indicating deprecation because it's a persistent warning that can convey any miscellaneous message.

YAMLyaml
Warning: 299 - "Deprecated API: This endpoint is deprecated and will be removed on 2023-11-11."

Some companies like UKG have documented this pattern but these APIs likely predate the introduction of the deprecation header.

Pros and Cons of Using the Warning Header

Pros

  • Standardized Format: The Warning header is part of the HTTP specification.
  • Client Awareness: Many HTTP clients and browsers are designed to handle Warning headers.
  • Flexibility: Allows for detailed messages about the deprecation.

Cons

  • Less Specific: Not specifically designed for deprecation notices.
  • Possible Misinterpretation: Clients might associate warnings with caching issues rather than deprecation.

I'd recommend that you steer clear of using the warning header and reserve it for actual runtime issues. Recall the deprecated APIs are still supposed to be functional until sunset. Now how would you report an actual issue if the warning header is being occupied by a deprecation message?

Unorthodox: Use the JSON Response Body

Depending on the format of your API response, you can include additional properties that are parsed at runtime.

JSONjson
{
  "deprecated": 1688169599,
  "sunset": "2023-11-11T23:59:59Z",
  "data": {...}
}

I suppose the only benefit is that developers are more likely to look at response bodies than they are at headers - but its impossible for API client tooling to adopt this pattern, which is a bad tradeoff. Additionally, how would you deprecate an API that doesn't return JSON? Don't try this in prod, kids.

The Deprecation Header is Just the Start

Although the HTTP deprecation header is helpful in the process of deprecating an API—there's a lot more you need to know. The deprecation header is one part of a full lifecycle: planning, communicating, brownouts, and sunset. The following resources will help you run that process well.

Deprecating REST APIs

A full guide to deprecating REST APIs: planning timelines, communicating with consumers, brownouts, and sunset.

Deprecation lifecycleCommunication strategiesSunset and brownouts
Tags:#API Best Practices#API Lifecycle Management#Tutorial

Related Articles

Continue learning from the Zuplo Learning Center.

API Key Authentication

How to Implement API Key Authentication: A Complete Guide

Learn how to implement API key authentication from scratch — generation, secure storage, validation, rotation, and per-key rate limiting with practical code examples.

API Documentation

Developer Portal Comparison: Customization, Documentation, and Self-Service

Compare developer portal platforms — Zuplo/Zudoku, ReadMe, Redocly, Stoplight, and SwaggerHub — across customization, auto-generated docs, self-service API keys, and theming.

On this page

Benefits of Implementing the Deprecation HeaderOther Deprecation Header FormatsExtending the HTTP Deprecation HeaderImplementing the HTTP Deprecation HeaderImplementing the HTTP Deprecation Header with ZuploTry It YourselfAlternatives to the HTTP Deprecation HeaderThe Deprecation Header is Just the Start

Scale your APIs with
confidence.

Start for free or book a demo with our team.
Book a demoStart for Free
SOC 2 TYPE 2High Performer Spring 2025Momentum Leader Spring 2025Best Estimated ROI Spring 2025Easiest To Use Spring 2025Fastest Implementation Spring 2025

Get Updates From Zuplo

Zuplo logo
© 2026 zuplo. All rights reserved.
Products & Features
API ManagementAI GatewayMCP ServersMCP GatewayDeveloper PortalRate LimitingOpenAPI NativeGitOpsProgrammableAPI Key ManagementMulti-cloudAPI GovernanceMonetizationSelf-Serve DevX
Developers
DocumentationBlogLearning CenterCommunityChangelogIntegrations
Product
PricingSupportSign InCustomer Stories
Company
About UsMedia KitCareersStatusTrust & Compliance
Privacy PolicySecurity PoliciesTerms of ServiceTrust & Compliance
Docs
Pricing
Sign Up
Login
ContactBook a demoFAQ
Zuplo logo
DocsPricingSign Up
Login