---
title: "Start an E-E-A-T analysis on a guide's top SERP competitors"
method: POST
path: "/api/v1/eeat-competitors"
tags: ["v1", "In-guide features"]
---

# Start an E-E-A-T analysis on a guide's top SERP competitors

`POST /api/v1/eeat-competitors`

## 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/eeat-competitors`
- Auth: HTTP bearer

Starts an asynchronous E-E-A-T analysis on the top competitors of the guide's SERP.
Each competitor is fetched and scored individually. Use GET /api/v1/eeat-competitors to
poll for results until `pending` reaches `0`.

**Token cost:** This endpoint charges `eeatCompetitorsTokensCostPerCompetitor`
(see /api/v1/tokens-usage) per competitor analyzed, up to 10 competitors.
Example: 10 competitors × 5 tokens = 50 tokens. 6 competitors × 5 tokens = 30 tokens.
The number of competitors corresponds to the deduplicated URLs in the guide's top-10 SERP
results (available via GET /api/v1/guide).

## Request body

- object
  - `guideId` string, required: ID of the guide whose competitors should be analyzed

## Response `200`

Competitor analysis successfully started

- object
  - `success` boolean
  - `data` object: Initial state of the analysis (counts and pending competitors)

## Other responses

- `400`: Bad request - Insufficient tokens or failed to consume tokens
- `401`: Unauthorized - Invalid API key or user doesn't own the guide
- `404`: Guide not found
- `409`: Conflict. Most often: no SERP corpus is available for this guide, so its competitors cannot be analyzed. A corpus is missing when its pages were never collected, or when they have been purged (pages older than 180 days are purged nightly). The tokens reserved for the call are refunded before this response is returned, **and `refunded` tells you whether that actually succeeded**. Trust that field, not the sentence: when `refunded` is `false` the refund failed, it is logged server-side for a manual replay, and `error` says so instead of claiming that nothing was charged.
- `410`: Guide expired. Guides are locked 180 days after their creation, because the Google results they are built on are no longer representative. The body is `{ success: false, error: "Guide expired", expiresAt: "<ISO 8601 expiry date>" }`. Definitive: do not retry, create a new guide on the same keyword. No token is reserved nor consumed by this refusal, so there is nothing to refund and no `refunded` field: unlike the 409 below, which counts pages and can say nothing about a date, this refusal reads the creation date and nothing else.
- `500`: Internal server error. When the failure comes from the backend call (unreachable, timeout, backend 500), the tokens reserved for it are refunded before this response is returned and the body carries `refunded`, with the same meaning as on the 409: `true` means the credit is on the ledger, `false` means the refund failed and is logged for a manual replay. The `error` sentence follows that field and never claims more. When the failure comes from writing the token ledger itself, the tokens are refunded too and `refunded` is carried the same way. That case is worth telling apart: the balance was already debited, only the ledger line failed, so the sentence never claims the debit did not happen.

---

[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/885ab1bdaa96?raw)
