---
title: "Create new guides"
method: POST
path: "/api/v1/guides"
tags: ["v1", "Guide"]
---

# Create new guides

`POST /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

Create one or more new guides based on provided queries.
Each guide targets exactly ONE engine and ONE analysis mode, chosen with the optional `source` field (default `google`).

How to request each guide type:
1. Google SERP guide (1 credit per guide): omit `source`, or pass `source: "google"`.
   Example payload: {"queries": ["best crm"], "lang": "en-us"}
1bis. Google AI Overview guide (1 credit per guide). Two modes, like AI engines:
   `source: "google_ai_overview"` builds the guide from the TEXT of Google's AI answers
   (AI Overview, completed with AI Mode answers) ; `source: "google_ai_overview_citations"`
   builds it from the content of the web SOURCES those answers cite (recommended for GEO).
   Same language/country parameters as a Google SERP guide, 1 credit per guide in both modes.
   Example payload: {"queries": ["best crm"], "lang": "en-us", "source": "google_ai_overview_citations"}
2. LLM ANSWER guide (4 credits per guide): pass the engine name alone, e.g. `source: "chatgpt"`.
   The guide is built from the answer text the AI generates for the query.
   Example payload: {"queries": ["best crm"], "lang": "en-us", "source": "chatgpt"}
3. LLM CITATIONS guide (4 credits per guide) [RECOMMENDED AI mode]: pass the engine name with the `_citations` suffix, e.g. `source: "chatgpt_citations"`.
   The guide is built from the content of the web pages the AI cites in its answer.
   Example payload: {"queries": ["best crm"], "lang": "en-us", "source": "chatgpt_citations"}

Which AI mode to pick? For GEO (getting a page visible in AI answers), prefer `<engine>_citations`:
AI engines send traffic by CITING pages as sources, so the winning move is to look like the pages they cite.
The answer-text mode (`<engine>` alone) is mostly useful to analyze how the AI phrases its own answer.
When in doubt, pick `<engine>_citations`.

The same two modes exist for every AI engine (chatgpt, perplexity, claude, gemini, grok, mistral, deepseek).
To optimize the same page for several engines or modes (e.g. Google AND ChatGPT answers AND ChatGPT sources), create one guide per source value on the same query.

IMPORTANT, HOW TO READ THE RESPONSE OF THIS ENDPOINT, WHICH SPENDS CREDITS.
Queries listed in `guidesFailed` are PROVEN not to have produced a guide and their credit was
given back (unless the account has unlimited credits, where nothing was reserved): re-sending
them is free and correct. Queries listed in `guidesUnknown` have an UNDECIDABLE outcome and
their credit is deliberately KEPT, because the guide was most likely written: DO NOT re-send
them, you would pay for the same guide twice. Look them up in `GET /api/v1/guides` after a few
minutes instead, and contact support if nothing shows up.
Finally, a `200` is NOT a promise that every query produced a guide: compare `guides.length`
with the number of queries you sent, never read `success` alone, and never re-send a query
just because it is missing from `guides`.

## Request body

- object
  - `queries` string[], required: Array of queries to create guides for
  - `lang` string, required: Language code for the guides
  - `source` 'google' | 'google_ai_overview' | 'google_ai_overview_citations' | 'chatgpt' | 'chatgpt_citations' | 'perplexity' | 'perplexity_citations' | 'claude' | 'claude_citations' | 'gemini' | 'gemini_citations' | 'grok' | 'grok_citations' | 'mistral' | 'mistral_citations' | 'deepseek' | 'deepseek_citations': Target engine AND analysis mode the guide optimizes for. One guide = one source. `google` analyzes the Google SERP (1 credit per guide). Google's AI answers have the same two modes as AI engines : `google_ai_overview` analyzes the TEXT of the AI answers (AI Overview, completed with AI Mode) ; `google_ai_overview_citations` analyzes the content of the web SOURCES those answers cite, the recommended mode for GEO. 1 credit per guide in both modes, same language/country parameters as `google`. For AI engines (chatgpt, perplexity, claude, gemini, grok, mistral, deepseek), pick the mode: `<engine>` analyzes the AI's generated ANSWER for the query; `<engine>_citations` analyzes the content of the web SOURCES the AI cites, which is the recommended mode for GEO (become one of the cited sources). Both AI modes cost 4 credits per guide. Omit for the default `google`.

## Response `200`

No requested query landed in `guidesFailed` nor in `guidesUnknown`. Returned with `206` instead as soon as one requested query landed in either list. WARNING, A `200` IS NOT A PROMISE THAT EVERY QUERY PRODUCED A GUIDE, AND THE CREDIT IS STILL SPENT. When the backend answers success WITHOUT a usable guide id, the query enters NONE of the three lists and its credit is KEPT on purpose (the guide was most likely written, so retrying would pay for it twice). A batch made only of such queries therefore answers `200 { success: true, guides: [], guidesFailed: [], guidesUnknown: [] }` with the credits debited. Always compare `guides.length` with the number of queries you sent, never read `success` alone; on a difference, look the guides up in `GET /api/v1/guides` instead of re-sending the query.

- object
  - `success` boolean: `true` only when BOTH `guidesFailed` and `guidesUnknown` are empty. An undecidable outcome is not a success: its credit was kept, so reporting it as a complete success would hide a charge with nothing to show yet. WARNING, `true` still does not mean that every query produced a guide: a query answered as a success WITHOUT a usable guide id enters neither list, so `success` stays `true` while `guides` can be shorter than the queries you sent, credit spent. `guides.length` is the only reliable count of what was created.
  - `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)
    - `userId` string
    - `createdAt` string, date-time
  - `guidesFailed` object[]: Queries whose guide is PROVEN not to exist (validation refusal, or a 5xx that proves nothing was saved). Their credit was refunded, so requesting them again is free and correct. On an account with unlimited credits no credit was reserved in the first place, so there is nothing to refund and re-requesting is free all the same.
    - `query` string
    - `lang` string
  - `guidesUnknown` object[]: Queries whose outcome is UNDECIDABLE: the backend saves the guide BEFORE starting its task, so a non-proving 5xx, a timeout that reached the server or a dropped connection all leave a document the worker will pick up. Their credit is deliberately KEPT (refunding would make a produced guide free), except on an account with unlimited credits, where no credit was reserved and therefore none is kept. Do NOT re-submit these queries: the guide will most likely show up in `GET /api/v1/guides` within a few minutes, and re-submitting charges the same guide twice. Contact support if nothing appears.
    - `query` string
    - `lang` string
  - `credits` number, nullable: Spendable balance (plan credits plus non-expired One-Shot) re-read from the source AFTER every movement. `null` when that read failed: the guides were still created and charged, the balance is simply unknown. Never a locally estimated figure, which would silently open or close the creation path.
  - `hasUnlimitedCredits` boolean: Whether the account spends from an unlimited plan. Reported on the same response as `credits` because it decides what a client may TRUTHFULLY say about money: credits are only reserved when this is `false`, so a message claiming a charge is wrong on an unlimited account, and omitting it hides a real charge on every other one. Read it from here rather than from a value cached when the page was loaded.
  - `guidesCountBefore` integer, nullable: Number of guides the user owned BEFORE this call (0 for a first guide). `null` when the count could not be read.

## Other responses

- `206`: Partial success, and the ONLY status under which `guidesUnknown` can be non-empty. At least one requested query landed in `guidesFailed` (absence PROVEN, credit refunded, retrying is free and correct) or in `guidesUnknown` (outcome UNDECIDABLE, credit KEPT on purpose because the guide was most likely written, so DO NOT retry: you would pay for it twice). `success` is `false`. The body has exactly the same shape as the `200` above, `guides`, `guidesFailed`, `guidesUnknown`, `credits`, `hasUnlimitedCredits` and `guidesCountBefore` included; read the three arrays to know which query is in which state. The schema is deliberately NOT repeated here: two copies would drift apart, and this one describes money.
- `400`: Bad request. `queries` is missing, is not an array of non-empty strings, or `lang` is invalid.
- `402`: Monthly API guide quota exceeded. Applies only to the Conqueror plan, to guides created through the API or MCP, and only on a billing cycle that started on or after the date the refusal went live, or on the calendar month (UTC) for a Conqueror account without a subscription: `GET /api/v1/usage` returns `enforced: true` when it applies to the current window. The WHOLE request is refused when the guides already created in the window plus the requested ones exceed the limit: no guide is created and nothing is charged. `details.remaining` tells how many can still be created, `details.upgrade_url` where to raise the quota (absent when the add-on cannot raise it, at its highest volume or without a subscription). Guides created in the web interface are never refused. Other plans have no API quota: their credits are the only bound.
- `403`: Forbidden. Either not enough credits for the requested guides, or the requested `source` is in beta and currently restricted to administrators.
- `429`: Too many guides already waiting or in progress for this account (20 by default). The whole request is refused before any credit is reserved: no guide was created and nothing was charged. When the account is beyond the priority guides of its plan this month (generation slowed down to one guide per hour), the body carries `code: "PRIORITY_QUEUE_FULL"`, an explicit `error` message, the `Retry-After: 3600` header and, when the "Priority and API volume" add-on can raise the volume, `upgrade_url`. Otherwise the body is `{ success: false, error: "Too many guides in progress" }` without `code`: retry once some of the guides in progress are ready.
- `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)
