
# Deprecation usage report

`GET /v1/reports/deprecation-usage` · permission `reports:read`

Shows which of your clients still call operations that are scheduled for removal, so you can migrate them before the sunset date (see the [versioning policy](/docs/policies/versioning)). Calls are counted per UTC day and grouped by deprecation, client and SDK version. When no operation is deprecated, the report is empty.

The environment always comes from the API key; there is no environment parameter. Rows contain no IP address, `User-Agent` or end-user identifier.

## Request

| Parameter | In | Required | Description |
|---|---|---|---|
| `from` | query | no | First day to include, a full date (`YYYY-MM-DD`, UTC). Defaults to `to` minus 30 days. Limited by the report history of your plan (see below). |
| `to` | query | no | Last day to include, a full date (`YYYY-MM-DD`, UTC). Defaults to today. `from` must not be after `to`. |
| `limit` | query | no | Page size, 1 to 100. Default 50. |
| `cursor` | query | no | `next_cursor` of the previous page. Valid only for the environment, `from` and `to` it was issued for. |

Rows are ordered by `deprecation_id`, `client_id`, `sdk_package`, `sdk_version`. Both ends of the range are inclusive. A cursor from a default range (no `from`/`to` sent) stops working when the UTC day changes; send `from` and `to` explicitly when you page.

### Report history by plan

| Plan | History |
|---|---|
| Free | 30 days |
| Startup, Business | 13 months |
| Enterprise | 25 months, capped at 400 days |

The report table keeps 400 days, so no plan reaches further back than 400 days. A `from` older than the allowed history fails with `422 report_range_exceeds_plan`; the earliest allowed date is in the message and in `errors[0].detail` (`earliest_allowed_date=YYYY-MM-DD`).

## Response

`200 OK`. `data` holds the rows on the page; `next_cursor` is `null` on the last page.

| Field | Description |
|---|---|
| `deprecation_id` | Id in the deprecation registry (`dep-YYYY-NN`). |
| `client_id` | `key_…` for a management API key, `app_…` for a management OAuth client, `dashboard` for the dashboard. |
| `sdk_package` | SDK package from the `Idp-Client` header; `other` for a package outside the catalog, `none` when the header is absent. |
| `sdk_version` | SemVer version, or an empty string. |
| `call_count` | Calls in the range. |
| `last_seen_at` | Last call in the range (RFC 3339, UTC). |
| `sunset_at` | Removal date from the deprecation registry (`YYYY-MM-DD`), `null` when unknown. After this day the operation answers `410 endpoint_sunset`. |

```json
{
  "data": [
    {
      "deprecation_id": "dep-2027-01",
      "client_id": "key_01j9xk3m7q8r2s4t6v8w0y2z4d",
      "sdk_package": "keenauth-go",
      "sdk_version": "1.4.0",
      "call_count": 1280,
      "last_seen_at": "2027-03-02T09:30:00Z",
      "sunset_at": "2028-01-17"
    }
  ],
  "next_cursor": null
}
```

### CSV

Send `Accept: text/csv` to receive the same columns as CSV (RFC 4180) with a header row. Text cells that start with `=`, `+`, `-`, `@`, a tab or a carriage return are prefixed with a single quote so that spreadsheets do not run them as formulas. The cursor of the next page is in the `Link` header (`rel="next"`); the range is spelled out in that link.

```text
deprecation_id,client_id,sdk_package,sdk_version,call_count,last_seen_at,sunset_at
dep-2027-01,key_01j9xk3m7q8r2s4t6v8w0y2z4d,keenauth-go,1.4.0,1280,2027-03-02T09:30:00Z,2028-01-17
```

## Notes

Counts are collected per minute and written to the report asynchronously, so the newest calls can take a few minutes to appear. A crash can lose up to 60 seconds of counts. The report is not a billing input.

## Errors

Every error is an `application/problem+json` body with a stable `code`.

| HTTP | `code` | When |
|---|---|---|
| 400 | `invalid_filter` | `from` or `to` is not a `YYYY-MM-DD` date, a date is repeated, or `from` is after `to`. |
| 400 | `invalid_cursor` | The cursor is malformed or was not issued for this environment and range. |
| 422 | `report_range_exceeds_plan` | `from` is older than the report history of your plan. |
| 422 | `validation_failed` | `limit` is out of range or a parameter is repeated. |
| 401 | `unauthenticated` | The API key is missing, invalid or revoked. |
| 403 | `insufficient_permissions` | The key lacks `reports:read`. |
| 429 | `rate_limited` | The rate limit was exceeded; honor `Retry-After`. |
| 503 | `service_unavailable` | The reporting service is temporarily unavailable; retry later. |

## Example

```bash
curl "https://api.eu.keenauth.com/v1/reports/deprecation-usage?from=2027-03-01&to=2027-03-31" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

```bash
keenauth reports deprecation-usage --from 2027-03-01 --to 2027-03-31
keenauth reports deprecation-usage --format csv > deprecation-usage.csv
```
