# List recommendations

> List a brand's Action Center recommendations, newest first, with each done one's measurement window and lift.

Source: https://ranqo.ai/docs/api/reference/list-recommendations

```http
GET https://api.ranqo.ai/v1/brands/{brand_id}/recommendations
```

The brand's Action Center recommendations, newest first.

## Path parameters

| Name | Type | Description |
| --- | --- | --- |
| `brand_id` | string | The brand id, from `GET /v1/brands`. |

## Query parameters

Every parameter is optional. A parameter the endpoint does not take is refused with `unknown_parameter`.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `limit` | integer | `50` | Items per page, 1 to 100. |
| `cursor` | string |  | The `next_cursor` of the previous page. |
| `status` | string |  | Only those in this column. One of `suggested`, `in_progress`, `done`, `dismissed`. |

## Response

The response body, as JSON.

| Field | Type | Description |
| --- | --- | --- |
| `data` | array of objects |  |
| `data[].id` | string |  |
| `data[].title` | string |  |
| `data[].description` | string |  |
| `data[].rationale` | string |  |
| `data[].category` | string | What kind of gap it answers, such as `content_gap` or `citation_opportunity`. |
| `data[].action_type` | string or null | `create_content`, `optimize_page`, `fix_technical`, `build_authority` or `outreach`; null on older ones. |
| `data[].priority` | string or null | One of `quick_win`, `strategic`, `moderate`. |
| `data[].impact` | integer | 1-3, low to high. |
| `data[].effort` | integer | 1-3, low to high. |
| `data[].status` | string | The Action Center column it sits in. `done` includes one an Outreach target marked done moved there. One of `suggested`, `in_progress`, `done`, `dismissed`. |
| `data[].steps` | array of objects |  |
| `data[].steps[].text` | string |  |
| `data[].steps[].completed` | boolean |  |
| `data[].expected_outcome` | string or null |  |
| `data[].related_domains` | array of strings |  |
| `data[].related_competitors` | array of strings |  |
| `data[].related_pages` | array of strings |  |
| `data[].created_at` | string | RFC 3339 timestamp in UTC. |
| `data[].started_at` | string or null | RFC 3339 timestamp in UTC. When it first moved to in progress. |
| `data[].done_at` | string or null | RFC 3339 timestamp in UTC. When it last moved to done; null unless done. |
| `data[].measurement` | object or null | Null unless it is done. |
| `data[].measurement.state` | string | `awaiting`: its window is open and nothing is measured yet. `measured`: re-measured at least once. `unmeasurable`: no baseline was recorded, or it was done before measurement windows existed, so the board shows no countdown. One of `awaiting`, `measured`, `unmeasurable`. |
| `data[].measurement.expects_visibility_lift` | boolean | False for technical fixes, which are not expected to move visibility. |
| `data[].measurement.metric` | object or null | What it is measured against: `overall`, `category:<category>` or `platform:<engine>`. |
| `data[].measurement.metric.key` | string |  |
| `data[].measurement.metric.label` | string or null |  |
| `data[].measurement.baseline` | number or null | The metric, 0-100, from the run it was generated from. |
| `data[].measurement.current` | number or null | The metric at the latest re-measure. |
| `data[].measurement.lift` | number or null | `current` minus `baseline`, in points, only when it is larger than `noise_band` either way, as the Action Center shows it; null otherwise. |
| `data[].measurement.noise_band` | number | Points a quiet week moves this metric, measured over real runs. |
| `data[].measurement.measured_at` | string or null | RFC 3339 timestamp in UTC. |
| `data[].measurement.window_opened_at` | string or null | RFC 3339 timestamp in UTC. When its measurement window opened: the first time it moved to done or in review. Null when none opened. |
| `data[].measurement.runs_in_window` | integer or null | Completed runs since its window opened, counted over the brand's latest 60 as the board counts them. Null when no window opened. |
| `data[].measurement.answers` | object or null | The answers inside the metric, compared with generation as of `measured_at`; null until it is re-measured after a run in its window, and on older ones recorded without a per-answer baseline. |
| `data[].measurement.answers.won` | integer | Answers missing the brand at generation that named it in both runs compared. |
| `data[].measurement.answers.provisional` | integer | Answers missing it at generation that named it in the latest run compared only. |
| `data[].measurement.answers.lost` | integer | Answers that named it at generation and missed it in both runs compared. |
| `data[].measurement.answers.held` | integer | Answers that named it at generation and still do. |
| `data[].measurement.answers.runs_compared` | integer | Runs after its window opened that the last re-measure compared, at most two. |
| `data[].measurement.answers.confirmable` | boolean | True once two runs were compared. Until then `won` and `lost` are 0 and every gain is provisional. |
| `has_more` | boolean | Whether another page follows. |
| `next_cursor` | string or null | Pass as `cursor` for the next page; null on the last page. |

## Response headers

| Header | Description |
| --- | --- |
| `X-Request-Id` | The request id; quote it to support. |
| `RateLimit` | Requests left in this window and seconds until it resets. |
| `RateLimit-Policy` | The key's limit per window. |

## Example request

```bash title="curl"
curl "https://api.ranqo.ai/v1/brands/BRAND_ID/recommendations" \
  -H "Authorization: Bearer $RANQO_API_KEY"
```

## Errors

Errors are problem details (`application/problem+json`) with a stable `code`. See [Errors](https://ranqo.ai/docs/api/errors) for each one.

| Status | Codes |
| --- | --- |
| 400 | [`invalid_parameter`](https://ranqo.ai/docs/api/errors#invalid_parameter), [`unknown_parameter`](https://ranqo.ai/docs/api/errors#unknown_parameter), [`invalid_cursor`](https://ranqo.ai/docs/api/errors#invalid_cursor), [`api_key_in_url`](https://ranqo.ai/docs/api/errors#api_key_in_url) |
| 401 | [`missing_api_key`](https://ranqo.ai/docs/api/errors#missing_api_key), [`invalid_api_key`](https://ranqo.ai/docs/api/errors#invalid_api_key), [`api_key_revoked`](https://ranqo.ai/docs/api/errors#api_key_revoked), [`api_key_expired`](https://ranqo.ai/docs/api/errors#api_key_expired), [`api_key_orphaned`](https://ranqo.ai/docs/api/errors#api_key_orphaned) |
| 403 | [`plan_upgrade_required`](https://ranqo.ai/docs/api/errors#plan_upgrade_required), [`subscription_inactive`](https://ranqo.ai/docs/api/errors#subscription_inactive) |
| 404 | [`not_found`](https://ranqo.ai/docs/api/errors#not_found) |
| 429 | [`rate_limited`](https://ranqo.ai/docs/api/errors#rate_limited) |
| 500 | [`internal_error`](https://ranqo.ai/docs/api/errors#internal_error) |
| 503 | [`service_unavailable`](https://ranqo.ai/docs/api/errors#service_unavailable) |
