PageSourceSearch

https://semalt.com/_nuxt/BedIzWDy2.js

js semalt.com collected 2026-10-01 12:10:40 UTC 32,793 bytes, 204 lines download raw bytes

1import{Et as e,I as t,Ot as n,P as r,d as i,f as a,j as o,l as s,nt as c,p as l,q as u,r as d,st as f,u as p,v as m,x as h}from"./CEGevduf.js";import{t as g}from"./D781LUgP.js";import{t as _}from"./B93R48Yq.js";import{t as v}from"./CoCbcoVa.js";import{t as y}from"./BDNMzG2s.js";import{n as b,t as x}from"./CayTFGZ0.js";var S={id:`api-key`,class:`api-key-card`,"aria-labelledby":`api-key-title`},C={class:`api-key-card__copy`},w={class:`api-key-card__action`},T={key:0,class:`api-key-card__status`,role:`status`},E={class:`api-key-card__error`,role:`alert`},D={key:0,class:`api-key-card__key-wrap`},O={class:`api-key-card__key-row`},k=[`type`,`value`],A=[`aria-label`,`title`],j=[`aria-label`],M={key:1,class:`api-key-card__missing`},N=[`disabled`],P={key:0,class:`api-key-card__error`,role:`alert`},F=Object.assign(y(h({__name:`ApiKeyCard`,props:{returnPath:{default:`/api-docs#api-key`}},setup(h){let y=h,b=g(),{copy:F}=x(),{isUserAuthenticated:I,loadUser:L}=v(),R=c(`loading`),z=c(``),B=c(!0),V=c(!1),H=c(!1),U=c(``),W=null,G=s(()=>R.value===`authenticated`&&I.value),K=s(()=>({path:`/authorize`,query:{mode:`signup`,redirect:y.returnPath}}));async function q(){let e=await b.$get(`User.getApiKey`);z.value=String(e?.token||``).trim()}async function J(){R.value=`loading`,U.value=``;try{if(await L(),!I.value){R.value=`guest`;return}await q(),R.value=`authenticated`}catch{R.value=`error`,U.value=`We could not load your API access. Please try again.`}}async function Y(){if(!H.value){H.value=!0,U.value=``;try{await b.$post(`User.regenerateApiKey`),await q(),B.value=!0}catch{U.value=`We could not generate an API key. Please try again.`}finally{H.value=!1}}}function X(e){let t=e.target;t instanceof HTMLInputElement&&t.select()}async function Z(){z.value&&(await F(z.value),V.value=!0,W&&clearTimeout(W),W=setTimeout(()=>{V.value=!1},1600))}return r(J),o(()=>{W&&clearTimeout(W)}
1),(r,o)=>{let s=_;return t(),l(`section`,S,[p(`div`,C,[o[7]||=p(`p`,{class:`api-key-card__eyebrow`},[p(`i`,{class:`fa-solid fa-terminal`,"aria-hidden":`true`}),m(`
2				Developer access
3			`)],-1),o[8]||=m(),f(G)?(t(),l(d,{key:0},[o[1]||=p(`h2`,{id:`api-key-title`},`Your Semalt API key`,-1),o[2]||=m(),o[3]||=p(`p`,null,`
4					Use this key to connect to the Public API or the MCP server. Keep it private because it provides access to your Semalt account data.
5				`,-1)],64)):(t(),l(d,{key:1},[o[4]||=p(`h2`,{id:`api-key-title`},`Get your Semalt API key`,-1),o[5]||=m(),o[6]||=p(`p`,null,`
6					Create a free Semalt account to access the Public API and connect AI tools through MCP.
7				`,-1)],64))]),o[22]||=m(),p(`div`,w,[f(R)===`loading`?(t(),l(`div`,T,[...o[9]||=[p(`span`,{class:`api-key-card__spinner`,"aria-hidden":`true`},null,-1),m(`
8				Loading API access...
9			`,-1)]])):f(R)===`error`?(t(),l(d,{key:1},[p(`p`,E,n(f(U)),1),o[11]||=m(),p(`button`,{class:`api-key-card__button api-key-card__button--secondary`,type:`button`,onClick:J},[...o[10]||=[p(`i`,{class:`fa-solid fa-rotate-right`,"aria-hidden":`true`},null,-1),m(`
10					Try again
11				`,-1)]])],64)):f(G)?(t(),l(d,{key:2},[f(z)?(t(),l(`div`,D,[o[15]||=p(`label`,{class:`api-key-card__label`,for:`semalt-api-key`},`API key`,-1),o[16]||=m(),p(`div`,O,[p(`input`,{id:`semalt-api-key`,class:`api-key-card__input`,type:f(B)?`text`:`password`,value:f(z),readonly:``,spellcheck:`false`,autocomplete:`off`,onFocus:X},null,40,k),o[13]||=m(),p(`button`,{class:`api-key-card__icon-button`,type:`button`,"aria-label":f(B)?`Hide API key`:`Show API key`,title:f(B)?`Hide API key`:`Show API key`,onClick:o[0]||=e=>B.value=!f(B)},[p(`i`,{class:e(f(B)?`fa-solid fa-eye-slash`:`fa-solid fa-eye`),"aria-hidden":`true`},null,2)],8,A),o[14]||=m(),p(`button`,{class:`api-key-card__copy-button`,type:`button`,"aria-label":f(V)?`API key copied`:`Copy API key`,onClick:Z},[p(`i`,{class:e(f(V)?`fa-solid fa-check`:`fa-regular fa-copy`),"aria-hidden":`true`},null,2),o[12]||=m(),p(`span`,null,n(f(V)?`Copied`:`Copy`),1)],8,j)])])):(t(),l(`div`,M,[o[18]||=p(`p`,null,`Your account does not have an API key yet.`,-1),o[19]||=m(),p(`button`,{class:`api-key-card__button api-key-card__button--primary`,type:`button`,disabled:f(H),onClick:Y},[o[17]||=p(`i`,{class:`fa-solid fa-key`,"aria-hidden":`true`},null,-1),m(` `+n(f(H)?`Generating...`:`Generate API key`),1)],8,N),o[20]||=m(),f(U)?(t(),l(`p`,P,n(f(U)),1)):a(``,!0)]))],64)):(t(),i(s,{key:3,class:`api-key-card__button api-key-card__button--primary`,to:f(K)},{default:u(()=>[...o[21]||=[p(`i`,{class:`fa-solid fa-key`,"aria-hidden":`true`},null,-1),m(`
12				Get API key
13			`,-1)]]),_:1},8,[`to`]))])])}}}),[[`__scopeId`,`data-v-a85ba47c`]]),{__name:`DeveloperApiKeyCard`}),I=[`id`],L=[`innerHTML`],R=Object.assign(y(h({__name:`PublicDocsSection`,props:{section:{}},setup(e){let r=e,i=s(()=>b(r.section.body,{preserveLineBreaks:!1}));return(r,a)=>(t(),l(`section`,{id:e.section.id,class:`public-docs-section`},[p(`h2`,null,n(e.section.title),1),a[0]||=m(),p(`div`,{class:`public-docs-body`,innerHTML:f(i)},null,8,L)],8,I))}}),[[`__scopeId`,`data-v-93d3d3cb`]]),{__name:`PublicDocsSection`}),z={version:1,documents:[{id:`public-api`,title:`Semalt Public API v1`,language:`en`,sections:[{id:`quick-start`,title:`Quick start`,body:"Base URL: `https://semalt.com/api/v1`\n\nAuthenticate every request with the API key from your Semalt account:\n\n```http\nAuthorization: Bearer YOUR_API_KEY\n```\n\nStart with `/me` to identify the API key owner, then `/accounts` to discover\navailable account contexts:\n\n```bash\ncurl 'https://semalt.com/api/v1/me' \\\n  -H 'Authorization: Bearer YOUR_API_KEY' \\\n  -H 'Accept: application/json'\n```\n\nAlternatively, pass the key as `token` in the query string. Header authentication\nis recommended because URLs can appear in logs and browser history:\n\n```bash\ncurl 'https://semalt.com/api/v1/me?token=YOUR_API_KEY' \\\n  -H 'Accept: application/json'\n```"},{id:`account-context`,title:`Account context`,body:"One API key can read and manage the accounts available to it. Use `/me` to\nidentify the API key owner and `/accounts` to discover account contexts\navailable for selection.\n\n1. Call `GET /api/v1/me`. `data.account_id` identifies the API key owner.\n2. Call `GET /api/v1/accounts` to discover accounts available for selection with\n   names and emails. The collection supports `search`, `limit`, and curs
13or pagination.\n3. Use `/api/v1/accounts/{account_id}/...` for every account operation while\n   keeping the same API key. `GET /accounts/{account_id}` reads its details.\n\n`/me` always identifies the token owner. There is no persistent account\nselection. Do not pass account_id in query parameters or JSON bodies.\nAccount responses include `meta.actor_account_id` and `meta.account_id` so\nclients can distinguish the key owner from the selected account. Account\nidentifiers, including `owner_account.account_id`, are returned as strings.\n`linked_account_ids` in `/me` and account details describes the linked group of\nthe account returned by that endpoint and includes the account itself. It is\nrelationship metadata, not the list of all accounts available to the API key;\nuse `/accounts` to determine which account IDs are selectable.\n\n- Sites and analytics use the selected account’s own, linked and explicitly\n  shared sites. `access_type=own` restricts the list to its own records.\n- New websites and keyword groups belong to the selected account.\n- Site Tags belong to its linked group and are shared by the group’s members.\n- Keyword Groups retain individual owners; linked accounts can view and edit\n  them. Groups are domain-scoped, even when accessed through a physical site id.\n- My SEO campaigns belong to the selected account. List them at\n  `/accounts/{account_id}/my-seo/campaigns` and use the returned `campaign_id`\n  for `/accounts/{account_id}/my-seo/campaigns/{campaign_id}/keywords` and\n  `/accounts/{account_id}/my-seo/campaigns/{campaign_id}/backlinks`.\n  Campaigns for the same domain in different accounts remain separate.\n- Indexing history and balance belong to the selected account. URL submissions\n  consume that account’s balance. Linked balances are not pooled.\n\nAccess is checked for every request. Explicit sharing of one website does not\ngrant access to its owner’s account context. Product limits and campaign\nrequirements apply to every selected account. The authenticated global ranking\nendpoints `/google-serp/rankings` and `/ai-analytics/rankings` are account-independent.\n\nMCP uses the same rules: call `semalt_get_me` or `semalt_list_accounts`, then\npass the required integer `account_id` to each account tool. Use\n`semalt_list_my_seo_campaigns` for `campaign_id`. No switch-account tool or\nconnection change is needed."},{id:`site-identity`,title:`Site identity`,body:"Site collections preserve separate accessible website records without domain\nor Search Console property deduplication. Hidden and removed records are\nexcluded. `access_type` is `own`, `linked`, or `shared` relative to the selected\naccount. Use the site record’s `id` as `site_id` in that same account context.\nSelecting a linked site does not automatically switch to its owner."},{id:`pagination`,title:`Pagination`,body:"Site collections use stable cursor pagination:\n\n```http\nGET /api/v1/accounts/ACCOUNT_ID/sites?limit=50&cursor=12345\n```\n\nUse `meta.next_cursor` for the next request while `meta.has_more` is true. The\nmaximum `limit` is 200.\n\nUse descriptive query parameters such as `search`, `search_engine_id`,\n`sort_direction`, and `url_contains`. AI Analytics accepts `model` with\n`gpt-4.1-nano` or `gpt-5-nano`; implementation-specific model identifiers are\nnot part of the public contract. The OpenAPI files below define the filters,\nallowed values, defaults, and pagination style for each endpoint.\n\nEvery site response contains `tags` from the selected linked group. Filter site collections with\ncomma-separated `tag_ids`, combine them with `tag_match=any|all`, and exclude\ntags with `exclude_tag_ids`. Reusable keyword groups are managed under\n`/accounts/{account_id}/sites/{site_id}/keyword-groups` and can filter My SEO keywords, Google SERP\nkeywords, and Google SERP best pages through `keyword_group_id`."},{id:`write-requests`,title:`Write requests`,body:`Write endpoints accept one JSON object and require
14\`Content-Type: application/json\`. Actions without fields still expect an empty
15JSON object \`{}
15\`. They add sites, manage site tags and keyword
16groups, add manual FullSEO campaign keywords, and submit URLs for indexing.
17The maximum JSON body size is 2 MB; product limits such as 10,000 URLs or
18keywords per request still apply.
19
20\`\`\`bash
21curl --request POST \\
22  --url 'https://semalt.com/api/v1/accounts/ACCOUNT_ID/sites' \\
23  --header 'Authorization: Bearer YOUR_API_KEY' \\
24  --header 'Content-Type: application/json' \\
25  --data '{"domain":"example.com"}'
26\`\`\`
27
28Replace \`ACCOUNT_ID\` with an account_id returned by \`/me\` or \`/accounts\`.
29
30Adding the same site, site-tag assignment, or keyword-group keyword again is
31safe: the API returns the existing record or skips the duplicate. Delete and
32membership-removal operations use explicit POST action URLs so an AI client can
33request user confirmation before invoking them.
34
35### My SEO keyword controls
36
37The My SEO keyword endpoints use public \`snake_case\` fields, including
38\`target_url\`, \`backlink_weight\`, \`backlink_share\`, and \`sort_direction\`.
39
40- \`POST /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keyword-mode\`
41  changes a launched FullSEO campaign between \`auto\` and \`manual\` mode.
42- \`POST .../keywords/status\` updates keyword review statuses. Auto mode allows
43  rejecting keywords and restoring rejected keywords to \`pending\`; manual mode
44  also allows \`approved\`.
45- \`POST .../keywords/backlink-weights\` changes integer weights from 1 to 10000
46  for approved keywords in manual mode.
47- \`POST .../keywords/backlink-allocation\` applies the dashboard’s one-shot
48  percentage allocation to approved keywords in manual mode. Supplied keyword
49  percentages are fixed for that request and omitted approved keywords share
50  the remainder equally. The fixed percentages are not persisted as a separate
51  configuration; call the keyword list endpoint afterwards to inspect the
52  resulting weights and shares.
53
54Keyword ids are the \`id\` values returned by the campaign keyword list. The
55allocation request accepts decimal percentages from \`0.01\` to \`100\` with at
56most two decimal places. All four control endpoints return the selected public
57campaign and a snake_case result summary.
58
59\`POST /accounts/{account_id}/indexing/urls\` consumes indexing balance and does not currently accept
60an idempotency key. If a client loses the response after sending the request,
61it should check \`GET /accounts/{account_id}/indexing/urls\` before retrying instead of retrying
62automatically.`},{id:`request-example`,title:`Request example`,body:`\`\`\`bash
63curl --request GET \\
64  --url 'https://semalt.com/api/v1/accounts/ACCOUNT_ID/search-console/sites?limit=25' \\
65  --header 'Authorization: Bearer YOUR_API_KEY' \\
66  --header 'Accept: application/json'
67\`\`\`
68
69Machine-readable contracts:
70
71- [OpenAPI JSON](https://semalt.com/api/v1/openapi.json)
72- [OpenAPI YAML](https://semalt.com/api/v1/openapi.yaml)
73
74Human-readable documentation is published at \`https://semalt.com/api-docs\`.`},{id:`errors`,title:`Errors`,body:"Errors use `application/problem+json` and include a stable `code` plus a\n`request_id`. Send the request id to support when investigating an error.\n\nCommon statuses are 401 for a missing or invalid API key, 403 for a product\nscope restriction, 404 for an inaccessible site id, and 502 when an analytics\ndata source is temporarily unavailable."},{id:`pdf-reports`,title:`PDF reports`,body:`Call \`GET /accounts/{account_id}/report-center/catalog\` first. Each item contains
75a ready-to-fill \`definition_template\`. Copy it into the run request and replace
76the \`null\` value in \`scope\` with an ID returned by \`/sites\` or
77\`/my-seo/campaigns\`.
78The template's \`scope.id_field\` is the exact field name (\`site_id\`,
79\`campaign_id\`, or no field for account/global items). Add only filters, columns,
80and comparison modes listed by that item. For custom PDF branding, call
81\`GET .../white-labels?search=...\`, take the returned \`white_label_id\`, and add it
82to the report \`definition\`. Omit \`white_label_id\` to use Semalt branding. All
83paths below are relative to \`/api/v1\`.
84
85For example, a catalog item for a site report provides a structure like this:
86
87\`\`\`json
88{
89  "scope": { "type": "site", "id_field": "site_id", "required": true },
90  "definition_template": {
91    "kind": "report",
92    "key": "search_console.site_overview",
93    "scope": { "site_id": null },
94    "period": { "type": "latest_snapshot" },
95    "filters": {}
96  }
97}
98\`\`\`
99
100To find a custom brand, use the same \`account_id\` as the report run:
101
102\`\`\`http
103GET /api/v1/accounts/20/report-center/white-labels?search=Acme
104\`\`\`
105
106The endpoint returns active white labels with uploaded logos. Use the exact
107\`data[].white_label_id\` value in \`definition.white_label_id\`; do not send the
108logo URL or company name in the run request:
109
110\`\`\`json
111{
112  "data": [
113    {
114      "white_label_id": "42",
115      "name": "Acme Reports",
116      "company_name": "Acme Ltd"
117    }
118  ],
119  "meta": {
120    "limit": 50,
121    "has_more": false
122  }
123}
124\`\`\`
125
126\`\`\`bash
127curl --request POST 'https://semalt.com/api/v1/accounts/20/report-center/runs' \\
128  --header 'Authorization: Bearer YOUR_API_KEY' \\
129  --header 'Content-Type: application/json' \\
130  --data '{
131    "definition": {
132      "kind": "report",
133      "key": "search_console.site_overview",
134      "scope": { "site_id": "123" },
135      "period": {
136        "type": "fixed",
137        "date_from": "2026-08-01",
138        "date_to": "2026-08-31"
139      },
140      "comparison": { "type": "previous_period" },
141      "white_label_id": "42"
142    },
143    "execution": "sync",
144    "disposition": "inline",
145    "idempotency_key": "gsc-123-2026-08"
146  }'
147\`\`\`
148
149The request waits for generation and returns JSON. Inspect \`data.status\`:
150
151- \`ready\`: \`view_url\` opens the PDF, \`download_url\` requests an attachment, and
152  \`url\` selects the requested disposition. Browser preferences can override inline display.
153- \`processing\`: an identical request is already running; use \`GET .../runs/{run_id}\`.
154- \`failed\`: inspect \`error_code\`; use a new idempotency key for another attempt.
155- \`expired\`: the original artifact has expired; use a new key to generate another.
156
157The required idempotency key is scoped to the actor and selected account, shared
158across REST/MCP, and retained with the run. A changed definition with the same key
159returns \`409\`. Replays do not consume another generation quota. Replayed ready
160runs receive new links to the same artifact; old links remain valid until revoked
161or expired. GET status/history never creates public links.
162
163PDF links grant **anyone holding the URL** access without an API key until 90 days
164after generation or explicit revocation. Site-access changes do not automatically
165revoke an already shared copy. \`POST .../runs/{run_id}/links\` issues another link;
166\`POST .../runs/{run_id}/links/revoke\` with \`{}\` revokes all current links. Issuing a
167link never extends artifact retention. Revocation does not delete the private PDF
168or prevent an authorized user from explicitly issuing a new link.
169
170\`GET .../runs\` lists owned/linked Report Center history, including browser runs,
171using descending ID cursors. API-created runs have no saved report definition and
172appear in dashboard history. No schedule, saved definition, or email is created.
173Public link issuance currently supports PDF only.
174
175Generation defaults: 1 concurrent / 3 per minute / 50 per rolling 24 hours for a
176standard actor; authorized staff have higher configured quotas. Account and global
177concurrency caps always apply, including to staff. \`429\` and capacity \`503\` errors
178include \`Retry-After\` when applicable; MCP errors include \`errors.retry_after\`.
179The default generation budget is 50 seconds. Allow a longer transport timeout to
180receive the completed response and accommodate admission and response overhead.
181
182Use fixed dates for an exact period. The template uses \`latest_snapshot\` by default;
183time-series sources resolve that to the latest available 28-day window. When the
184catalog item lists \`previous_period\`, add
185\`"comparison": {"type":"previous_period"}\` to put the immediately preceding
186period of the same length into the same PDF with comparison charts and deltas.
187Arbitrary internal \`params\`, account overrides, HTML, logo URLs, and export-source
188overrides are rejected.`}]},{id:`public-mcp`,title:`Semalt MCP server`,language:`en`,sections:[{id:`connect`,title:`Connect`,body:`Configure a remote Streamable HTTP MCP server with a URL that contains your Semalt API key as the \`token\` query parameter. This works for MCP clients that accept only a server URL.
189
190\`\`\`json
191{
192  "mcpServers": {
193    "semalt": {
194      "url": "https://semalt.com/mcp?token=YOUR_API_KEY"
195    }
196  }
197}
198\`\`\`
199
200>
200 **Keep the key private.** A URL token can appear in browser history, access logs, proxy logs, or shared configuration. Use a dedicated API key for URL-only MCP connections and rotate it if the URL is exposed.`},{id:`choose-an-account-context-with-one-key`,title:`Choose an account context with one key`,body:'The connection key identifies the token owner. Call `semalt_get_me` to identify that owner’s `account_id`, then `semalt_list_accounts` to discover accounts available for selection by name and email. Keep the same connection and pass the chosen `account_id` to each account tool.\n\nFor example, a key owned by account `10` can list indexing URLs for another available account `20` using these tool-call arguments:\n\n```json\n{\n  "name": "semalt_list_indexing_urls",\n  "arguments": {\n    "account_id": 20,\n    "page": 1,\n    "page_size": 50\n  }\n}\n```\n\nEvery account tool requires `account_id`. The server does not remember a selected account between calls. `semalt_get_account` reads a selected account’s details; `semalt_get_me` always identifies the key owner. `linked_account_ids` describes the returned account’s linked group and includes the account itself; it is not the list of all accounts available to the API key. Use `semalt_list_accounts` to determine which account IDs are selectable. Responses return IDs as strings; supply account, site and campaign IDs as integers in tool arguments.\n\nAccount results include `meta.actor_account_id` for the key owner and `meta.account_id` for the selected account. The two global ranking tools do not take an `account_id`.\n\n- **Sites and analytics:** tools show records owned by, linked to or explicitly shared with the selected account. Use `access_type=own` to show only its own sites. Added websites belong to the selected account.\n- **Site Tags:** shared across the selected linked group. Editing a tag affects every account in that group.\n- **Keyword Groups:** owned by individual accounts and editable by linked accounts. New groups belong to the selected account; editing an existing group preserves its owner. Groups apply to a site’s domain.\n- **My SEO:** use `semalt_list_my_seo_campaigns` to obtain `campaign_id`. Use that ID together with the same selected `account_id` for keywords and backlinks. Campaigns for the same domain in different accounts remain separate. A launched FullSEO campaign can switch between `auto` and `manual` keyword mode. Auto mode permits rejecting keywords and restoring rejected keywords to `pending`; manual mode also permits approving and rejecting keywords, changing approved-keyword backlink weights, and applying a one-shot percentage allocation.\n- **Indexing:** URL history and balance belong to the selected account. `semalt_add_indexing_urls` spends **that account’s balance**; linked-account balances are not pooled.\n\nCheck the intended account before submitting indexing URLs. If a submission response is lost, check that same account’s URL list before retrying; indexing submissions do not support an idempotency key.'},{id:`how-the-ai-should-work`,title:`How the AI should work`,body:"1. Call `semalt_get_me` for the token owner or `semalt_list_accounts` for account contexts available for selection, then explicitly pass the intended `account_id` to each account tool.\n2. Use only account IDs returned by `semalt_get_me` or `semalt_list_accounts` when selecting an account. Treat `linked_account_ids` as relationship metadata, not as the account-selection list.\n3. Call a `semalt_list_*_sites` tool in that account context to discover accessible site records.\n4. Keep duplicate domains: they can represent distinct account or GSC records.\n5. Use a site record’s `id` as `site_id` in site detail tools. Its `owner_account.account_id` identifies the owner; it does not automatically select that account. Use `campaign_id` from `semalt_list_my_seo_campaigns` for campaign tools.\n6. Follow `next_cursor` while `has_more` is true.\n7. For AI Analytics, use `model=gpt-4.1-nano` or `model=gpt-5-nano`.\n8. Use site tags to organize and filter domains, and keyword groups to filter My SEO and Google SERP keyword data.\n9. Ask for explicit confirmation before deleting a tag or keyword group, or removing tag/group members."},{id:`generate-a-pdf-report`,title:`Generate a PDF report`,body:'Call `semalt_get_report_catalog(account_id)` first. Each item contains a ready-to-fill `definition_template` and a `scope.id_field` that names the exact ID field. Copy the template into `semalt_generate_report` and replace its `null` scope ID with a value from the matching site or campaign tool.\n\nFor custom PDF branding, call `semalt_list_report_white_labels(account_id)`, take the returned `white_label_id`, and add it inside the report `definition`. The white-label tool lists active labels with uploaded logos. Omit `white_label_id` to use Semalt branding.\n\n```text\nsemalt_list_report_white_labels({ "account_id": 20, "search": "Acme" })\n\n{\n  "data": [\n    {\n      "white_label_id": "42",\n      "name": "Acme Reports",\n      "company_name": "Acme Ltd"\n    }\n  ],\n  "meta": { "limit": 50, "has_more": false }\n}\n```\n\n```text\nsemalt_get_report_catalog({ "account_id": 20 })\n\nsemalt_generate_report({\n  "account_id": 20,\n  "idempotency_key": "keywords-456-latest",\n  "definition": {\n    "kind": "table",\n    "ke
200y": "my_seo.keywords",\n"scope": { "campaign_id": 456 },\n"period": { "type": "latest_snapshot" },\n"filters": { "status": "approved" },\n"white_label_id": "42"\n},\n"disposition": "attachment"\n})\n```\n\nThe template already contains `kind`, `key`, `scope`, `period`, and `filters`. Add only optional fields listed by that catalog item; `white_label_id` is the optional global field for custom PDF branding. For Search Console reports and supported tables, `comparison: { type: "previous_period" }` puts the preceding equal-length period into the same PDF.\n\n```text\nsemalt_generate_report({\n  "account_id": 20,\n  "idempotency_key": "gsc-123-2026-08-compare",\n  "definition": {\n    "kind": "report",\n    "key": "search_console.site_overview",\n    "scope": { "site_id": 123 },\n    "period": { "type": "fixed", "date_from": "2026-08-01", "date_to": "2026-08-31" },\n    "comparison": { "type": "previous_period" }\n  }\n})\n```\n\nAnyone holding a report link can open the PDF for up to 90 days, unless the links are revoked. Use `inline` to open it or `attachment` to download it. A report generation does not send email.\n\nIf a tool response is lost, reuse the same `idempotency_key` and definition. A `processing` result can be checked with `semalt_get_report_run`. A failed generation requires a new key for another attempt. Existing files and new links retain their original expiry.'},{id:`access-rules`,title:`Access rules`,body:`The MCP server uses the API key from your Semalt account. Each account tool checks access to the selected account and then to the requested resource. A shared website alone does not grant access to its owner’s account context. Hidden and removed records are excluded.
201
202A campaign_id must belong to the selected account_id. Access to the selected account and requested resource is checked on every call; the selected account’s normal linked-group scope applies to site, tag and keyword-group operations. Product limits and campaign requirements continue to apply. Percentage allocation uses the same one-shot behavior as the dashboard: supplied approved-keyword percentages are fixed for that request, and omitted approved keywords share the remainder equally. It does not create a persistent fixed-percentage setting; call \`semalt_list_my_seo_keywords\` afterwards to inspect the resulting weights and shares.`},{id:`prefer-direct-http`,title:`Prefer direct HTTP?`,body:`Use the same data contracts without MCP through Public API v1.
203
204View API documentation`}]}
204],mcp_tools:[{name:`semalt_get_me`,description:`Get the API key owner account_id and that account’s linked_account_ids.`},{name:`semalt_list_accounts`,description:`List accounts available for selection with this API key.`},{name:`semalt_get_account`,description:`Get the selected account and its linked_account_ids.`},{name:`semalt_list_sites`,description:`List every accessible physical Semalt site row.`},{name:`semalt_get_site`,description:`Get one physical Semalt site row by site_id.`},{name:`semalt_list_search_console_sites`,description:`List physical Search Console rows with summary metrics.`},{name:`semalt_get_search_console_overview`,description:`Get Search Console summary and charts for a site_id.`},{name:`semalt_get_search_console_traffic`,description:`Get a daily Search Console metric series for a site_id.`},{name:`semalt_list_search_console_data`,description:`List Search Console queries, pages, devices, or countries.`},{name:`semalt_list_google_serp_sites`,description:`List physical sites with Google SERP metrics.`},{name:`semalt_get_google_serp_overview`,description:`Get Google SERP summary metrics for a site_id.`},{name:`semalt_get_google_serp_data`,description:`Get Google SERP keywords, pages, or competitors.`},{name:`semalt_list_google_serp_rankings`,description:`List global Google SERP rankings.`},{name:`semalt_list_ai_analytics_sites`,description:`List physical sites with AI visibility metrics.`},{name:`semalt_get_ai_analytics_overview`,description:`Get AI visibility summary metrics for a site_id.`},{name:`semalt_get_ai_analytics_data`,description:`Get AI Analytics queries, pages, or competitors.`},{name:`semalt_list_ai_analytics_rankings`,description:`List global AI visibility rankings.`},{name:`semalt_list_my_seo_campaigns`,description:`List campaigns owned by account_id and obtain campaign_id for detail tools.`},{name:`semalt_list_my_seo_keywords`,description:`List keywords for a campaign_id owned by account_id.`},{name:`semalt_set_my_seo_keyword_mode`,description:`Set a launched FullSEO campaign keyword_mode to auto or manual.`},{name:`semalt_update_my_seo_keyword_statuses`,description:`Update keyword_ids with status pending, approved, or rejected according to the campaign keyword mode.`},{name:`semalt_update_my_seo_keyword_backlink_weights`,description:`Set items shaped as {id, backlink_weight} for approved campaign keywords; backlink_weight is 1 to 10000.`},{name:`semalt_apply_my_seo_backlink_allocation`,description:`Set items shaped as {id, percentage} for a one-shot allocation; omitted approved keywords share the remainder equally and no fixed setting is persisted.`},{name:`semalt_list_my_seo_backlinks`,description:`List backlinks for a campaign_id owned by account_id.`},{name:`semalt_list_indexing_urls`,description:`List indexing URLs and statuses for account_id.`},{name:`semalt_add_site`,description:`Add a website owned by account_id.`},{name:`semalt_add_my_seo_keywords`,description:`Add manual keyword and target URL pairs to a launched FullSEO campaign.`},{name:`semalt_add_indexing_urls`,description:`Submit URLs for indexing using account_id’s balance. Check the intended payer and avoid automatic retries after a lost response.`},{name:`semalt_list_site_tags`,description:`List site tags shared by the selected linked group.`},{name:`semalt_create_site_tag`,description:`Create a site tag shared by the selected linked group.`},{name:`semalt_update_site_tag`,description:`Rename or recolor a site tag.`},{name:`semalt_delete_site_tag`,description:`Delete a site tag and its assignments after confirmation.`},{name:`semalt_list_site_tag_sites`,description:`List domains assigned to a site tag.`},{name:`semalt_add_sites_to_tag`,description:`Assign a site tag to accessible domains.`},{name:`semalt_remove_sites_from_tag`,description:`Remove a site tag from domains after confirmation.`},{name:`semalt_list_keyword_groups`,description:`List reusable keyword groups for a site.`},{name:`semalt_create_keyword_group`,description:`Create a reusable keyword group for a site.`},{name:`semalt_update_keyword_group`,description:`Rename an editable keyword group.`},{name:`semalt_delete_keyword_group`,description:`Delete an editable keyword group after confirmation.`},{name:`semalt_list_keyword_group_keywords`,description:`List keywords in a reusable group.`},{name:`semalt_add_keyword_group_keywords`,description:`Add keywords to an editable group.`},{name:`semalt_remove_keyword_group_keywords`,description:`Remove keyword rows from a group after confirmation.`}
204,{name:`semalt_get_report_catalog`,description:`Discover PDF report types, ready-to-fill definition templates, comparison modes, columns, and quotas.`},{name:`semalt_list_report_white_labels`,description:`Find active white labels with uploaded logos. Use the returned white_label_id inside semalt_generate_report definition for custom PDF branding.`},{name:`semalt_generate_report`,description:`Generate a PDF synchronously from a catalog definition_template and return public links valid for 90 days. Add white_label_id from semalt_list_report_white_labels inside definition for custom branding. Search Console reports and supported Search Console tables accept comparison.type=previous_period for comparison charts and deltas. Reuse the idempotency key after a lost response.`},{name:`semalt_list_report_runs`,description:`List report generation history.`},{name:`semalt_get_report_run`,description:`Get a report generation status and metadata.`},{name:`semalt_create_report_links`,description:`Issue public view and download links for a ready PDF.`},{name:`semalt_revoke_report_links`,description:`Revoke all existing public links for a report run.`}]};export{R as n,F as r,z as t};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.