---
title: "List a site's pages"
method: GET
path: "/api/v1/sites/{slug}/pages"
tags: ["Pages"]
---

# List a site's pages

`GET /api/v1/sites/{slug}/pages`

## Request

- Base URL: `https://api.dotsy.ai`
- URL: `https://api.dotsy.ai/api/v1/sites/{slug}/pages`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

One row per page, with its URL, layout, title, what it places (sections, menus, listings) and whether it has staged changes. A route that stands for many pages (a collection) appears as one row with a `pattern`. The rows come from an index, so no page bodies are read. Filter with `q` (path or title), `layout` or `noLayout`, `flag` (single chip), and page with `limit` and `cursor`. Pass `group=layout` for layout-key group order and `pv3.` cursors (default order keeps `pv2.`).

## Path parameters

- `slug` string, required

## Query parameters

- `limit` integer
- `cursor` string
- `q` string
- `layout` string
- `noLayout` boolean
- `flag` 'changes' | 'unpublished' | 'hidden' | 'test' | 'norule'
- `group` 'layout'
- `pagesLimit` integer
- `pagesCursor` string
- `pagesQ` string

## Response `200`

One page of rows.

- PagesList
  - `routes` PageRow[], required
    - `path` string, required: The URL path. For a page with no route, the path its file name serves.
    - `contentKey` string, nullable, required
    - `layout` string, nullable, required: The layout's file key.
    - `title` string, nullable, required: The route title, else the page's `<title>`.
    - `parts` PagePart[], nullable, required: What the page places (sections, menus, listings). `null` until the page is indexed.
      - `kind` 'section' | 'menu' | 'list' | 'slot' | 'chrome', required: `section`: a shared fragment. `menu`: a navigation block. `list`: a collection listing. `slot`: where the page body goes. `chrome`: the page's own header or footer.
      - `name` string
      - `dynamic` true
    - `ownChrome` boolean, nullable, required: The page carries its own header or footer. `null` until indexed.
    - `noindex` boolean, required
    - `experiment` boolean, required: The page has a draft or running A/B test.
    - `hasChanges` boolean, required: The page has a staged change.
    - `published` boolean, required: False for a page that was never published.
    - `pattern` object: A dynamic route that stands for several pages.
      - `count` integer, required
      - `collection` string, nullable, required
    - `noRoute` true: The page exists as a file but no route points at it.
  - `nextCursor` string, nullable, required: Pass as `cursor` (with the same `limit`) for the next page; null on the last page.
  - `routesListTotal` integer, nullable, required: Rows that match the filter. `null` when the list is a partial window.
  - `partial` boolean, required: True when the list is a window of the site rather than all of it.
  - `indexing` object, required
    - `pending` integer, required: Pages whose structure is not indexed yet.
    - `running` boolean, required: Indexing is still running.

## Other responses

- `400`: The `cursor` or a filter is not valid (`invalid_cursor`, `invalid_params`).
- `401`: Missing or invalid credentials.
- `403`: The key or token cannot read this site.
- `404`: No such site (`site_not_found`).
- `409`: The site's storage is not ready yet (`backend_not_ready`). Retry shortly.
- `503`: The page index could not be read (`outline_unavailable`). Retry shortly.

---

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