# Get visibility

> Read a brand's visibility, share of voice, position and sentiment over a window, against the one before, by engine or category.

Source: https://ranqo.ai/docs/api/reference/get-visibility

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

The brand's visibility, position, sentiment and share of voice over a window, with the equal window before it, as the Visibility page shows them. Answers that failed are not counted.

## 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 |
| --- | --- | --- | --- |
| `period` | string |  | `7d`, `30d` and `90d` run from midnight in `tz` that many days back to now; `365d` runs from midnight 365 days back to the end of today. Default `30d`. Not with `start_date`. One of `7d`, `30d`, `90d`, `365d`. |
| `start_date` | string |  | First day of a custom window, in `tz`. Send with `end_date`. |
| `end_date` | string |  | Last day of a custom window, in `tz`, included. The window may span at most 366 days, both dates counted. |
| `tz` | string |  | IANA time zone for day boundaries, such as `Asia/Kolkata`. Default `UTC`. |
| `platforms` | string |  | Engines to count: claude, chatgpt, perplexity, gemini, grok, google_aio. |
| `categories` | string |  | Prompt categories to count: discovery, problem_solution, use_case, expert, comparison, brand_research. |
| `locations` | string |  | Prompt locations to count, as stored on the prompt. |
| `theme_ids` | string |  | Theme ids to count; `none` counts prompts with no theme. |
| `is_branded` | string |  | Count only prompts that do, or do not, name the brand. One of `true`, `false`. |
| `group_by` | string |  | Add a breakdown by engine or prompt category. One of `platform`, `category`. |

## Response

The response body, as JSON.

| Field | Type | Description |
| --- | --- | --- |
| `brand_id` | string |  |
| `window` | object | The answers a report counts: those from completed runs inside the window. |
| `window.start` | string | RFC 3339 timestamp in UTC. |
| `window.end` | string | RFC 3339 timestamp in UTC. |
| `window.previous_start` | string | The comparison window runs from here to `start`: the whole days before `start` for `7d`, `30d` and `90d`, the same length as the window otherwise. |
| `window.time_zone` | string |  |
| `window.period` | string or null | The preset, or null for a custom window. One of `7d`, `30d`, `90d`, `365d`. |
| `window.carried_from` | string or null | RFC 3339 timestamp in UTC. Set when the window held no completed run: the figures are the latest run before it, which completed at this time, and nothing is compared. |
| `answer_count` | integer | Answers counted, after filters. |
| `prompt_count` | integer | Distinct prompts behind them. |
| `visibility` | object | Percent of answers naming the brand, 0-100, each engine weighted. |
| `visibility.current` | number or null | Null when there is nothing to measure: no matching answer, or for position and sentiment no answer naming it, or for share of voice no mention of any brand. |
| `visibility.previous` | number or null | Over the comparison window; null when that window has nothing to measure or the figures are carried. |
| `visibility.change` | number or null | `current` minus `previous`, rounded once from the unrounded values as the dashboard shows it; null when either is null. |
| `average_position` | object | Average position when named, 1 = named first; lower is better. The same fields as `visibility`. |
| `sentiment_score` | object | 0-100: positive counts 1, neutral half, negative nothing. The same fields as `visibility`. |
| `share_of_voice` | object | The brand's share of brand mentions in the answers, 0-100. Rivals count when named in more than one answer, named with their website, or watched. The same fields as `visibility`. |
| `position_distribution` | object | Answers by where the brand was named. |
| `position_distribution.first` | integer |  |
| `position_distribution.second` | integer |  |
| `position_distribution.third` | integer |  |
| `position_distribution.fourth_plus` | integer |  |
| `position_distribution.not_named` | integer |  |
| `sentiment_distribution` | object | Answers naming the brand, by tone. |
| `sentiment_distribution.positive` | integer |  |
| `sentiment_distribution.neutral` | integer |  |
| `sentiment_distribution.negative` | integer |  |
| `breakdown` | object or null | Present when `group_by` is sent. |
| `breakdown.group_by` | string | One of `platform`, `category`. |
| `breakdown.rows` | array of objects |  |
| `breakdown.rows[].key` | string | The engine id, or the prompt category (`uncategorized` for none). |
| `breakdown.rows[].answer_count` | integer |  |
| `breakdown.rows[].named_count` | integer | Answers that named the brand. |
| `breakdown.rows[].prompt_count` | integer | Distinct prompts behind those answers. |
| `breakdown.rows[].visibility` | number | Percent of these answers naming the brand, 0-100. A category row weights each engine, as the Visibility page does. |
| `breakdown.rows[].average_position` | number or null | When named; lower is better. Null when never named. |
| `breakdown.rows[].sentiment_score` | number or null | 0-100; null when never named. |

## 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/visibility" \
  -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), [`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) |
