---
title: "List Tracked Content"
method: POST
path: "/api/v1/content"
tags: ["Content"]
---

# List Tracked Content

`POST /api/v1/content`

Returns paginated tracked content with citation, impression, and response metrics joined for the requested date range. Hidden content (`is_hidden = true`) is excluded.

Pagination uses `page_size + 1` lookahead — `pagination.has_more === true` means the next page exists; there is no total-count field.

Use the `sheet_id`, `content_type`, and standard `filters` knobs to scope the result. Pass an unknown `sheet_id` (or one from another website) and the endpoint returns 403.

## Request body

- ContentListRequest — Request body for listing tracked content.
  - `website_id` string, uuid, required — The website to list tracked content for.
  - `filters` ApiFilters, required — Filters for querying responses and metrics. Pass location filters in the JSON body as `filters.location_ids`.
    - `start_date` string, date-time, required — Filter start date (UTC)
    - `end_date` string, date-time — Filter end date (UTC)
    - `models` string[] — Filter by AI models
    - `prompt_ids` string[] — Filter by specific prompt IDs
    - `competitor_ids` string[] — Filter by specific competitor IDs
    - `location_ids` string[] — Filter by location IDs. Pass this in the JSON body as `filters.location_ids`, even when filtering by a single location. Use IDs returned by `GET /api/v1/locations`.
    - `prompt_status` 'active' | 'paused' — Filter by prompt status
    - `prompt_type` 'branded' | 'non_branded' — Filter by prompt type
  - `content_type` 'external' | 'imported' | 'manual' | 'athena_created' | 'draft' | 'snipe' | 'optimize' | 'slice' — Restrict to a single content type. `manual` is user-authored content created directly in the editor (the Blank Editor flow). `athena_created` is a shortcut for the four Athena-generated subtypes (draft, snipe, optimize, slice). Omit to span every type. This endpoint lists tracked (published) content, so a draft-state row — `manual`, `draft`, `snipe`, `optimize`, or `slice` — appears only after it is published.
  - `sheet_id` string, uuid — Restrict to content on a single Content Hub tab. Use `GET /api/v1/content/sheets` to discover IDs. Omit to span every tab.
  - `mentioned` boolean — If `true`, only count responses that mention your brand. If `false`, only count responses that do not. Omit to count every response.
  - `page_num` integer — Zero-indexed page number.
  - `page_size` integer — Number of items per page (1–100).

## Response `200`

Successful response with the page of tracked content.

- ContentListResponse
  - `content` ContentItem[], required
    - `content_id` string, uuid, required — Unique identifier for the content item. Pass this as `content_id` to `POST /api/v1/content/prompts` to drill into per-prompt citation data.
    - `title` string, nullable, required — Page or post title (nullable for unscraped URLs).
    - `url` string, nullable, required — Canonical URL (display form, may include `www.`).
    - `normalized_url` string, nullable, required — URL after protocol/trailing-slash normalization. Used to join with citation data.
    - `type` string, nullable, required — Content type — one of `external`, `imported`, `draft`, `snipe`, `optimize`, `slice` (or null for legacy rows).
    - `topic_name` string, nullable, required — Topic the content is paired with (if any). 3rd-party content often has no topic.
    - `sheet_id` string, uuid, nullable, required — Content Hub tab the item is pinned to. `null` for content not pinned to any tab.
    - `sheet_name` string, nullable, required — Human-readable name of the tab. `null` when `sheet_id` is null.
    - `citations` number, required — Count of AI responses in the date range that cite this URL.
    - `citation_percent` number, required — Percentage of all responses (in the date range, matching the filters) that cite this URL.
    - `estimated_impressions` number, nullable, required — Estimated impressions attributable to the URL across the date range. May be null when impression modeling is not available for the matched prompts.
    - `total_responses` number, required — Total responses considered for the citation calculation (the denominator behind `citation_percent`).
    - `mark_as_done_time` string, date-time, required — When the content was marked as published / done in Content Hub. Falls back to `created_at` when the row was never marked.
    - `created_at` string, date-time, required — When the content row was created (UTC).
  - `pagination` Pagination, required — Pagination metadata. Uses `page_size + 1` lookahead — `has_more=true` means the next page is non-empty. No total-count field, by design (avoids the extra `COUNT(*)` round-trip).
    - `page_num` integer, required — Zero-indexed page number returned.
    - `page_size` integer, required — Maximum items per page.
    - `has_more` boolean, required — `true` if another page is available.

## Other responses

- `400` — Bad request — invalid parameters.
- `401` — Unauthorized — invalid or missing API key.
- `403` — Forbidden — you don't have access to this website, or a sub-resource ID (`prompt_ids`, `competitor_ids`, `location_ids`, `sheet_id`) belongs to another website.
- `500` — Internal server error.

---

[API](https://skmtc.net/athenahq/apis/athenahq-api.md) · [All operations](https://skmtc.net/athenahq/apis/athenahq-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/athenahq/athenahq-api/revisions/6c5d71622cb9/schema)
