Keyword.com
DATA · DATA & ANALYTICS
Rank-tracking projects, keywords, rankings, and competitors in that account.
Acts as the person, not as itself
Each user connects their own account. Every call carries both identities — the agent and the person it is acting for — so the agent can never reach past what that individual can already do.
Credentials never touch the agent
Tokens live in the vault and attach server-side at call time. The agent holds a session, not a secret, and revoking access does not mean rotating a key.
Every call on the record
Who asked, which agent acted, which action ran, and the verdict that let it through — one audit trail across every integration, not one per vendor.
What an agent can do
Each action is granted on its own. An agent allowed to read is not thereby allowed to write, and the scope beside each row is what the acting user must have connected for it to run at all.
keyword_delete_api_v2_groups_by_project_nameWRITEDelete project via DELETE /api/v2/groups/{project_name}. IRREVERSIBLE. Deletes the project or group by name, and with it every keyword in it and all of their historic ranking data. There is no recycle bin and no undo -- Restore project un-archives an ARCHIVED project and cannot bring back a deleted one. If the intent is to stop tracking for now, use Archive project instead: it is reversible and keeps the history. Deleting a parent project takes its groups with it.
keyword_delete_api_v2_groups_by_project_name_keywords_by_keyword_idWRITEDelete keyword via DELETE /api/v2/groups/{project_name}/keywords/{keyword_id}. IRREVERSIBLE, and it destroys history: the vendor's own words are "this cannot be undone and when deleted you lose all historic ranking data". To stop tracking a keyword while keeping its history, Update keyword with `status = 0` (inactive) or `2` (archived) instead. Deletes exactly the one keyword named in the path; use Bulk delete keywords for many at once.
keyword_delete_api_v2_projects_by_project_id_keywordsWRITEBulk delete keywords via DELETE /api/v2/projects/{project_id}/keywords. IRREVERSIBLE, and for many keywords at once: every id in `data.ids` is deleted from the project, with all of its historic ranking data, exactly as Delete keyword does one. THE TARGET IS THE NUMERIC `project_id`, not the project NAME the single-keyword tools take -- `attributes.project_id` from List projects. Read the ids back with List keywords and check them before calling; there is no undo and no recycle bin. To stop tracking reversibly, use Update keywords with `status` instead.
keyword_get_api_v2_ai_visibility_domainsREADList AI Visibility domains via GET /api/v2/ai-visibility/domains. Every AI Visibility domain configured on the account. THIS IS A SECOND PRODUCT on the same host and the same credential: AI Visibility tracks how a brand appears in AI search answers (ChatGPT, Perplexity, Google AI Overviews and others), while the rest of this integration tracks Google SERP rankings. Call this first -- every other AI Visibility tool needs the numeric `domain_id` it returns. An account without the AI Visibility product will have no domains to return.
keyword_get_api_v2_ai_visibility_domains_by_domain_idREADGet AI Visibility domain via GET /api/v2/ai-visibility/domains/{domain_id}. One AI Visibility domain by its numeric id, as returned by List AI Visibility domains.
keyword_get_api_v2_ai_visibility_domains_by_domain_id_metricsREADGet AI Visibility metrics via GET /api/v2/ai-visibility/domains/{domain_id}/metrics. The dashboard metrics for one AI Visibility domain. Three sections: `data.ownBrandMetrics` -- `visibilityScore`, `sentiment`, `mentions`, `citations`, `avgPosition`, `detectionRate`, `top3` and `validMetricsCount`, plus `trends`, `historicalData` and the per-topic and per-engine breakdowns; `data.competitorMetrics` -- the same figures per competitor; and `data.competitorTimeSeriesData` -- the series, keyed `hourly`, `daily`, `weekly` and `monthly`. `timeframe` sets the period length (`24h`, `7d`, `30d`, `3m`, `1y`; a bare number is days, default 30), `period_offset` steps BACKWARDS with a NEGATIVE value (-1 to -365; `0` is the current period) and `aggregation` picks the series granularity (`hourly`, `daily`, `weekly`, `monthly`; default `daily`). `topics[]`, `search_terms[]` and `engine[]` are repeatable filters -- pass each value as its own parameter. This is REPORTING data: the AI Visibility API exposes aggregates, not individual executions and not the raw AI answers.
keyword_get_api_v2_ai_visibility_domains_by_domain_id_metrics_citationsREADGet AI Visibility citations via GET /api/v2/ai-visibility/domains/{domain_id}/metrics/citations. Citation analytics for one AI Visibility domain: how often and where the domain is cited as a source in AI answers, aggregated at domain and URL level and broken down by AI engine and by query, with brand and competitor comparisons. `topics[]` and `search_terms[]` are repeatable filters. Keyword.com documents the payload by section rather than by field and publishes no schema for it.
keyword_get_api_v2_ai_visibility_domains_by_domain_id_metrics_sentimentREADGet AI Visibility sentiment via GET /api/v2/ai-visibility/domains/{domain_id}/metrics/sentiment. Sentiment analytics for one AI Visibility domain: brand and company sentiment aggregates, keyword clouds, and a sentiment breakdown per AI engine. `topics[]` and `search_terms[]` are repeatable filters. Keyword.com documents the payload by section rather than by field and publishes no schema for it.
keyword_get_api_v2_ai_visibility_domains_by_domain_id_search_termsREADList AI Visibility search terms via GET /api/v2/ai-visibility/domains/{domain_id}/search-terms. The tracked search terms (prompts) for one AI Visibility domain. Each carries the AI engines it is tracked on (`aiSearchEngines`, e.g. `chatgpt_gui`, `google_ai_overview`), its `status`, how many times it has run (`executionsAmount`), its update `interval`, its `region`, whether web search was enabled for it (`websearch`), its topic (`searchTermTopicRef`) and its tags. `lastExecutionTime` and `nextScheduledExecutionTime` say when the data was last refreshed and when it will be again -- worth reading before treating a metric as current, because the default interval is monthly. The term strings here are what the `search_terms[]` filter on the metric tools expects.
keyword_get_api_v2_alertsREADList alerts via GET /api/v2/alerts. Documented by Keyword.com as every alert on the account -- the ranking-movement notifications its dashboard and its emails show. THIS TOOL CANNOT BE CALLED and refuses before any request is sent: Keyword.com documents GET /api/v2/alerts in its own OpenAPI 3.2.0 contract and in its reference site, and the route is not mounted. MEASURED 2026-09-22 and again 2026-09-23, four ways each -- with a bogus bearer, with no Authorization header at all, with and without a trailing slash -- it answers 404 {"errors":[{"code":"404","title":"HTTP Error","detail":"Resource not found"}]} every time, byte-identical to an invented path on the same host, while every one of the other 23 documented routes answers 401 Unauthenticated to the same request. The 404 arrives BEFORE authentication, so it is the router and not an entitlement gate: no token, plan or setting reaches it. Alerts are readable in the Keyword.com dashboard and by email; there is no API for them today.
keyword_get_api_v2_groups_activeREADList projects via GET /api/v2/groups/active. Every ACTIVE project and group on the account, with its tags, its keyword count and its timestamps. This is the tool to call first: almost every other tool addresses a project by NAME (`project_name`) or by its numeric id (`project_id`), and both are in this reply -- `attributes.name` and `attributes.project_id`. Groups are sub-projects and are named with the `[sub]` convention (`Disney[sub]Disney Classics`); pass that whole string wherever a `project_name` is asked for. ARCHIVED PROJECTS ARE NOT HERE -- the path is `/groups/active` and there is no documented listing that includes archived ones, so a project that has been archived can still be read, restored or deleted by name but will not appear in this list. The reply also carries each project's `attributes.auth` -- the PROJECT AUTH KEY, a second credential Keyword.com issues for sharing one project's data with third parties -- and `shortkey`/`password`, which belong to its public ViewKey share link. Treat all three as secrets: they are returned by this read, and passing them on grants access to that project's data.
keyword_get_api_v2_groups_by_project_nameREADGet project via GET /api/v2/groups/{project_name}. One project or group by name, with the same shape List projects returns for each row: groups, tags, keyword counts and the project's numeric `project_id`. Works for an ARCHIVED project too, which is how an archived project is found at all -- List projects only returns active ones. Like the listing, this reply carries the project's `attributes.auth` project auth key and its ViewKey `shortkey`/`password`; all three are secrets that grant access to this project's data.
keyword_get_api_v2_groups_by_project_name_keywordsREADList keywords via GET /api/v2/groups/{project_name}/keywords. Every keyword in a project or group with its settings and its current ranking metrics, and the tool that yields the `keyword_id` values the other keyword tools need. PAGINATE: the default page size is 20 and the vendor recommends `per_page=250` with `page` walked upward -- a 500-keyword project is two calls at 250, twenty-five at the default. `date` (YYYY-MM-DD) returns the ranking data for one past day instead of the latest.
keyword_get_api_v2_groups_by_project_name_keywords_by_keyword_idREADGet keyword via GET /api/v2/groups/{project_name}/keywords/{keyword_id}. One keyword's settings and ranking metrics, by the `keyword_id` List keywords or Add keywords returned. `date` (YYYY-MM-DD) returns that day's ranking data instead of the latest, which is the cheapest way to answer "where did this rank on X" without pulling a whole chart.
keyword_get_api_v2_groups_by_project_name_keywords_ranking_urlsREADGet top pages via GET /api/v2/groups/{project_name}/keywords/ranking-urls. The pages of the tracked domain that actually rank in this project or group, with the keywords each one ranks for. Answers "which of my URLs is doing the work" without walking every keyword. Project-wide: there is no per-keyword or per-tag filter on this route.
keyword_get_api_v2_groups_by_project_name_metricsREADGet keyword metrics via GET /api/v2/groups/{project_name}/metrics. Aggregate movement for a project, group or tag: how many keywords improved, declined and held, and the counts per ranking band, each over daily, weekly, monthly, six-month, yearly and lifetime windows. `tagId` narrows it to one tag and `timeframe` to a number of days (the vendor's example is `30`). This is the project-level summary; per-keyword positions are in List keywords and the day-by-day series is in Get rank history.
keyword_get_api_v2_groups_by_project_name_regionsREADList regions via GET /api/v2/groups/{project_name}/regions. Every Google region (`google.com`, `google.co.uk`, ...) tracked in a project or group, with the number of keywords in each. Useful before Add keywords, whose `region` must be one of Keyword.com's accepted Google domains, and for reading a project's geographic spread without listing its keywords.
keyword_get_api_v2_groups_by_project_name_undo_archiveWRITERestore project via GET /api/v2/groups/{project_name}/undo/archive. WRITES, despite being a GET. Un-archives the named project or group and returns it to the active list; the ledger classifies this operation by its verb and this build reclassifies it as a write, because a read-only grant must not be able to change a project's state. Restored keywords resume updating at the next scheduled automatic cycle -- use Refresh keywords if the data is needed sooner. Only an ARCHIVED project can be restored; a DELETED one is gone.
keyword_get_api_v2_metrics_by_project_name_competitors_by_keyword_id_historyREADGet keyword competitors via GET /api/v2/metrics/{project_name}/competitors/{keyword_id}/history. The competitor ranking history for ONE keyword over a date range: which other domains held which positions, day by day. `dateRange` is REQUIRED and is ONE string with both halves joined by a DOT -- `2023-04-01.2023-04-15`. Both halves must be YYYY-MM-DD and the end must not precede the start. Do not send it as an array or an indexed parameter: `dateRange[]=` and `dateRange[0]=` are rejected with a 422.
keyword_get_api_v2_metrics_by_project_name_mindshare_latestREADGet share of voice (latest) via GET /api/v2/metrics/{project_name}/mindshare/latest. Documented by Keyword.com as the top 10 domains for a project's Share of Voice, as one current snapshot rather than a series. THIS TOOL CANNOT BE CALLED and refuses before any request is sent: Keyword.com documents GET /api/v2/metrics/{project_name}/mindshare/latest ("Get the top 10 domains for Share of Voice") in its own OpenAPI 3.2.0 contract, and the route is not mounted. MEASURED 2026-09-22 and again 2026-09-23, four ways each, it answers 404 Resource not found -- byte-identical to an invented path -- while its sibling GET /api/v2/projects/{project_id}/mindshare/from-cache answers 401 to the same request. The 404 precedes authentication, so no credential changes it. USE THE HISTORY TOOL INSTEAD: Get share of voice history reads the same mindshare data for a date range from Keyword.com's cache and IS mounted; ask it for the last few days and read the most recent point.
keyword_get_api_v2_projects_by_project_id_mindshare_from_cacheREADGet share of voice history via GET /api/v2/projects/{project_id}/mindshare/from-cache. Share of Voice ("mindshare") over a period, from Keyword.com's cache: which domains own what share of the visibility for this project's keywords. Ask either with `start_date`/`end_date` or with the `daysrange` shorthand (7, 30, 90, 180 or 365) -- `daysrange` is IGNORED when the explicit dates are given. THE SAMPLING INTERVAL FOLLOWS THE RANGE, which is the part worth knowing before charting the result: 7 days gives a point per day, 30 days a point per 7 days, 90 a point per 14, 180 a point per 30, and 365 a point per 60. `tagId` narrows it to one tag (0 or omitted means every keyword). Defaults are the last 30 days. THE TARGET IS THE NUMERIC `project_id`, not the project name. This is also the tool to use for the LATEST figures: the documented latest-only route is not mounted (see Get share of voice (latest)).
keyword_get_api_v2_projects_by_project_id_sharing_settingsREADGet sharing settings via GET /api/v2/projects/{project_id}/sharing-settings. The shared-report configuration for a project: the read-only page a Keyword.com share link opens. Returns the RESOLVED settings -- the per-project override where one is set, otherwise the account-wide default -- covering `visibility`, which keyword-table columns render, and the Overview and keyword charts. ONE READING TRAP the vendor documents: `visibility.hide_top_pages` reads `true` whenever `visibility.hide_overview` is `true`, because hiding the Overview tab hides Top Pages with it -- so a `true` there does not mean Top Pages was hidden on its own. THE TARGET IS THE NUMERIC `project_id`.
keyword_get_api_v2_users_selfREADGet current user via GET /api/v2/users/self. The account this connection is authenticated as: its identity, settings and plan. `include=subscriptions` adds the subscription records, which is where the plan's keyword allowance and its daily on-demand refresh quota are read -- check them before Refresh keywords, which is rejected whole (403, code 10003) when it would overrun the day's quota. This is also the integration's connection health check: it is the cheapest authenticated read on the API and touches no project.
keyword_patch_api_v2_groups_by_project_name_keywords_by_keyword_idWRITEUpdate keyword via PATCH /api/v2/groups/{project_name}/keywords/{keyword_id}. Change one keyword's settings. Only the attributes sent are changed. Three behaviours worth knowing before calling: `tags` REPLACES the keyword's whole tag set by name (a name the project does not have yet is created, and an empty array removes every tag -- there is no add-one-tag form); `category` MOVES the keyword into another project or group of the same account, which must already exist; and `status` is the reversible alternative to deleting -- `0` inactive, `1` active, `2` archived, all keeping the ranking history that Delete keyword destroys. `baseline` (0-100) resets the rank that the keyword's change figures are measured from.
keyword_patch_api_v2_projects_by_project_id_keywordsWRITEUpdate keywords via PATCH /api/v2/projects/{project_id}/keywords. Apply ONE set of attribute changes to MANY keywords: `data.ids` names them and `data.attributes` is applied to all of them. `tags` replaces the full tag set of EVERY listed keyword (an empty array clears their tags), and `url`, `region`, `language` and `type` re-point or re-target the whole batch, so check the id list before calling -- this is the fastest way to change a hundred keywords and the fastest way to change the wrong hundred. THE TARGET IS THE NUMERIC `project_id`, not the project name.
keyword_patch_api_v2_projects_by_project_id_sharing_settingsWRITEUpdate sharing settings via PATCH /api/v2/projects/{project_id}/sharing-settings. Change a project's shared-report configuration and get the full resolved settings back. PARTIAL, but not uniformly so, and the asymmetry is the thing to get right: a section that is sent is applied and a section that is omitted is left alone, but `visibility` and `keyword_columns.columns` merge MEMBER BY MEMBER while `keyword_charts` and `overview_charts` REPLACE their whole section -- so sending one chart in `overview_charts` removes every other one. `password` is three-state: omit the key to leave it unchanged, send `null` or an empty string to remove protection, send a non-empty string to set it. TWO ENTITLEMENTS GATE THIS: everything except `is_active` needs the caller's white-label management permission (without it the call answers 403), and setting a password on a project that has none additionally needs the account's white-label PLAN. A 403 here is a permission or plan answer, not a bad credential. THE TARGET IS THE NUMERIC `project_id`.
keyword_post_api_v2_groupsWRITECreate project via POST /api/v2/groups. Create one project, or one group inside an existing project. `data.attributes.category` is the NAME (the spec calls the field `category`); `currency_code` sets the currency cost figures are reported in. TO CREATE A GROUP rather than a top-level project, name it with the `[sub]` convention -- `Disney[sub]Disney Classics` -- and CREATE THE PARENT FIRST: the vendor states the parent project must exist before a group is added to it. Creating a project does not add keywords; use Add keywords afterwards.
keyword_post_api_v2_groups_by_project_name_keywordsWRITEAdd keywords via POST /api/v2/groups/{project_name}/keywords. Add one or more keywords to a project or group. `data` is an ARRAY, one entry per keyword, and each entry requires `category` (the project or group name, matching the path), `url` (the domain to track), `region` (a Google domain such as `google.com` or `google.co.uk`), `language` and `kw` (the keyword itself, 150 characters maximum). `url` WITHOUT a trailing slash tracks the whole domain; WITH one it tracks that exact URL -- the difference is load-bearing and easy to miss. `type` picks the device (`se` desktop, `sem` mobile) and `near` adds a location for local rank tracking. THE REPLY CARRIES NO RANKING DATA: the keywords are created and their metrics are collected in the background, so read them back with List keywords or Get keyword rather than expecting positions here. Adding keywords consumes the plan's keyword allowance.
keyword_post_api_v2_keywords_chartREADGet rank history via POST /api/v2/keywords/chart. READS, despite being a POST: the keyword ids go in the body because a list of them does not fit a query string, and nothing is created. The ledger classifies by verb and this build reclassifies it as a read. Returns the daily ranking position for each id in `kwid` for the last `limit` days -- up to 180, which is the documented maximum -- as both a chart-ready series of `[YYYY-MM-DD, rank]` pairs and the raw history with the ranking URLs. Pass `action=bulkChart` when asking for more than one keyword. Keyword ids come from List keywords.
keyword_post_api_v2_keywords_refreshWRITERefresh keywords via POST /api/v2/keywords/refresh. Run an on-demand ranking update for every keyword in the named projects, instead of waiting for the next scheduled cycle. `data.project_ids` is a list of NUMERIC project ids; `include_sub_groups` extends it to their groups. SPENDS QUOTA: every keyword refreshed consumes one on-demand refresh from the plan's DAILY quota, and a request that would exceed what is left is rejected WHOLE -- HTTP 403 with error code `10003` -- rather than partly served. So size the request first (List keywords gives the count per project) and read the account's remaining quota with Get current user. Results arrive asynchronously: the reply acknowledges the request, and new positions appear on the keyword reads a few minutes later.
keyword_put_api_v2_groups_by_project_nameWRITEArchive project via PUT /api/v2/groups/{project_name}. Move a project or group to the Archived state. Send `data.attributes.status = 2`; the spec's enum allows nothing else, so this operation only archives. Archiving is REVERSIBLE -- Restore project un-archives it -- and it is not a delete: the keywords and their ranking history stay. The project leaves List projects (which returns active projects only) and can still be read by name with Get project. Restoring resumes ranking updates at the next scheduled cycle.
Often connected alongside
Put Keyword.com behind one governed endpoint.
Same permissions, same audit trail, whatever else you connect next.