---
title: "How to Deprecate a REST API: The Complete Developer's Guide"
description: "API Deprecation is the process of signaling to developers that an API, or a part of it (ex. endpoint or field), is scheduled to be discontinued or replaced."
canonicalUrl: "https://zuplo.com/learning-center/deprecating-rest-apis"
pageType: "learning-center"
authors: "adrian"
tags: "API Best Practices, API Lifecycle Management, Tutorial"
image: "https://zuplo.com/og?text=How%20to%20Deprecate%20a%20REST%20API%3A%20The%20Complete%20Developer%27s%20Guide"
---
All good things eventually come to an end - and sometimes bad things like our
abhorrent API design choices do too. Unfortunately for us API devs, you can't
always delete your old endpoint and start over - you need to have a deprecation
strategy in place so your API consumers aren't caught unaware.

API deprecation signals to developers that an endpoint or version is being
retired. Here's how to plan, communicate, and execute a deprecation without
breaking your consumers. Most other articles just cover concepts - but we'll get
our hands dirty with code to show you how to deprecate your APIs.

## What Does It Mean to Deprecate an API

Deprecating an API refers to the process of signaling to developers that a
particular API, or a part of it (like an endpoint or field), is scheduled to be
discontinued or replaced. Deprecation is a formal way to communicate that while
the API is still functional, it should no longer be used, and alternative
solutions should be adopted. Unless the API is being totally phased out, the API
provider will have a new version of the API ready to be adopted. Check out our
[article on API versioning](/learning-center/how-to-version-an-api) to learn
more.

## Why You Should Deprecate an API

Deprecating APIs is essential for maintaining a clean, efficient, and secure
system. It's a key part of your broader
[API lifecycle strategy](/learning-center/api-lifecycle-strategies). Here are
some reasons why you might deprecate an API:

- **Security Enhancements**: Older APIs may have vulnerabilities that are
  addressed in newer versions.
- **Performance Improvements**: Newer APIs might offer better performance.
- **Feature Upgrades**: Introducing new features that aren't compatible with
  older versions.
- **Maintenance Overhead**: Reducing the burden of supporting outdated APIs.
- **Regulatory Compliance**: Ensuring APIs meet current legal and compliance
  standards.

## Phases of API Deprecation

Before we can get into the process of actually deprecating an API, here's a
quick overview of phases of API deprecation - just so we are clear on
terminology going forward.

![Phases of API Deprecation](/media/posts/2024-10-24-deprecating-rest-apis/image-3.png)

API deprecation typically follows the following timeline:

1. **Deprecation Planning**: The API is still being actively used, but for the
   reasons outlined above, you've decided to decommission it.
2. **Deprecation Announcement**: The API's deprecation date has been announced,
   both through a deprecation notice provided to users and through the API
   itself (more on this later). The period between this announcement and the
   deprecation date is a grace period in which users can start migrating to one
   of the provided alternative options.
3. **Deprecation Day**: The day has finally arrived to deprecate the API.
   Crucially, the API must remain functional to allow time for users to migrate.
   This is also a good time to reach out to users again and let them know the
   sunset date.
4. **Sunset Day**: You've hopefully migrated the last of your users away from
   the deprecated API at this point. You can begin deletion of the old API. It's
   usually good practice to leave behind the API documentation (users might have
   it bookmarked), but update it to reflect the sunset status.

### Key Terms

- **Deprecation Notice**: A warning provided to users about the upcoming
  discontinuation.
- **Grace Period**: A timeframe during which the deprecated API remains
  operational before being retired.
- **Alternative Options**: Information about newer versions or other APIs that
  should be used instead.

### Deprecation vs. Sunsetting an API

While often used interchangeably, deprecation and
[sunsetting](./2025-08-17-how-to-sunset-an-api.md) (aka decommissioning or
retiring) an API are distinct phases in an API's lifecycle.

- **Deprecation**: The period where users are warned that an API will be
  discontinued in the future. The API remains functional but is no longer
  recommended for use.
- **Sunsetting**: The point at which the API is no longer available. Users must
  have migrated to newer versions or alternatives.

## Technical Considerations for Deprecating an API

When deprecating an API (and planning the replacement), consider the following
technical aspects:

- **Monitoring Usage**: Track how often the API you want to deprecate is used to
  gauge the impact of deprecation.
- **Versioning Strategy**: Implement a
  [versioning strategy](/learning-center/how-to-version-an-api) to make the
  transition smoother..
- **Backwards Compatibility**: Make it easy to migrate from the old endpoint to
  the new one. A radically different API will make users reluctant to migrate,
  and harder for you to sunset the API. See our guide on
  [API versioning and backward compatibility best practices](/learning-center/api-versioning-backward-compatibility-best-practices)
  for more on this topic.
- **Documentation Updates**: Keep all API documentation up-to-date with
  deprecation notices. The best place to typically do this is within your
  OpenAPI document (see how below).

## Types of API Deprecation

Deprecation doesn't always refer to an entire API - in fact you can actually
deprecate endpoints and even features of endpoints. This avoids having to create
an entirely new version of your API -
[moving clients off old versions of your API](/learning-center/how-to-get-clients-to-move-off-old-version-of-api)
can be quite challenging. Note that you will likely follow the same steps as
above, but potentially less rigorously (ex. deprecating a parameter might be
announced in a general patch note).

Given the prevalence of OpenAPI, and its use in API documentation platforms -
here are examples of how to perform different types of deprecations, which most
OpenAPI tooling should handle. One unfortunate missing feature in OpenAPI 3.1 is
that there isn't a formal way to guide users to the latest version of your API -
despite a spec
[being proposed years ago](https://github.com/OAI/OpenAPI-Specification/issues/782),
so we'll have to hack that into the description.

### How to Deprecate an API Endpoint

Deprecating an API endpoint involves updating your API documentation and
specifications to indicate the deprecation.

```yaml
paths:
  /v1/old-endpoint:
    get:
      deprecated: true
      summary: "Deprecated endpoint for retrieving user data"
      description:
        "This endpoint is deprecated and will be removed on YYYY-MM-DD. Use
        /v2/new-endpoint instead."
      responses:
        "200":
          description: Successful response
```

1. **Set `deprecated: true`**: This signals that the endpoint is deprecated.
2. **Update `summary` and `description`**: Include a clear message about the
   deprecation and alternatives.
3. **Provide a Timeline**: You can use and document the `deprecation` header

### How to Deprecate an Entire API Version

I don't believe there is a canonical way of marking an entire API version as
being deprecated in OpenAPI - so I'll just make one up.

```yaml
openapi: 3.0.0
info:
  version: "1.0.0"
  title: "Deprecated API Version"
  description:
    "Version 1.0.0 is deprecated and will be retired on YYYY-MM-DD. Please
    upgrade to version 2.0.0."
  x-deprecated: "2023-11-11T23:59:59Z"
paths:
  /v1/endpoint:
    get:
      summary: "Endpoint in deprecated API version"
      responses:
        "200":
          description: Successful response
```

1. **Add `x-deprecated: <Date>` in the `info` section**: Custom extension to
   indicate the date the API will be deprecated. This can be useful for API
   client generators to take advantage of to warn users.
2. **Update `description`**: Clearly state the deprecation status and guide
   users to the new version.

### How to Deprecate an API Field

Sometimes, only a specific field within an API response or request needs to be
deprecated.

```yaml
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: string
        username:
          type: string
        fullName:
          type: string
          deprecated: true
          description:
            "This field is deprecated and will be removed on YYYY-MM-DD. Use
            'firstName' and 'lastName' instead."
        firstName:
          type: string
        lastName:
          type: string
```

1. **Set `deprecated: true` on the field**: Indicates that the field should no
   longer be used.
2. **Update Field Description**: Provide details about the deprecation and
   alternatives.
3. **Maintain Backward Compatibility**: Keep the field operational during the
   deprecation period.

## The HTTP Deprecation Header

The [HTTP `Deprecation` header](/learning-center/http-deprecation-header) is
used to inform clients that a resource is deprecated. We have a
[full guide](/learning-center/http-deprecation-header) to this header, but
here's a quick overview:

### How It Works

According to the recently released
[RFC 9745](https://datatracker.ietf.org/doc/html/rfc9745), the field should be
an [RFC 9651 Date](https://datatracker.ietf.org/doc/html/rfc9651#name-dates),
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:

```yaml
Deprecation: @1688169599
```

In addition to updating your docs via OpenAPI - the deprecation header provides
a runtime warning to consumers of your API. This can be more useful than
updating your OpenAPI given that API consumers usually don't check your docs
after they are done integrating.

Implementation is also pretty straight-forward:

```javascript
const express = require("express");
const app = express();

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

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

## Framework Support for API Deprecation

Many API frameworks have some support for API deprecation - typically only
covering deprecating individual endpoints. Given that many frameworks generate
OpenAPI specs for you, they often provide annotations that hook into the
generated spec.

### Fastify (Javascript/Typescript)

There are many API frameworks for JS/TS, but Fastify is one of our favorites.
Fastify allows you to set custom metadata for routes, and when combined with the
fastify-swagger plugin, you can mark routes as deprecated in your OpenAPI
documentation.

```typescript
const fastify = require("fastify")();
fastify.register(require("@fastify/swagger"), {
  exposeRoute: true,
  routePrefix: "/documentation",
  swagger: {
    info: {
      title: "API Documentation",
      version: "1.0.0",
    },
  },
});

fastify.get(
  "/v1/old-endpoint",
  {
    schema: {
      deprecated: true,
      summary: "Deprecated endpoint",
      description:
        "This endpoint is deprecated and will be removed in the future.",
      response: {
        200: {
          type: "object",
          properties: {
            message: { type: "string" },
          },
        },
      },
    },
  },
  async (request, reply) => {
    reply.header("Deprecation", `@${Math.floor(Date.now() / 1000)}`);
    return { message: "This endpoint is deprecated." };
  },
);

fastify.listen(3000, (err) => {
  if (err) throw err;
  console.log("Server running on port 3000");
});
```

If you'd like to see more Node framework examples - check out
[6 more framework examples](/learning-center/deprecate-node-rest-api) we
created.

### Spring (Java)

Spring Framework recognizes the `@Deprecated` annotation at the method or class
level. When combined with Swagger integration tools like Springfox or SpringDoc,
deprecated APIs are automatically documented as such.

```java
@RestController
public class UserController {

    @Deprecated
    @GetMapping("/v1/old-endpoint")
    public ResponseEntity<String> oldEndpoint() {
        return ResponseEntity.ok("This endpoint is deprecated.");
    }

    @GetMapping("/v2/new-endpoint")
    public ResponseEntity<String> newEndpoint() {
        return ResponseEntity.ok("This is the new endpoint.");
    }
}
```

### .Net

Use the `[Obsolete]` attribute to mark controllers or action methods as
deprecated. Tools like Swashbuckle (for OpenAPI integration) recognize this
attribute and update the API documentation accordingly.

```csharp
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    [Obsolete("This endpoint is deprecated. Use GET /v2/some-endpoint instead.", false)]
    [HttpGet("v1/some-endpoint")]
    public IActionResult OldEndpoint()
    {
        return Ok("This endpoint is deprecated.");
    }

    [HttpGet("v2/some-endpoint")]
    public IActionResult NewEndpoint()
    {
        return Ok("This is the new endpoint.");
    }
}
```

### Django Rest Framework (Python)

DRF supports deprecation through third-party packages like drf-yasg for Swagger
documentation, which recognizes the deprecated parameter.

```python
from rest_framework.decorators import api_view
from rest_framework.response import Response
from drf_yasg.utils import swagger_auto_schema

@swagger_auto_schema(method='get', deprecated=True)
@api_view(['GET'])
def old_endpoint(request):
    return Response({'message': 'This endpoint is deprecated.'})
```

## What if I Use an API Management Tool?

If you're using an API management tool or a managed API gateway - then the
platform likely includes some sort of deprecation functionality. Here's some
common tools and how to deprecate an API with them

### Deprecate a Zuplo API

Zuplo is natively powered by OpenAPI and is also fully-programmable using
Typescript. That means the OpenAPI deprecation examples and deprecation header
implementation from above are fully compatible with Zuplo! Your auto-generated
[developer portal](https://zuplo.com/features/developer-portal) will be
automatically updated to reflect the deprecation.

### Deprecate a Kong API

Kong supports adding custom headers through plugins.

```yaml
plugins:
  - name: response-transformer
    config:
      add:
        headers:
          - "Deprecation: @1688169599"
```

### Deprecate an Apigee API

Apigee allows you to set headers via policies. I apologize in advance for the
XML.

```xml
<AssignMessage async="false" continueOnError="false" enabled="true" name="AddDeprecationHeader">
    <Add>
        <Headers>
            <Header name="Deprecation">@1688169599</Header>
        </Headers>
    </Add>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>
```

## Examples of Successful API Deprecations

### Twitter API v1 to v2 Transition

Twitter successfully deprecated its v1 API in favor of v2, providing extensive
documentation, developer support, and a long deprecation timeline to allow
developers to transition smoothly.

**Key Strategies:**

- **Comprehensive Communication**: Regular updates via blogs, emails, and
  developer forums.
- **Extended Support Period**: Provided ample time for developers to migrate.
- **Robust Documentation**: Detailed guides and tutorials for the new API.

## Lessons from API Deprecation Failures

### Google Reader API Shutdown

When Google retired the Google Reader service, many applications relying on its
API were left without alternatives, leading to significant disruption.

**What Went Wrong:**

- **Short Notice**: The deprecation and shutdown happened rapidly.
- **Lack of Alternatives**: No direct replacement or migration path provided.
- **Insufficient Communication**: Users and developers felt blindsided by the
  decision.

**Takeaways:**

- **Provide Adequate Time**: Always give users sufficient time to adapt.
- **Offer Alternatives**: Guide users to other services or APIs.
- **Maintain Open Communication**: Keep the developer community informed at
  every step.

## Your API Deprecation Action Plan

API deprecation is an inevitable part of evolving software services. Before you
pull the trigger, work through this checklist:

1. **Monitor usage** to understand how many consumers will be affected
2. **Set a timeline** with clear deprecation and sunset dates
3. **Update your OpenAPI spec** with `deprecated: true` on affected endpoints,
   versions, or fields
4. **Add the HTTP Deprecation header** to provide runtime warnings to consumers
5. **Communicate early and often** via changelogs, emails, and developer portals
6. **Provide migration guides** pointing to replacement endpoints or versions
7. **Maintain documentation** even after sunset, with clear status indicators

If you need to handle unexpected issues during the migration, our guide on
[API changes and rollbacks](/learning-center/api-changes-and-rollbacks) covers
how to recover gracefully.