Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,070Paid calls: 1,528Letters: 13Defects: 1,322counted 1 min ago
teppi

Server definition

Hash
sha256:76822885d2aeead70d9bdd0372a7e433e45bfed9f720fe1b362314a77a701834
What it is
What a remote MCP server returned when asked what it offers: 33 tools

The blob, as servednamed by its sha256

{ "instructions": null, "tools": [ { "description": "Test whether ChatGPT, Perplexity and Google AI Overview cite a website for one question (free tool)\n\nAsks one question to three AI answer engines (ChatGPT with web search, Perplexity, Google AI\nOverview) in the chosen market, and reports for each engine whether your domain is cited as a\nsource (`cited`, a citation on your registrable domain or one of its subdomains), whether your\nbrand is named in the answer (`mentioned`, which is NOT a citation), which of your pages are cited,\nan excerpt of the answer, its sources, and the domains cited instead of yours.\n\n**One answer, on one day.** This is a snapshot, not a lasting measure: AI answers change from one week\nto the next, and between two calls. Run the test again to compare.\n\n**Asynchronous, poll the result.** This call only starts the test and answers HTTP 202 with a\n`checkId` and a `pollUrl`. Call `GET /api/v1/tools/citation-check?checkId=...` every 3 seconds\nuntil `status` is `done` or `failed`; a test usually takes less than 2 minutes. MCP clients must\ncall the `get_citation_check` tool again until the status is terminal.\n\n**Identical questions are reused for 24 hours.** The same question (case and spaces ignored) in\nthe same market, asked less than 24 hours ago, returns the engine answers already collected,\nrecomputed for your domain: HTTP 200 with `reused` true and `status` already `done`. Nothing is\npaid for again, and your daily quota is given back.\n\n**Domain.** Send a domain name or any URL of the site: it is reduced to its registrable domain\n(`https://www.example.co.uk/blog/` becomes `example.co.uk`). IP addresses, local names and unknown\nsuffixes return 400 INVALID_DOMAIN.\n\n**Tiers, per UTC day.**\n- Without an API key, free anonymous tier: 1 test per day per IP address.\n- Signed-in account, or API key of an account whose plan includes API access: 10 tests per day.\n\nThe API key of an account whose plan does NOT include API access does not authenticate, and the\ncall returns 401. Remove the `Authorization` header to use the free anonymous tier instead.\n\nQuota headers: `X-RateLimit-Limit`, `X-RateLimit-Used`, `X-RateLimit-Remaining`,\n`X-RateLimit-Reset` (Unix time of the next UTC midnight). `Retry-After` is set on 429 and 503.\nA 502 or 503 answer gives the consumed quota back, and so does a 429 FREE_CAPACITY_REACHED\nand a 200 reused answer; SERVICE_UNAVAILABLE consumes none.\n\n**Request format.** Send the body as JSON with `Content-Type: application/json`: any other\ncontent type returns 415. Without an `Authorization` header, a request sent by a web page of\nanother site (an `Origin` other than the SERPmantics app, or `Sec-Fetch-Site: cross-site`)\nreturns 403. Server-to-server calls send no `Origin` header and are not affected.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "domain": { "description": "Domain to look for in the answers, or any URL of the site. Reduced to the registrable domain.", "type": "string" }, "market": { "description": "Language and country in which the engines are asked.", "enum": [ "fr-FR", "en-US", "es-ES", "de-DE", "it-IT" ], "type": "string" }, "question": { "description": "The question a prospect would ask an AI assistant, 10 to 200 characters once spaces are collapsed.", "type": "string" } }, "required": [ "domain", "question", "market" ], "type": "object" }, "name": "create_citation_check", "outputSchema": null }, { "description": "Start an E-E-A-T analysis on a guide content\n\nStarts an asynchronous E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) analysis\non the HTML content provided for a given guide. The analysis runs in the background — use\nGET /api/v1/eeat to poll for results until `status` is `done` (or `failed`).\n\n**Note:** This endpoint uses tokens (check /api/v1/tokens-usage for the cost, might vary).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide to analyze", "type": "string" }, "html_content": { "description": "HTML of the article to analyze (without `<mark>` tags)", "type": "string" } }, "required": [ "guideId", "html_content" ], "type": "object" }, "name": "create_eeat", "outputSchema": null }, { "description": "Start an E-E-A-T analysis on a guide's top SERP competitors\n\nStarts an asynchronous E-E-A-T analysis on the top competitors of the guide's SERP.\nEach competitor is fetched and scored individually. Use GET /api/v1/eeat-competitors to\npoll for results until `pending` reaches `0`.\n\n**Token cost:** This endpoint charges `eeatCompetitorsTokensCostPerCompetitor`\n(see /api/v1/tokens-usage) per competitor analyzed, up to 10 competitors.\nExample: 10 competitors × 5 tokens = 50 tokens. 6 competitors × 5 tokens = 30 tokens.\nThe number of competitors corresponds to the deduplicated URLs in the guide's top-10 SERP\nresults (available via GET /api/v1/guide).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide whose competitors should be analyzed", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "create_eeat_competitors", "outputSchema": null }, { "description": "Create new guides\n\nCreate one or more new guides based on provided queries.\nEach guide targets exactly ONE engine and ONE analysis mode, chosen with the optional `source` field (default `google`).\n\nHow to request each guide type:\n1. Google SERP guide (1 credit per guide): omit `source`, or pass `source: \"google\"`.\n Example payload: {\"queries\": [\"best crm\"], \"lang\": \"en-us\"}\n1bis. Google AI Overview guide (1 credit per guide). Two modes, like AI engines:\n `source: \"google_ai_overview\"` builds the guide from the TEXT of Google's AI answers\n (AI Overview, completed with AI Mode answers) ; `source: \"google_ai_overview_citations\"`\n builds it from the content of the web SOURCES those answers cite (recommended for GEO).\n Same language/country parameters as a Google SERP guide, 1 credit per guide in both modes.\n Example payload: {\"queries\": [\"best crm\"], \"lang\": \"en-us\", \"source\": \"google_ai_overview_citations\"}\n2. LLM ANSWER guide (4 credits per guide): pass the engine name alone, e.g. `source: \"chatgpt\"`.\n The guide is built from the answer text the AI generates for the query.\n Example payload: {\"queries\": [\"best crm\"], \"lang\": \"en-us\", \"source\": \"chatgpt\"}\n3. LLM CITATIONS guide (4 credits per guide) [RECOMMENDED AI mode]: pass the engine name with the `_citations` suffix, e.g. `source: \"chatgpt_citations\"`.\n The guide is built from the content of the web pages the AI cites in its answer.\n Example payload: {\"queries\": [\"best crm\"], \"lang\": \"en-us\", \"source\": \"chatgpt_citations\"}\n\nWhich AI mode to pick? For GEO (getting a page visible in AI answers), prefer `<engine>_citations`:\nAI engines send traffic by CITING pages as sources, so the winning move is to look like the pages they cite.\nThe answer-text mode (`<engine>` alone) is mostly useful to analyze how the AI phrases its own answer.\nWhen in doubt, pick `<engine>_citations`.\n\nThe same two modes exist for every AI engine (chatgpt, perplexity, claude, gemini, grok, mistral, deepseek).\nTo 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.\n\nIMPORTANT, HOW TO READ THE RESPONSE OF THIS ENDPOINT, WHICH SPENDS CREDITS.\nQueries listed in `guidesFailed` are PROVEN not to have produced a guide and their credit was\ngiven back (unless the account has unlimited credits, where nothing was reserved): re-sending\nthem is free and correct. Queries listed in `guidesUnknown` have an UNDECIDABLE outcome and\ntheir credit is deliberately KEPT, because the guide was most likely written: DO NOT re-send\nthem, you would pay for the same guide twice. Look them up in `GET /api/v1/guides` after a few\nminutes instead, and contact support if nothing shows up.\nFinally, a `200` is NOT a promise that every query produced a guide: compare `guides.length`\nwith the number of queries you sent, never read `success` alone, and never re-send a query\njust because it is missing from `guides`.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "lang": { "description": "Language code for the guides", "type": "string" }, "queries": { "description": "Array of queries to create guides for", "items": { "type": "string" }, "type": "array" }, "source": { "description": "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`.", "enum": [ "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" ], "type": "string" } }, "required": [ "queries", "lang" ], "type": "object" }, "name": "create_guides", "outputSchema": null }, { "description": "Generate search intent analysis for a guide\n\nAnalyzes search intent for a guide and optionally analyzes provided content against that intent. \n**Note:** This endpoint uses tokens (check /api/v1/tokens-usage for the cost, might vary).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "content": { "description": "Optional content to analyze against the intent (only after intent analysis was created)", "type": "string" }, "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "create_intent", "outputSchema": null }, { "description": "Generate internal linking suggestions for a guide\n\nAnalyzes a guide and generates internal linking suggestions based on content analysis. \n**Note:** This endpoint uses tokens (check /api/v1/tokens-usage for the cost, might vary).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "create_internal_links", "outputSchema": null }, { "description": "Generate SEO meta titles and descriptions for a guide\n\nGenerates optimized meta titles and descriptions based on guide content analysis.\n**Note:** This endpoint uses tokens (check /api/v1/tokens-usage for the cost, might vary).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "create_meta", "outputSchema": null }, { "description": "Generate content outline for a guide\n\nGenerates a content outline based on SERP analysis for a guide.\n**Note:** This endpoint uses tokens (check /api/v1/tokens-usage for the cost, might vary).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "create_outline", "outputSchema": null }, { "description": "Generate an AI persona and brand voice brief from the pages of a website (free tool)\n\nReads public pages of a website and produces an editorial persona and writing style brief:\nwho writes, for whom, tone on 6 axes, vocabulary, structure, do and don't lists, verified\nquotes from the pages, style metrics measured on the text, and a ready-to-paste writing\nprompt for any AI writing tool (`brief.writingPrompt`, plus `brief.writingPromptCompact`\nof at most 1500 characters).\n\n**Asynchronous, poll the result.** This call only starts the job and answers HTTP 202 with a\n`briefId` and a `pollUrl`. Call `GET /api/v1/tools/persona-brief?briefId=...` every 3 seconds\nuntil `status` is `done` or `failed`. A brief takes about 80 seconds plus 5 seconds per page,\nrounded up to the half minute: about 2 min for 3 pages, 2 min 30 s for 10 pages.\nMCP clients must call the `get_persona_brief` tool again until the status is terminal.\n\n**Identical requests are reused for 72 hours.** The same set of URLs, in any order, with the\nsame `outputLanguage` and the same `brandName`, returns the brief already computed instead of\ncomputing it again: HTTP 200 with `reused` true, `status` already `done`, the original\n`briefId` and `reusedCreatedAt`, the date of the brief it reuses. Nothing is created, and your\ndaily quota is given back, so a reused answer costs you nothing. The pages of a reused brief\nare listed in the order of the original request, not in the order you just sent. Send\n`force` true to skip the lookup and compute a new brief, which answers 202 and consumes quota.\n\n**Addresses.** Duplicate URLs, compared once normalized, are read once. A private, local or\nblocked address is not refused by this call: the brief is created, and that page ends with\n`status` failed and `failureReason` BLOCKED_ADDRESS (the brief fails with NO_USABLE_PAGE when\nno other page could be read).\n\n**Tiers, per UTC day.** Every tier is capped at 10 URLs per brief since 21 September 2026.\n- Without an API key, free anonymous tier: 3 briefs per day per IP address, 10 URLs per brief.\n- Signed-in account on the web interface, plan without API access: 10 briefs per day, 10 URLs per brief.\n- API key of an account whose plan includes API access, pro tier: 50 briefs per day, 10 URLs per brief.\n\nThe API key of an account whose plan does NOT include API access does not authenticate, and the\ncall returns 401. Remove the `Authorization` header to use the free anonymous tier instead.\n\nQuota headers: `X-RateLimit-Limit`, `X-RateLimit-Used`, `X-RateLimit-Remaining`,\n`X-RateLimit-Reset` (Unix time of the next UTC midnight). `Retry-After` is set on 429 and 503.\nA 502 or 503 answer gives the consumed quota back, and so does a 429 FREE_CAPACITY_REACHED\nand a 200 reused answer; SERVICE_UNAVAILABLE consumes none.\n\n**Request format.** Send the body as JSON with `Content-Type: application/json`: any other\ncontent type returns 415. Without an `Authorization` header, a request sent by a web page of\nanother site (an `Origin` other than the SERPmantics app, or `Sec-Fetch-Site: cross-site`)\nreturns 403. Server-to-server calls send no `Origin` header and are not affected.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "brandName": { "description": "Optional brand name, on a single line, used in the brief.", "type": "string" }, "force": { "description": "True to compute a new brief even when an identical one exists, which answers 202 and consumes quota. Any value that is not a boolean returns 400 INVALID_BODY.", "type": "boolean" }, "outputLanguage": { "description": "Language in which the brief is written. When omitted, the service chooses it.", "enum": [ "fr", "en", "es", "de", "it" ], "type": "string" }, "urls": { "description": "Public http(s) URLs of representative pages of one website, 5 to 10 articles give the best brief. At most 10 URLs, whatever the tier, each of at most 2048 characters.", "items": { "type": "string" }, "type": "array" } }, "required": [ "urls" ], "type": "object" }, "name": "create_persona_brief", "outputSchema": null }, { "description": "Analyze content optimization score\n\nAnalyzes the optimization score of the provided content for a specific guide\n\nMCP channel defaults: this tool sends scoreProgressive=false, includeEmbedding=false when you leave them out. That is specific to this channel and overrides the default documented on those parameters, which describes the REST API. What it changes in the response: with scoreProgressive=false, contentAnalysis.progressiveScores comes back empty ({}); with includeEmbedding=false, contentAnalysis.embeddingAnalysis is omitted from the response. Set a flag to true in your arguments to get its content back; any value you do pass is sent unchanged, including false. The whole response is handed to the model, and this is where most of its size goes, so it is opt-in on this channel: ask only for what you are going to read.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "content": { "description": "Content to analyze", "type": "string" }, "guideId": { "description": "ID of the guide to analyze", "type": "string" }, "includeEmbedding": { "description": "Whether to compute the semantic embedding analysis, i.e. proximity and PCA (default: true). When false, the embeddingAnalysis key is omitted from the response. Null is treated as \"not provided\", so the default applies.\n", "type": "boolean" }, "pageUrl": { "description": "Optional. Read only for a visitor of a guide shared in read-only mode: the URL of one of the guide's SERP pages, whose stored content is then analysed instead of the guide's text. Ignored for the owner and for a guide shared in edit mode. Unknown URL: the guide's text is analysed.\n", "type": "string" }, "saveToGuide": { "description": "Whether to save the content and the analysis score back to the guide (default: true)\n", "type": "boolean" }, "scoreProgressive": { "description": "Whether to compute the progressive score build-up curve (default: true). When false, progressiveScores is returned empty. Null is treated as \"not provided\", so the default applies.\n", "type": "boolean" } }, "required": [ "guideId", "content" ], "type": "object" }, "name": "create_score", "outputSchema": null }, { "description": "Delete a guide\n\nDeletes a specific guide. Deliberately NOT blocked by the 180-day expiry: an expired guide can no longer be read, but it can always be deleted, so that you can still clean up your account.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "id": { "description": "The ID of the guide to delete", "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "delete_guide", "outputSchema": null }, { "description": "Delete multiple guides\n\nDeletes multiple guides at once", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": {}, "type": "object" }, "name": "delete_guides", "outputSchema": null }, { "description": "Delete generated intent analysis for a guide\n\nRemoves previously generated intent analysis for the given guide.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "delete_intent", "outputSchema": null }, { "description": "Delete generated internal-links suggestions for a guide\n\nRemoves previously generated internal-links suggestions for the given guide.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "delete_internal_links", "outputSchema": null }, { "description": "Delete generated meta for a guide\n\nRemoves previously generated meta titles/descriptions for the given guide.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "delete_meta", "outputSchema": null }, { "description": "Delete generated outline for a guide\n\nRemoves previously generated outline data for the given guide.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "delete_outline", "outputSchema": null }, { "description": "Find the representative pages of a website from its sitemaps, before generating a persona brief (free tool)\n\nReads the sitemaps of a website (declared in robots.txt, otherwise /sitemap.xml,\n/sitemap_index.xml and /wp-sitemap.xml) and returns up to 200 URLs of the same host, editorial\npages first. The first URLs, as many as the URL limit of your tier, are flagged `suggested`:\nsend them in `urls` to `POST /api/v1/tools/persona-brief`.\n\nSame tiers as the creation call, with their own daily counter per UTC day: 20 discoveries per\nday per IP address without an API key, 50 for a signed-in account, 200 with the API key of an\naccount whose plan includes API access. A key whose plan does not include API access returns\n401: remove the `Authorization` header to use the free anonymous tier.\n\nQuota headers: `X-RateLimit-Limit`, `X-RateLimit-Used`, `X-RateLimit-Remaining`,\n`X-RateLimit-Reset`. `Retry-After` is set on 429 and 503. A 400, 502 or 503 answer gives the\nconsumed quota back; SERVICE_UNAVAILABLE consumes none.\n\n**Request format.** Send the body as JSON with `Content-Type: application/json`: any other\ncontent type returns 415. Without an `Authorization` header, a request sent by a web page of\nanother site (an `Origin` other than the SERPmantics app, or `Sec-Fetch-Site: cross-site`)\nreturns 403. Server-to-server calls send no `Origin` header and are not affected.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "site": { "description": "URL or domain of the website. A bare domain is completed with https.", "type": "string" } }, "required": [ "site" ], "type": "object" }, "name": "discover_persona_brief_pages", "outputSchema": null }, { "description": "Get the current user's available AI tokens\n\nReturns the number of AI tokens available to the authenticated user.\n\nThese tokens fund EVERY AI feature in SERPmantics — meta, outline,\nintent, internal-links, EEAT, EEAT competitors, score, AND the\nAISSistant prompts. The endpoint lives under /aissistant for\nhistorical reasons but the balance is shared across all AI features.\n\nDo NOT confuse with guide-creation credits (see /api/v1/credits).\nFor a combined view (credits + tokens) prefer /api/v1/credits.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": {}, "type": "object" }, "name": "get_aissistant_tokens", "outputSchema": null }, { "description": "Read an AI citation test, poll until it is done\n\nReturns the test started by `POST /api/v1/tools/citation-check`. While `status` is `pending` or\n`running`, call again every 3 seconds: each engine fills in as soon as it has answered. When\n`status` is `done`, at least one engine answered; `summary.citedBy` engines cite your domain out\nof `summary.enginesAnswered` engines that answered. When `status` is `failed`, `failureCode` says\nwhy (NO_ENGINE_ANSWERED, TIMEOUT, INTERNAL).\n\nPer engine: `cited` is true when a source of the answer is on your registrable domain or one of\nits subdomains, and `citedUrls` lists those pages; `mentioned` is true when your brand name appears\nin the answer text, which is NOT a citation. `status` no_answer means the engine showed no answer\nfor this question (Google often shows no AI Overview), which is not a failure.\n\nNo quota is consumed. The `checkId` is random: whoever holds it can read the test, which is what\nmakes share links work. Tests expire after 30 days. Reads that are not attributed to an account are\ncapped at 1000 per IP address and per UTC day, far above any legitimate polling: crossing it returns\n429 READ_RATE_LIMITED with `Retry-After`.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "checkId": { "description": "The checkId returned by the creation call (22 characters).", "type": "string" } }, "required": [ "checkId" ], "type": "object" }, "name": "get_citation_check", "outputSchema": null }, { "description": "Grand-livre crédits d'un compte (admin)\n\nTimeline complète et immuable des mouvements de crédits d'un utilisateur (octrois, consommations, refunds, resets, ajustements admin), avec libellés FR en clair, delta signé, solde après, source, auteur et référence. Inclut le solde reconstruit à une date arbitraire (paramètre `at`) et un contrôle de cohérence (solde == dernier balanceAfter == somme des deltas). Réservé aux administrateurs. Lecture seule.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "at": { "description": "Date ISO pour reconstruire le solde à cet instant (point-in-time).", "type": "string" }, "limit": { "description": "Nombre maximum de lignes (défaut 200, max 1000).", "type": "number" }, "userId": { "description": "Identifiant Mongo de l'utilisateur.", "type": "string" } }, "required": [ "userId" ], "type": "object" }, "name": "get_credit_ledger", "outputSchema": null }, { "description": "Get user balance (guide credits + AI tokens)\n\nReturns the authenticated user's full balance.\n\nSERPmantics has TWO distinct currencies:\n\n- **credits** (`credits`): how many NEW GUIDES the user can still create.\n Consumed once per guide creation. `\"unlimited\"` if the user's plan\n grants unlimited guide creation (`hasUnlimitedCredits: true`).\n\n- **AI tokens** (`tokens`): pool consumed by every AI feature (meta,\n outline, intent, internal-links, EEAT, EEAT competitors…).\n Each feature has its own cost — call `/api/v1/tokens-usage` to get\n the per-feature pricing.\n\nDo not confuse the two: running out of `credits` blocks new guides;\nrunning out of `tokens` blocks AI features inside existing guides.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": {}, "type": "object" }, "name": "get_credits", "outputSchema": null }, { "description": "Get E-E-A-T analysis results\n\nRetrieves the result of an E-E-A-T analysis.\n\n`guideId` is **always required**: access is granted on the guide, so a request without it\nis answered with `404 Guide not found`. `eeatId` is an optional filter on top of it: pass it\nto fetch one specific analysis of that guide, omit it to fetch the latest one.\nAn `eeatId` that does not belong to `guideId` is answered with `404`, never with the\nother account's data.\n\nPoll this endpoint until `status` is `done` (results available) or `failed`.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "eeatId": { "description": "Optional filter, ID of one specific analysis of that guide (returned by POST /api/v1/eeat). Omit it to get the latest analysis of `guideId`.", "type": "string" }, "guideId": { "description": "ID of the guide the analysis belongs to. Required, and access is checked on it.", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "get_eeat", "outputSchema": null }, { "description": "Get E-E-A-T analysis results for a guide's competitors\n\nRetrieves the E-E-A-T analysis results for the top competitors of a guide.\nPoll this endpoint until `pending` is `0` to know when the full analysis is complete.\nIndividual competitor results are available as soon as their `status` is `done`.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide whose competitors should be returned", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "get_eeat_competitors", "outputSchema": null }, { "description": "Get data for a specific guide\n\nRetrieves details of a specific guide. While the guide is being created, the endpoint returns 202 (poll again later). If the creation failed permanently (explicit terminal flag, or a failure older than 15 minutes with no retry left, see progressStatus.terminalInferred), it returns 200 with success=false, status=failed, a human-readable French error message, creationFailed=true, refunded (whether the consumed credits were automatically given back) and guide.progressStatus (raw reason, message, terminal). Stop polling in that case.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "id": { "description": "The ID of the guide to retrieve", "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "get_guide", "outputSchema": null }, { "description": "List user's guides\n\nReturns a list of guides for the authenticated user.\n\nUse `query` to check whether a guide already exists before creating one\n(creating a duplicate costs credits). Beware of two behaviours of this endpoint:\n- `query` and `group` are case-insensitive REGULAR EXPRESSIONS, not exact matches:\n special characters in the value are interpreted as regex syntax, and an invalid\n regex returns no result at all. (`status` is different: a known status is matched\n exactly, any other value falls back to a regex.) Always compare the returned\n `query` and `source` yourself, and fall back to an unfiltered paginated scan\n before concluding that nothing exists;\n- `totalCount` does NOT take `query` nor `group` into account (known limitation:\n both are applied as application-level regexes that the count query does not\n know, so it returns 0 as soon as either is used, alone or combined with\n `status`). Filtering on `status` alone does give a correct `totalCount`, since\n it is a real stored field. For an existence check, trust the `guides` actually\n returned; `totalCount` is only reliable for paginating a listing filtered by\n `status` alone, or not filtered at all.\n\nAn empty result is returned as a 404 with `success: false` and\n`error: \"No guides returned\"`, not as an empty list.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "group": { "description": "Filter on the guide group. Case-insensitive partial match, interpreted as a regular expression.", "type": "string" }, "page": { "description": "Page number for pagination" }, "pageSize": { "description": "Number of guides per page" }, "query": { "description": "Filter on the guide query. Case-insensitive partial match, interpreted as a regular expression (see the endpoint description).", "type": "string" }, "status": { "description": "Filter on the guide status. Exact match when the value is one of the known statuses, otherwise a case-insensitive regular expression.", "enum": [ "draft", "active", "review", "published", "archived" ], "type": "string" } }, "type": "object" }, "name": "get_guides", "outputSchema": null }, { "description": "Get search intent analysis for a guide\n\nRetrieves existing intent analysis results for a guide", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "get_intent", "outputSchema": null }, { "description": "Get internal linking suggestions for a guide\n\nRetrieves existing internal linking suggestions for a guide", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "get_internal_links", "outputSchema": null }, { "description": "Get generated meta titles and descriptions for a guide\n\nRetrieves generated SEO meta titles and descriptions for a guide", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "get_meta", "outputSchema": null }, { "description": "Get generated page structure for a guide\n\nRetrieves the generated page structure (flat heading list) for a guide.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "guideId": { "description": "ID of the guide", "type": "string" } }, "required": [ "guideId" ], "type": "object" }, "name": "get_outline", "outputSchema": null }, { "description": "Read an AI persona and brand voice brief, poll until it is done\n\nReturns the brief started by `POST /api/v1/tools/persona-brief`. While `status` is `pending`,\n`fetching`, `analyzing` or `synthesizing`, call again every 3 seconds: `progress` and `pages`\nshow what has been read so far. When `status` is `done`, `brief` holds the structured brief,\n`brief.writingPrompt` the ready-to-paste prompt and `markdown` the full document. When `status`\nis `failed`, `failureReason` says why (NO_USABLE_PAGE, LLM_UNAVAILABLE, TIMEOUT, INTERNAL).\n\nA page with a `failureReason` did not contribute to the brief. ANALYSIS_FAILED is the only one\non a page that was read: it keeps its `title` and `wordCount`, stays counted in\n`progress.pagesFetched` and never enters `progress.pagesAnalyzed` nor `metrics`.\n\nNo quota is consumed. The `briefId` is random: whoever holds it can read the brief, which is\nwhat makes share links work. Briefs expire after 90 days. Reads that are not attributed to an\naccount are subject to three anti-abuse counters, all per IP address and per UTC day:\nthe total number of requests, the reads of a single brief, and the number of different\nbriefs read. All three are far above any legitimate polling, including the busiest paid\naccount: crossing any of them returns 429 READ_RATE_LIMITED with `Retry-After`. Once the\ncost ceiling is reached, further requests keep being refused until it resets, whether or\nnot they carry a valid briefId.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "briefId": { "description": "The briefId returned by the creation call (22 characters).", "type": "string" } }, "required": [ "briefId" ], "type": "object" }, "name": "get_persona_brief", "outputSchema": null }, { "description": "Get API token usage costs for different endpoints\n\nReturns the number of tokens required for each API endpoint operation.\n\nNote: `eeatCompetitorsTokensCostPerCompetitor` is a **per-competitor** cost.\nThe total cost of POST /api/v1/eeat-competitors equals this value × the number of\ncompetitors analyzed (deduplicated URLs in the guide's top-10 SERP, capped at 10).\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": {}, "type": "object" }, "name": "get_tokens_usage", "outputSchema": null }, { "description": "Get current API usage and quota status\n\nReturns the current period's API guide usage, quota limit, remaining count and the renewal date. Aligned on the Stripe subscription billing cycle. Does not consume credits.\n", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": {}, "type": "object" }, "name": "get_usage", "outputSchema": null }, { "description": "Update a guide\n\nUpdates editable fields of a specific guide (group, status, share state, linked URL, meta, hidden expressions). Only owners may update.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "properties": { "group": { "description": "Group/folder the guide belongs to (triggers cannibalisation analysis on previous and new group)", "type": "string" }, "hiddenExpressions": { "description": "Expressions to hide from the optimisation suggestions", "items": { "type": "string" }, "type": "array" }, "id": { "description": "The ID of the guide to update", "type": "string" }, "linkedUrl": { "description": "Public URL where the guide content is published (validated as URL)", "type": "string" }, "meta": { "additionalProperties": {}, "description": "SEO meta override for the guide", "properties": { "description": { "type": "string" }, "title": { "type": "string" } }, "type": "object" }, "shareState": { "description": "Sharing mode. Any value outside the enum is rejected with 400 (the check is case-sensitive). Plan must allow shared-read or shared-edit, otherwise 403 is returned.", "enum": [ "private", "shared-read", "shared-edit" ], "type": "string" }, "status": { "description": "Editorial status of the guide. Empty string clears the status.", "enum": [ "", "draft", "active", "review", "published", "archived" ], "type": "string" } }, "required": [ "id" ], "type": "object" }, "name": "update_guide", "outputSchema": null } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:76822885d2aeead70d9bdd0372a7e433e45bfed9f720fe1b362314a77a701834 | sha256sum