accueil / serveurs / Recherche & Web / io.apptail/apptail
io.apptail/apptail
serveur MCP (Model Context Protocol) · AppTail – ASO & Keyword Research 2.37.0
Référencé dans l'annuaire. Seul le pentest comportemental fait foi, et il n'a pas encore été exécuté sur ce serveur.
Est-ce que io.apptail/apptail est sûr ?
Au dernier audit MCP Hub, le serveur MCP « io.apptail/apptail » est classé « Non encore testé ». Référencé dans l'annuaire. Seul le pentest comportemental fait foi, et il n'a pas encore été exécuté sur ce serveur. Le verdict est réévalué en continu ; consultez la fiche pour l'état à jour.
Méthode : MCP Hub analyse la description de chaque outil (couche 1) et, pour le verdict fort, exécute le serveur dans une micro-VM isolée avec leurres et réseau bloqué (couche 2). On publie des noms et des compteurs, jamais le contenu brut renvoyé par un outil.
Les 25 outils
- add_app≈ 2164 tokens
Add an app to the account as one of the user's own. Takes an Apptail app_id, an App Store URL, or a name — resolved and imported the way search_apps does. Tracking starts immediately (rankings, reviews, competitors); measured downloads and proceeds still require connecting App Store Connect in the console, which cannot be done from here.
Paramètres, retour & exemple (3)
Paramètresapp· string · requis
The app to claim: an Apptail app_id, a full App Store URL, or the app's name. A URL is the reliable form — a name resolves against the whole store, and two apps can share one.country· string · optionnel
Primary storefront for this app, ISO 3166-1 alpha-2 (e.g. US, DE). Defaults to US. This is the storefront its keywords and rankings are tracked in first; more can be added in the console.dry_run· boolean · optionnel
Resolve the app and report what would happen without claiming it. Worth doing when the user gave a name rather than a URL, so they can confirm it is the right app before it counts against their plan.
Exemple d'appel{"name": "add_app", "arguments": {"app": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"app": {}, "note": "texte", "status": "added", "country": "texte", "apps_used": 1, "connected": true, "apps_limit": 1, "console_url": "texte"}} - add_competitors≈ 1004 tokens
Track one or more rival apps against one of YOUR apps. Each competitor can be given as an Apptail app_id, an App Store URL, or just a name — names and URLs are resolved and imported the way search_apps does, so you do NOT need to look up an app_id first. Returns one outcome per item: what was added, what was already tracked, and what a plan limit refused.
Paramètres, retour & exemple (4)
Paramètresapp_id· integer · requis
Apptail app id for one of YOUR apps — from get_account. The rivals are tracked FOR this app: competitor sets belong to an app, not to the account, so removing one later affects only this app.country· string · optionnel
Storefront to resolve names in, ISO 3166-1 alpha-2 (e.g. US, DE). Omit and it is guessed from the script the name is written in. Ignored for items given as an app_id.dry_run· boolean · optionnel
Resolve every item and report what would happen, without tracking anything. Use it when the user named apps ambiguously and you want to confirm you found the right ones before changing their account.competitors· array · requis
The rivals, up to 20. Each item is an Apptail app_id, a full App Store URL, or an app name in any language. Send all of them in one call — the plan limit is checked per item, so a batch that runs out of room still adds what fits and says which items did not.
Exemple d'appel{"name": "add_competitors", "arguments": {"app_id": 1, "competitors": []}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"app_id": 1, "dry_run": true, "outcomes": [], "remaining": 1, "added_count": 1, "requested_count": 1}} - add_keywords≈ 1114 tokens
Start tracking search terms for one of your apps, in one storefront. Send terms, or `keyword_ids` for suggestions returned by discover_keywords — a suggestion MUST be added by id, because re-resolving its term can land on a different keyword row. Counts against the plan's per-app keyword limit; `dry_run` reports what would happen without writing anything. Terms already in the corpus come back under `already_tracked` rather than as an error — that is the state the caller asked for.
Paramètres, retour & exemple (5)
Paramètresapp_id· integer · requis
Apptail app id for one of YOUR apps — get it from get_account. Not the numeric id in an App Store URL (that is apple_app_id). Keywords are tracked per app.country· string · requis
Storefront to track these terms in, ISO 3166-1 alpha-2 (e.g. US, GB, DE). Required and not defaulted: a term tracked in the wrong storefront is a wasted keyword slot. Ranks are per storefront — the same term ranks differently in each.dry_run· boolean · optionnel
Report what would be added, and how many slots are left, without tracking anything. Nothing is written and nothing counts against the plan.keywords· array · optionnel
Search terms to start tracking, as a user would type them into the App Store (e.g. ["fitness tracker", "workout app"]). Send the whole batch in one call rather than one term per call. Terms we have never seen are created. Every added term whose results are more than a day old is crawled straight away, and positions usually land within a few minutes: a get_keywords read made immediately after this call shows those terms as unmeasured, which means not crawled yet and not that the app is missing from the results. Either this or `keyword_ids` is required.keyword_ids· array · optionnel
Apptail keyword ids to start tracking — the `keyword_id` on a discover_keywords row. Use this rather than the term whenever you have an id: a term is re-resolved and can land on a different keyword row than the one you were shown.
Exemple d'appel{"name": "add_keywords", "arguments": {"app_id": 1, "country": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"added": [], "limit": 1, "app_id": 1, "country": "texte", "dry_run": true, "skipped": [], "remaining": 1, "added_count": 1, "limit_reached": "texte", "skipped_count": 1, "already_tracked": []}} - discover_keywords≈ 1658 tokens
Terms an app could be tracking but is not, merged from every source and each labelled with where it came from: what tracked competitors rank for, what the store's similar apps rank for, what those competitors put in their own titles and subtitles, what the store's own mining surfaced, and — reading the listing cold — what the app's own title, subtitle and description suggest. The last is the only source that works on an app added minutes ago; `listing` is the only one that can surface a phrase nobody has ranked for yet, and it offers a phrase only when two or more rivals publish it and Apple reports somebody searching it. Pass `contains` to also match terms already in AppTail's database. Already-tracked and already-dismissed terms are never returned. This is a list of candidates, not a measure of coverage: for how much of a niche's vocabulary the account is missing, and which holes matter most, call get_landscape and read `term_gap`. Discovery can persist shared suggested keyword records, cache generated suggestions, and queue background popularity collection. It does not add those terms to account tracking.
Paramètres, retour & exemple (5)
Paramètreslimit· integer · optionnel
Max suggestions, most-searched first. Default 60, capped at 200. The answer always says how many there were.app_id· integer · requis
Apptail app id to suggest for. get_account for the user's own apps. Suggestions are derived from this app's listing, its rivals and its neighbours, so they are only meaningful for the app they were asked about.source· array · optionnel
Which sources to read. Omit for all five that need no argument — `competitors`, `similar`, `listing`, `store`, `ai`. `corpus` is a text match against terms AppTail already holds and does nothing without `contains`, which is why "all" does not silently include it. An unknown name is refused rather than ignored.country· string · optionnel
Storefront to suggest for (e.g. US, DE). Defaults to the app's primary storefront — which is only one of them: an app localized into several languages is searched for in several storefronts, so call once per entry in get_app's `listing_storefronts`. Discovery is per storefront and never a blend: a German term is not a translation of an English one — `spritverbrauch` beats `kraftstoffverbrauch` by a margin no dictionary would tell you.contains· string · optionnel
Only terms containing this text. With `source: ["corpus"]` this is a search of AppTail's keyword database. Note it searches terms AppTail holds, not the App Store: a phrase nobody has ever tracked returns nothing, and to start tracking a brand-new term you pass it straight to add_keywords.
Exemple d'appel{"name": "discover_keywords", "arguments": {"app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"count": 1, "total": 1, "app_id": 1, "country": "texte", "sources": [], "app_name": "texte", "by_source": {}, "truncated": true, "console_url": "texte", "suggestions": []}} - edit_market_corpus≈ 1242 tokens
Add terms to one storefront's corpus, or take terms out of it. Add for a term the corpus SHOULD hold and does not — a rival's brand, a phrase Apple has never measured the popularity of, the term a thin storefront is really about; a pinned term is kept through every rebuild and refreshed on the same 72-hour cadence as the rest. Remove for a term that does not belong: ANY term can go, and one the heuristic found is also kept out of future rebuilds rather than returning within 72 hours. This is NOT `save_market`: seeds are what the corpus is expanded FROM and changing one re-runs the whole heuristic over that storefront, where these two writes act on single terms in the result.
Paramètres, retour & exemple (4)
Paramètresadd· array · optionnel
Terms to pin, as somebody would type them into the App Store. Send the batch in one call. Terms already in the corpus come back under `already_present` rather than as an error.remove· array · optionnel
Keyword ids to take out of the corpus — the `keyword_id` on ANY get_market corpus row. A term the heuristic found is also recorded as excluded so rebuilds do not re-derive it; `add` on the same term later clears that again.country· string · requis
Which storefront's corpus, ISO 3166-1 alpha-2 (e.g. US, DE). Required and not defaulted: a corpus belongs to one storefront, and there is no market-wide term list to add to.market_id· integer · requis
Apptail market id — from list_markets or save_market.
Exemple d'appel{"name": "edit_market_corpus", "arguments": {"country": "texte", "market_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"cap": 1, "terms": 1, "pinned": [], "caveats": [], "country": "texte", "refused": [], "removed": [], "excluded": [], "market_id": 1, "console_url": "texte", "not_removed": [], "already_present": []}} - explain_period≈ 6095 tokens
Return an account or owned-app summary for a requested period: available measured App Store Connect performance, storefront changes, tracked keyword movements, recorded signals, review volume and the last sent digest. Returns comparison data, coverage and caveats identifying unavailable sections. Reads account data without changing tracking or publishing content.
Paramètres, retour & exemple (6)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.app_id· integer · optionnel
Narrow to one of the account's own apps — get_account lists them. Omit for the whole portfolio, which excludes apps the owner has hidden.period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `last_month`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.compare· string · optionnel · none | previous | year_ago
What to read the period against. `previous` (the default) is the period immediately before — for a calendar month, the calendar month before. `year_ago` is the same dates a year earlier, for comparison with the corresponding period in the previous year.country· string · optionnel
Storefront for the keyword half only; the money is reported across all of them with a per-storefront split. Defaults to the app's primary storefront. Ranks only exist per storefront.
Exemple d'appel{"name": "explain_period", "arguments": {"to": "texte", "from": "texte", "app_id": 1, "period": "texte", "compare": "none", "country": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"digest": {}, "window": {}, "app_ids": [], "caveats": [], "reviews": {}, "signals": {}, "headline": [], "keywords": {}, "performance": {}, "comparison_window": {}}} - get_account≈ 3026 tokens
The account: its apps with Apptail ids, its plan and the limits that can refuse a write, App Store Connect health per app, how fresh the first-party data is, and the storefronts it focuses on. Call this first whenever the request is about "my app" or "my keywords" — every other tool needs an app_id, and the focus countries and hidden apps here are what keep your answer agreeing with what the customer sees in the console.
Paramètres, retour & exemple (2)
Paramètresinclude_hidden· boolean · optionnel
Also return apps the owner has set aside. Default true, because they are still tracked and still answerable — each one is marked `hidden: true`, and they must be left out of portfolio totals. Set false for just the working portfolio.include_competitors· boolean · optionnel
Also return the rival apps tracked under this account's apps, each marked `is_competitor`. Default false: including them makes any portfolio total wrong, and get_competitors is the tool that answers questions about them.
Exemple d'appel{"name": "get_account", "arguments": {"include_hidden": true, "include_competitors": true}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"apps": [], "plan": {}, "count": 1, "connection": {}, "data_through": "texte", "focus_countries": []}} - get_app≈ 7428 tokens
Everything AppTail holds about one app, at the depth you ask for. The base answer is the store listing **in one storefront** — the localised title and subtitle a shopper in `country` actually reads, the price and its currency, version, category, release dates, the publisher's ids. `include` adds sections: `prices` (what it costs in every storefront), `ratings` (every storefront's rating and vote count, pooled honestly, plus a daily series and per-storefront movement with `history_days`), `charts` (the charts it currently ranks in), `popularity` (organic reach), `developer` (the publisher and its portfolio), `versions` (release cadence) and `screenshots`. Works for ANY app in the store, not only the user's own. It does NOT return impressions, downloads or revenue — get_performance does, and only for the user's own connected apps.
Paramètres, retour & exemple (4)
Paramètresapp_id· integer · requis
Apptail app id. get_account for the user's own apps, search_apps for any other app in the store. Not the numeric id in an App Store URL (that is apple_app_id).country· string · optionnel
Storefront to read the listing in (e.g. US, GB, DE). Defaults to the app's primary storefront. Title, subtitle, price, rating and screenshots all differ per storefront, so this changes the answer rather than filtering it — the `name` you get back is the title as published *there*, which for a localised app is not the title in any other market. `ratings.overall`, `ratings.by_country`, `ratings.history` and the `prices` section ignore it — they are every storefront — and `charts` is returned for all of them regardless.include· array · optionnel
Extra sections to read. Omit for the listing alone, which is the cheap answer. `ratings`, `charts` and `popularity` need a Starter or Pro plan and are refused by name without one — the rest are free. Ask for what the question needs and nothing else: each section is a query.history_days· integer · optionnel
With `include: ["ratings"]`, also return the rating and the vote count day by day, this many days back from today, **and how each storefront moved over that window** — `ratings_gained` and `rating_change` on every row of `ratings.by_country`. Capped at 365. Ask for it whenever the question is whether a rating is *moving* or *where* it is moving: an average slides for weeks before enough people write about it, and a cross-section cannot tell a market that has always been low from one that fell this month. Ignored without the `ratings` include.
Exemple d'appel{"name": "get_app", "arguments": {"app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"icon": "texte", "name": "texte", "tier": 1, "price": 1, "store": "apple", "app_id": 1, "charts": [], "prices": {}, "country": "texte", "is_mine": true, "ratings": {}, "version": "texte"}} - get_competitors≈ 2305 tokens
List tracked competitor apps for one of your apps, with how many more the plan allows — and `suggested`: up to ten rivals the account does not track yet, ranked by how many of the app's own search terms they sit in the top ten for. Works on an app with no keywords: its listing is read for terms and the store is crawled for them. Read `suggested_basis.terms_pending` before calling a short list complete. Suggestions can persist shared keyword records and queue background crawls. Suggested apps are not added to your competitor watchlist.
Paramètres, retour & exemple (1)
Paramètresapp_id· integer · requis
Apptail app id for one of YOUR apps — get it from get_account. Not the numeric id in an App Store URL (that is apple_app_id).
Exemple d'appel{"name": "get_competitors", "arguments": {"app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"count": 1, "limit": 1, "app_id": 1, "remaining": 1, "suggested": [], "competitors": [], "suggested_basis": {}}} - get_keyword_serp≈ 1596 tokens
The App Store search results for one term in one storefront, on one day: who ranked, in what order, with their names, subtitles and ratings. This is how you find out WHO took the places an app lost — a rank that fell is a fact, and the results page on the day it fell is the reason. Works for ANY term in the store, tracked or not, known to us or not: pass `keyword_id` for a term you already have an id for, or `keyword` + `country` for words a user typed, which resolves the term and crawls the storefront live when what we hold is over a day old. Omit the date for the most recent crawl. A lookup can persist a new shared keyword record and queue a background crawl that updates stored search observations. It does not track the keyword for your account.
Paramètres, retour & exemple (5)
Paramètresdate· string · optionnel
The day to read, `YYYY-MM-DD`. Omit for the most recent crawl, which is the only mode that ever crawls live — naming a day is a question about the past and is answered from what was recorded. A day nobody crawled comes back empty with `crawled: false` rather than as an error; pick one from `crawled_days`, which the answer always returns.limit· integer · optionnel
How deep to read. Default 25, capped at 50. Below about 25 nobody is competing with you for the term.country· string · optionnel
Storefront for `keyword`, e.g. "us", "jp". Required with `keyword` and ignored with `keyword_id`, because a keyword already names its storefront. There is no worldwide search results page — every App Store search happens in one country.keyword· string · optionnel
The search term itself, for words a user typed rather than an id — "sleep tracker", "заметки". Needs `country`. A term nobody has ever looked up is created and the storefront is read live, so this answers for any search in the store and not only for terms Apptail already holds. Prefer `keyword_id` when you have one: it is the exact row, where words go through the store's own normalisation first.keyword_id· integer · optionnel
Apptail keyword id — from get_keywords or discover_keywords, or off a `rank.move` signal. The storefront is fixed by the keyword itself; a term is tracked per country. Give this OR `keyword` + `country`, not both.
Exemple d'appel{"name": "get_keyword_serp", "arguments": {"date": "texte", "limit": 1, "country": "texte", "keyword": "texte", "keyword_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"apps": [], "date": "texte", "count": 1, "country": "texte", "crawled": true, "keyword": "texte", "refreshed": true, "keyword_id": 1, "popularity": 1, "console_url": "texte", "my_position": 1, "crawled_days": []}} - get_keywords≈ 8690 tokens
The account's tracked keywords for an app — or across the whole portfolio — over any window: where each term ranked at the start and end, how far it moved, how many days it held and how many days it was measured, and optionally its day-by-day history, the same terms measured for named competitors, Search Visibility (a 0–100 score per storefront with the terms that moved it), and the terms two of your own apps are both on. Sorted worst movement first by default, so "what dropped" is at the top of a 300-term corpus — which also makes the returned rows a selection rather than a sample: `movers` and `coverage` are counted over the whole corpus and are what a summary comes from. Filter by `contains` to ask about one term by name. This is the tool for every question about tracked terms; it replaces get_tracked_keywords, get_keyword_positions and compare_keyword_positions.
Paramètres, retour & exemple (13)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.sort· string · optionnel · movement | rank | volume | competition
`movement` (the default) puts terms that left the results first, then real drops by size — the top of the list is what to ask about. `rank` is best position first, `volume` is most searched (Apple popularity), `competition` is most crowded. **Every sort selects, so a capped list is never a sample**: a movement-sorted read of 15 terms returns 15 movers whatever the corpus did. Count from `movers` and `coverage`, never from the rows.limit· integer · optionnel
Max terms returned, after sorting. Default 100, capped at 300. The answer always says how many the corpus holds.scope· string · optionnel · app | portfolio
`app` (the default) reads one app's corpus and needs `app_id`. `portfolio` reads every app the account owns and reports each term under whichever of them ranks best for it — that is the scope `include: ["shared"]` needs, and hidden apps are excluded from it.app_id· integer · optionnel
Apptail app id for one of YOUR apps — get_account lists them. Required for `scope: "app"`. Not the numeric id in an App Store URL (that is apple_app_id).period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.tag_id· integer · optionnel
Only keywords carrying this tag. Tag ids come back on the keywords in this tool's own output. Omit for the whole corpus.country· string · optionnel
Storefront to read ranks in (e.g. US, GB). Defaults to the app's primary storefront. Ranks only exist per storefront — the same term ranks differently in each — so one call answers for one market.include· array · optionnel
Extra blocks. `history` adds a day-by-day series per term, capped at 25 terms — pair it with `keyword_ids` for specific terms. `visibility` adds **Search Visibility** — the 0–100 answer to "is our ASO working here", its like-for-like change and the terms that moved it, plus a line per storefront — and each row's `points_change` and `brand`; also the daily top-N counts, which are over every term the app appeared for, not over this corpus. `shared` adds the terms two of your own apps are both on, and needs `scope: "portfolio"`.contains· string · optionnel
Only terms whose text carries this substring, matched case-insensitively and applied before the sort and the cap. This is how to ask about a term by name — "how is `mpg` doing" — without looking up its id first, and the only way to see a term that sits mid-table by movement and so never reaches the top of a sorted list.keyword_ids· array · optionnel
Only these terms, by Apptail keyword id — from this tool's own output or discover_keywords. Ids the account does not track are still answered when the scope is one app, because "how is my app doing for this term" is a real question; the answer says so. Omit for the whole corpus.compare_with· array · optionnel
Apptail app ids to measure on these same terms — from get_competitors or search_apps. Rivals are measured on YOUR corpus, not theirs. At most 5 are used and the answer names which; send the ones that matter first.
Exemple d'appel{"name": "get_keywords", "arguments": {"to": "texte", "from": "texte", "sort": "movement", "limit": 1, "scope": "app", "app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"sort": "texte", "count": 1, "scope": "texte", "total": 1, "movers": {}, "shared": [], "window": {}, "app_ids": [], "caveats": [], "country": "texte", "coverage": {}, "keywords": []}} - get_landscape≈ 3702 tokens
Who the App Store shows beside one of your apps for the terms it competes on, in one storefront: every app in the niche with how many of your terms it ranks for and owns the top 10 for, its ratings, its review flow and its size, plus which apps arrived or fell out this window — and `term_gap`, how much of the niche's own vocabulary you do not track yet, with the biggest holes ready for add_keywords. This is the niche, not your watchlist: most rows are apps nobody added, and get_competitors answers the other question.
Paramètres, retour & exemple (5)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.app_id· integer · requis
Apptail app id for one of YOUR apps — get it from get_account. Not the numeric id in an App Store URL (that is apple_app_id).period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.country· string · optionnel
Storefront to read the niche in (e.g. US, GB). A niche exists per storefront and is never blended across them. Defaults to the first of the account's focus_countries this app is actually tracked in, then the app's primary storefront.
Exemple d'appel{"name": "get_landscape", "arguments": {"app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"count": 1, "terms": 1, "total": 1, "app_id": 1, "window": {}, "caveats": [], "country": "texte", "members": [], "app_name": "texte", "term_gap": {}, "truncated": true, "visibility": {}}} - get_market≈ 12376 tokens
Read iOS App Store niche data by saved market_id or by query and countries. Returns storefront competition, search visibility, app membership and optional corpus or movement data. Phrase research can create shared keyword records and persist crawled search observations; it does not save an account market. Downloads and revenue are labelled third-party rolling 30-day estimates. Reports per-storefront values, coverage and caveats.
Paramètres, retour & exemple (11)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.query· string · optionnel
A phrase to resolve into a market right now, e.g. "AI calorie tracking". Requires `countries`. Can persist shared keywords and search observations. No market is saved to your account — call save_market with the same phrase to keep it.store· string · optionnel
Read only this one storefront of a saved market. Omit for every storefront compared, which is where `overlap` and the contest range come from.app_id· integer · optionnel
Scopes `include: ["app_terms"]` to one app — an Apptail app id from `members`, `search_apps` or `get_landscape`. This is the audit trail for membership: it returns every (term, storefront) place that app holds in this market, how many days it held each, and which clause of the rule put it in `apps` or in `fringe`. Reach for it when the user disagrees with a market's membership, or asks why a particular app is or is not in the niche.period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.include· array · optionnel
Extra sections, each costing a query: `members` (the leaderboard), `corpus` (every term with why it is in), `movement` (who arrived and who left), `app_terms` (which terms ONE app holds here and whether that makes it a competitor — needs `app_id`). Ask for what the question needs.countries· array · optionnel
Storefronts to ask the question in, ISO 3166-1 alpha-2 (e.g. ["US","GB","DE"]). Required with `query`. Each storefront gets its own corpus seeded from the same phrase; that is deliberate, and a phrase nobody searches in a storefront comes back with a thin corpus, which is itself the finding.market_id· integer · optionnel
Apptail market id for a market this account has saved — from list_markets. A saved market is a pure read: no crawling, sub-second. Send this OR `query`, not both.budget_seconds· integer · optionnel
How long a live `query` may spend crawling, shared across ALL storefronts rather than each. Default 5, max 30. It is rarely the binding limit — at most 12 terms are crawled per call whatever the clock says.new_within_days· integer · optionnel
Keep only apps FIRST RELEASED inside this many days — "what has launched into this niche lately". Applied to every app ranking for the corpus before the list is cut, so these are the new apps in the market and not the new apps among its leaders; a young app is rarely a leader yet, so filtering the leaderboard itself would answer nothing. Affects `members` only. `share` stays a share of the WHOLE market, which is the point of it. Not the same question as `movement`: that is who started ranking here, which is mostly apps that are not new at all.
Exemple d'appel{"name": "get_market", "arguments": {"to": "texte", "from": "texte", "query": "texte", "store": "texte", "app_id": 1, "period": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"apps": 1, "left": [], "name": "texte", "slug": "texte", "terms": 1, "corpus": [], "fringe": 1, "spread": "texte", "status": "texte", "window": {}, "caveats": [], "entered": []}} - get_performance≈ 3545 tokens
Read measured App Store Connect impressions, store views, downloads, sales and proceeds for apps connected to the authenticated account. Supports an owned app or portfolio, documented time windows, period comparisons and breakdowns by storefront or traffic source. Returns the actual reporting window, connection coverage and caveats. Does not provide private analytics for apps outside the account.
Paramètres, retour & exemple (9)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.grain· string · optionnel · day | week | month | quarter | year
Bucket size for the series. Omit and it is chosen to fit the window — a day for a month, a week for a year. A grain too fine or too coarse for the window is ignored rather than refused.scope· string · optionnel · portfolio | app
`portfolio` (the default) sums every app the account owns; `app` reports one, and then `app_id` is required. Hidden apps are in the portfolio sum only if the account has not hidden them — they are excluded, matching what the console shows.split· string · optionnel · none | country | source
Break the totals down. `country` gives one row per storefront Apple named; `source` gives Apple's own attribution — App Store search, browse, app and web referrers. `source` reports the attribution associated with measured downloads. Rows need not add up to the total; the caveats say so.app_id· integer · optionnel
Apptail app id, required when `scope` is `app`. Must be one of the user's own apps — get_account lists them. Measured analytics require an authorised App Store Connect connection for the account.period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.compare· string · optionnel · none | previous | year_ago
What to read the window against. `previous` (the default) is the period immediately before — for a calendar month that is the calendar month before, not the same number of days. `year_ago` is the same dates a year earlier, for comparison with the corresponding period in the previous year.include_apps· boolean · optionnel
On `portfolio` scope, also return one row per app so a portfolio move can be attributed to the app that caused it. Default false.
Exemple d'appel{"name": "get_performance", "arguments": {"to": "texte", "from": "texte", "grain": "day", "scope": "portfolio", "split": "none", "app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"apps": [], "grain": "texte", "scope": "texte", "split": "texte", "series": [], "totals": [], "window": {}, "app_ids": [], "caveats": [], "coverage": {}, "truncated": true, "split_rows": []}} - get_reviews≈ 3299 tokens
Reviews for any app over a window, filtered by storefront, star rating, text, or whether the developer has replied — plus the shape of the period: how many arrived per bucket, what they averaged, and where the app's pooled store rating stood while they did. Reviews exist for every app whether or not App Store Connect is connected, because they are read from the public store. This is the tool for "what are people complaining about": filter it and read the reviews yourself rather than asking for a summary. Every review says whether it can be answered (`can_reply`) and where an existing reply stands (`reply_state`); `reply_to_reviews` is what answers them.
Paramètres, retour & exemple (9)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.limit· integer · optionnel
Max reviews, newest first. Default 25, capped at 200. The answer always says how many matched.app_id· integer · requis
Apptail app id. get_account for the user's own apps, search_apps for any other. Reviews are readable for any app in the store, including competitors.period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling. **This tool also takes `all`**, which is the app's whole review history and the only period that reaches a backlog older than three years. Reviews are kept for the life of the app and the console's own reviews screen has no date bound at all, so the ceiling above is about first-party analytics and not about these rows. Send `all` for "what have we never answered" and for anything asking about a review from years ago; the trend then buckets by quarter or year.rating· array · optionnel
Only these star ratings, e.g. `[1, 2]` for the critical ones. Omit for all five. The `summary` counts are deliberately NOT filtered by this, so a call asking only for one-stars still learns how many reviews the period actually held.country· string · optionnel
Only reviews from this storefront (e.g. de). Omit for every storefront, which is usually right — one storefront's reviews are a thin sample. Send it when `ratings.by_country` on get_app has pointed at a market, which is the follow-up that finds out why it is low.contains· string · optionnel
Only reviews whose title or body contains this text, case-insensitively. Title as well as body, because a complaint is as often the headline as the paragraph. This is how you check a hypothesis — "crash", "subscription", "ads" — rather than reading everything.unanswered· boolean · optionnel
Only reviews the developer has never replied to. False or omitted for all of them. Combined with `rating: [1, 2]` this is the work queue the console leads with — and **a backlog has no window**, so send `period: "all"` when you mean all of it. `summary.unanswered` is the whole-history count either way, and a list that is smaller than it is a windowed list, not a shorter backlog.
Exemple d'appel{"name": "get_reviews", "arguments": {"app_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"count": 1, "total": 1, "trend": {}, "app_id": 1, "window": {}, "country": "texte", "replies": {}, "reviews": [], "summary": {}, "app_name": "texte", "filtered": true, "truncated": true}} - get_signals≈ 3414 tokens
What actually happened, from the record the product keeps: rank moves on tracked terms, chart entries, review spikes, competitor releases and price changes, plus — for the user's own apps only — week-over-week traffic and conversion shifts, download collapses, new reviews and rating moves. Each carries the two numbers behind it and the sentence that states the finding. This is a stored table read, not a reconstruction, so it is both cheaper and more reliable than diffing rank histories yourself. Covers the user's own apps and the competitors tracked under them; a rival's finding never `asks_action`.
Paramètres, retour & exemple (8)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.limit· integer · optionnel
Max findings, newest first. Default 50, capped at 200. The answer always says how many the window actually holds.types· array · optionnel
Only these kinds of finding. Omit for all of them. An unknown name is refused rather than ignored, so a filtered answer is never returned as though it were unfiltered.app_id· integer · optionnel
Narrow to one of the user's own apps — get_account lists them. Findings about the competitors tracked under it are included, because a rival taking your places is something that happened to you. Omit for the whole portfolio.period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.include_sent· boolean · optionnel
Mark the findings that already went out in an alert digest the user has read. Default false. Set it whenever you are about to summarise a period for someone: without it you cannot tell news from something they read at breakfast, and repeating the second as the first is how an assistant stops being believed.min_severity· string · optionnel · neutral | opportunity | warning | critical
Floor on how loudly a finding speaks. Default `neutral`, which is everything. `warning` drops a rival shipping a point release, which is worth knowing and not worth acting on. It is NOT the same as "what needs my attention" — read `asks_action` on each finding for that: a competitor taking a run of 1–2★ reviews is a warning about somebody else's week and asks nothing of this user.
Exemple d'appel{"name": "get_signals", "arguments": {"to": "texte", "from": "texte", "limit": 1, "types": [], "app_id": 1, "period": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"count": 1, "total": 1, "digest": {}, "window": {}, "app_ids": [], "by_type": {}, "signals": [], "truncated": true, "by_severity": {}}} - get_top_charts≈ 1540 tokens
Get top app charts (free, paid, or grossing) for a store, country, and category.
Paramètres, retour & exemple (5)
Paramètreslimit· integer · optionnel
How deep to read the chart. Default 25, capped at 100.store· string · optionnel · apple
Only the App Store is covered. Google Play is in the data model but nothing is crawled for it, so omit this.country· string · optionnel
Storefront to read the chart for (e.g. US, GB, JP). Defaults to US. An unrecognised code falls back to US rather than failing — the reply echoes the storefront actually used, so check it.category· string · optionnel
Apple category id as a number, e.g. 6014 Games, 6015 Finance, 6017 Education, 6023 Food & Drink, 6013 Health & Fitness, 6012 Lifestyle. Omit for the overall chart across all categories. An id we do not recognise is ignored and you get the overall chart.chart_type· string · optionnel · free | paid | grossing
Which chart. Default free. Use grossing for revenue questions — top free ranks by downloads and says nothing about money. An unrecognised value falls back to free and the reply says which chart it read.
Exemple d'appel{"name": "get_top_charts", "arguments": {"limit": 1, "store": "apple", "country": "texte", "category": "texte", "chart_type": "free"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"apps": [], "count": 1, "country": "texte", "chart_type": "free"}} - list_markets≈ 3360 tokens
List markets saved by the authenticated account, including market ids, storefronts, competition ranges, app counts and observed changes for the requested period. Reads saved account configuration and market observations without creating, updating or deleting markets. Returned ids can be used with get_market.
Paramètres, retour & exemple (3)
Paramètresto· string · optionnel
End date, `YYYY-MM-DD`, inclusive. Send it alone and the window is the three years before it.from· string · optionnel
Start date, `YYYY-MM-DD`, inclusive. Overrides `period` when both are sent. Send it alone and the window runs to today.period· string · optionnel
The window to report on. A calendar month as `2026-07`, a calendar year as `2026`, `last_month`, `this_month`, `last_year`, or a trailing window: `today`, `7d`, `14d`, `30d`, `90d`, `180d`, `365d`, `730d`, `1095d`. Defaults to `30d`. A calendar period is compared against the calendar period before it — July against June, not against the 31 days ending 30 June. Three years is the ceiling.
Exemple d'appel{"name": "list_markets", "arguments": {"to": "texte", "from": "texte", "period": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"count": 1, "limit": 1, "window": {}, "markets": []}} - remove_competitors≈ 794 tokens
Remove one or more competitor tracking relationships for an app owned by the authenticated account. Accepts AppTail app ids, App Store URLs or names. Name and URL resolution can query the public App Store and import shared app records. Removes the selected pairing only; public apps and pairings for other apps remain. Requires write authorisation and returns one outcome per item.
Paramètres, retour & exemple (2)
Paramètresapp_id· integer · requis
Apptail app id for one of YOUR apps — from get_account. Only this app's competitor set is touched.competitors· array · requis
The rivals to stop tracking, up to 20. Each item is an Apptail app_id (as returned by get_competitors), a store URL, or a name. Ids are the reliable form here — a name is resolved against the whole store, not against what you track.
Exemple d'appel{"name": "remove_competitors", "arguments": {"app_id": 1, "competitors": []}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"app_id": 1, "outcomes": [], "remaining": 1, "removed_count": 1, "requested_count": 1}} - remove_keywords≈ 397 tokens
Remove tracked keywords from an app. Frees the slots against the plan limit; position history is kept, so re-adding a term later does not start from nothing.
Paramètres, retour & exemple (2)
Paramètresapp_id· integer · requis
Apptail app id for one of YOUR apps — get it from get_account. Not the numeric id in an App Store URL (that is apple_app_id).keyword_ids· array · requis
Apptail keyword ids to stop tracking, as returned by get_keywords. Ids, not terms — two apps can track the same word and only these rows are removed. Frees the slots against your plan limit. Position history is kept, so re-adding a term later does not start from nothing.
Exemple d'appel{"name": "remove_keywords", "arguments": {"app_id": 1, "keyword_ids": []}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"app_id": 1, "remaining": 1, "removed_count": 1, "requested_count": 1}} - remove_market≈ 417 tokens
Delete a saved market, or just one of its storefronts. Pass `store` to drop a single storefront and leave the rest of the market with its corpora and its build clocks untouched; omit it to delete the whole market. Deleting frees a slot on the account's plan. The terms themselves are not deleted — they are shared with any other market or tracked app using them.
Paramètres, retour & exemple (2)
Paramètresstore· string · optionnel
Drop only this storefront, ISO 3166-1 alpha-2. Omit to delete the whole market. Dropping the last storefront deletes the market too, because a market asked nowhere is not a market.market_id· integer · requis
Apptail market id — from list_markets.
Exemple d'appel{"name": "remove_market", "arguments": {"market_id": 1}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"name": "texte", "deleted": true, "market_id": 1, "markets_remaining": 1, "removed_storefronts": [], "remaining_storefronts": []}} - reply_to_reviews≈ 1475 tokens
Create, update or remove public App Store review responses for apps owned by the authenticated account, using its connected App Store Connect API key. Requires write authorisation and eligible review ids. Submitted text is sent verbatim under the developer's name. Obtain approval for the exact text or requested removal before submitting. dry_run validates without publication. Accepts up to ten items and returns per-item outcomes; pending means Apple has accepted a response but has not published it.
Paramètres, retour & exemple (2)
Paramètresdry_run· boolean · optionnel
Check every item and report what would happen, without publishing anything. **Worth using by default here** — it confirms the reviews resolve, the account's key reaches their apps and the text fits, before anything reaches the store.replies· array · requis
The replies, up to 10 per call. Send them in one call rather than one at a time: each is answered separately, so a batch where one app is not covered still posts the rest and says which it did not.
Exemple d'appel{"name": "reply_to_reviews", "arguments": {"replies": []}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"dry_run": true, "outcomes": [], "max_items": 1, "failed_count": 1, "posted_count": 1, "removed_count": 1, "requested_count": 1}} - save_market≈ 838 tokens
Create or update a saved market in the authenticated account from a query, countries and optional per-storefront seed terms. An existing name updates that market, adding storefronts or replacing seed configuration and rebuilding requested storefronts. Persists account configuration and queues background corpus collection using public App Store data. Requires write authorisation. Returns market_id, build status, affected storefronts and caveats; collection may still be pending.
Paramètres, retour & exemple (4)
Paramètresname· string · optionnel
What to call it. Defaults to `query`. Passing the name of a market this account already has ADDS the new storefronts to it rather than creating a second one.query· string · requis
The phrase to build the market from, e.g. "AI calorie tracking". Used as the seed in every storefront unless `seeds` overrides it.seeds· object · optionnel
Per-storefront seed terms, keyed by country code: {"de": ["kalorienzähler"]}. OPTIONAL, and optional per storefront. A storefront you leave out is not seeded from `query`: its terms are read off the localised listings of the leaders of the storefront that WAS phrased, and each one is searched there before it is kept — so it ends up with the local phrasing rather than an English phrase nobody types. Pass a storefront explicitly when you know the local phrase (to use the supplied local terms) or when you want to ask a different question there. Up to five terms each.countries· array · requis
Storefronts to ask it in, ISO 3166-1 alpha-2 (e.g. ["US","DE"]). Each keeps its own corpus; nothing is blended across them.
Exemple d'appel{"name": "save_market", "arguments": {"query": "texte", "countries": []}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"name": "texte", "slug": "texte", "status": "texte", "caveats": [], "created": true, "market_id": 1, "console_url": "texte", "storefronts": [], "added_storefronts": []}} - search_apps≈ 1640 tokens
Search for iOS apps by name, bundle ID, or App Store URL. Supports all languages including Cyrillic, Chinese, etc. If the app is not in our database, it will be fetched from the App Store, persisted as a shared public app record, and queued for enrichment. This does not add the app to your account or competitor watchlist. Auto-detects the likely App Store region from the query language (e.g. Cyrillic → Russia, Chinese → China). To add what you find, add_competitors and add_app take the same name or URL directly — you do not have to look up an app_id first.
Paramètres, retour & exemple (3)
Paramètreslimit· integer · optionnel
Max results. Default 10, capped at 25.query· string · requis
App name in any language, a bundle id (com.example.app), or a full App Store URL. Searches Apptail first and falls back to the App Store, importing anything it finds — so this returns a usable app_id even for an app we have never seen. This is how you turn a name a user typed into an app_id.country· string · optionnel
Storefront to search (e.g. "us", "ru"). Omit and it is guessed from the script the query is written in — Cyrillic implies ru, and so on. Pass it explicitly when the user names a market, because the guess is about language and not about where they sell.
Exemple d'appel{"name": "search_apps", "arguments": {"query": "texte"}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"apps": [], "hint": "texte", "note": "texte", "count": 1, "source": "url", "country": "texte"}} - tag_keywords≈ 1312 tokens
Put tracked keywords under a tag, in bulk — or clear their tag — and/or say whether they are brand terms for Search Visibility. The tag is named, not looked up: a name that does not exist yet is created. A keyword carries at most one tag, so assigning replaces whatever it had. `brand` is separate from tags: `own` (your app's name) and `competitor` (a rival's name) leave the terms out of the visibility score, `none` counts them whatever detection says, `auto` hands them back to detection. Send `brand` without `tag` to change only that — the tags stay as they are. This is the tool for organising a large corpus after reading it with get_keywords, which is drudgery in the console and one call here.
Paramètres, retour & exemple (5)
Paramètrestag· string · optionnel
The tag name to put them under. Created if it does not exist. Omit — or send null — to clear the tag off these keywords instead.brand· string · optionnel · own | competitor | none | auto
Whether these terms are somebody's name, for Search Visibility (get_keywords `include: ["visibility"]`). `own` = your app's name, `competitor` = a rival's: both are listed and left out of the score, because you rank #1 for your own name whatever your ASO does. `none` = count them anyway. `auto` = let title-word detection decide again. Detection is shown on each row's `brand.reason`; override it when it is wrong (a transliterated rival name, a generic word it took for a name). Omit to leave the brand decision alone. Sent without `tag`, only the brand decision changes.color· string · optionnel
Hex colour for a tag being created, e.g. "#2563eb". Ignored when the tag already exists. Omit and one is picked from the palette that the app is not already using.app_id· integer · requis
Apptail app id for one of YOUR apps — from get_account. Tags belong to an app.keyword_ids· array · requis
Apptail keyword ids to tag, as returned by get_keywords. Ids, not terms. Up to 500 in one call. A keyword the app does not track is reported back rather than silently ignored.
Exemple d'appel{"name": "tag_keywords", "arguments": {"app_id": 1, "keyword_ids": []}}Exemple de retour{"content": [{"type": "text", "text": "…"}], "structuredContent": {"tag": {}, "tags": [], "brand": "texte", "action": "assigned", "app_id": 1, "tag_created": true, "unknown_ids": [], "changed_count": 1, "requested_count": 1, "brand_changed_count": 1}}
C'est votre serveur ?
Revendiquez-le sur l'espace créateur (preuve GitHub, domaine ou npm) pour afficher le badge « propriétaire vérifié » et lancer un pentest comportemental à la demande afin d'obtenir le badge « Vérifié ».