---
title: "List user's guides"
method: GET
path: "/api/v1/guides"
tags: ["v1", "Guide"]
---

# List user's guides

`GET /api/v1/guides`

## Request

- Base URL: `https://app.serpmantics.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.serpmantics.com/api/v1/guides`
- Auth: HTTP bearer

Returns a list of guides for the authenticated user.

Use `query` to check whether a guide already exists before creating one
(creating a duplicate costs credits). Beware of two behaviours of this endpoint:
- `query` and `group` are case-insensitive REGULAR EXPRESSIONS, not exact matches:
  special characters in the value are interpreted as regex syntax, and an invalid
  regex returns no result at all. (`status` is different: a known status is matched
  exactly, any other value falls back to a regex.) Always compare the returned
  `query` and `source` yourself, and fall back to an unfiltered paginated scan
  before concluding that nothing exists;
- `totalCount` does NOT take `query` nor `group` into account (known limitation:
  both are applied as application-level regexes that the count query does not
  know, so it returns 0 as soon as either is used, alone or combined with
  `status`). Filtering on `status` alone does give a correct `totalCount`, since
  it is a real stored field. For an existence check, trust the `guides` actually
  returned; `totalCount` is only reliable for paginating a listing filtered by
  `status` alone, or not filtered at all.

An empty result is returned as a 404 with `success: false` and
`error: "No guides returned"`, not as an empty list.

## Query parameters

- `query` string
- `group` string
- `status` 'draft' | 'active' | 'review' | 'published' | 'archived'

## Response `200`

Successful response with guides

- object
  - `success` boolean
  - `guides` object[]
    - `id` string
    - `query` string
    - `lang` string
    - `source` string: Engine and analysis mode the guide targets, returned as the UPPERCASE database form of the source (e.g. `GOOGLE`, `CHATGPT`, `CHATGPT_CITATIONS`, `GOOGLE_AI_OVERVIEW`, `GOOGLE_AI_OVERVIEW_CITATIONS`). Either the Google SERP (`GOOGLE`), Google's AI answers as `GOOGLE_AI_OVERVIEW` (answer text analysis) or `GOOGLE_AI_OVERVIEW_CITATIONS` (analysis of the cited sources), or an AI engine as `<ENGINE>` (AI answer analysis) or `<ENGINE>_CITATIONS` (analysis of the sources the AI cites)
    - `createdAt` string, date-time
    - `shareState` 'private' | 'shared-read' | 'shared-edit': Sharing mode of the guide. Absent from the item when the guide has never been shared, which is equivalent to `private` (GET /api/v1/guide always returns the effective value, plus the public `shareUrl`). Change it with PUT /api/v1/guide.
    - `expired` boolean: Present and `true` ONLY when the guide is expired (more than 180 days after its creation). Absent otherwise. This listing is the only endpoint that still returns expired guides: reading them (GET /api/v1/guide, score, eeat, outline, meta...) answers 410, but DELETE /api/v1/guide still removes them so you can clean up. Their analysis payload is stripped from the item.
    - `expiresAt` string, date-time: Date at which the guide became unreadable (creation + 180 days). Present only alongside `expired: true`.
    - `progressStatus` GuideProgressStatus: Creation progress of a guide (shared by /guide and /guides). When `step` is `failed`, `generationFailed`, `terminal`, `reason`, `message` and `kind` are set, and `failureFacts` may be (only for sources whose web pages we read).
      - `isReady` boolean: True once the guide is ready to be read
      - `pct` number: Creation progress in percent (0 to 100)
      - `step` 'notStarted' | 'queued' | 'created' | 'serpFetched' | 'pagesCrawled' | 'ready' | 'failed': Current creation step. `queued` (returned by GET /api/v1/guides, and by the 202 of GET /api/v1/guide): the guide has not started and is held because the account is beyond the priority guides of its plan for the current month; held guides start at a rate of one per hour, in creation order. See `estimatedStartAt`.
      - `estimatedStartAt` string, date-time: Only when step is `queued`. Estimated start of the generation (UTC). An estimate, not a promise: the guide then moves to `created` and the usual steps.
      - `upgradeUrl` string: Only when step is `queued`, and only when the "Priority and API volume" add-on can raise this account's monthly volume. Absolute URL where to buy it.
      - `requiresValidation` boolean: Present and true when the guide waits for the user to validate the results to analyse
      - `generationFailed` boolean: Present and true when the creation failed (step `failed`)
      - `terminal` boolean: Only when step is `failed`. True when the failure is definitive (explicit backend flag, or inferred when the failure is older than 15 minutes, see `terminalInferred`). False while the backend may still retry (failure younger than 15 minutes without the explicit flag).
      - `terminalInferred` boolean: Only when step is `failed` and `terminal` is true without the explicit backend flag (failure older than 15 minutes, no retry will happen). Present and true in that case only. The refund status is then given by the `refunded` field of /guide, never promised in `message`.
      - `reason` 'exception-creation' | 'no-serp-results' | 'not-enough-serp-results' | 'not-enough-fetchable-pages' | 'no-top10-fetchable-pages' | 'failed-to-save-serp-results' | 'exception-fetch-serp' | 'exception-fetch-results' | 'exception-fetch-llm-citations' | 'no-citations' | 'unsupported-locale' | 'exception-fetch-llm-content' | 'no-ai-overview-available' | 'exception-fetch-ai-overview' | 'exception-process-corpus' | 'exception-wrap-up' | 'failed-task' | 'relaunch_count_exceeded', nullable: Only when step is `failed`. Raw, stable failure reason slug
      - `message` string: Only when step is `failed`. Human-readable French message, depending on the reason and the source of the guide
      - `kind` 'legitimate' | 'technical': Only when step is `failed`. `legitimate`: the query or the source does not allow a guide to be built (no results, too few readable pages, no AI Overview, unsupported language); nothing is broken, change the query or the source. `technical`: an error on our side, including any unknown reason.
      - `failureFacts` object: Only when step is `failed`, only for the reasons `not-enough-fetchable-pages` and `no-top10-fetchable-pages`, only for sources whose web pages we read (a search engine such as `GOOGLE` or `BING`, or a `_CITATIONS` source), and only when the figures could be read and cross-checked. Never set for a source in answer mode (`GOOGLE_AI_OVERVIEW`, `CHATGPT`, `PERPLEXITY`, ... without `_CITATIONS`): those guides are built from AI answers, no web page is read. Absent otherwise: never assume 0. Always `attempted = readable + notAnalyzable + invalidContent + unreachable`.
        - `attempted` integer, required: Number of results whose page we tried to read.
        - `readable` integer, required: Number of pages read and usable for the analysis.
        - `unreadable` object, required: Pages that could not be read, by cause.
          - `notAnalyzable` integer, required: Pages on sites we do not analyze (social networks, video platforms).
          - `invalidContent` integer, required: Pages whose content is too short or unreadable.
          - `unreachable` integer, required: Pages that are unreachable or protected.
    - `corpusTopWindow` GuideCorpusTopWindow: Present ONLY on a guide built from pages ranked beyond the top 10 (shared by /guide and /guides). None of the first 10 results of the search engine could be kept for the analysis, so the guide relies on the next ranked pages instead of failing. Absent on every other guide, which is the normal case: treat a missing field as "built on the top 10". Positions are the real ranks, never renumbered.
      - `fallback` boolean: Always `true` when the object is present.
      - `maxPosition` integer: Rank of the last page the guide relies on (30 at most).
      - `documents` integer: Number of pages the guide relies on.

## Other responses

- `401`: Unauthorized
- `404`: No guide matches. The body is `{ success: false, error: "No guides returned" }`. This is the normal answer for an empty result, not an error to retry.
- `500`: Server error
- `503`: Service temporarily unavailable: the database could not be reached while authenticating the request. Possible on EVERY authenticated endpoint. Your API key is NOT in question: do not regenerate or revoke it. Retry after the number of seconds given by the `Retry-After` header. Never returned as 401, 403, 404 or 410.

---

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