---
title: "endoflife.ai EOL data source plugin for Grafana"
description: "Query end-of-life dates and EOL Risk Scores for 700+ software products from endoflife.ai, as tables you can use in any Grafana panel."
---

> This is the Markdown version of https://grafana.com/grafana/plugins/endoflifeai-eol-datasource/

# endoflife.ai EOL

- Developer: endoflife.ai
- Version: 1.0.5
- [Change log](https://grafana.com/grafana/plugins/endoflifeai-eol-datasource/changelog.md)

![Example dashboard: risk score, batch stack check, all tracked versions](https://grafana.com/api/plugins/endoflifeai-eol-datasource/versions/1.0.5/images/img/screenshots/dashboard.png)

![Query editor in Explore: Version score, Product versions and Batch query types](https://grafana.com/api/plugins/endoflifeai-eol-datasource/versions/1.0.5/images/img/screenshots/explore.png)

![Data source settings: the API key is required and stored server-side](https://grafana.com/api/plugins/endoflifeai-eol-datasource/versions/1.0.5/images/img/screenshots/config.png)

# endoflife.ai EOL data source for Grafana

Query end-of-life dates and EOL Risk Scores for 700+ software products from [endoflife.ai](https://endoflife.ai/), as tables you can use in any Grafana panel: table, stat, gauge, bar gauge, or as the input to transformations and joins with your own inventory data.

Version 1.0.4. A commercial plugin for distribution through the Grafana Marketplace, licensed under the [End-User Licence Agreement](https://endoflife.ai/grafana-datasource-eula).

## What it does

- Three query types: **Version score**, **Product versions** and **Batch**.
- Every query returns one table-shaped data frame with typed columns (dates as time fields, numbers as numbers), and the same columns for all three types, so a panel can be switched between them.
- Dashboard variables: list every tracked product slug, or the versions of one product.
- Grafana template variables work inside the product, version and batch inputs.
- The API key is stored encrypted by Grafana and added on the server. It never reaches the browser.

## Requirements

- Grafana 12.3 or later.
- Outbound HTTPS from the Grafana server to `api.endoflife.ai`. Requests go through Grafana's data source proxy; browsers do not call the API directly.

## Configure

Connections > Data sources > Add new data source > **endoflife.ai EOL**.

| Setting | Required | Notes                                                                                                                                                                                                                                                                                      |
| ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| API key | Yes      | A key is issued with your Marketplace subscription and carries its request allowance and batch size. A free key, which does not expire, is available at <https://endoflife.ai/api#free-key>. The API answers data requests only with a valid key; without one, queries fail with HTTP 401. |

**Save & test** calls `GET /v1` on the API. With a valid key it reports success, with the API version, your key's tier and its request allowance. The API answers a request with no key, or with a key it does not recognise, as anonymous, and Save & test then reports an authentication error that asks for a valid key. That applies to provisioned data sources too. If the call itself fails, the test shows the HTTP error.

The key is sent as the `X-API-Key` header by the proxy route declared in `plugin.json`.

### Provisioning

The data source can be provisioned from a file. The API key is required. A minimal example:

```yaml
apiVersion: 1
datasources:
  - name: endoflife.ai EOL
    type: endoflifeai-eol-datasource
    access: proxy
    # required: your endoflife.ai API key, stored encrypted by Grafana
    secureJsonData:
      apiKey: ${EOL_API_KEY}
```

Set `EOL_API_KEY` in Grafana's environment. Run Save & test on the provisioned data source to confirm the key is accepted.

## Query types

All three return these columns:

| Column                     | Type    | Meaning                                                                                                                          |
| -------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- |
| product                    | string  | Product slug                                                                                                                     |
| version                    | string  | Release cycle                                                                                                                    |
| status                     | string  | `active`, `warn` (end of life within 180 days), `eol`, `unknown`; `not-tracked` or `error` for a pair that could not be answered |
| eol_date                   | time    | End of life date (midnight UTC). Empty when the vendor publishes no date                                                         |
| days_until_eol             | number  | Set while the date is in the future                                                                                              |
| days_past_eol              | number  | Set once the date has passed                                                                                                     |
| score                      | number  | EOL Risk Score, 0 to 100 (methodology: <https://endoflife.ai/risk-score>)                                                        |
| band                       | string  | Risk band for the score                                                                                                          |
| grade                      | string  | Letter grade for the score                                                                                                       |
| cisa_kev_exposure          | number  | The CISA Known Exploited Vulnerabilities factor of the score                                                                     |
| extended_support_available | boolean | Whether a commercial extended support option exists for the product                                                              |
| extended_support_date      | time    | End of the vendor's own extended or paid phase, where one is published                                                           |
| eol_date_source            | string  | Provenance of the date, for example `vendor-fetched` or `upstream`                                                               |
| eol_date_confidence        | string  | Confidence grade of the date                                                                                                     |
| latest_release             | string  | Latest release in the cycle                                                                                                      |
| release_date               | time    | First release of the cycle                                                                                                       |
| score_card_url             | string  | Link to the score card on endoflife.ai                                                                                           |
| error                      | string  | The API's message for a row that could not be answered                                                                           |

### 1. Version score

Inputs: product slug and version, for example `python` and `3.10`. Calls `GET /v1/score/{product}/{version}`. One row: the version's end-of-life date, days until or past that date, EOL Risk Score with band and grade, the CISA KEV factor, whether extended support exists, and where the date comes from. Leave the version blank to get the product's highest-risk tracked version (`GET /v1/score/{product}`).

A product or version the API does not know gives one row with status `not-tracked`, not a panel error.

### 2. Product versions

Input: product slug, for example `postgresql`. Calls `GET /v1/product/{product}`. One row per tracked version of the product, each with its status, end-of-life date and score.

An unknown product gives an empty table with a warning notice that carries the API's message and its closest slug suggestions.

### 3. Batch

Input: one `product version` pair per line. `product:version` is also accepted, blank lines and lines starting with `#` are skipped, and a line with only a product asks for its highest-risk version.

```
python 3.10
postgresql 13
mysql 8.0
not-a-real-product 1
```

Calls `POST /v1/batch`. The API limits the batch size by tier, so the plugin reads the tier once from `GET /v1`, splits the list into groups of that size and sends at most four requests at a time. Rows come back in input order. A pair the API does not know becomes a row with status `not-tracked`, empty values and the API's message in `error`; it never fails the panel. HTTP-level failures (for example a rate limit answer) are shown as a panel error with the API's message.

Answers are cached in the browser session for five minutes, so a refreshing dashboard does not spend the daily allowance on identical questions.

## Dashboard variables

Add a variable of type Query on this data source:

| Query                                      | Result                              |
| ------------------------------------------ | ----------------------------------- |
| `products` (or blank)                      | Every tracked product slug          |
| `versions(python)` or `versions($product)` | The tracked versions of one product |

## Known limits

- Frontend plugin with a proxy route; there is no backend component, so Grafana alert rules cannot use it yet.
- Package URL (purl) and SBOM lookups offered by the API are not exposed yet.

## Privacy

The plugin sends only product names and versions to `api.endoflife.ai`, plus your API key. It sends no hostnames, no inventory identifiers, no dashboard content and no user information. Requests are made by your Grafana server through its data source proxy.

## Pricing and licence

The plugin is sold through the Grafana Marketplace once it is listed there; the catalog listing shows the current price. Use is governed by the [End-User Licence Agreement](https://endoflife.ai/grafana-datasource-eula). What the plugin sends and stores is described in the [privacy note](https://endoflife.ai/grafana-datasource-privacy).

## Support

Written support by email: <partners@endoflife.ai>. Corrections to lifecycle data are published at <https://endoflife.ai/accuracy>.

## Development

Build and test steps, the API calls behind each query type and sample outputs captured from the live API are in DEVELOPMENT.md, next to this README in the plugin's source code.

Contact: <partners@endoflife.ai>
