Documentation » Tool Reference
Tool Reference
Every tool the Kafkai MCP server exposes, grouped by what it does. Tool names are stable identifiers — your agent sees exactly these names.
To see the tools in use before reading them one by one, start with the Example Prompts page; each prompt there lists the tools the agent calls behind it.
Conventions
- Responses are JSON. Every tool returns a JSON document.
Successful responses include a
next_step_suggestionfield: advice the server computes for the agent's next move (which tool to call, or what to search the web for). Agents follow these hints without special prompting. - Usage reporting. Metered tools append a
_usageobject showing what the call cost and your remaining balance. See Credits and Billing. - Limits.
limitarguments are capped server-side (100 for keyword lists, 50 for clusters). Asking for more returns the cap, not an error. Lists longer than the cap are read a page at a time — see Reading a long list below. - Identifiers. Projects are addressed by
project_id(fromkafkai_list_projects), competitors bycompetitor_domain(fromkafkai_list_competitors), and publishing destinations bydestination_id(fromkafkai_list_publishing_destinations).
Reading a long list
A research run can return far more keywords than one call should carry, so the list tools return one page at a time. Every paged response says where its page sits:
count— rows in this response.total_matching— rows in the whole list the page came from.offset— rows skipped to reach this page.
To read the next page, call the same tool again with offset raised
by your limit. While rows remain, next_step_suggestion names the
exact offset to use, so an agent walks a long list without being told
how. A count smaller than your limit means the page is the last
one. An offset past the end returns no rows and reports how many
there are, rather than failing.
The keyword, cluster, backlink, Search Console and analytics list
tools all take offset. The tools that return one short list —
projects, competitors, publishing destinations — do not.
Each page is a separate call carrying its own flat call fee, so one call of 100 rows costs less than five calls of 20. Read in the largest pages a tool allows, and stop once you have what you need. See Credits and Billing.
Projects and competitors
kafkai_list_projects
Lists your projects with id, site URL, status, location, and
keyword and competitor counts. This is the usual first
call — later tools need the project_id it returns.
Arguments: none.
kafkai_get_project_summary
A full overview of one project: site metadata, niche, location,
keyword counts per 4C strategy and for your own ranking baseline,
the competitor list, and three blocks that say what data exists —
authority (your site's strength next to each competitor's),
backlinks (whether backlink data exists for your site and each
competitor, with the whole-profile totals, and a next_step_suggestion
naming which backlink tool to call) and search_console (whether
Kafkai can read your site's Google Search Console property, whether
the domain is verified for your account (domain_verified) and the
window its data covers, with a next_step_suggestion that names the
two Search Console tools or the step still missing: verifying the
domain, or granting access). The
response also names a recommended_strategy — the strategy with the
most keyword opportunities — with the reason. last_research is the
project's latest research run — a full update, or the research an added
competitor bought: pending while it is still running, then its verdict
(success, partial or failed) with the reason when something failed.
Arguments:
project_id— the project to summarise.
kafkai_list_competitors
Lists the competitor sites tracked in a project, with each
competitor's keyword count and research status. A competitor whose
research failed reads failed, with the reason in error; its keyword
lists are incomplete, and the response's next_step_suggestion says how
to retry — kafkai_update_keywords researches every domain again, or
remove the competitor and add it again for the competitor fee. The
response highlights the top_competitor by keyword count and carries
last_research, the project's latest research run.
Arguments:
project_id
kafkai_find_competitors
Finds the sites a project's site competes with in search, from the
keywords the site actually ranks for — not from a guess about its
homepage. Kafkai takes the domains that rank for the same keywords in
the project's country (the 1,000 largest sites on the web excluded),
scores each by how much of the two keyword footprints overlap, sizes
it against your site with the same winnability rule the 4C tools use,
and reads what each site is. Unrelated domains are dropped.
Competitors the project already tracks are flagged already_tracked,
so the list reads as "who else".
The response holds two lists:
competitors— the sites that compete with yours.comparison_sites— review sites, comparison sites, directories and listicle publishers. They are not competitors, so Kafkai keeps them out ofcompetitorsand returns them separately. If your business grows through affiliate and comparison sites, these are the sites to watch.
Each row in both lists carries domain, relationship (direct,
adjacent, or unknown when it could not be judged; always
aggregator in comparison_sites), winnability, rank (0–1000),
intersections (the keywords you share), overlap (that count as a
share of both footprints, 0–1), avg_position, etv,
keywords_count, sample_keywords and already_tracked.
filtered_out counts the unrelated domains Kafkai dropped, and site
gives your own keyword count, traffic estimate and rank. Competitors
are ordered direct competitors first, then winnable before avoid, then
by overlap. Comparison sites are ordered by overlap.
Three things to know when reading the rows:
- A site Google does not rank for anything yet is answered from the
searches its customers make (
methodiscustomer_searches, andseed_keywordslists them): who ranks on page one for those, smallest sites first.overlap,etvandkeywords_countare empty on that path andwinnabilityisunknown. - Kafkai returns the candidates and the evidence; which of them
matter is your agent's reading. Adding one is a separate, priced
step:
kafkai_add_competitor. - To follow a comparison site, add it with
kafkai_add_competitor. Kafkai then tracks its keywords and positions like any competitor. To see which comparison sites are on page one for a keyword, callkafkai_check_search_results.
Carries its own call fee, higher than a plain read, because the tool
buys fresh competitor, authority and judgement data rather than
returning what the project already holds; the per-row amount is the
same as every other read and counts the rows in competitors only.
Rows in comparison_sites are not charged. The answer is cached for
a day, so a repeat call returns the same lists. See
Credits and Billing.
Arguments:
project_idlimit— max competitors to return (default 10, max 20). The same limit capscomparison_sites.
kafkai_get_competitor_analysis
A focused analysis of one competitor: its brand description, the keywords it ranks for that you do not (Catch-up), and the keywords you both rank for (Compete). Higher base cost than a plain list.
Every keyword carries competitor_previous_rank and
competitor_rank_change (and our_previous_rank and
our_rank_change on Compete rows): the move since Kafkai's previous
measurement.
Arguments:
project_idcompetitor_domain— fromkafkai_list_competitors.include_history— set to true to include each keyword's dated positions:competitor_historyfor this competitor,our_historywhere you rank too.
Keyword research — the 4C strategies
The four strategy tools share their shape: each returns keyword
objects with search volume, keyword difficulty, CPC, ranks, the
ranking page's SERP title and description where relevant, tags, and
freshness timestamps (first_seen, last_updated). A recommended
subset highlights the strongest starting keywords by volume and
difficulty.
Every rank is dated. Each keyword also carries the move of each side
since Kafkai's previous measurement: our_previous_rank and
our_rank_change where you rank, competitor_previous_rank and
competitor_rank_change where the competitor does. A positive change
means the position moved up. Catch-up, Consolidate and Compete also
accept include_history: set it and each keyword carries the dated
positions Kafkai has recorded for every side that ranks
(our_history, competitor_history), oldest first, with unchanged
positions collapsed. For "what moved over the last three months", use
kafkai_get_ranking_changes below instead.
Catch-up, Consolidate and Compete each measure your site against a
competitor, so they stay empty until the project has at least one.
Complement does not — it works from your own topics, with or without
competitors. To see what your site ranks for when no competitor is
registered, use kafkai_get_ranked_keywords below.
All four take the same arguments:
project_idlimit— max keywords to return (default 20, max 100).offset— rows to skip, for paging (default 0). The response'snext_step_suggestionnames the next offset while more rows remain, andtotal_matchingsays how many rows there are in all.include_history— Catch-up, Consolidate and Compete only. Set to true to include the dated positions of each side that ranks.
kafkai_get_catchup_keywords
Catch-up: keywords competitors rank for that you do not — your content gaps. Each keyword shows which competitor ranks and with what title, so the agent knows exactly what page it is up against.
kafkai_get_consolidate_keywords
Consolidate: keywords you already rank for that competitors do not — the territory that is working and worth strengthening.
kafkai_get_compete_keywords
Compete: keywords where both you and a competitor rank — head-to-head battles. Both ranks are returned, so the agent can pick fights where the gap is small.
kafkai_get_complement_keywords
Complement: related keywords that neither you nor your competitors
target yet — what to add next to the topic map. Each keyword is
returned once, however many of your topics suggested it, so limit
counts distinct keywords.
kafkai_get_keyword_clusters
Semantic clusters: groups of related keywords that one comprehensive article can cover together. Each cluster carries its average search volume, difficulty, and CPC, plus its member keywords. The response recommends the highest-volume cluster.
Arguments:
project_idlimit— max clusters (default 10, max 50).offset— clusters to skip, for paging (default 0). The response'snext_step_suggestionnames the next offset while more clusters remain, andtotal_matchingsays how many there are in all.
Your own rankings
kafkai_get_ranked_keywords
Every keyword your site already ranks for, and how each position has moved. This is not one of the 4C strategies: those compare your site against a competitor, while this one reads your own positions directly. It works on a project with no competitors at all, which makes it the first useful call on a brand-new project.
Each keyword returns your current position, the previous one, the
change since the last measurement, whether the keyword is newly
ranking, plus search volume, difficulty, CPC and the page that ranks.
A progress object tallies what improved, declined, stayed flat and
is new, and how many keywords sit in the top 3 and top 10.
Set include_history and each keyword also carries the positions
Kafkai has recorded over time, oldest first — enough to chart a trend.
Unchanged positions are collapsed, so you get the moves rather than
one point per update.
Three things to know when reading the numbers:
- A keyword here may also appear under Consolidate or Compete. This is your whole ranking picture, not a slice of it.
progresscounts only the keywords this call returned, not the whole project. The project-wide figure istotal_ranked_keywords.- On the first call for a new project there is no earlier Kafkai measurement to compare against, so the change is counted from the position first seen.
Positions refresh when you run kafkai_update_keywords — that is what
adds the next point to each keyword's history.
Arguments:
project_idlimit— max keywords to return (default 20, max 100).offset— rows to skip, for paging (default 0). The response'snext_step_suggestionnames the next offset while more rows remain, andtotal_matchingsays how many rows there are in all.include_history— set to true to include past positions for each keyword.
Ranking changes over time
kafkai_get_ranking_changes
Which keywords gained or lost positions over a period — for your own site, one competitor, or every competitor at once. Every rank Kafkai measures is dated, so the tool compares each keyword's position at the start of the period with its position now and sorts the biggest moves first. It answers "what moved in the last three months", "where is this competitor slipping", "which keywords did I lose", and "what are my opportunities from competitors' falling rankings".
Each keyword returns its movement — improved, declined, new
(ranks now, did not at the period start) or lost (ranked at the
period start, does not now) — with current_rank and measured_at,
baseline_rank and baseline_measured_at, rank_change (positive
when the position moved up), first_seen, search volume, difficulty,
CPC and the ranking page. Competitor reports add competitor_domain
and our_rank: where your site sits on the same keyword right now. A
competitor sliding on a keyword you sit close behind, or do not rank
for yet, is the opening to write for.
A summary counts what improved, declined, stayed unchanged, is new
and is lost across every keyword measured for the site, not just the
rows returned. Unchanged keywords are counted there and left out of
the list.
Three things to know when reading the numbers:
- Updates run on demand, so there is no measurement for "exactly 90
days ago". The baseline is the latest measurement at or before the
period start, and
baseline_measured_atsays when that was. - When tracking began inside the period (
period.tracked_since), the first measurement stands in for the period start, and the keywords from that first run are not "new". - Rows are merged per keyword, so a keyword that moved between strategies keeps one continuous history.
Positions refresh when you run kafkai_update_keywords — that is what
adds the next dated measurement.
Arguments:
project_idcompetitor_domain— empty for your own site, a competitor's domain (fromkafkai_list_competitors) for that competitor, orallfor every competitor merged into one list (the response then also carriescompetitor_domainsand aby_competitorbreakdown).days— length of the period in days (default 90, max 365).movement—all(default; every kind of move but unchanged),improved,declined,neworlost.limit— max keywords to return (default 20, max 100).offset— rows to skip, for paging (default 0).total_matchingcounts the rows that matchmovement;summarystill counts the whole site.
Backlinks
Who links to your site and to each competitor, how strong those sites are, when each link was last seen, and how many links each site gained and lost over time. Kafkai returns the data; the reading — what the linking sites have in common, which lost link is worth chasing — is your agent's.
Kafkai fetches backlinks as part of every research run: for the site
and each competitor when a project is created, for the new competitor
when one is added, and for every site on kafkai_update_keywords. The
three read tools below answer from that snapshot; kafkai_update_backlinks
refreshes backlinks alone, without re-buying keyword data. Every
response says when the snapshot was taken (as_of), and a site that
has not been fetched yet says so instead of returning empty rows.
kafkai_get_backlinks
The sites linking to your site or to one competitor — one row per
referring domain, its strongest link, strongest first. It answers "who
links to competitor X", "how strong are the sites linking to me", and,
with status set to lost, "which links did competitor X lose that I
could win": every lost row names a site that once linked to a page like
target_page and stopped, with last_seen dating the loss.
Each row carries referring_domain, referring_page, target_page,
page_title, anchor, link_type, dofollow, link_rank,
referring_page_rank and referring_domain_rank (0–1000, higher is
stronger), spam_score, platform_types, country, first_seen,
last_seen, is_lost, is_new, is_broken and links_from_domain.
Two things to know when reading the numbers:
profileholds the whole link profile:domain_rank,backlinks_total,referring_domains_total, the nofollow and broken counts, and the link type, platform, country and TLD mixes. Quote those totals for the size of the profile.- The rows are a sample of it. Kafkai stores the strongest link from up
to 1,000 referring domains, and the strongest links lost within the
last year.
coveragesays how many rows are stored and whether the live sample is complete, so an agent can say "the strongest 1,000 of 18,452" rather than imply it saw everything.
Arguments:
project_idcompetitor_domain— empty for your own site, or a competitor's domain (fromkafkai_list_competitors). One site per call.status—live(default),lost(links that disappeared within the last year) orall.limit— max rows to return (default 20, max 100).offset— rows to skip, for paging (default 0). The response'snext_step_suggestionnames the next offset while more rows remain.
kafkai_get_backlink_changes
How many backlinks and referring domains a site gained and lost over a period — your own site, one competitor, or every site in the project side by side. Kafkai keeps a daily new/lost count for each site (a year of history from the first fetch), so the period is summed from that, with a month-by-month breakdown. It answers "how many links did competitor X win in the last three months", "is their link building accelerating", and "am I keeping pace".
Each site row carries status and as_of, totals_now (backlinks,
referring_domains, domain_rank), period_totals (new_backlinks,
lost_backlinks, net_backlinks, new_referring_domains,
lost_referring_domains, net_referring_domains), by_month, and
data_from / data_to — the days the stored history actually covers.
A site whose status is not ready has no counts yet.
Arguments:
project_idcompetitor_domain— empty for your own site, a competitor's domain (fromkafkai_list_competitors), orallfor your site and every competitor, one row each.days— length of the period in days (default 90, max 365).
kafkai_get_link_gaps
The sites that link to two or more of your competitors but not to you
— the link gap. One row per referring domain, strongest first, with the
link it gives each competitor (referring_page, target_page,
anchor, dofollow, link_rank, last_seen). A site that already
links to several competitors covers your topic and accepts links to
sites like yours, so it is the first place to ask for one. Kafkai
returns the rows; which sites to approach, and what to offer them, is
your agent's reading.
Each row carries referring_domain, competitor_count,
referring_domain_rank (0–1000, higher is stronger), spam_score,
country and links. competitors_with_data and
competitors_without_data say which competitors the answer covers.
Two things to know when reading the rows:
- It needs backlink data for your own site — that is how "not linking
to you" is decided — and for at least
min_competitorscompetitors. Until then the response names the sites still missing and how to fetch them. - "Not linking to you" is judged against the stored sample of your live
links (
own_site_coverage, the same shape ascoverageabove), so a site outside that sample can appear in the list although it links to you.
Arguments:
project_idmin_competitors— how many competitors a site must link to before it counts as a gap (default 2, minimum 1). Pass1to see every site that links to any competitor but not to you.limit— max rows to return (default 20, max 100).offset— rows to skip, for paging (default 0). The response'snext_step_suggestionnames the next offset while more rows remain.
kafkai_update_backlinks
Fetches fresh backlink data for your site and every competitor in a project: the linking sites and their strength, the links lost in the last year with the date each was last seen, and a year of daily gained/lost counts. This is what the three read tools above answer from.
Backlinks are already fetched by kafkai_create_project,
kafkai_add_competitor and kafkai_update_keywords. Use this tool to
refresh them without re-buying keyword data — for a project created
before backlinks existed, after a failed fetch, or when a day-old
snapshot is not fresh enough.
The fetch runs in the background and takes about a minute per site. A
site fetched within the last day is skipped, and a site whose fetch is
still running is not fetched twice, so calling this twice in a row costs
nothing extra. The response lists the sites it is fetching now
(domains), the ones it skipped (skipped_fresh) and the ones already
running (in_flight).
Charges a backlinks-only fee once per site actually fetched — smaller than a full update, because no keyword data is bought; see Credits and Billing.
Arguments:
project_id
Domain verification
Kafkai serves a site's own private data — its Search Console queries,
pages and clicks today, other sources later — only to an account that
has proved it controls the domain. The proof is one DNS TXT record on
the project's registered (apex) domain — a project on blog.example.com
is proved at example.com, and example.co.jp is proved at
example.co.jp (the Public Suffix List decides what "registered" means,
so a two-label country suffix is kept whole). One record opens every
subdomain project for your account. The code is unique to your account
and that domain. Two accounts can both verify one domain — a site owner
and their agency, say — each with their own record. Both tools are free.
- Call
kafkai_verify_domainwith theproject_id. The response'sdns_recordgives the record to add:type(TXT),name(the domain) andvalue(kafkai-verification=followed by the code). - Add that record at the DNS provider for the domain.
- Call
kafkai_check_domain_verification. Kafkai looks the record up; when it is there,statusbecomesverified. DNS changes usually show within minutes but can take up to 48 hours, so call again later if the record was not found yet.
Kafkai re-checks verified domains periodically. A record that is later removed stops the data until it is put back; the code stays the same, so there is nothing to redo but the record.
The same record, check button and status are on the Domains page of your account, one entry per domain — use it when you would rather copy the record from a browser than through the agent. Both paths share one code per domain.
kafkai_verify_domain
Starts verifying the project's domain, or returns the existing code, with the DNS record to add. Calling it again never changes the code.
Arguments:
project_id
The response carries domain (the project's registered domain, where
the record goes), status (pending or verified), dns_record
(type, name, value), verified_at, last_checked, last_error
and a next_step_suggestion.
kafkai_check_domain_verification
Looks the record up now and reports the result in the same shape as
kafkai_verify_domain. A missing record keeps status at pending
and says in last_error what was looked for. A lookup that got no
answer (a timeout) changes nothing; try again in a few minutes. Calling
this before kafkai_verify_domain is fine: the code is created and the
record to add is in the answer.
Arguments:
project_id
Search Console
Your own Google Search Console data, read by two tools. Kafkai's ranking data is a sample of search results; Search Console is what Google actually recorded for your site — every query it appeared for, with real clicks, impressions, click-through rate and average position. Together they answer what the rankings alone cannot: what people searched, which pages they clicked, and what changed.
Both tools describe one period: the latest 28-day window Kafkai has
stored, compared with the 28 days before it. Every row and the
property-wide totals carry clicks_change, impressions_change and
position_change against that prior window. position_change is
positive when your site moved up the page — the same sign the ranking
tools use.
Two steps stand between a project and its data. While
search_console.status is not_connected, both tools name the first
one still missing in their next_step_suggestion, so your agent can
pass it on to you.
- Verify the domain (see Domain verification above). Until then Kafkai serves nothing for the domain, not even whether a property exists.
- Grant Kafkai read access to the property. This is one step in Search
Console, and shares nothing but an email address: open the property
in Google Search Console,
go to Settings > Users and permissions > Add user, enter
the Kafkai reader address and choose the Restricted permission
level. The address is in the
next_step_suggestiononce the domain is verified. For a walkthrough with screenshots, see Connect Google Search Console.
Kafkai picks the property up at the next research run
(kafkai_update_keywords), backfills 16 months of history, and
refreshes it at the end of every later run. Until the first sync
finishes the status is syncing.
Two things to know when reading the numbers, both Google's doing:
- Google leaves out the queries it anonymises, so the query rows add
up to less than the property's true totals.
totalsare exact, andcoveragereports the impressions the query rows carry (visible_impressions), the exact total (total_impressions) and the share between them (visible_impressions_share). The share is measured over the rows the call returns, so it describes what you can actually see. - Google Discover reports pages and totals but no queries, so
search_type='discover'works with the pages and trend views only.
kafkai_get_search_console_data
The queries your site appears for, the pages that earn the traffic, or the daily totals — three views of one period.
view='queries'(default): one row per search query in the current window —query,clicks,impressions,ctr,position, the prior window's numbers underprior, and the three change fields.view='pages': one row per page of your site, summed from Google's daily page figures, which are exact.view='trend': one row per day, oldest first, taken from the recent end of the prior and current windows — enough to see the day traffic turned. Passlimit=100for the whole series.
Every response carries search_console (property, status,
domain_verified),
window, prior_window and totals (current, prior and the
change fields). Use it next to kafkai_get_ranked_keywords: a query
here that the ranking data does not show is a real search Kafkai's
sample missed.
Arguments:
project_idview—queries(default),pagesortrend.order_by— for the queries view:impressions(default),clicksorposition(best first). Pages are always ordered by impressions.contains— only queries (or page URLs) containing this text, case-insensitive. The trend view has neither, so it ignores this and does not echo it back.search_type—web(default) ordiscover.limit— max rows to return (default 20, max 100). For the trend view it is a number of days counted back from the most recent, solimit=100returns the whole series in one call.total_matchingalways says how many days the two windows hold.offset— rows to skip, for paging (default 0). The trend view counts back from the most recent day, sooffsetsteps further into the past. The response'snext_step_suggestionnames the next offset while more rows remain.
kafkai_get_search_console_insights
What to work on first, computed by Kafkai from your Search Console
data. Five kinds of flag, each a query or page with the numbers behind
it in evidence and a score to rank by within its kind:
striking_distance— queries ranking just off page one (positions 8–20 by default) with real impressions. Score: the extra clicks expected from reaching position 5.ctr_gap— queries whose click-through rate is far below what their position normally earns on your site: usually a title or snippet problem, not a ranking problem. Score: clicks lost.cannibalisation— one query split across two or more of your pages, each taking a real share of the impressions. Score: the impressions at stake.new_query— queries your site newly appears for, compared with the prior window. Score: impressions.decay— pages whose clicks dropped hard against the prior window, computed for web search and Google Discover separately. Score: clicks lost.
The response's definitions states each rule with the thresholds in
force, and counts says how many flags of each kind exist. Scores
compare within a kind only — the units differ. Kafkai computes the
flags; deciding what to change is your agent's reading of the
evidence, with kafkai_get_search_console_data for the surrounding
rows.
Arguments:
project_idinsight_type—all(default) or one ofstriking_distance,ctr_gap,cannibalisation,new_query,decay. Withall,limitandoffsetapply per kind.limit— max rows to return per kind (default 20, max 100).offset— rows to skip per kind, for paging (default 0).
Analytics
Your own traffic analytics, read by one tool. Search Console covers the search angle — what people searched for and what Google recorded. Analytics covers the whole visit: how many people came, which pages they opened, where they came from, and what they used to browse. It answers what the search data cannot: how much traffic the site gets overall, and what visitors do once they arrive.
Two steps stand between a project and its data, and the analytics.status
block (not_verified, not_configured, unavailable, ready) names
the one still missing in next_step_suggestion:
- Verify the domain (see Domain verification above). Until then Kafkai serves nothing for the domain, not even whether analytics tracking exists for it.
- Ask Kafkai support to set up tracking for the site. Kafkai sets it up on its own analytics instance; there is no customer-side setup, and nothing to connect afterwards: the first call finds the site automatically and keeps it. A site set up a moment ago can take up to ten minutes to appear. A project on a subdomain uses the site of its registered domain when it has none of its own.
unavailable means Kafkai could not reach its analytics service on
this call; it says nothing about whether tracking exists. Try again in
a minute.
Unlike Search Console there is nothing to wait for: the data is read
live at call time, so once the status is ready the next call returns
what the site holds right now.
kafkai_get_analytics_data
Traffic, pages, referrers, visitor location and devices, in 21
reports. By default it covers the last 30 days; pass
period='day' and date='last30' for a daily time series.
Every response carries analytics (status, domain_verified,
id_site, site_url), the report, a short description of the
report, the period and date in force, count and rows. While
more rows remain, next_step_suggestion names the offset for the
next page.
Arguments:
project_idreport— one of:summary(default),pages,entry_pages,exit_pages,page_titles,outlinks,downloads,referrers,search_engines,keywords,social,websites,campaigns,countries,regions,cities,device_types,browsers,browser_versions,operating_systems,screen_resolutions.summaryreturns one metrics row — visits, unique visitors, actions, bounce rate and average visit duration; the rest return a list of rows.period—day,week,month,yearorrange. Empty defaults torange.date— empty defaults to the last 30 days. Examples:today,last30,2024-01-01,2024-01-31(forperiod='range').segment— optional segment definition to filter visits.limit— max rows to return for list reports (default 20, max 100). Ignored bysummary.offset— rows to skip, for paging (default 0).
kafkai_get_ga_analytics_data
The customer's own Google Analytics 4 data: traffic, pages, landing pages, channels, source/medium, countries, cities, devices, browsers, operating systems and key events. Read live from the customer's GA4 property — not stored, so there is nothing to sync or wait for once access is granted.
Same domain-verification gate as Search Console and analytics. The
ga_analytics.status block (not_verified, not_connected,
ambiguous, unavailable, ready) names the step still missing in
next_step_suggestion:
- Verify the domain (see Domain verification above).
- In Google Analytics, go to Admin › Property access management › Add users, enter the Kafkai reader address and pick the Viewer role. Kafkai finds the property on the next tool call — no research run needed.
ambiguous means more than one GA4 property claims the site; contact
Kafkai support with the property id to use.
Every response carries ga_analytics (status, domain_verified,
property_id, property_name, stream_uri), the report, a short
description, start_date and end_date in force, count, total,
subject_to_thresholding and rows. GA4 can take 24-48 hours to
process data, and may hide small rows for privacy —
subject_to_thresholding says when that happened. Numbers will not
match Search Console: GA4 counts sessions from all sources, Search
Console counts clicks from Google Search.
Arguments:
project_idreport— one of:summary(default),daily,pages,landing_pages,channels,source_medium,organic_landing_pages,countries,cities,devices,browsers,operating_systems,key_events.summaryreturns one metrics row; the rest return a list of rows.start_date— ISO date (2026-08-01) or GA4 relative date (30daysAgo,yesterday,today). Empty defaults to 30daysAgo.end_date— ISO date or GA4 relative date. Empty defaults to yesterday.limit— max rows to return (default 20, max 100). Ignored bysummary.offset— rows to skip, for paging (default 0).
SERP intelligence
kafkai_get_keyword_serp_data
Everything known about one keyword in a project: who ranks (domains,
SERP titles, descriptions, URL types), your rank, competitor ranks,
rank changes, search volume, difficulty, CPC, and tags. The response
includes a ranking_context interpretation — for example, "competitor
ranks #3, you don't rank — write content to capture this demand".
If the exact keyword is not found, near matches are returned instead.
Higher base cost.
Arguments:
project_idkeyword— the exact keyword to look up (falls back to a contains-match).
kafkai_check_search_results
Checks which sites are on page one of Google for keywords you choose, in the project's country and language, and reports what changed since the last check. Use it to monitor the sites that rank for your main keywords: whether your site is on page one, which comparison and review sites rank, and who entered or left since last week.
This tool differs from kafkai_get_keyword_serp_data in two ways.
It returns every site on page one, not only your site and your
competitors. And the keyword does not have to be in the project's
research data — you can check any keyword.
For each keyword, checks holds one entry:
keyword— the keyword as checked (trimmed and lowercased).checked_at— when Kafkai fetched the page.fetched_fresh—truewhen this call fetched the page,falsewhen Kafkai returned a page stored within the last 24 hours.own_site_position— your site's best position on the page, ornullwhen it is not on page one.results— the organic results of page one, up to 10 rows.changes— what changed since the previous stored page.nullon the first check of a keyword.
Each row in results carries position (among organic results),
rank_absolute (among every element on the page, the number the
keyword tools report), domain, url, title, description and
three flags:
is_own_site— the result belongs to the project's site.is_tracked_competitor— the result belongs to a competitor the project tracks.links_to_own_site— the site has a live link to your site in Kafkai's backlink data. That data is a sample, andown_site_backlink_coveragesays how complete it is. Sofalsemeans "no link in the sample", andnullmeans Kafkai has no backlink data for your site yet. A link that goes through an affiliate network's redirect domain is not detected.
changes holds previous_checked_at and three lists, compared site
by site: entered (sites new on page one), left (sites no longer
on page one) and moved (sites whose position changed; change is
positive when the site moved up).
Four things to know:
- Kafkai checks only when you call the tool. Nothing runs on a schedule. To follow the changes, call the tool again with the same keywords, for example once a week.
- A page stored within the last 24 hours is returned again. Kafkai does not fetch it a second time, and that keyword adds nothing to the cost.
- Kafkai returns who ranks, not what the pages say. To see whether
a comparison page lists your service, and at which place, your agent
opens the
urlof the row and reads the page. - A keyword whose fetch failed is listed in
failedand is not charged. Call the tool again to retry it.
Cost: 1 credit per call, plus 5 credits for each keyword Kafkai
fetches fresh. A call with 10 keywords costs at most 51 credits. A
call that returns only stored pages costs 1 credit. A call that is
refused, or that returns no page at all, costs nothing. The response
reports the charge in billing. See
Credits and Billing.
Arguments:
project_idkeywords— the keywords to check, as a list. Up to 10 per call; a longer list is refused.
Project management
These tools change data. Research runs asynchronously — queue it,
keep working, and check back with kafkai_get_project_summary.
kafkai_create_project
Creates a project for a site, adds any competitors you give, and queues the full keyword research — including the backlinks of the site and of each competitor (see Backlinks). Priced per site researched: a base fee for your site plus a competitor fee for each competitor you give; see Credits and Billing.
Arguments:
site_url— the site to analyse, for examplehttps://example.com. Required.site_name— a display name; defaults to the URL.description— a short description of the site.location_code— the country whose search results the project targets. Required, with no default. The code is 2 followed by the country's ISO 3166-1 numeric code: Japan is2392, Malaysia2458, the United States2840. Call the tool without it and it fails for free, listing every market you can pick.competitors_url— a list of competitor site URLs. Optional.
Competitors are optional, and you can add them later with
kafkai_add_competitor. Without them, Catch-up, Consolidate and
Compete stay empty — each needs a competitor to compare against — but
Kafkai still collects your own ranking baseline and Complement
keywords, so a project starts useful with nothing but a domain and a
country.
A project is locked to one country. Research for the wrong country costs the same and tells you nothing, which is why Kafkai asks instead of guessing.
kafkai_add_competitor
Adds one competitor to an existing project and fetches only that competitor's data — its keywords and its backlinks. Existing competitors and the site itself are not re-fetched, so this is much cheaper than a full update: it charges the competitor fee once.
The research runs in the background and is logged like a full update;
the response carries its update_log_id. Check kafkai_list_competitors
a few minutes later: the competitor's status reads ready when its
data is in, or failed with the reason in error. While the research
runs, kafkai_update_keywords and the delete tools are refused for the
project.
Arguments:
project_idcompetitor_url
kafkai_delete_competitor
Removes one competitor from a project, together with every keyword Kafkai collected for it and that keyword's ranking history. Use it when a competitor was added by mistake and its unrelated keywords are polluting the Catch-up, Consolidate and Compete lists. Free.
The deletion is permanent, so the tool runs in two steps:
- Call it without
confirmation_token. Nothing is deleted. The response lists what would be removed (keywords per strategy, research sessions, ranking history) and what would be kept, and includes aconfirmation_tokenvalid for 15 minutes. - Your agent shows you that summary and asks you to confirm. Only
then does it call the tool again with the same
project_idandcompetitor_domainplus the token. The competitor is marked for deletion and its data is removed in the background; check withkafkai_list_competitorsa few minutes later.
A token is bound to one competitor and one account. Reused for a different competitor, or after it expires, it is refused and nothing happens. The deletion is refused while a keyword update for the project is running; wait for it to finish and ask again.
Arguments:
project_idcompetitor_domain— fromkafkai_list_competitors; a full URL is accepted too.confirmation_token— empty for the preview; the token from the preview to run the deletion.
kafkai_update_keywords
Queues a fresh ranking update for the whole project: all strategies
and your own ranking baseline are re-fetched, ranks on existing
keywords refresh, and keywords that dropped out are marked lost. This
is what adds the next point to each keyword's position history, so run
it before asking kafkai_get_ranked_keywords or
kafkai_get_ranking_changes what moved. The backlinks of the site and
of every competitor are refreshed in the same run (a site fetched within
the last day is reused). Priced like creation: the base fee for your
site plus the competitor fee for every competitor in the project.
Only one research run per project happens at a time; a second request while one is running — including the research an added competitor triggers — is refused. A project whose deletion you have confirmed cannot be updated either; that request is refused before anything is charged. Updates run on demand — Kafkai does not re-fetch rankings on its own schedule.
Arguments:
project_id
kafkai_delete_project
Deletes a project and everything in it: competitors, every keyword with its ranking history, and research sessions. Use it for a project you no longer need, or one that was set up with the wrong site. Free.
The deletion is permanent, so the tool runs in two steps:
- Call it without
confirmation_token. Nothing is deleted. The response lists what would be removed (competitors, keywords per strategy, research sessions) and what is not touched, and includes aconfirmation_tokenvalid for 15 minutes. - Your agent shows you that summary and asks you to confirm. Only
then does it call the tool again with the same
project_idplus the token. The project is marked as deleting and its data is removed in the background; check withkafkai_list_projectsa few minutes later.
A token is bound to one project and one account. Reused for a different project, or after it expires, it is refused and nothing happens. Posts already published to your own site stay live, and publishing destinations and publication records belong to your account and are kept. The deletion is refused while a keyword update for the project is running; wait for it to finish and ask again.
Arguments:
project_idconfirmation_token— empty for the preview; the token from the preview to run the deletion.
Publishing
Kafkai does not write articles. Your agent writes the piece from the data above, then hands the finished text to Kafkai to publish. Kafkai keeps a snapshot of exactly what it sent — title, body, language — as the publication record; it holds no other copy of the article.
To set up a WordPress site as a destination, see Connect WordPress. You need a WordPress username with write permission and an Application Password — not the WordPress login password.
kafkai_list_publishing_destinations
Lists the active publishing destinations on your account — WordPress
sites and webhooks — with each one's destination_id, name, type and
URL. Destinations belong to the account, not to a project. Free.
Arguments: none.
kafkai_add_publishing_destination
Adds a destination. For WordPress, pass the site URL and an application password; for a webhook, the endpoint URL and its credentials. The credentials are stored encrypted and never returned. Free.
Arguments:
name— a label for the destination (unique on your account).destination_type—wordpress(default) orwebhook.url— the site or endpoint URL.auth_type—basic(default),api_key,beareroroauth2.credentials— the login details for that auth type. For WordPress:usernameandpassword, where the password is an Application Password, not the WordPress login password. A WordPress destination without both is rejected. For a webhook:username(oremail) andpassword, sent as HTTP Basic Auth. A webhook without them is called with no authentication. Bearer tokens and API keys are not supported for webhooks yet.
kafkai_delete_publishing_destination
Removes a destination. Posts already published through it stay where they are, and their publication records are kept. Free.
Arguments:
destination_id
kafkai_publish_article
Publishes text your agent wrote to one destination and returns where
the post went (external_url). Pass the body as HTML in content, or
as Markdown in content_markdown — when content is empty, the
Markdown is rendered to HTML for you, and webhook destinations also
receive the Markdown as written. The post goes up as a draft unless you
ask for it to go live, so you can review it on your own site first.
To update an existing post instead of creating a new one, pass its
external_id (returned by a previous publish call). This edits the
existing post on the destination rather than creating a duplicate.
To publish one article in several languages, call the tool once per
language, with language set (en, ja). Give every language version
the same slug: a receiver such as kafkai.ai uses the slug to link the
versions as translations. To update one version later, pass the
external_id that the call for that language returned.
Arguments:
project_id— the project the article was written for; its market sets the default language.destination_id— fromkafkai_list_publishing_destinations.titlecontent— the body as HTML. Required unlesscontent_markdownis given.content_markdown— the body as Markdown.language— e.g.enorja. Defaults to the project's market language.post_status—draft(default) orlive.categories— category names, e.g.["Education", "Coffee"]. On WordPress, categories that don't exist yet are created automatically. Webhook destinations receive the list as-is.slug— the URL slug for the post, e.g.my-first-article. Webhook destinations receive it as-is. Use the same slug for every language version of one article.external_id— the ID of an existing post on the destination to update instead of creating a new one. Use theexternal_idreturned by a previous publish call for the same language. When omitted, a new post is created.author— the author's email or display name, as the destination knows it. Up to 255 characters.excerpt— a short summary for article listings. Up to 2,000 characters.seo_title— the title shown in search results (the HTML<title>), when it differs fromtitle. Up to 255 characters.meta_description— the text shown under the headline in search results. Up to 2,000 characters.featured_image_url— the publichttporhttpsURL of the featured image, up to 2,000 characters. The receiver downloads it. Kafkai rejects a URL whose host is private, local or internal (localhost,10.0.0.5, a name that resolves to such an address), so the receiver never downloads from its own network.
A value that breaks one of these rules is rejected before anything is stored or sent.
author, excerpt, seo_title, meta_description and
featured_image_url are sent to webhook destinations only. WordPress
destinations ignore them for now. Kafkai stores all five on the
publication record with the title and body. Some webhook receivers
require author and slug; kafkai.ai requires both.
Webhook request and response
This section is for the developer who builds a webhook receiver.
Request. Kafkai sends one POST to the destination URL for every
kafkai_publish_article call:
- Header
Content-Type: application/json. - HTTP Basic Auth (
Authorization: Basic …) when the destination has ausername(oremail) and apassword. Without them, noAuthorizationheader is sent. - No signature header.
- Kafkai waits 30 seconds for the response. It does not retry: a timeout or an error response fails the call.
The JSON body:
| Field | Sent | Value |
|---|---|---|
title |
always | The post title. |
content |
always | The body as HTML. Rendered from content_markdown when the agent gave only Markdown. |
status |
always | draft or live. |
content_markdown |
when not empty | The body as Markdown, as the agent wrote it. |
language |
when not empty | A language code such as en or ja. |
slug |
when not empty | The URL slug. Shared by every language version of one article. |
categories |
when not empty | A list of category names. |
author |
when not empty | The author's email or display name. |
excerpt |
when not empty | A short summary for listings. |
seo_title |
when not empty | The title for search results. |
meta_description |
when not empty | The text under the headline in search results. |
featured_image_url |
when not empty | A public http/https image URL to download. |
external_id |
on update only | The ID of the post to update. |
Example:
{
"title": "How to build an AI strategy",
"content": "<p>Rendered HTML</p>",
"content_markdown": "Markdown body",
"status": "live",
"language": "en",
"slug": "build-ai-strategy",
"author": "[email protected]",
"categories": ["AI Strategy"],
"excerpt": "One or two sentences for listings.",
"seo_title": "How to Build an AI Strategy | Example",
"meta_description": "Text shown under the headline in search results.",
"featured_image_url": "https://example.com/hero.jpg",
"external_id": "123"
}
Response. Kafkai accepts status 200, 201 or 202 with a JSON
body (Content-Type: application/json):
id(orexternal_id) — required. The receiver's ID for the post. Kafkai returns it to the agent asexternal_id.url— the public or preview URL of the post. Kafkai returns it to the agent asexternal_url. When it is missing, Kafkai returns the webhook URL instead.
Any other status fails the call. Kafkai shows the agent the error or
message field of a JSON error body. A success status with an HTML
body, a non-JSON body or no ID also fails the call.
Updates. An update is the same POST to the same URL, with
external_id in the body. The receiver decides between create and
update from external_id: with it, change that post; without it,
create a new one.
Languages. One call sends one language version. An article in
English and Japanese is two requests with the same slug and a
different language. The receiver links the versions by the slug, and
returns a different id for each. Each version is later updated with
its own id.
Account
kafkai_get_account
Which Kafkai account this connection uses. Free.
If you connect more than one Kafkai account to your agents, ask the agent "which Kafkai account am I connected to?". The agent calls this tool and tells you. It also calls it before a tool that costs credits when you say you have more than one connection, so you know which account pays.
Returns:
email— the email address you sign in to Kafkai with.name— the account name, empty when you have not set one.connection— how this agent is connected:typeisoauth(you approved the agent in Kafkai) orapi_token(you pasted a token from Kafkai),labelis the agent's name or the token's name, andauthorized_atis when you connected it.credit_balance— the account's balance.
Kafkai reads all of this from the connection itself. The tool takes no arguments, so it cannot show any other account. If you connect a shared agent, such as a team chat bot, everyone who uses that agent can see this account's email address.
Arguments: none.
Credits
kafkai_get_credit_balance
Your current balance, lifetime totals, and the last ten transactions with per-call cost breakdowns. Free — checking your balance never costs credits.
Credits are valid for 90 days from the day they are added, and the
oldest are spent first. expiring lists every batch still unused with
its valid_until — the last day those credits can be spent — soonest
first, so an agent can tell you when to use what is left.
Arguments: none.