---
title: "Export rank history"
method: GET
path: "/projects/{project_id}/exports/rank-history"
tags: ["rank-checks"]
---

# Export rank history

`GET /projects/{project_id}/exports/rank-history`

## Request

- Base URL: `https://eu.bisibility.com/api/v1`
- URL: `https://eu.bisibility.com/api/v1/projects/{project_id}/exports/rank-history`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `/api/auth/oauth2/authorize`, token URL `/api/auth/oauth2/token`, scopes: `api:read`)

Returns paginated JSON or streams CSV.

## Path parameters

- `project_id` string, required: Public project ID; membership and token scope are enforced.

## Query parameters

- `version` '1' | '2'
- `stream` 'observations' | 'attempts'
- `basis` 'observed_at' | 'recorded_at'
- `from` string, date-time
- `to` string, date-time
- `aggregation` 'none'
- `format` 'csv' | 'json'
- `keyword_id` string[]
- `range` '30' | '90' | 'all'
- `granularity` 'daily' | 'weekly'
- `cursor` string
- `limit` integer

## Headers

- `Bisibility-API-Version` 'v1'
- `X-Bisibility-Source` 'sdk' | 'cli' | 'mcp'

## Response `200`

Paginated JSON or complete bounded CSV rank history

- union
  - RankHistoryExportResponse
    - `data` RankHistoryExportRow[], required
      - `checked_at` string, date-time, required
      - `id` string, required
      - `keyword` string, required
      - `keyword_id` string, required
      - `normalization_version` string, nullable
      - `position` integer, nullable, required
      - `previous_position` integer, nullable, required
      - `provider` string, nullable
      - `ranking_url` string, nullable, required
      - `requested_depth` integer, nullable
    - `meta` object, required
      - `next_cursor` string, nullable, required
  - RankHistoryReportResponse
    - `data` RankHistoryReportRecord[], required
      - union
        - object
          - `checked_at` string, date-time, required
          - `check_recorded_at` string, date-time, required
          - `observed_at` string, date-time, nullable, required
          - `recorded_at` string, date-time, required
          - `requested_at` string, date-time, nullable, required
          - `comparison_digest` string, nullable, required
          - `complete_through` integer, nullable, required
          - `completeness` string, required
          - `configured_scope` object, nullable, required
            - `device` string, required
            - `engine` string, required
            - `identity_revision` string, nullable, required
            - `language` string, required
            - `location` string, required
            - `policy_revision` string, nullable, required
            - `rank_scale` string, required
            - `result_kind` string, required
            - `surface` string, required
            - `target_revision` string, nullable, required
          - `effective_scope` object, nullable, required
            - `device` string, required
            - `engine` string, required
            - `identity_revision` string, nullable, required
            - `language` string, required
            - `location` string, required
            - `policy_revision` string, nullable, required
            - `rank_scale` string, required
            - `result_kind` string, required
            - `surface` string, required
            - `target_revision` string, nullable, required
          - `evidence` string, required
          - `expected_url_at_check` string, nullable, required
          - `freshness` string, required
          - `freshness_as_of` string, date-time, required
          - `freshness_reason` string, nullable, required
          - `id` string, required
          - `keyword_id` string, required
          - `keyword` string, required
          - `normalization_version` string, nullable, required
          - `position` number, nullable, required
          - `provider` string, nullable, required
          - `ranking_url` string, nullable, required
          - `reason` string, nullable, required
          - `reported_position` number, nullable, required
          - `requested_depth` integer, nullable, required
          - `normalized_items` object[], required
            - `id` string, required
            - `check_id` string, required
            - `keyword_id` string, required
            - `checked_at` string, date-time, required
            - `check_recorded_at` string, date-time, required
            - `observed_at` string, date-time, nullable, required
            - `recorded_at` string, date-time, required
            - `requested_at` string, date-time, nullable, required
            - `source_observed_at` string, date-time, nullable, required
            - `block_position` integer, nullable, required
            - `business_name` string, nullable, required
            - `cid` string, nullable, required
            - `domain` string, nullable, required
            - `maps_url` string, nullable, required
            - `ordinal` integer, required
            - `place_id` string, nullable, required
            - `position_in_block` integer, nullable, required
            - `rank_absolute` integer, nullable, required
            - `rank_group` integer, nullable, required
            - `rank_scale` string, nullable, required
            - `promotion` string, nullable, required
            - `source_page` integer, nullable, required
            - `source_block_id` string, nullable, required
            - `source_ordinal` integer, nullable, required
            - `result_kind` string, required
            - `title` string, nullable, required
            - `url` string, nullable, required
          - `normalized_item_count` integer, required
        - object
          - `checked_at` string, date-time, required
          - `check_recorded_at` string, date-time, required
          - `observed_at` string, date-time, nullable, required
          - `recorded_at` string, date-time, required
          - `requested_at` string, date-time, nullable, required
          - `deferred_reason` string, nullable, required
          - `error_code` string, nullable, required
          - `finished_at` string, date-time, nullable, required
          - `id` string, required
          - `keyword_id` string, required
          - `keyword` string, required
          - `kind` 'logical_rank_check', required
          - `provider` string, nullable, required
          - `reported_provider_attempt_count` integer, required
          - `started_at` string, date-time, nullable, required
          - `status` string, required
        - object
          - `recorded_at` string, date-time, required
          - `started_at` string, date-time, nullable, required
          - `finished_at` string, date-time, nullable, required
          - `status` string, required
          - `blocked_reason` string, nullable, required
          - `run_id` string, required
          - `rank_check_state` 'not_attached', required
          - `kind` 'rank_check_run_item', required
          - `id` string, required: Opaque retained run-item ID, identical to the run-items API.
          - `keyword_id` string, required
          - `keyword` string, required
          - `not_before` string, date-time, nullable, required
          - `run_status` string, required
          - `run_outcome` string, nullable, required
          - `scope_membership` 'persisted_run_item', required
        - object
          - `recorded_at` string, date-time, required
          - `started_at` string, date-time, nullable, required
          - `finished_at` string, date-time, nullable, required
          - `status` string, required
          - `blocked_reason` string, nullable, required
          - `run_id` string, required
          - `rank_check_state` 'not_attached', required
          - `kind` 'rank_check_run', required
          - `id` string, required
          - `planned_for` string, date-time, nullable, required
          - `launched_at` string, date-time, nullable, required
          - `outcome` string, nullable, required
          - `trigger` string, required
          - `selection_kind` string, required
          - `scope_membership` 'persisted_run_items' | 'project_only', required
          - `counts` object, required
            - `requested` integer, required
            - `total` integer, required
            - `completed` integer, required
            - `failed` integer, required
            - `deferred` integer, required
            - `skipped` integer, required
            - `cancelled` integer, required
    - `meta` object, required
      - `next_cursor` string, nullable, required
      - `report` RankHistoryReportMetadata, required
        - `version` 2, required
        - `aggregation` 'none', required
        - `as_of` string, date-time, required
        - `window` object, required
          - `basis` 'observed_at' | 'recorded_at', required
          - `from` string, date-time, required
          - `to` string, date-time, required
        - `summary_basis` 'current_definition_as_of_registered_baseline', required
        - `definition_version` string, required
        - `metric_id` string, required
        - `selection_digest` string, required
        - `total_count` integer, required
        - `excluded_unknown_time` integer, required
        - `unresolved_membership_count` integer, required: No-check runs omitted from a selected/filtered export because retained keyword membership cannot be proved. Project-only runs remain in full-project exports.
        - `normalized_items` object, required
          - `total_count` integer, required
          - `completeness` 'retained_only', required
          - `is_truncated` false, required
          - `capacity` integer, required
          - `paging` 'observation_pages_only', required
        - `membership` string, required: Explicit membership policy: full project retained history, explicit selected retained history, or current active filtered query.
        - `summary` object, required
          - `comparison` string, required
          - `metric` object, required
            - `metric_id` string, required
            - `definition_version` string, required
            - `as_of` string, date-time, required
            - `value` number, nullable, required
            - `delta` number, nullable, required
            - `counts` object, required
              - …
            - `data_coverage` number, nullable, required
            - `observed_coverage` number, nullable, required
            - `freshness` string, required
            - `freshness_reason` string, nullable, required
            - `imputed_weight_share` number, nullable, required
            - `contributions` object[], required
              - …
            - `exclusions` object[], required
              - …
            - `added` string[], nullable, required
            - `removed` string[], nullable, required
            - `composition_reason` string, nullable, required
            - `weight_provenance` object, required
              - …
            - `included_count` integer, required
            - `eligible_total` integer, required
            - `is_truncated` boolean, required
          - `movement_counts` object, nullable, required
            - `improved` integer, required
            - `declined` integer, required
            - `entered` integer, required
            - `exited` integer, required
            - `first` integer, required
            - `moved` integer, required
            - `re_entered` integer, required
            - `steady` integer, required
            - `unknown` integer, required
          - `retained_history` object, required
            - `checks` integer, required
            - `completeness` 'retained_only', required
            - `targets` integer, required
          - `selection_digest` string, required
          - `time_basis` object, required
            - `as_of` string, date-time, required
            - `baseline` object, nullable, required
              - …
            - `current_not_before` string, date-time, nullable, required
        - `resolutions` object[], required
          - `baseline` object, nullable, required
            - `comparison_digest` string, nullable, required
            - `evidence` string, required
            - `freshness` string, required
            - `freshness_reason` string, nullable, required
            - `id` string, required
            - `normalization_version` string, nullable, required
            - `observed_at` string, date-time, nullable, required
            - `position` number, nullable, required
            - `provider` string, nullable, required
            - `ranking_url` string, nullable, required
            - `reason` string, nullable, required
            - `recorded_at` string, date-time, required
            - `reported_position` number, nullable, required
            - `requested_depth` integer, nullable, required
          - `comparison` string, required
          - `comparison_boundary` object, nullable, required
            - `point` object, nullable, required
              - …
            - `reason` string, required
          - `comparison_window` object, nullable, required
            - `before` string, date-time, required
            - `not_before` string, date-time, nullable, required
          - `comparison_unavailable_reason` string, nullable, required
          - `current` object, nullable, required
            - `comparison_digest` string, nullable, required
            - `evidence` string, required
            - `freshness` string, required
            - `freshness_reason` string, nullable, required
            - `id` string, required
            - `normalization_version` string, nullable, required
            - `observed_at` string, date-time, nullable, required
            - `position` number, nullable, required
            - `provider` string, nullable, required
            - `ranking_url` string, nullable, required
            - `reason` string, nullable, required
            - `recorded_at` string, date-time, required
            - `reported_position` number, nullable, required
            - `requested_depth` integer, nullable, required
          - `event` string, nullable, required
          - `keyword_id` string, required
          - `last_success` object, nullable, required
            - `comparison_digest` string, nullable, required
            - `evidence` string, required
            - `freshness` string, required
            - `freshness_reason` string, nullable, required
            - `id` string, required
            - `normalization_version` string, nullable, required
            - `observed_at` string, date-time, nullable, required
            - `position` number, nullable, required
            - `provider` string, nullable, required
            - `ranking_url` string, nullable, required
            - `reason` string, nullable, required
            - `recorded_at` string, date-time, required
            - `reported_position` number, nullable, required
            - `requested_depth` integer, nullable, required
          - `latest_attempt` object, nullable, required
            - `id` string, required
            - `measurement_recorded_at` string, date-time, required
            - `observed_at` string, date-time, nullable, required
            - `recorded_at` string, date-time, nullable, required
            - `status` string, required
          - `movement` number, nullable, required
          - `current_scope_state` string, required
          - `last_known` object, required
            - `baseline` object, nullable, required
              - …
            - `comparison` string, required
            - `comparison_boundary` object, nullable, required
              - …
            - `comparison_window` object, nullable, required
              - …
            - `comparison_unavailable_reason` string, nullable, required
            - `current` object, nullable, required
              - …
            - `event` string, nullable, required
            - `keyword_id` string, required
            - `last_success` object, nullable, required
              - …
            - `latest_attempt` object, nullable, required
              - …
            - `movement` number, nullable, required

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `409`: Unsupported API version
- `429`: Rate limited

## Changes

- **2026-10-19** `a6e1ec0dec82`: 2 breaking, 7 info
  - added the new path request parameter `project_id`
  - added `subschema #1, subschema #2, subschema #3, subschema #4` to the `anyOf[#/components/schemas/RankHistoryReportResponse]/data/items/` response property `oneOf` list for the response status `200`
  - the endpoint scheme security `AppOAuth` was added to the API
  - media type `application/json` was changed to a more specific media type `application/problem+json` for the response status `400`
  - …5 more

[Operation history](https://skmtc.dev/bisibility/apis/bisibility-public-api/changes/projects/:project_id/exports/rank-history/get.md)

---

[API](https://skmtc.dev/bisibility/apis/bisibility-public-api.md) · [All operations](https://skmtc.dev/bisibility/apis/bisibility-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/bisibility/apis/bisibility-public-api/revisions/a6e1ec0dec82?raw)
