---
title: "List opportunities"
method: GET
path: "/opportunities"
tags: ["Opportunities"]
---

# List opportunities

`GET /opportunities`

## Request

- Base URL: `https://next.frase.io/api/v1`
- URL: `https://next.frase.io/api/v1/opportunities`
- Auth: one of:
  - API key in header `X-API-KEY`
  - HTTP bearer

Unified opportunity list across gap, programmatic and decay sources. By default the response EXCLUDES dismissed, completed and auto_resolved opportunities; pass ?status= to request a specific status explicitly. The default response also EXCLUDES rows judged off-strategy (no cluster fit and no evidence tying the topic to your site); pass ?include_off_strategy=true to see them - each row's `relevance` field carries the bucket and reason. `auto_resolved` means a scan found the site already covers the topic — it is distinct from `dismissed` (a user signal) and `completed` (published from the row). An unrecognized status returns 400 rather than being ignored.

## Query parameters

- `page` integer
- `page_size` integer
- `site_id` string, uuid
- `view` 'all' | 'quick-wins' | 'growth' | 'strategic'
- `source` 'all' | 'gsc' | 'competitor' | 'programmatic' | 'decay'
- `status` 'new' | 'reviewed' | 'in_progress' | 'completed' | 'dismissed' | 'auto_resolved'
- `include_off_strategy` 'true' | 'false'

## Response `200`

Opportunities

- object
  - `data` object[]
    - `id` string
    - `title` string
    - `description` string, nullable
    - `source` 'gsc' | 'competitor' | 'programmatic' | 'decay'
    - `action` 'update' | 'create' | 'batch'
    - `view` 'quick-wins' | 'growth' | 'strategic'
    - `scores` object
      - `overall` number
      - `effort` object
      - `impact` object
      - `speed` object
      - `strategic` object
    - `confidence` 'high' | 'medium' | 'low'
    - `relevance` object, nullable: How far this topic travels. off_strategy rows appear only when include_off_strategy=true; uncertain rows are listed but demoted and never auto-publish.
      - `bucket` 'confident' | 'uncertain' | 'off_strategy'
      - `reason` string
    - `estimated_traffic` integer, nullable
    - `search_volume` integer, nullable
    - `current_position` number, nullable
    - `difficulty` integer, nullable
    - `page_count` integer, nullable
    - `programmatic_type` string, nullable
    - `site_id` string, nullable
    - `site_domain` string, nullable
    - `existing_content_id` string, nullable
    - `existing_content_title` string, nullable
    - `cluster_id` string, nullable
    - `cluster_name` string, nullable
    - `competitors` object[], nullable
      - `domain` string
      - `position` integer, nullable
      - `url` string, nullable
    - `status` 'new' | 'reviewed' | 'in_progress' | 'completed' | 'dismissed' | 'auto_resolved' | 'unknown': `unknown` is a read-time value for a DB string outside the known set; no row is created with it.
    - `detected_at` string, date-time
    - `last_analyzed_at` string, date-time
  - `pagination` object
    - `page` integer
    - `page_size` integer
    - `total` integer
    - `has_more` boolean

## Other responses

- `400`: Invalid query parameter

---

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