ASO tools for AI agents: keyword research, rank tracking, competitor analysis (iOS & Android).
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Bearer <Sonar API key (aso_...)>. Create one at https://trysonar.app/developers
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Append a screen to a screenshot set (at the end; reorder with sonar_update_screenshot_set). Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
Screenshot set to append to.
Omit for a blank screen.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Append a screen to a screenshot set (at the end; reorder with sonar_update_screenshot_set). Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| layout | object | Omit for a blank screen. |
| set_id* | string | Screenshot set to append to. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"set_id"
],
"properties": {
"layout": {
"type": "object",
"description": "Omit for a blank screen.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"set_id": {
"type": "string",
"minLength": 1,
"description": "Screenshot set to append to."
}
}
}The detected alert events for your workspace, newest first — the same feed as the in-app Recent Alerts panel and the email digest: rank drops/gains, top-10 entries/exits, new rankings, rating drops, review spikes, and competitor changes, each with a type-specific payload (app/keyword names, old vs new values). Events only exist for alert types you've enabled rules for (sonar_set_alert); detection runs once daily. Poll with `since` to react to changes programmatically. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| type | string | Filter to one alert type. Omit for all types. |
| limit | integer | Max events to return (1-200). Default 50. |
| since | string | Only events created at/after this ISO 8601 timestamp (e.g. "2026-08-01T00:00:00Z"). Use your last poll time to fetch only new events. |
| app_id | string | Filter to events about one tracked app (Sonar app UUID or store id). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"type": {
"enum": [
"rank_drop",
"rank_gain",
"entered_top10",
"left_top10",
"new_ranking",
"rating_drop",
"review_spike",
"competitor_change",
"top_chart"
],
"type": "string",
"description": "Filter to one alert type. Omit for all types."
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Max events to return (1-200). Default 50."
},
"since": {
"type": "string",
"minLength": 1,
"description": "Only events created at/after this ISO 8601 timestamp (e.g. \"2026-08-01T00:00:00Z\"). Use your last poll time to fetch only new events."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Filter to events about one tracked app (Sonar app UUID or store id)."
}
}
}WRITE tool — generates a fresh AI competitive insight for one of your own apps: clusters the keyword gaps vs your competitors into named opportunity themes (with a why-now narrative and per-keyword metrics), writes threat narratives for competitors climbing on your keywords, and diffs against the previous analysis. At most one analysis per app per 7 days (429 with the next available time while in cooldown — use sonar_competitor_landscape to read the current one). Requires a paid (non-trial) Indie plan and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID of YOUR OWN tracked app to analyze. NOT a store id, NOT a competitor id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar app UUID of YOUR OWN tracked app to analyze. NOT a store id, NOT a competitor id."
}
}
}Calculate an ASO (App Store Optimization) audit score (0-100) for an app. Returns the overall score plus an itemized breakdown of checks (title length, keyword usage, screenshots, ratings, etc.) so you can identify what to improve. Works without an API key (free tier, limited daily use per IP).
| Argument | Type | Description |
|---|---|---|
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Any App Store storefront (175 countries) or Google Play market (145). Default "us". |
| store_id* | string | Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store",
"store_id"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Any App Store storefront (175 countries) or Google Play market (145). Default \"us\"."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
}
}
}Change history for a tracked app — detected releases, metadata edits, screenshot swaps, price changes, category moves, iOS product page header swaps (`header`: data.action added/changed/removed + header artwork) and newly listed iOS In-App Events (`in_app_event`: title, kind, dates), newest first. Useful for correlating rank movements with what the app (or a competitor) changed. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| type | string | Filter to one change type. Omit for all types. |
| limit | integer | Max changes to return (1-200). Default 50. |
| app_id* | string | Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"type": {
"enum": [
"release",
"metadata",
"screenshots",
"price",
"category",
"header",
"in_app_event"
],
"type": "string",
"description": "Filter to one change type. Omit for all types."
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Max changes to return (1-200). Default 50."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
}
}
}App Store Connect App Analytics for one of your own iOS apps: the impressions → product page views → downloads funnel with conversion rates (`page_view_rate`, `download_rate`) and App Store search share, impressions by source (App Store search, browse, app referrer, web referrer…), plus daily installs, deletions and sessions. Impressions follow App Store Connect's definition and INCLUDE product page views, so totals reconcile with ASC. Downloads come from the Sales report. Same numbers as the Engagement page. iOS only. Requires the Agency plan (403 on other plans) AND an App Store Connect connection with an Admin-role key (`key_lacks_analytics` otherwise); Apple delivers the first analytics 24-48 hours after connecting (`pending`). Always check `status`: anything other than `ready` (not_connected, not_ios, app_not_in_account, pending, key_lacks_analytics) means there's no data and `message` says how to fix it — never read an empty series as zero. Days Apple hasn't reported yet have `reported: false` and null metrics.
| Argument | Type | Description |
|---|---|---|
| end | string | Last day of the window (YYYY-MM-DD, inclusive). Default yesterday (UTC) — Apple posts a day the next morning at the earliest. |
| days | integer | Window length in days (1-366) when `start` is omitted. Default 30. |
| start | string | First day of the window (YYYY-MM-DD, inclusive). Omit to count `days` back from `end`. |
| store | string | Only needed when `app_id` is a store id tracked in both stores. App Store Connect data is iOS-only. |
| app_id |
Extract the most likely target keywords from an app's title and description, ranked by relevance. Useful for understanding what an app (yours or a competitor) is optimizing for. Works without an API key (free tier, limited daily use per IP).
| Argument | Type | Description |
|---|---|---|
| max | integer | Maximum number of keywords to extract (1-50, default 20). |
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Any App Store storefront (175 countries) or Google Play market (145). Default "us". |
| store_id* | string | Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store",
"store_id"
],
"properties": {
"max": {
"type": "integer",
"default": 20,
"maximum": 50,
"minimum": 1,
"description": "Maximum number of keywords to extract (1-50, default 20)."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Any App Store storefront (175 countries) or Google Play market (145). Default \"us\"."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
}
}
}List the keywords tracked for an app in the caller's Sonar workspace, with latest difficulty, popularity, results count, note, and starred_at (favorite/target marker) per keyword. Returns the tracked-keyword ids used by sonar_update_keyword_note and sonar_star_keyword, and the keyword_ids used by sonar_keyword_rankings. Cursor-paginated (default 50 per page). Requires an Indie plan (trial counts). `popularity` (5-100) is the value Sonar's dashboard shows: Apple's Search Popularity when Apple has a real reading; when Apple reports a keyword below its threshold (popularity_apple 5, about 20) it is Sonar's estimate (at most 18). `popularity_source` says which (apple | proxy), `popularity_apple` is Apple's own reading (null on Android), `popularity_proxy` is Sonar's estimate beside a floored reading.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Page size (1-200). Server default applies when omitted. |
| app_id* | string | Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
| cursor | string | Pagination cursor from a previous call's `next_cursor`. Omit for the first page. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Page size (1-200). Server default applies when omitted."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
},
"cursor": {
"type": "string",
"minLength": 1,
"description": "Pagination cursor from a previous call's `next_cursor`. Omit for the first page."
}
}
}Look up a single app by its store ID. Returns app metadata including name, developer, category, rating, reviews, installs (Android), and price. Works without an API key (free tier, limited daily use per IP). If the store is throttling, the result may be Sonar's stored copy: it then comes back as `{ data, meta }` with `meta.stale: true`, its date in `meta.stale_as_of`, and a `meta.note` to pass on to the user.
| Argument | Type | Description |
|---|---|---|
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Any App Store storefront (175 countries) or Google Play market (145). Default "us". |
| store_id* | string | Store-specific app identifier. iOS: bundle ID (e.g. "com.spotify.client") or numeric track ID (e.g. "324684580") — the `storeId` returned by sonar_app_search works as-is. Android: package name (e.g. "com.spotify.music"). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store",
"store_id"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Any App Store storefront (175 countries) or Google Play market (145). Default \"us\"."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier. iOS: bundle ID (e.g. \"com.spotify.client\") or numeric track ID (e.g. \"324684580\") — the `storeId` returned by sonar_app_search works as-is. Android: package name (e.g. \"com.spotify.music\")."
}
}
}The dashboard's computed scoreboard for one of your apps in a single call: visibility index and share of voice (with 7-day deltas and a daily spark), ranked / top-10 keyword counts with movement, best rank, the biggest 7-day improvements and drops, the rank-distribution trend, and the actionable opportunity list (near_page_one / top_three_push / easy_target). Use it when asked how an app is doing: these are the same numbers the dashboard renders, already computed from rank history. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| days | integer | Rank-history window in days (7-90). Default 30. |
| app_id* | string | Sonar app UUID of one of your own tracked apps — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"days": {
"type": "integer",
"maximum": 90,
"minimum": 7,
"description": "Rank-history window in days (7-90). Default 30."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your own tracked apps — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
}
}
}Rank history for an app's tracked keywords — daily ranks over the requested window, one history array per keyword. Prefer observations for daily status: ranked has a numeric rank; not_found means a completed search did not return the app (results_count is the returned search size); not_observed means no confirmed check, including legacy gaps. Never interpret an absent rank as a collection failure or assign a numeric rank to it. The legacy history array contains positive ranks only. Use this to check how rankings moved after a metadata change or to find keywords trending up or down. Cursor-paginated over keywords (default 50 per page). Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| days | integer | History window in days (1-365). Default 30. |
| limit | integer | Page size (1-200). Server default applies when omitted. |
| app_id* | string | Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
| cursor | string | Pagination cursor from a previous call's `next_cursor`. Omit for the first page. |
| keyword_id | string | Restrict to one keyword — a keyword_id from sonar_app_keywords. Omit for all tracked keywords. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"days": {
"type": "integer",
"maximum": 365,
"minimum": 1,
"description": "History window in days (1-365). Default 30."
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Page size (1-200). Server default applies when omitted."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
},
"cursor": {
"type": "string",
"minLength": 1,
"description": "Pagination cursor from a previous call's `next_cursor`. Omit for the first page."
},
"keyword_id": {
"type": "string",
"minLength": 1,
"description": "Restrict to one keyword — a keyword_id from sonar_app_keywords. Omit for all tracked keywords."
}
}
}Estimate monthly revenue for an app, based on install counts, ratings, and category benchmarks. Returns the dollar estimate, a confidence grade (high/medium/low) with the factors behind it, and the methodology used. The figure is a model estimate, not reported revenue; the confidence grade is the part that says how far to trust it. Needs a Sonar API key or connected account (1 credit per call on prepaid API credits); not part of the free tier.
| Argument | Type | Description |
|---|---|---|
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Any App Store storefront (175 countries) or Google Play market (145). Default "us". |
| store_id* | string | Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store",
"store_id"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Any App Store storefront (175 countries) or Google Play market (145). Default \"us\"."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
}
}
}Fetch user reviews for any app, live from the store (up to ~500 of the most recent or most helpful for the country). The star-rating filters and `limit` apply to that fetched window, so a narrow filter on a small app can return few or no reviews. Useful for sentiment analysis, feature-request mining, and competitive research; for an already-summarized view of a tracked app, sonar_review_insights returns themed AI analysis instead. Needs a Sonar API key or connected account (1 credit per call on prepaid API credits); not part of the free tier. If the store is throttling, the result may be Sonar's stored copy: it then comes back as `{ data, meta }` with `meta.stale: true`, its date in `meta.stale_as_of`, and a `meta.note` to pass on to the user.
| Argument | Type | Description |
|---|---|---|
| lang | string | Android only: fetch one language feed (e.g. ar, fr). Omit to merge the market language plus en, es, fr, ar; coverage is not exhaustive. |
| sort | string | Sort order. "recent" returns newest first, "helpful" returns most-voted first. |
| limit | integer | Maximum number of reviews to return (1-200). |
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Any App Store storefront (175 countries) or Google Play market (145). Default "us". |
App Store Connect sales for one of your own iOS apps: daily first-time downloads, redownloads, in-app purchase units and approximate USD proceeds (`proceeds_usd_approx`, converted with a static FX table — present it as approximate), window totals, and a per-country breakdown sorted by downloads. Same numbers as the Performance page. iOS only. Requires the Agency plan (403 on other plans) AND an App Store Connect connection at /settings/connections. Always check `status`: anything other than `ready` (not_connected, not_ios, app_not_in_account, pending, key_lacks_analytics) means there's no data and `message` says how to fix it — never read an empty series as zero. Days Apple hasn't reported yet have `reported: false` and null metrics.
| Argument | Type | Description |
|---|---|---|
| end | string | Last day of the window (YYYY-MM-DD, inclusive). Default yesterday (UTC) — Apple posts a day the next morning at the earliest. |
| days | integer | Window length in days (1-366) when `start` is omitted. Default 30. |
| start | string | First day of the window (YYYY-MM-DD, inclusive). Omit to count `days` back from `end`. |
| store | string | Only needed when `app_id` is a store id tracked in both stores. App Store Connect data is iOS-only. |
| app_id* | string | Sonar app UUID of one of your own tracked iOS apps — the `id` returned by sonar_list_apps or sonar_create_product. The app's store id (bundle id) also works; pass `store` if it exists in both stores. |
Find apps in the App Store or Google Play by keyword, e.g. to get an app's store ID before calling other tools. Returns matching apps with metadata (name, developer, icon, rating). This is for finding apps, NOT for checking rankings: never report an app's position in this list as its rank. On iOS the list follows the iTunes Search API's text-match order, which is not the App Store's real ranking — below the top 10 the two can be dozens of places apart. For rank positions, track the keyword (sonar_track_keywords) and read sonar_app_rankings or sonar_keyword_rankings, which follow the App Store's own search order. Works without an API key (free tier, limited daily use per IP). If the store is throttling, the result may be Sonar's stored copy: it then comes back as `{ data, meta }` with `meta.stale: true`, its date in `meta.stale_as_of`, and a `meta.note` to pass on to the user.
| Argument | Type | Description |
|---|---|---|
| num | integer | Number of results to return (1-50, default 10). |
| query* | string | Search query (e.g. "meditation", "meal planner"). |
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Any App Store storefront (175 countries) or Google Play market (145). Default "us". |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"query",
"store"
],
"properties": {
"num": {
"type": "integer",
"default": 10,
"maximum": 50,
"minimum": 1,
"description": "Number of results to return (1-50, default 10)."
},
"query": {
"type": "string",
"minLength": 1,
"description": "Search query (e.g. \"meditation\", \"meal planner\")."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Any App Store storefront (175 countries) or Google Play market (145). Default \"us\"."
}
}
}WRITE tool — cancel a scheduled reply (manual or auto mode) before it posts; it goes back to draft. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| review_id* | string | Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"review_id"
],
"properties": {
"review_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id)."
}
}
}Keywords a tracked competitor currently ranks for (last 7 days of SERP data), with difficulty and popularity per keyword. Pass own_app_id for gap analysis: keywords where the competitor ranks but your app doesn't are marked gap=missing. Cursor-paginated (default 50 per page). Requires an Indie plan (trial counts). `popularity` (5-100) is the value Sonar's dashboard shows: Apple's Search Popularity when Apple has a real reading; when Apple reports a keyword below its threshold (popularity_apple 5, about 20) it is Sonar's estimate (at most 18). `popularity_source` says which (apple | proxy), `popularity_apple` is Apple's own reading (null on Android), `popularity_proxy` is Sonar's estimate beside a floored reading.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Page size (1-200). Server default applies when omitted. |
| cursor | string | Pagination cursor from a previous call's `next_cursor`. Omit for the first page. |
| own_app_id | string | Sonar app UUID of your own app. When set, each keyword includes your current rank and a gap marker for keywords you don't rank for. |
| competitor_app_id* | string | Sonar app UUID of the competitor — the `competitor.id` from sonar_track_competitor, or an `id` from sonar_list_apps where is_own is false. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"competitor_app_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Page size (1-200). Server default applies when omitted."
},
"cursor": {
"type": "string",
"minLength": 1,
"description": "Pagination cursor from a previous call's `next_cursor`. Omit for the first page."
},
"own_app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of your own app. When set, each keyword includes your current rank and a gap marker for keywords you don't rank for."
},
"competitor_app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of the competitor — the `competitor.id` from sonar_track_competitor, or an `id` from sonar_list_apps where is_own is false. NOT a store id."
}
}
}The full competitive keyword picture for one of your own apps vs every tracked competitor, in one call: live stats (keyword gaps where competitors rank and you don't, winnable gaps, competitors climbing on your tracked keywords, keywords you lead), the top gap/threat/lead rows with metrics, and the latest AI insight if one was generated (opportunity clusters, threat narratives, strengths, posture). Use it when choosing which keywords to target next. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID of YOUR OWN tracked app (an `id` from sonar_list_apps where is_own is true). NOT a store id, NOT a competitor id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar app UUID of YOUR OWN tracked app (an `id` from sonar_list_apps where is_own is true). NOT a store id, NOT a competitor id."
}
}
}WRITE tool — creates a product in the caller's Sonar workspace and starts tracking the given app(s). A product is the cross-store unit (one iOS + one Android app, or just one of either). Returns the product id and the Sonar app ids needed by sonar_track_keywords and sonar_track_competitor. Own apps count against the plan cap (Indie 10, Agency 50; competitors are not capped) — at the cap the call fails with a 403 plan_limit error. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| apps* | array | 1-2 store versions: a single iOS or Android app, or one of each for a cross-store product. |
| name | string | Product name. Optional — defaults to the first app's name. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"apps"
],
"properties": {
"apps": {
"type": "array",
"items": {
"type": "object",
"required": [
"store",
"store_id"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "ISO 3166-1 alpha-2 country code (e.g. \"us\"). Optional — defaults server-side."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
}
},
"description": "One store version of the product."
},
"maxItems": 2,
"minItems": 1,
"description": "1-2 store versions: a single iOS or Android app, or one of each for a cross-store product."
},
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Product name. Optional — defaults to the first app's name."
}
}
}Create an app-store screenshot set for a product, from your own `screens` layouts or a built-in template. The layout JSON format and template ids are documented by sonar_screenshot_layout_guide. The set is immediately visible/editable for humans in the Screenshot Studio (studio_url in the response). Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| name | string | Display name. |
| store* | string | Target app store. |
| screens | array | Initial screens, in order (max 10). Either this or template_id, not both; with neither you get one blank screen. |
| product_id* | string | Product the set belongs to. |
| device_size* | string | Device id from sonar_screenshot_devices, e.g. "iphone-6.7". |
| template_id | string | Seed from a built-in template (see sonar_screenshot_layout_guide) instead of providing screens. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"product_id",
"store",
"device_size"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Display name."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "Target app store."
},
"screens": {
"type": "array",
"items": {
"type": "object",
"description": "A screenshot layout document ({background, layers}) — see sonar_screenshot_layout_guide. Image fields accept https:// URLs.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"maxItems": 10,
"minItems": 1,
"description": "Initial screens, in order (max 10). Either this or template_id, not both; with neither you get one blank screen."
},
"product_id": {
"type": "string",
"minLength": 1,
"description": "Product the set belongs to."
},
"device_size": {
"type": "string",
"minLength": 1,
"description": "Device id from sonar_screenshot_devices, e.g. \"iphone-6.7\"."
},
"template_id": {
"type": "string",
"minLength": 1,
"description": "Seed from a built-in template (see sonar_screenshot_layout_guide) instead of providing screens."
}
}
}WRITE tool — delete an alert subscription in the caller's Sonar workspace. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| id* | string | The alert subscription UUID — the `id` returned by sonar_list_alerts or sonar_set_alert. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The alert subscription UUID — the `id` returned by sonar_list_alerts or sonar_set_alert."
}
}
}WRITE tool — delete a product in the caller's Sonar workspace and untrack every app linked to it, with their tracked keywords, discovered keywords, and competitor links. The product's screenshot sets are deleted too. Shared store data (app metadata, snapshots, rank history) is not deleted. Returns { id, deleted, untracked_apps }. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| product_id* | string | Sonar product UUID — the `id` returned by sonar_list_products or sonar_create_product. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"product_id"
],
"properties": {
"product_id": {
"type": "string",
"minLength": 1,
"description": "Sonar product UUID — the `id` returned by sonar_list_products or sonar_create_product."
}
}
}Delete one screen from a screenshot set. A set keeps at least one screen — deleting the last one is rejected. Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| screenshot_id* | string | Screen id to delete. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"screenshot_id"
],
"properties": {
"screenshot_id": {
"type": "string",
"minLength": 1,
"description": "Screen id to delete."
}
}
}Permanently delete a screenshot set and everything in it (screens, translations). Irreversible — confirm with the user before deleting work they may want. Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| set_id* | string | Screenshot set id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"set_id"
],
"properties": {
"set_id": {
"type": "string",
"minLength": 1,
"description": "Screenshot set id."
}
}
}WRITE tool — stop tracking one keyword/app pair in the caller's Sonar workspace. Identify the pair by its tracked-keyword id (from sonar_app_keywords). Equivalent to sonar_untrack_keywords with a single id; that tool removes several (or all) of an app's keywords in one call. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| tracked_keyword_id* | string | The tracked-keyword UUID — the `id` returned by sonar_app_keywords. NOT the keyword_id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"tracked_keyword_id"
],
"properties": {
"tracked_keyword_id": {
"type": "string",
"minLength": 1,
"description": "The tracked-keyword UUID — the `id` returned by sonar_app_keywords. NOT the keyword_id."
}
}
}Keywords Sonar's discovery engine surfaced for one of your tracked apps but that aren't tracked yet — ranked finds (the app already ranks, unnoticed), competitor gaps, and AI/autocomplete-sourced ideas — each with popularity, difficulty, AI relevance, and an opportunity score (0-100, best first). This is Sonar's "what should I track next" answer; rows can be tracked with sonar_track_keywords. Requires an Indie plan (trial counts). `popularity` (5-100) is the value Sonar's dashboard shows: Apple's Search Popularity when Apple has a real reading; when Apple reports a keyword below its threshold (popularity_apple 5, about 20) it is Sonar's estimate (at most 18). `popularity_source` says which (apple | proxy), `popularity_apple` is Apple's own reading (null on Android), `popularity_proxy` is Sonar's estimate beside a floored reading.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Max rows to return (1-500). Default 200. |
| app_id* | string | Sonar app UUID of one of your tracked apps — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
| bucket | string | Filter by classification: "ranked" = the app already ranks for it, "gap" = a competitor ranks but the app does not, "idea" = verified research suggestion with no rank evidence yet. Omit for all. |
| source | string | Filter by how the keyword was discovered. Omit for all sources. |
| status | string | Filter by row status. Default "new" — the still-actionable suggestions; "all" includes rows already tracked or hidden. |
WRITE tool — mark a review as not needing a reply (also cancels a scheduled post). Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| review_id* | string | Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"review_id"
],
"properties": {
"review_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id)."
}
}
}WRITE tool — write a fresh AI reply draft for a review using the app's instructions (and an optional hint), with English translations. Counts against the monthly AI-draft allowance, then 1 credit per draft. Never posts. Tip: agents can skip this and write the reply themselves with sonar_update_review_reply (not metered). Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| hint | string | One-off direction for this draft, e.g. "mention the fix in 2.1". |
| review_id* | string | Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"review_id"
],
"properties": {
"hint": {
"type": "string",
"maxLength": 300,
"description": "One-off direction for this draft, e.g. \"mention the fix in 2.1\"."
},
"review_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id)."
}
}
}WRITE tool — generates a fresh AI review analysis for a tracked app from its recent reviews (praise/complaint themes, sentiment, feature requests, trend vs the previous run). At most one analysis per app+country every 90 days (429 with the next available time while in cooldown — use sonar_review_insights to read the current one); needs at least 5 recent reviews. Requires a paid (non-trial) Indie plan and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID of a tracked app — your own or a competitor (an `id` from sonar_list_apps). NOT a store id. |
| country | string | Reviews market (ISO country code). Insights are generated per country. Default "us". |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of a tracked app — your own or a competitor (an `id` from sonar_list_apps). NOT a store id."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Reviews market (ISO country code). Insights are generated per country. Default \"us\"."
}
}
}Get full details for one tracked app in the caller's Sonar workspace: store metadata plus up to 90 daily snapshots of rating, review count, version, and installs. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
}
}
}Fetch a screenshot set in full: every screen's layout JSON plus per-screen translation overrides keyed by locale. By default inline image data is replaced with placeholders to keep the response readable. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| set_id* | string | Screenshot set id. |
| include_image_data | boolean | When false (default), inline base64 images are replaced with short placeholders to keep the response small. Set true only when you need the raw data URLs (a layout containing placeholders is rejected on update). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"set_id"
],
"properties": {
"set_id": {
"type": "string",
"minLength": 1,
"description": "Screenshot set id."
},
"include_image_data": {
"type": "boolean",
"default": false,
"description": "When false (default), inline base64 images are replaced with short placeholders to keep the response small. Set true only when you need the raw data URLs (a layout containing placeholders is rejected on update)."
}
}
}Difficulty + popularity for a specific keyword (or up to 25 in bulk). Use this when you already know which keywords you care about — costs 1 credit per keyword. Works without an API key for up to 5 keywords/day (free tier, per IP); an API key removes that cap. Use sonar_keyword_search instead when you want related keyword ideas alongside metrics. Answers within about 30 seconds: a keyword that can't be computed in that time comes back as `pending` (queued on Sonar's scrape fleet, not charged, results are being cached) — call again after `retry_after_seconds` for just those keywords. Each row carries `measured_at` (when difficulty was measured) and `popularity_measured_at` (when the popularity value was measured — can be older), both ISO 8601 UTC. `stale: false` means both are under 7 days old; `stale: true` rows are real but older data (refreshed in the background) — check the timestamps when freshness matters. `popularity` (5-100) is the value Sonar's dashboard shows: Apple's Search Popularity when Apple has a real reading; when Apple reports a keyword below its threshold (popularity_apple 5, about 20) it is Sonar's estimate (at most 18). `popularity_source` says which (apple | proxy), `popularity_apple` is Apple's own reading (null on Android), `popularity_proxy` is Sonar's estimate beside a floored reading.
| Argument | Type | Description |
|---|---|---|
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | One of Sonar's 72 keyword-research markets, as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "jp", "br"). Keyword data isn't available for other storefronts. Default "us". |
| keyword | string | Single keyword to fetch metrics for. Use this OR `keywords`, not both. |
SERP history for one tracked keyword — which apps ranked in the top results on each measured day, newest first. Use this to see who competes on a keyword and how the top spots shifted over time. The keyword must be tracked in the caller's Sonar workspace. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| days | integer | History window in days (1-365). Default 30. |
| keyword_id* | string | Sonar keyword UUID — a `keyword_id` from sonar_app_keywords or sonar_competitor_keywords. NOT the keyword text. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"keyword_id"
],
"properties": {
"days": {
"type": "integer",
"maximum": 365,
"minimum": 1,
"description": "History window in days (1-365). Default 30."
},
"keyword_id": {
"type": "string",
"minLength": 1,
"description": "Sonar keyword UUID — a `keyword_id` from sonar_app_keywords or sonar_competitor_keywords. NOT the keyword text."
}
}
}Research a keyword and related terms. Returns up to 10 rows — the seed keyword plus the store's top autocomplete suggestions — each with difficulty (0-100), popularity score, and results count. Use this to find keywords worth targeting; for metrics on terms you already know, sonar_keyword_metrics is cheaper. On prepaid API credits it costs 10 credits per call (rows that could not be computed are refunded); it needs a Sonar API key or connected account and is not part of the free tier. Answers within about 30 seconds. Each row carries `measured_at` (difficulty) and `popularity_measured_at` (popularity, can be older), ISO 8601 UTC; `stale: true` means at least one of them is older than 7 days. A related term that couldn't be computed in time is re-checked while the call's time budget allows (through the metrics endpoint, 1 credit per keyword served); one still not ready comes back marked `pending` (queued, not charged) — get it later with sonar_keyword_metrics. `popularity` (5-100) is the value Sonar's dashboard shows: Apple's Search Popularity when Apple has a real reading; when Apple reports a keyword below its threshold (popularity_apple 5, about 20) it is Sonar's estimate (at most 18). `popularity_source` says which (apple | proxy), `popularity_apple` is Apple's own reading (null on Android), `popularity_proxy` is Sonar's estimate beside a floored reading.
| Argument | Type | Description |
|---|---|---|
| query* | string | Seed keyword to research (e.g. "meditation", "recipe app"). |
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | One of Sonar's 72 keyword-research markets, as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "jp", "br"). Keyword data isn't available for other storefronts. Default "us". |
Get autocomplete suggestions for a seed keyword from the App Store or Google Play, in the order the store shows them. List position is the only demand signal: the `priority` field is 0 on Google Play and currently 0 on the App Store as well. Lighter and faster than sonar_keyword_search — use when you only need term ideas without difficulty/popularity scoring. Works without an API key (free tier, limited daily use per IP). If the store is throttling, the result may be Sonar's stored copy: it then comes back as `{ data, meta }` with `meta.stale: true`, its date in `meta.stale_as_of`, and a `meta.note` to pass on to the user.
| Argument | Type | Description |
|---|---|---|
| seed* | string | Seed keyword. The store will return autocomplete suggestions starting from this term. |
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Nearly every App Store storefront and Google Play market works; the few small storefronts that are not supported return an error naming them. Default "us". |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"seed",
"store"
],
"properties": {
"seed": {
"type": "string",
"minLength": 1,
"description": "Seed keyword. The store will return autocomplete suggestions starting from this term."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Nearly every App Store storefront and Google Play market works; the few small storefronts that are not supported return an error naming them. Default \"us\"."
}
}
}List your alert subscriptions — each rule defines a change type (rank drops, review spikes, etc.), its scope (a specific app or org-wide), threshold, and whether it's enabled. Requires an Indie plan (trial counts).
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}List the apps tracked in the caller's Sonar workspace (own apps + competitors), each with its latest snapshot (rating, review count, version, installs). Returns the Sonar app UUIDs needed by sonar_get_app, sonar_app_keywords, sonar_app_rankings, and sonar_app_changes. Cursor-paginated (default 100 per page). Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| limit | integer | Page size (1-200). Server default applies when omitted. |
| cursor | string | Pagination cursor from a previous call's `next_cursor`. Omit for the first page. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Page size (1-200). Server default applies when omitted."
},
"cursor": {
"type": "string",
"minLength": 1,
"description": "Pagination cursor from a previous call's `next_cursor`. Omit for the first page."
}
}
}List every product in your workspace (unpaginated): each product's id, name, country, competitor count, and its linked store versions (Sonar app id, store, store_id, name). Product ids are what sonar_track_app, sonar_track_competitor, sonar_remove_competitor, sonar_delete_product, and the screenshot-set tools take; for per-app snapshots and competitor apps use sonar_list_apps. Requires an Indie plan (trial counts).
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}List a product's app-store screenshot sets (metadata only: store, device size, locales, studio_url). Use sonar_get_screenshot_set for full layouts. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| product_id* | string | Product id (find it with sonar_list_products). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"product_id"
],
"properties": {
"product_id": {
"type": "string",
"minLength": 1,
"description": "Product id (find it with sonar_list_products)."
}
}
}The whole portfolio's health in one call — for orgs managing many apps: per-app KPIs (visibility + 7-day delta, ranked/top-10 counts, net rank movement, rating, review count), org-wide totals, the biggest keyword movers in both directions, a needs-attention triage list (visibility drops, rating drops, not-ranked apps), and the best discovered-keyword opportunities across all apps. Same numbers as the /portfolio page. Requires an Agency plan (403 on other plans).
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}WRITE tool — PUBLIC ACTION: publishes the reply on the App Store under the developer's name (now, or after delay_minutes). Overwrites an existing response (Apple keeps one per review and marks it edited). Apple shows it within ~24h: status pending_publish, then published. Needs an Admin-role App Store Connect key. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| body | string | Replace the reply text before posting. Omit to post the current draft. |
| review_id* | string | Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id). |
| delay_minutes | integer | Schedule instead of posting now (minutes). 0/omitted = post now. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"review_id"
],
"properties": {
"body": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "Replace the reply text before posting. Omit to post the current draft."
},
"review_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id)."
},
"delay_minutes": {
"type": "integer",
"maximum": 1440,
"minimum": 0,
"description": "Schedule instead of posting now (minutes). 0/omitted = post now."
}
}
}WRITE tool — remove a competitor from a product in the caller's Sonar workspace. Drops the competitor link under every own app of the product; if no other own app in the workspace still references the competitor, the competitor app is untracked as well. 404 when the product has no such competitor. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| product_id* | string | Sonar product UUID — the `id` returned by sonar_list_products or sonar_create_product. |
| competitor_app_id* | string | Sonar app UUID of the competitor to remove (the competitor's `id`, NOT a store id). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"product_id",
"competitor_app_id"
],
"properties": {
"product_id": {
"type": "string",
"minLength": 1,
"description": "Sonar product UUID — the `id` returned by sonar_list_products or sonar_create_product."
},
"competitor_app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of the competitor to remove (the competitor's `id`, NOT a store id)."
}
}
}An own iOS app's App Store reviews (synced from App Store Connect every 5 minutes) with their reply state: the AI draft or your text, English translations of non-English reviews and drafts, hold reasons (needs_human, quota, daily_cap), schedule time, and any live App Store response. Newest first, with per-status counts. Use the review `id` with sonar_update_review_reply / sonar_post_review_reply. Requires an Indie plan (trial counts), App Store Connect connected in Sonar, and the app to be one of your own iOS apps.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Page size, 1-100 (default 25). |
| app_id* | string | Sonar app UUID of one of your own iOS apps (an `id` from sonar_list_apps). NOT a store id. |
| cursor | string | next_cursor from the previous page. |
| rating | integer | Only reviews with this star rating. |
| status | string | needs_reply = no reply yet (incl. AI drafts waiting for approval, held and failed ones), scheduled = will post soon, replied = live or waiting for Apple (incl. replies made in App Store Connect), dismissed. Omit for all. |
| country | string | Only reviews from this storefront (ISO alpha-2). |
| language |
The latest AI review analysis for a tracked app (your own or a competitor): what users praise and complain about as named themes with frequency, verbatim quotes, and trend movement (new / persisting / growing / improving / resolved), plus overall sentiment, surfaced feature requests, and what changed vs the previous analysis. `insight` is null if none has been generated yet — use sonar_generate_review_insights. Requires an Indie plan (trial counts).
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID of a tracked app — your own or a competitor (an `id` from sonar_list_apps). NOT a store id. |
| country | string | Reviews market (ISO country code). Insights are generated per country. Default "us". |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of a tracked app — your own or a competitor (an `id` from sonar_list_apps). NOT a store id."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Reviews market (ISO country code). Insights are generated per country. Default \"us\"."
}
}
}The review responder's configuration for an own iOS app: whether it is switched on, manual vs auto mode (auto posts AI replies after a delay, only for reviews written after auto was enabled and within the star range), the reply instructions, sign-off, reply language, last sync, plus whether App Store Connect is connected and this month's AI-draft usage (included allowance, then 1 credit per extra draft). settings is null until the responder is switched on. Requires an Indie plan (trial counts), App Store Connect connected in Sonar, and the app to be one of your own iOS apps.
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID of one of your own iOS apps (an `id` from sonar_list_apps). NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your own iOS apps (an `id` from sonar_list_apps). NOT a store id."
}
}
}WRITE tool — runs an AI keyword discovery scan on a tracked competitor: generates the search terms the competitor's listing is optimized for (brand terms included), queues them for SERP verification, and verifies the first batch inline (~30s), recording both apps' ranks. Returns generated/queued/verified_now counts; the rest verify in the background over the following hours — read results with sonar_competitor_keywords. Each account can scan a limited number of different competitors per UTC day (50 on trial and Indie, 250 on Agency); re-scanning one already scanned today is free, and past the limit the tool reports when it resets. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| own_app_id* | string | Sonar app UUID of your own app the scan compares against. The competitor must be linked to this app. |
| competitor_app_id* | string | Sonar app UUID of the competitor to scan — the `competitor.id` from sonar_track_competitor, or an `id` from sonar_list_apps where is_own is false. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"competitor_app_id",
"own_app_id"
],
"properties": {
"own_app_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar app UUID of your own app the scan compares against. The competitor must be linked to this app."
},
"competitor_app_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar app UUID of the competitor to scan — the `competitor.id` from sonar_track_competitor, or an `id` from sonar_list_apps where is_own is false. NOT a store id."
}
}
}List the device sizes supported for app-store screenshot sets, with their canvas dimensions (the pixel coordinate space all layouts use) and which store each belongs to — including the landscape App Store creative-asset canvases (category "creative": product page header and search results asset). Pick a device here before sonar_create_screenshot_set. Requires an Indie plan (trial counts).
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}The layout-format reference for Sonar screenshot sets: static text, so one call per session is enough. It documents the layout JSON schema, coordinate system, image handling (remote URLs), flowing background shapes, fonts, translation overrides, and the recommended workflow.
No arguments.
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {}
}WRITE tool — create or update an alert subscription in the caller's Sonar workspace. Upserts on (type + scope): re-submitting the same type/scope updates the existing rule. Omit `threshold` for the per-type default; omit `scope_app_id` for an org-wide rule. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| type* | string | The alert type to subscribe to. top_chart = one of your own apps entered or left a store top chart (overall + its category, free/paid/grossing). new_review = a new App Store review arrived for an own iOS app (needs App Store Connect connected and the review responder switched on for the app). |
| cadence | any | new_review only: email cadence. instant = within ~5 minutes of the review syncing, hourly = at most one email an hour, daily = the 08:30 UTC digest. Omit to keep the stored value (daily on create). |
| enabled | boolean | Whether the rule is active. Defaults to enabled when omitted. |
| countries | any | top_chart only: storefronts to watch (ISO 3166-1 alpha-2, e.g. ["us", "de"]), max 10. Omit to keep the stored list; null or [] = the countries you track keywords in. |
| threshold | any | Trigger threshold; omit or null for the default. rank_drop / rank_gain: positions moved (default 5). rating_drop: tenths of a star (default 2 = a 0.2-star drop). review_spike: new reviews since the previous daily snapshot (default 25). top_chart: rank cutoff, 1-200 (default 200). new_review: highest star rating that alerts, 1-5 (default 5 = every review; 3 = only 1-3★). Ignored by entered_top10, left_top10, new_ranking, competitor_change. |
WRITE tool — switch the review responder on/off for an own iOS app and update its instructions or auto-mode policy (partial update; omitted fields keep their value). Turning auto mode on only affects reviews written afterwards; anything the AI flags as needing a human is held. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| mode | string | manual = every reply waits for approval; auto = AI replies post automatically after auto_delay_minutes. |
| app_id* | string | Sonar app UUID of one of your own iOS apps (an `id` from sonar_list_apps). NOT a store id. |
| enabled | boolean | Switch the responder on (starts the review backfill) or off. |
| sign_off | any | Sign-off appended to every reply (null clears it). |
| instructions | string | Instructions for the AI: tone, support contact, product facts, known issues and fixes. |
| auto_daily_cap | integer | Auto mode: max auto replies per app per day (default 50). |
| reply_language | string | review = reply in the reviewer's language (default); en = always English. |
| auto_max_rating |
Write a locale's translation overrides for screens in a screenshot set (text copy, localized captures/images). Geometry and styling always come from the source layout; anything not overridden falls back to it. The locale is auto-enabled on the set. Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| locale* | string | Target locale code, e.g. "de-DE", "pt-BR", "zh-Hans". |
| set_id* | string | Screenshot set id. |
| entries* | array | One entry per screen to localize. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"set_id",
"locale",
"entries"
],
"properties": {
"locale": {
"type": "string",
"maxLength": 8,
"minLength": 2,
"description": "Target locale code, e.g. \"de-DE\", \"pt-BR\", \"zh-Hans\"."
},
"set_id": {
"type": "string",
"minLength": 1,
"description": "Screenshot set id."
},
"entries": {
"type": "array",
"items": {
"type": "object",
"required": [
"screenshot_id",
"overrides"
],
"properties": {
"overrides": {
"type": "object",
"description": "Sparse overrides keyed by layer id, e.g. {\"headline\": {\"text\": \"…\"}, \"device\": {\"screenshotDataUrl\": \"https://…\"}}. Replaces the screen's stored overrides for this locale wholesale.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"screenshot_id": {
"type": "string",
"minLength": 1,
"description": "Screen this entry localizes."
}
}
},
"maxItems": 50,
"minItems": 1,
"description": "One entry per screen to localize."
}
}
}WRITE tool — stars or unstars a tracked keyword in the caller's Sonar workspace. A star marks the keyword as a favorite/target the user is actively pursuing; starred keywords carry a starred_at timestamp in sonar_app_keywords results. Idempotent: re-starring refreshes the timestamp, unstarring a non-starred keyword is a no-op. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| starred* | boolean | true to star the keyword (mark as a favorite/target), false to unstar. |
| tracked_keyword_id* | string | Tracked-keyword UUID — the `id` (not keyword_id) returned by sonar_app_keywords or sonar_track_keywords. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"tracked_keyword_id",
"starred"
],
"properties": {
"starred": {
"type": "boolean",
"description": "true to star the keyword (mark as a favorite/target), false to unstar."
},
"tracked_keyword_id": {
"type": "string",
"minLength": 1,
"description": "Tracked-keyword UUID — the `id` (not keyword_id) returned by sonar_app_keywords or sonar_track_keywords."
}
}
}Get a store top chart (free / paid / grossing, overall or by category) with day-over-day movement: per-app rank delta, apps new to the chart, biggest movers and apps that dropped out. Use to see what's rising in a market or category. Note: summary, movers and droppedApps always describe the full top 200 — `limit` truncates the returned entries only. Movement is empty on the first day a chart is requested (no previous snapshot yet). Answers within about 30 seconds: when a live refresh can't finish in time the newest stored chart is returned with `stale: true` and its `measuredAt` date. Works without an API key (free tier, limited daily use per IP).
| Argument | Type | Description |
|---|---|---|
| chart | string | Chart type: "free", "paid" or "grossing". Default "free". |
| limit | integer | Number of chart entries to return (1-200). Default 50. |
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | Market as an ISO 3166-1 alpha-2 code (e.g. "us", "gb", "de", "mt"). Nearly every App Store storefront and Google Play market works; the few small storefronts that are not supported return an error naming them. Default "us". |
| category | string | Category key; keys differ by store (e.g. iOS "SOCIAL_NETWORKING" / "GAMES", Android "SOCIAL" / "GAME"; "HEALTH_AND_FITNESS" exists on both). An unknown key is rejected with an error. Use "overall" (default) for the store-wide chart. |
WRITE tool — links the second-store version of an existing Sonar product (e.g. the product already tracks the iOS app and you want to add the Android version, or vice versa). Each product holds at most one iOS + one Android app; to start tracking a brand-new app, use sonar_create_product instead. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | ISO 3166-1 alpha-2 country code (e.g. "us"). Optional — defaults server-side. |
| store_id* | string | Store-specific app identifier of the version to link. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name. |
| product_id* | string | Sonar product UUID (from sonar_create_product). NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"product_id",
"store",
"store_id"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "ISO 3166-1 alpha-2 country code (e.g. \"us\"). Optional — defaults server-side."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier of the version to link. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
},
"product_id": {
"type": "string",
"minLength": 1,
"description": "Sonar product UUID (from sonar_create_product). NOT a store id."
}
}
}WRITE tool — adds a competitor app under a Sonar product so its keywords and rankings get tracked alongside the product's own app. The product must already have its own app linked in the same store as the competitor. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| store* | string | App store. "ios" for Apple App Store, "android" for Google Play. |
| country | string | ISO 3166-1 alpha-2 country code (e.g. "us"). Optional — defaults server-side. |
| store_id* | string | Store-specific app identifier of the COMPETITOR app to track. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name. |
| product_id* | string | Sonar product UUID (from sonar_create_product). NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"product_id",
"store",
"store_id"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "ISO 3166-1 alpha-2 country code (e.g. \"us\"). Optional — defaults server-side."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier of the COMPETITOR app to track. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
},
"product_id": {
"type": "string",
"minLength": 1,
"description": "Sonar product UUID (from sonar_create_product). NOT a store id."
}
}
}WRITE tool — starts daily rank tracking for one or more keywords on an app in the caller's Sonar workspace. Idempotent: re-posting the same terms reports them as already_tracked instead of creating duplicates. Returns per-keyword outcomes (created / already_tracked / failed). Tracked keywords count against the workspace's plan cap (Indie 2,500, Agency 10,000 per workspace); terms beyond the remaining headroom come back as failed with the plan-limit message while the rest are still tracked. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID — the `apps[].id` returned by sonar_create_product (or sonar_track_app). NOT a store id; the store is implied by the app. |
| country | string | ISO 3166-1 alpha-2 country code (e.g. "us"). Optional — defaults to the product's country. |
| keywords* | array | Keywords to start tracking (1-200). Duplicates and already-tracked terms are reported, not duplicated. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id",
"keywords"
],
"properties": {
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `apps[].id` returned by sonar_create_product (or sonar_track_app). NOT a store id; the store is implied by the app."
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "ISO 3166-1 alpha-2 country code (e.g. \"us\"). Optional — defaults to the product's country."
},
"keywords": {
"type": "array",
"items": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"maxItems": 200,
"minItems": 1,
"description": "Keywords to start tracking (1-200). Duplicates and already-tracked terms are reported, not duplicated."
}
}
}WRITE tool — untrack an app in the caller's Sonar workspace. Deletes the workspace's tracked keywords for it (with their notes and stars), its discovered keywords, and its competitor links, and detaches it from its product — deleting the product, and that product's screenshot sets, if no other app is left. Shared store data (app metadata, snapshots, rank history) is not deleted. To drop a competitor from one product use sonar_remove_competitor instead. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| app_id* | string | Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
}
}
}WRITE tool — bulk-untrack keywords for an app in the caller's Sonar workspace. Pass `all: true` to remove every tracked keyword, OR `ids: [...]` to remove specific ones (exactly one of the two). For a single keyword, sonar_delete_tracked_keyword is equivalent. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| all | boolean | Set true to untrack ALL keywords for the app. Mutually exclusive with `ids` — pass exactly one of `all` or `ids`. |
| ids | array | Tracked-keyword ids to untrack (from sonar_app_keywords). Mutually exclusive with `all` — pass exactly one of `all` or `ids`. |
| app_id* | string | Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"all": {
"type": "boolean",
"description": "Set true to untrack ALL keywords for the app. Mutually exclusive with `ids` — pass exactly one of `all` or `ids`."
},
"ids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1,
"description": "Tracked-keyword ids to untrack (from sonar_app_keywords). Mutually exclusive with `all` — pass exactly one of `all` or `ids`."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
}
}
}WRITE tool — sets or clears the note on a tracked keyword in the caller's Sonar workspace (e.g. why it's tracked, an optimization hypothesis, a reminder). Idempotent: re-sending the same note is a no-op. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| note* | any | Note text (max 1000 chars). Pass null or an empty string to clear the note. |
| tracked_keyword_id* | string | Tracked-keyword UUID — the `id` (not keyword_id) returned by sonar_app_keywords or sonar_track_keywords. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"tracked_keyword_id",
"note"
],
"properties": {
"note": {
"anyOf": [
{
"type": "string",
"maxLength": 1000
},
{
"type": "null"
}
],
"description": "Note text (max 1000 chars). Pass null or an empty string to clear the note."
},
"tracked_keyword_id": {
"type": "string",
"minLength": 1,
"description": "Tracked-keyword UUID — the `id` (not keyword_id) returned by sonar_app_keywords or sonar_track_keywords."
}
}
}WRITE tool — replace a review's reply text (not metered, doesn't post). Use sonar_post_review_reply to publish. Requires an Indie plan (trial counts) and an authorized Sonar account or an API key with the write scope.
| Argument | Type | Description |
|---|---|---|
| body* | string | The reply text. |
| review_id* | string | Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id). |
| translate_from_english | boolean | true = body is English; store its translation into the reviewer's language (keeps the English copy). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"review_id",
"body"
],
"properties": {
"body": {
"type": "string",
"maxLength": 5000,
"minLength": 1,
"description": "The reply text."
},
"review_id": {
"type": "string",
"format": "uuid",
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
"description": "Sonar review id (the `id` of an item from sonar_review_inbox — not Apple's review id)."
},
"translate_from_english": {
"type": "boolean",
"description": "true = body is English; store its translation into the reviewer's language (keeps the English copy)."
}
}
}Replace one screen's layout in a screenshot set. Whole-document replace — fetch the current layout, modify it, send it back. The change shows up immediately in the Screenshot Studio for human review. Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| layout* | object | The FULL replacement layout — this replaces the whole document, it does not merge. Never send a layout containing '[inline image omitted…]' placeholders; refetch with include_image_data first. |
| screenshot_id* | string | Screen id (from the set's screens array). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"screenshot_id",
"layout"
],
"properties": {
"layout": {
"type": "object",
"description": "The FULL replacement layout — this replaces the whole document, it does not merge. Never send a layout containing '[inline image omitted…]' placeholders; refetch with include_image_data first.",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"screenshot_id": {
"type": "string",
"minLength": 1,
"description": "Screen id (from the set's screens array)."
}
}
}Rename a screenshot set, replace its extra-locale list, and/or reorder its screens. Returns the updated set (with image data stripped). Requires an Indie plan (trial counts) and an authorized Sonar account or a write-scope API key.
| Argument | Type | Description |
|---|---|---|
| name | string | New display name. |
| set_id* | string | Screenshot set id. |
| locales | array | Replaces the extra-locale list (e.g. ["de-DE","fr-FR"]). Locales removed here lose their stored translations. |
| screen_order | array | Full permutation of the set's screen ids in the new display order. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"set_id"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "New display name."
},
"set_id": {
"type": "string",
"minLength": 1,
"description": "Screenshot set id."
},
"locales": {
"type": "array",
"items": {
"type": "string",
"maxLength": 8,
"minLength": 2
},
"maxItems": 40,
"description": "Replaces the extra-locale list (e.g. [\"de-DE\",\"fr-FR\"]). Locales removed here lose their stored translations."
},
"screen_order": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1,
"description": "Full permutation of the set's screen ids in the new display order."
}
}
}| string |
| Sonar app UUID of one of your own tracked iOS apps — the `id` returned by sonar_list_apps or sonar_create_product. The app's store id (bundle id) also works; pass `store` if it exists in both stores. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"end": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day of the window (YYYY-MM-DD, inclusive). Default yesterday (UTC) — Apple posts a day the next morning at the earliest."
},
"days": {
"type": "integer",
"maximum": 366,
"minimum": 1,
"description": "Window length in days (1-366) when `start` is omitted. Default 30."
},
"start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day of the window (YYYY-MM-DD, inclusive). Omit to count `days` back from `end`."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "Only needed when `app_id` is a store id tracked in both stores. App Store Connect data is iOS-only."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your own tracked iOS apps — the `id` returned by sonar_list_apps or sonar_create_product. The app's store id (bundle id) also works; pass `store` if it exists in both stores."
}
}
}| store_id* |
| string |
| Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name. |
| max_rating | integer | Filter to reviews with a star rating <= this value (1-5). |
| min_rating | integer | Filter to reviews with a star rating >= this value (1-5). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store",
"store_id"
],
"properties": {
"lang": {
"type": "string",
"pattern": "^[a-z]{2}$",
"description": "Android only: fetch one language feed (e.g. ar, fr). Omit to merge the market language plus en, es, fr, ar; coverage is not exhaustive."
},
"sort": {
"enum": [
"recent",
"helpful"
],
"type": "string",
"default": "recent",
"description": "Sort order. \"recent\" returns newest first, \"helpful\" returns most-voted first."
},
"limit": {
"type": "integer",
"maximum": 200,
"minimum": 1,
"description": "Maximum number of reviews to return (1-200)."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Any App Store storefront (175 countries) or Google Play market (145). Default \"us\"."
},
"store_id": {
"type": "string",
"minLength": 1,
"description": "Store-specific app identifier. iOS: bundle ID or numeric track ID — the `storeId` returned by sonar_app_search works as-is. Android: package name."
},
"max_rating": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "Filter to reviews with a star rating <= this value (1-5)."
},
"min_rating": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "Filter to reviews with a star rating >= this value (1-5)."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"end": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day of the window (YYYY-MM-DD, inclusive). Default yesterday (UTC) — Apple posts a day the next morning at the earliest."
},
"days": {
"type": "integer",
"maximum": 366,
"minimum": 1,
"description": "Window length in days (1-366) when `start` is omitted. Default 30."
},
"start": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day of the window (YYYY-MM-DD, inclusive). Omit to count `days` back from `end`."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "Only needed when `app_id` is a store id tracked in both stores. App Store Connect data is iOS-only."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your own tracked iOS apps — the `id` returned by sonar_list_apps or sonar_create_product. The app's store id (bundle id) also works; pass `store` if it exists in both stores."
}
}
}| country | string | Filter to one market (ISO country code). Omit for all markets. |
| min_relevance | integer | Only rows with AI relevance at or above this value (0-100). |
| min_opportunity | integer | Only rows with an opportunity score at or above this value (0-100). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Max rows to return (1-500). Default 200."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your tracked apps — the `id` returned by sonar_list_apps or sonar_create_product. NOT a store id."
},
"bucket": {
"enum": [
"ranked",
"gap",
"idea"
],
"type": "string",
"description": "Filter by classification: \"ranked\" = the app already ranks for it, \"gap\" = a competitor ranks but the app does not, \"idea\" = verified research suggestion with no rank evidence yet. Omit for all."
},
"source": {
"enum": [
"autocomplete",
"metadata",
"serp_scan",
"competitor",
"apple_ads",
"ai"
],
"type": "string",
"description": "Filter by how the keyword was discovered. Omit for all sources."
},
"status": {
"enum": [
"new",
"tracked",
"hidden",
"all"
],
"type": "string",
"description": "Filter by row status. Default \"new\" — the still-actionable suggestions; \"all\" includes rows already tracked or hidden."
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "Filter to one market (ISO country code). Omit for all markets."
},
"min_relevance": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Only rows with AI relevance at or above this value (0-100)."
},
"min_opportunity": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Only rows with an opportunity score at or above this value (0-100)."
}
}
}| keywords | array | Bulk list of keywords to fetch metrics for (max 25). Use this OR `keyword`, not both. 1 credit per keyword. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store"
],
"properties": {
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "One of Sonar's 72 keyword-research markets, as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"jp\", \"br\"). Keyword data isn't available for other storefronts. Default \"us\"."
},
"keyword": {
"type": "string",
"minLength": 1,
"description": "Single keyword to fetch metrics for. Use this OR `keywords`, not both."
},
"keywords": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 25,
"minItems": 1,
"description": "Bulk list of keywords to fetch metrics for (max 25). Use this OR `keyword`, not both. 1 credit per keyword."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"query",
"store"
],
"properties": {
"query": {
"type": "string",
"minLength": 1,
"description": "Seed keyword to research (e.g. \"meditation\", \"recipe app\")."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "One of Sonar's 72 keyword-research markets, as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"jp\", \"br\"). Keyword data isn't available for other storefronts. Default \"us\"."
}
}
}| string |
| Only reviews in this language (ISO 639-1). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "Page size, 1-100 (default 25)."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your own iOS apps (an `id` from sonar_list_apps). NOT a store id."
},
"cursor": {
"type": "string",
"description": "next_cursor from the previous page."
},
"rating": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "Only reviews with this star rating."
},
"status": {
"enum": [
"needs_reply",
"scheduled",
"replied",
"dismissed"
],
"type": "string",
"description": "needs_reply = no reply yet (incl. AI drafts waiting for approval, held and failed ones), scheduled = will post soon, replied = live or waiting for Apple (incl. replies made in App Store Connect), dismissed. Omit for all."
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "Only reviews from this storefront (ISO alpha-2)."
},
"language": {
"type": "string",
"maxLength": 3,
"minLength": 2,
"description": "Only reviews in this language (ISO 639-1)."
}
}
}| scope_app_id | any | Limit the alert to a single app (Sonar app UUID). Omit or null for an org-wide rule covering all tracked apps. |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"type"
],
"properties": {
"type": {
"enum": [
"rank_drop",
"rank_gain",
"entered_top10",
"left_top10",
"new_ranking",
"rating_drop",
"review_spike",
"competitor_change",
"top_chart",
"new_review"
],
"type": "string",
"description": "The alert type to subscribe to. top_chart = one of your own apps entered or left a store top chart (overall + its category, free/paid/grossing). new_review = a new App Store review arrived for an own iOS app (needs App Store Connect connected and the review responder switched on for the app)."
},
"cadence": {
"anyOf": [
{
"enum": [
"instant",
"hourly",
"daily"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "new_review only: email cadence. instant = within ~5 minutes of the review syncing, hourly = at most one email an hour, daily = the 08:30 UTC digest. Omit to keep the stored value (daily on create)."
},
"enabled": {
"type": "boolean",
"description": "Whether the rule is active. Defaults to enabled when omitted."
},
"countries": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string",
"maxLength": 2,
"minLength": 2
},
"maxItems": 10
},
{
"type": "null"
}
],
"description": "top_chart only: storefronts to watch (ISO 3166-1 alpha-2, e.g. [\"us\", \"de\"]), max 10. Omit to keep the stored list; null or [] = the countries you track keywords in."
},
"threshold": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"description": "Trigger threshold; omit or null for the default. rank_drop / rank_gain: positions moved (default 5). rating_drop: tenths of a star (default 2 = a 0.2-star drop). review_spike: new reviews since the previous daily snapshot (default 25). top_chart: rank cutoff, 1-200 (default 200). new_review: highest star rating that alerts, 1-5 (default 5 = every review; 3 = only 1-3★). Ignored by entered_top10, left_top10, new_ranking, competitor_change."
},
"scope_app_id": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "Limit the alert to a single app (Sonar app UUID). Omit or null for an org-wide rule covering all tracked apps."
}
}
}| integer |
| Auto mode: highest star rating to auto-reply to (default 5). |
| auto_min_rating | integer | Auto mode: lowest star rating to auto-reply to (default 4). |
| auto_delay_minutes | integer | Auto mode: minutes before posting (default 5). |
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"app_id"
],
"properties": {
"mode": {
"enum": [
"manual",
"auto"
],
"type": "string",
"description": "manual = every reply waits for approval; auto = AI replies post automatically after auto_delay_minutes."
},
"app_id": {
"type": "string",
"minLength": 1,
"description": "Sonar app UUID of one of your own iOS apps (an `id` from sonar_list_apps). NOT a store id."
},
"enabled": {
"type": "boolean",
"description": "Switch the responder on (starts the review backfill) or off."
},
"sign_off": {
"anyOf": [
{
"type": "string",
"maxLength": 120
},
{
"type": "null"
}
],
"description": "Sign-off appended to every reply (null clears it)."
},
"instructions": {
"type": "string",
"maxLength": 2000,
"description": "Instructions for the AI: tone, support contact, product facts, known issues and fixes."
},
"auto_daily_cap": {
"type": "integer",
"maximum": 1000,
"minimum": 1,
"description": "Auto mode: max auto replies per app per day (default 50)."
},
"reply_language": {
"enum": [
"review",
"en"
],
"type": "string",
"description": "review = reply in the reviewer's language (default); en = always English."
},
"auto_max_rating": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "Auto mode: highest star rating to auto-reply to (default 5)."
},
"auto_min_rating": {
"type": "integer",
"maximum": 5,
"minimum": 1,
"description": "Auto mode: lowest star rating to auto-reply to (default 4)."
},
"auto_delay_minutes": {
"type": "integer",
"maximum": 1440,
"minimum": 0,
"description": "Auto mode: minutes before posting (default 5)."
}
}
}{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [
"store"
],
"properties": {
"chart": {
"enum": [
"free",
"paid",
"grossing"
],
"type": "string",
"default": "free",
"description": "Chart type: \"free\", \"paid\" or \"grossing\". Default \"free\"."
},
"limit": {
"type": "integer",
"default": 50,
"maximum": 200,
"minimum": 1,
"description": "Number of chart entries to return (1-200). Default 50."
},
"store": {
"enum": [
"ios",
"android"
],
"type": "string",
"description": "App store. \"ios\" for Apple App Store, \"android\" for Google Play."
},
"country": {
"type": "string",
"default": "us",
"maxLength": 2,
"minLength": 2,
"description": "Market as an ISO 3166-1 alpha-2 code (e.g. \"us\", \"gb\", \"de\", \"mt\"). Nearly every App Store storefront and Google Play market works; the few small storefronts that are not supported return an error naming them. Default \"us\"."
},
"category": {
"type": "string",
"default": "overall",
"description": "Category key; keys differ by store (e.g. iOS \"SOCIAL_NETWORKING\" / \"GAMES\", Android \"SOCIAL\" / \"GAME\"; \"HEALTH_AND_FITNESS\" exists on both). An unknown key is rejected with an error. Use \"overall\" (default) for the store-wide chart."
}
}
}