Give your AI agent a read on the app market. This toolkit connects it to Appfigures: download and revenue estimates, reviews, rankings, keywords, and ads for any app on any major store, not just your own.
Ask it things like:
- "How many downloads and how much revenue is Spotify pulling in?"
- "Is Headspace growing or shrinking over the last six months?"
- "Who's advertising on 'meditation', and how dominant are they?"
- "What keywords does Duolingo rank for that we don't?"
- "What are users complaining about in an app's newest 1-star reviews?"
- "Who actually uses ChatGPT: their age, gender, and what else they use?"
Setting it up with a coding agent? Point it at llms.txt: the doc map for wiring this into your agent.
npm install @appfigures/agent-toolkitimport { AppfiguresAgentClient } from '@appfigures/agent-toolkit'
const af = new AppfiguresAgentClient() // reads APPFIGURES_API_KEY
const { results } = await af.apps.search({ q: 'spotify', count: 1 })
console.log(results[0]) // name, downloads_last_month, revenue_last_month_usd, storefronts …Get an API key at https://appfigures.com/developers/keys, then set it as APPFIGURES_API_KEY (or pass apiKey in code).
What a key can see. Estimates, ratings, reviews, ranks, keywords, and catalog data work for any app on any store, your own or a competitor's. Store-reported numbers for your own apps (actual sales, revenue, subscriptions, and ad spend) require linking that app's store account to Appfigures, or being granted access to it.
Bring Appfigures into your agent however it's built — as tools it calls, code it writes, a CLI, or over MCP. The actions and their JSON-serializable shape are identical across all four.
- Agent tools — your agent calls Appfigures actions as tools while it runs. AI SDK, OpenAI, LangChain. → Add the tools
- The client — your agent writes code that queries Appfigures and gets typed data back. → Use the client
- CLI — run Appfigures from a terminal or a sandbox. →
@appfigures/cli - MCP — connect Appfigures to Claude Desktop or Cursor. →
npx @appfigures/cli mcp
- App performance — download and revenue estimates, and any numeric metric, for your apps or a competitor's.
- Reviews and ratings — read reviews, break them down by rating or version, post developer replies.
- Store presence — rank history, top charts, full store listings, featured placements.
- Keywords and ASO — the organic and paid keywords an app ranks for, competitor ad spend, related terms, rank tracking.
- Audience — age and gender estimates, and the other apps your users use.
- Apple Ads — campaigns, ad groups, keywords, search terms, performance reports.
- App catalog — search and aggregate across millions of apps on every major store.
Every action, with its parameters, is in the action reference.
One tool per action. Reads run on their own. Writes wait for your approval.
Build the action surface once with createAppfiguresActions, then adapt it to your framework's tools with toAISDKTools, toOpenAITools, or toLangChainTools. The surface holds your API key and options; each adapter is a thin projection of it.
Install your framework's SDK next to the toolkit: ai and a model provider such as @ai-sdk/openai for the Vercel AI SDK, openai for OpenAI, or @langchain/core @langchain/langgraph for LangChain.
import { createAppfiguresActions } from '@appfigures/agent-toolkit'
import { toAISDKTools } from '@appfigures/agent-toolkit/ai'
import { generateText, stepCountIs, type LanguageModel } from 'ai'
// `model` is your provider's model, e.g. `openai('gpt-4o')` from `@ai-sdk/openai`.
export async function run(model: LanguageModel) {
const { tools } = toAISDKTools(createAppfiguresActions()) // reads APPFIGURES_API_KEY from env
const { text } = await generateText({
model,
tools,
stopWhen: stepCountIs(10),
prompt: 'What are the latest downloads and revenue for Spotify?',
})
return text
}The OpenAI SDK doesn't run tools for you. Call handleToolCall for each one, and loop until the model stops calling tools:
import { createAppfiguresActions } from '@appfigures/agent-toolkit'
import { toOpenAITools } from '@appfigures/agent-toolkit/openai'
import OpenAI from 'openai'
import type { ChatCompletionMessageParam } from 'openai/resources'
// The OpenAI SDK doesn't run tools for you: call handleToolCall for each and loop until it stops.
const client = new OpenAI() // reads OPENAI_API_KEY from env
const { tools, handleToolCall } = toOpenAITools(createAppfiguresActions()) // reads APPFIGURES_API_KEY
const messages: ChatCompletionMessageParam[] = [
{ role: 'user', content: 'What are the latest downloads and revenue for Spotify?' },
]
while (true) {
const { message } = (await client.chat.completions.create({ model: 'gpt-4o', messages, tools }))
.choices[0]!
messages.push(message)
if (!message.tool_calls?.length) break
for (const call of message.tool_calls) messages.push(await handleToolCall(call))
}Bind the tools to your LangChain chat model:
import { createAppfiguresActions } from '@appfigures/agent-toolkit'
import { toLangChainTools } from '@appfigures/agent-toolkit/langchain'
import type { BaseChatModel } from '@langchain/core/language_models/chat_models'
// `model` is your LangChain chat model, e.g. from `@langchain/openai`. For an automatic tool loop,
// hand `tools` to `createReactAgent` from `@langchain/langgraph` instead.
export async function run(model: BaseChatModel) {
const { tools } = toLangChainTools(createAppfiguresActions()) // reads APPFIGURES_API_KEY from env
return model.bindTools!(tools).invoke('What are the latest downloads and revenue for Spotify?')
}Every tool returns one of:
{ data }on success. Ahintsfield comes along when there's a caveat (see Configuration).{ error }on a handled failure, shaped for the model to fix its input and retry. An unapproved write is one of these, witherror.causeType === 'refusal'.{ error }withcauseType: 'unexpected'on a bug. The model gets a sanitizedinternal error in <tool>message and a hint to retry once, then degrade. The real error goes toonUnexpectedError(acreateAppfiguresActionsoption), never to the model.
For a framework these adapters don't cover, drive the action surface directly: actions.list() gives you the tool metadata to register, and actions.execute({ path, input, signal }) runs one. If your agent writes code instead, the client below runs anywhere.
The full tools reference is in docs/tools-api.md: the write gate, results, scoping, and per-request auth.
Tools are for an agent running inside a framework. But an agent also writes code: scripts, scheduled jobs, one-off analyses. For those, use the client. It calls Appfigures directly and returns typed data. Where a tool returns { data } or { error }, the client returns the data itself and throws on failure.
It's the same actions as the tools, called as methods:
import { AppfiguresAgentClient } from '@appfigures/agent-toolkit'
const af = new AppfiguresAgentClient({ apiKey: process.env.APPFIGURES_API_KEY })
const { results } = await af.apps.search({ q: 'spotify', count: 1 })
const spotify = results[0]
// spotify.name, spotify.downloads_last_month, spotify.revenue_last_month_usd, spotify.storefronts …
const tracked = await af.apps.tracked() // no required inputThe first draft runs, because:
- Data is the return value.
console.log(await af.metrics.query(…))prints the data. There's no envelope to unwrap. - Fully type-safe. Inputs and results are typed, so a wrong call fails to compile.
- One error type. Every failure throws
AppfiguresActionError, withcauseType,action,suggestedActions, andhints. Catch it withisAppfiguresActionError, notinstanceof.
The full client reference is in docs/client-api.md: returned data, errors, hints, and authentication.
Every option has a safe default, so none of this is required to start.
- Hints — a caveat that rides with the result: truncated data, another page, a deprecated action. Tools read them inline; the client prints them to
stderr. → client · tools - Approve writes — every write refuses until you approve it, so a prompt-injected
reviews.replynever posts. → tools-api.md - Scope the surface — expose only the actions you choose, by path or group wildcard. → tools-api.md
- Bring your own transport — customize the built-in one (retries, a proxy, a non-production base URL) or replace it outright. → client · tools
- Authenticate each request — build the surface once and vary credentials per call, for a server serving many users. → tools-api.md
Full parameters and examples for each action are in docs/api-reference.md. The tools mirror these as apps_get, metrics_query, and so on.
af.apps.search— Find apps by name or publisher.af.apps.tracked— List the apps your Appfigures account tracks.af.apps.get— Get an app's record: basic metadata (name, developer, etc) and, if the user tracks it, what data they can access.
af.explorer.listProducts— Read catalog fields for one app or many.af.explorer.aggregateProducts— Aggregate across the full catalog of millions of products across Apple, Google Play, Amazon, and other major stores: counts, averages, min/max, and histograms over any set of matching products.af.explorer.describeFields— List the catalog fields and the current user's access level for each.
af.metrics.query— Query any numeric dataset for one or more apps.af.metrics.describeDatasets— List every numeric datasetaf.metrics.queryaccepts, one row per dataset with its value type and whether it's limited to your own apps.
af.store.appRanks— Trace rank history for one or more apps across countries, device types, category subtypes, and categories, as time-series positions with day-over-day deltas.af.store.topCharts— List the top apps in a category chart for a given country and category, with current positions and day-over-day deltas.af.store.categories— List every store category with its ID.af.store.featured— List featured and editorial placements for an app or storefront product.af.store.appListing— Read the full store listing for one storefront: localized text (name, subtitle, description, release notes) plus screenshots, video, categories, monetization, supported devices, country availability, price, file size, and age rating.
af.audience.demographics— Read an app's audience demographics: the estimated age and gender breakdown.af.audience.crossUsage— Find the apps that an app's users also use.
af.reviews.list— Read individual reviews for one or more apps.af.reviews.breakdown— Aggregate review counts for one or more apps, bucketed by dimension.af.reviews.reply— Post or withdraw a developer response on a specific review. (write)
af.keywords.organic— Check the organic keywords one or more apps rank for, with position, popularity, and competitiveness.af.keywords.paid— List the paid keywords one or more apps run ads on, with impression share and organic rank.af.keywords.trackedRanks— View where all your tracked keywords rank for a single app+country combo, with each keyword's current position, movement since it last changed, starting position, popularity, and competitiveness.af.keywords.trackedTrend— Trace how one tracked keyword's rank changes over time for a single app+country combo.af.keywords.suggestions— Discover keyword ideas to consider targeting for a single app+country combo, ranked by relevance to the app and including some drawn from apps you compete with.af.keywords.rankingApps— List the apps ranking for a specific keyword in organic search, plus the keyword's own popularity and competitiveness scores.af.keywords.advertisers— List the apps advertising on a specific keyword, with each advertiser's impression share, organic rank, and how long they've been bidding.af.keywords.related— Find keywords related to a seed term for ASO research.af.keywords.tracked— List tracked keywords with their opaque IDs.af.keywords.track— Track a keyword to monitor your app's hourly rank for it over time and get automatic alerts when its position moves. (write)af.keywords.untrack— Stop tracking a keyword. (write)
af.appleAds.organizations— List the Apple Ads organizations you manage campaigns in, with each one's currency and timezone.af.appleAds.campaigns— List your Apple Ads campaigns with each one's status, budget, targeted countries, and schedule.af.appleAds.adGroups— List Apple Ads ad groups with each one's default bid, CPA cap, pricing model, and schedule.af.appleAds.keywords— List a campaign's bid keywords with each keyword's performance (impressions, taps, installs, spend, cost-per-install) over a date range, plus its match type, bid, and whether it's a targeting or negative term.af.appleAds.searchTerms— List the actual user search terms that triggered a campaign's ads, each with its all-time performance (impressions, taps, installs, spend, cost-per-install).af.appleAds.report— Report Apple Ads performance per campaign (impressions, taps, installs, spend, cost-per-install), plus an account-wide total, over a date range.af.appleAds.topKeywords— Rank a campaign's top-performing keywords by conversion rate, spend, and installs over a date range.
af.sdks.list— List every known SDK with its id, or search to find a specific one.
In docs/:
docs/api-reference.md— every action's params, types, and examplesdocs/client-api.md— the typed client: calling actions, returned data, errors, hints,signal, authenticationdocs/tools-api.md— the action surface and framework adapters: the write gate, results, scoping, per-request authdocs/recipes.md— worked recipes: real, multi-step flows shown as client callsdocs/catalog_playbook.md— theaf.explorer.*query grammar and field listdocs/numeric_metrics.md— the datasetsaf.metrics.queryacceptsdocs/glossary.md— key terms
An agent wired with the framework tools can fetch the last three at runtime via the docs_get tool.
Client scripts in examples/client/, each a real solution against live data. Run one with npx tsx examples/client/<file>:
app-stats.ts— one app's downloads, revenue, 6-month trend, and rating spread.competitor-report.ts— rank several apps head-to-head by last-month downloads and revenue.keyword-competition.ts— who ranks organically and who advertises on a keyword, plus related terms to target.review-triage.ts— an app's 1–2★ reviews by version and country, and the newest ones awaiting a reply.audience-overlap.ts— an app's age and gender split, and the apps its audience shares.
Tool-wiring for each framework in examples/tools/, matching the snippets above:
openai-tools.ts— the OpenAI tool-call loop, runnable end-to-end with an OpenAI key.ai-sdk-tools.ts— Vercel AI SDK wiring, exported asrun(model)so you pass your provider's model.langchain-tools.ts— LangChain wiring viabindTools, exported asrun(model)for your chat model.
@appfigures/agent-toolkit is built from Appfigures' internal monorepo and published as a compiled bundle. The dist/ files here are the released build, not editable source. Bug reports and feature requests are welcome in the issue tracker. Code changes are made upstream, so this repo doesn't accept pull requests.