---
title: "List page opportunities"
method: GET
path: "/api/v1/public/brands/{brandSlug}/page-opportunities/"
tags: ["Public: Opportunities"]
---

# List page opportunities

`GET /api/v1/public/brands/{brandSlug}/page-opportunities/`

## Request

- Base URL: `https://api.iterant.ai`
- URL: `https://api.iterant.ai/api/v1/public/brands/{brandSlug}/page-opportunities/`
- Auth: HTTP bearer

Pages Iterant thinks are worth building or improving, ranked by priority score.

Each row carries a `ref`: a stable, human-readable handle derived from the title. It is what the detail route takes. Refs are not constructible: use one that came back from here.

`status` is the derived display status, which folds in the state of any page the opportunity produced: `ready`/`enriched`/`discovered` are open work, `drafting`/`drafted`/`publishing` are in flight, `published`/`dismissed`/`superseded` are done.

Capped and paginated; the `note` says how to narrow when rows are hidden. Filtering by `status` walks rows, so it stops after the 500 highest-priority opportunities; past that bound `total` is null rather than a count of what happened to fit inside it.

## Path parameters

- `brandSlug` string, required

## Query parameters

- `archetype` 'comparison' | 'standard'
- `intent` 'commercial' | 'informational' | 'navigational' | 'transactional'
- `limit` string
- `offset` string
- `responseFormat` 'concise' | 'detailed'
- `role` 'pillar' | 'spoke' | 'standalone'
- `status` 'backlog' | 'discovered' | 'dismissed' | 'drafted' | 'drafting' | 'enriched' | 'failed_generation' | 'publish_failed' | 'published' | 'publishing' | 'ready' | 'republish_pending' | 'scheduled' | 'superseded'
- `surface` 'dual' | 'geo_primary' | 'seo_primary'

## Response `200`

- PublicPageOpportunityList: The schema for what ``paginated`` builds. Kept beside it deliberately. A list operation whose ``responses`` named the *item* serializer with ``many=True`` published a bare array while the runtime returned this object, so a generated client broke on its first call. Subclasses add ``items``: each operation needs its own named component or the item type is erased.
  - `total` integer, nullable, required: Rows matching the query, before `limit` and `offset`. Null when a `status` filter outran the scan bound and the true count is not knowable. `note` says so.
  - `offset` integer, required: Rows skipped. Echoed back so a caller can page without bookkeeping.
  - `limit` integer, required: Cap actually applied, which may be lower than the one requested.
  - `note` string, required: How to narrow, when the cap hid rows. Empty when the response is the whole answer.
  - `items` PublicPageOpportunitySummary[], required
    - `ref` string, required: Stable, human-readable handle. Pass it back to the opportunity detail route.
    - `id` string, uuid, required
    - `title` string, required
    - `status` string, required: Derived display status, folding in the state of any page the opportunity produced.
    - `intent` string, required
    - `role` string, required
    - `surface` string, required
    - `archetype` string, required
    - `primaryKeyword` string, required
    - `priorityScore` integer, required
    - `searchVolumeMonthly` integer, nullable, required
    - `keywordDifficulty` integer, nullable, required
    - `seoScore` integer, nullable, required
    - `geoScore` integer, nullable, required
    - `resultingUrlPath` string, nullable, required

## Other responses

- `400`
- `401`
- `404`
- `405`
- `406`
- `415`
- `429`
- `500`

---

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