# Upgrades & Downgrades

> Returns analyst rating changes (upgrades, downgrades, initiations).

`GET https://api.bavest.co/v2/estimates/upgrades-downgrades`

Group: Estimates. Route id: `v2_estimates_upgrades_downgrades`. Included in: Startup, Pro, Growth.

## Description

Returns analyst rating changes (upgrades, downgrades, initiations).
Each item is a weekly snapshot that lists every rating action known on
its `date`, so the newest snapshot holds the full history. By default
only the newest snapshot is returned; page back with `offset` or
`cursor`, at most 10 snapshots per request.

## Authentication

Send your API key in the `x-api-key` header on every request. No key yet? Sign up at https://dashboard.bavest.co/sign-up (free trial). The examples read the key from the `BAVEST_API_KEY` environment variable.

## Parameters

| Name | In | Type | Required | Description |
|---|---|---|---|---|
| `symbol` | query | string | one of symbol, isin | Stock ticker symbol (e.g., `AAPL`, `MSFT`, `GOOGL`). Provide exactly one of symbol or isin. Example `AAPL`. |
| `isin` | query | string | one of symbol, isin | ISIN code (e.g., `US0378331005`). Provide exactly one of symbol or isin. Clear the symbol example before using an ISIN. |
| `limit` | query | integer (int32) | no | Number of snapshots to return, newest first (default 1, max 10) Default `1`. |
| `offset` | query | integer (int32) | no | Number of results to skip for pagination (default 0) Default `0`. |
| `cursor` | query | string | no | Opaque cursor for cursor-based pagination. When provided, returns results after the cursor position. Takes precedence over offset. |

Required: one of `symbol`, `isin`.

## Response

200 Successful response (`application/json`).

| Field | Type | Always present | Description |
|---|---|---|---|
| `data` | array of UpgradeDowngradeRecord | no |  |
| `data[].date` | string (date) | yes | Date of the rating change. |
| `data[].symbol` | string | yes | Ticker symbol of the company. Example: `AAPL`. |
| `data[].ratings` | array of object | no | Detailed list of individual rating entries. |
| `data[].ratings[].url` | string \| null | no | URL to the full rating article or report. Null since the switch to the vendor's grade endpoint, which serves no article. Example: `https://www.streetinsider.com/Analyst+Comments/KeyBanc+Sidelined+on+Apple+%28AAPL%29%3A+%27don%27t+see+a+catalyst+with+the+stock+trading+in+line+with+its+historical+valuation%27/26148368.html`. Deprecated. |
| `data[].ratings[].title` | string \| null | no | Headline of the rating report. Null since the switch to the vendor's grade endpoint, which serves no article. Example: `KeyBanc Sidelined on Apple (AAPL): 'don't see a catalyst with the stock trading in line with its historical valuation'`. Deprecated. |
| `data[].ratings[].action` | string | no | Rating action described in this entry. Example: `hold`. |
| `data[].ratings[].newGrade` | string | no | New rating grade assigned. Example: `Sector Weight`. |
| `data[].ratings[].previousGrade` | string \| null | no | Previous rating grade before the change. Example: `Sector Weight`. |
| `data[].ratings[].publishedDate` | string | no | ISO 8601 timestamp when the rating was published. Example: `2026-03-12T09:50:00.000Z`. |
| `data[].ratings[].gradingCompany` | string | no | Name of the firm that issued the rating. Example: `KeyBanc`. |
| `data[].ratings[].priceWhenPosted` | number \| null | no | Stock price when the rating was published. Null since the switch to the vendor's grade endpoint, which serves no price. Example: `260.81`. Deprecated. |
| `meta` | ResponseMeta | no | Response metadata for paginated endpoints. Offset pagination returns `page`/`pageSize`/`totalPages`/`totalCount`; cursor pagination returns `pageSize`/`hasMore`/`nextCursor` and `totalCount` only when known. |
| `meta.time` | integer | no | Server-side processing time in milliseconds. Example: `17`. |
| `meta.parameters` | object | no | Echo of the request parameters the endpoint resolved. |
| `meta.page` | integer | no | Current page number (offset pagination) Example: `1`. |
| `meta.pageSize` | integer | no | Number of results per page. Example: `50`. |
| `meta.totalPages` | integer | no | Total number of pages (offset pagination) Example: `2`. |
| `meta.totalCount` | integer | no | Total number of results across all pages. Example: `100`. |
| `meta.hasMore` | boolean | no | Whether more results follow (cursor pagination) |
| `meta.nextCursor` | string \| null | no | Cursor for the next page (cursor pagination), null on the last page. |

## Example request

```bash
curl 'https://api.bavest.co/v2/estimates/upgrades-downgrades?symbol=AAPL' \
  -H "x-api-key: $BAVEST_API_KEY"
```

## Example response

```json
{
  "data": [
    {
      "date": "2026-09-27",
      "symbol": "AAPL",
      "ratings": [
        {
          "url": null,
          "title": null,
          "action": "maintain",
          "newGrade": "Buy",
          "previousGrade": "Buy",
          "publishedDate": "2026-09-23",
          "gradingCompany": "B of A Securities",
          "priceWhenPosted": null
        },
        {
          "url": null,
          "title": null,
          "action": "maintain",
          "newGrade": "Outperform",
          "previousGrade": "Outperform",
          "publishedDate": "2026-09-18",
          "gradingCompany": "Evercore ISI Group",
          "priceWhenPosted": null
        }
      ]
    }
  ],
  "meta": {
    "page": 1,
    "pageSize": 1,
    "totalPages": 29,
    "totalCount": 29,
    "parameters": {
      "limit": "1",
      "symbol": "AAPL"
    },
    "time": 23
  }
}
```

## Errors

| Status | Meaning |
|---|---|
| 400 | Invalid request parameters. Returned when required query parameters are missing, have invalid types, or violate constraints (e.g., providing both symbol and isin when they are mutually exclusive). |
| 401 | Missing or invalid API key. |
| 404 | Resource not found. |
| 429 | Rate limit exceeded. Retry after the `Retry-After` header interval. |
| 500 | An unexpected error occurred on the server. If the issue persists, contact support with the X-Request-Id header value. |
| 502 | Upstream data provider returned an error or is temporarily unavailable. Retry after a short delay. |
| 504 | The request timed out waiting for a response from the upstream data provider. This may occur for complex queries or during peak load. |
| default | An unexpected error occurred on the server. If the issue persists, contact support with the X-Request-Id header value. |

- `403` from the gateway: the API key is invalid or switched off.
- `429` with message `Limit Exceeded`: the monthly quota of the key is used up. With `Too Many Requests`: the key is throttled, or this route is not in the key's plan. Wait for `Retry-After` when it is sent.

## Links

- HTML page: https://dashboard.bavest.co/docs/v2_estimates_upgrades_downgrades
- OpenAPI: https://dashboard.bavest.co/openapi.json (YAML: https://dashboard.bavest.co/openapi.yaml)
- Authentication: https://dashboard.bavest.co/docs/authentication.md
- MCP server for AI agents: https://dashboard.bavest.co/docs/mcp.md
- All routes: https://dashboard.bavest.co/llms.txt
