App store lookup API
The app store lookup API at `GET /v1/app/{store}/{app_id}` returns App Store or Google Play listing status as `live`, `removed`, `not_found` or `unknown`. It includes the store's app name, developer and rating count, plus Bewary's first and last live sightings. The verdict stays `unknown` for a live app, and a removal adds `APP_REMOVED`, a medium caution. A call costs 1 credit, a free key gets 1,000 credits a month, no card.
- Endpoint
- GET
https://api.bewary.app/v1/app/{store}/{app_id} - Price
- 1 credit
- Free key
- 1,000 credits a month, no card
- Returns
- verdict, p_scam, entities with typed facts, reason codes
- MCP tool
lookup_app
Try it
Free from this page: 10 lookups a dayCall it
curl "https://api.bewary.app/v1/app/google_play/com.whatsapp" import requests
r = requests.get("https://api.bewary.app/v1/app/google_play/com.whatsapp", timeout=10)
result = r.json()
print(result["verdict"], result["p_scam"], result["reason_codes"]) const res = await fetch("https://api.bewary.app/v1/app/google_play/com.whatsapp")
const result = await res.json()
console.log(result.verdict, result.p_scam, result.reason_codes) Act on the result
Copy-paste code that turns the answer into a decision. It runs with or without BEWARY_API_KEY. TypeScript uses bewary.d.ts.
import os, requests
def app_status(store, app_id):
key = os.environ["BEWARY_API_KEY"] # a free key: bewary.app/account
headers = {"Authorization": f"Bearer {key}"}
r = requests.get(f"https://api.bewary.app/v1/app/{store}/{app_id}", headers=headers, timeout=15)
r.raise_for_status()
facts = r.json()["entities"][0]["facts"]
return facts["status"], facts["name"], facts["developer"]
print(app_status("google_play", "com.whatsapp"))
# ('live', 'WhatsApp', 'WhatsApp LLC') import type { Envelope } from "./bewary"
export async function appStatus(store: "apple" | "google_play", appId: string) {
const key = process.env.BEWARY_API_KEY! // a free key: bewary.app/account
const headers: Record<string, string> = { Authorization: `Bearer ${key}` }
const res = await fetch(`https://api.bewary.app/v1/app/${store}/${encodeURIComponent(appId)}`,
{ headers, signal: AbortSignal.timeout(15_000) })
if (!res.ok) throw new Error(`Bewary ${res.status}`)
const e = (await res.json() as Envelope).entities[0]
if (e.type !== "app") throw new Error("unexpected entity")
return { status: e.facts.status, name: e.facts.name, developer: e.facts.developer }
} Response
The fields you will use
entities[0].facts.status- live, removed (we saw it live and the store no longer lists it), not_found or unknown.
entities[0].facts.name- The store's title, from the last live sighting.
entities[0].facts.developer- The developer the store names.
entities[0].facts.missing_since- The first check that found it gone after a live sighting.
{ "schema_version": "1.7.0", "request_id": "req_01M69WJC3HPMWQ4A9WBVWVVWEV", "checked_at": "2026-10-31T21:06:38Z", "engine": "bewary-engine/3.0.0", "models": { "calibration": "interim-band-v0" }, "input": { "kind": "lookup", "channel": "unknown", "language": null, "region": null }, "verdict": "unknown", "p_scam": 0.2, "risk_score": 20, "confidence": 0, "classification": null, "reason_codes": [], "entities": [ { "id": "e1", "type": "app", "value": "google_play:com.whatsapp", "normalized": "google_play:com.whatsapp", "role": "mentioned", "verdict": "unknown", "p_scam": 0.2, "risk_score": 20, "reason_codes": [], "facts": { "store": "google_play", "app_id": "com.whatsapp", "status": "live", "name": "WhatsApp", "developer": "WhatsApp LLC", "rating_count": 246797088, "storefront": null, "first_seen": "2026-10-30T19:36:24Z", "last_seen": "2026-10-31T21:06:38Z", "missing_since": null }, "related": [], "datasets": [ { "dataset": "app_stores", "coverage": "WW", "in_coverage": true } ] } ], "signals": [], "degraded": false, "degraded_reasons": [], "cached": false, "explanation": null} Real responses, captured from the live API on 2026-10-31. Every response has this shape: see Response format.
Mobile app facts
Every key is in every response, null when unknown. A key marked Coming stays null until its source ships, so you can code against it now.
| Key | Type | Meaning |
|---|---|---|
store | apple | google_play or null | The store. |
app_id | string or null | Apple: the numeric App Store id. Google Play: the package name. |
status | live | removed | not_found | unknown or null | removed: we saw it live before and the store no longer lists it. |
name | string or null | The store's title for the app, from the last live sighting. |
developer | string or null | The developer or seller the store names. |
rating_count | integer or null | How many ratings the store shows. |
storefront | ISO code or null | Apple: the App Store country read. |
first_seen | timestamp or null | The first time we saw it live. |
last_seen | timestamp or null | The last time we saw it live. |
missing_since | timestamp or null | The first check that found it gone after a live sighting. |
Parameters
| Name | Type | Description |
|---|---|---|
storepath, required | string | apple (the App Store) or google_play. |
app_idpath, required | string | Apple: the numeric App Store id, e.g. 284882215 or id284882215. Google Play: the package name, e.g. com.whatsapp. |
storefrontquery | string | Apple only: the App Store country to read, ISO 3166-1 alpha-2. Default: where we last saw the app live, else US. |
Questions
How can I check whether the App Store or Google Play removed an app?
Call GET /v1/app/{store}/{app_id} with apple and the numeric App Store ID, or google_play and the package name. A removed result means Bewary saw the app live before and the store no longer lists it.
Does an app removed from Google Play mean it is a scam?
Not on its own. A removal adds APP_REMOVED, a medium caution, and the verdict follows all of the app's signals. A removed status means Bewary saw the app live before and the store no longer lists it.
Used for
- Your security tool checks an app's store listing when a message asks someone to install it.
- Your brand monitoring tool checks whether the store still lists an app reported for impersonation.
- Your marketplace checks an app's listing when a seller shares its store link in chat.
Reason codes it can return
| Code | Meaning | Severity |
|---|---|---|
LISTED_BLOCKLIST | On scam blocklist | Critical |
LISTED_CAUTION | On a broad threat list that also holds spam and malware hosts | Medium |
PLATFORM_TAKEDOWN | The hosting platform took it down | High |
PLATFORM_WARNING | The platform shows a phishing or malware warning in front of it | High |
APP_REMOVED | The store pulled the app | Medium |
Reserved codes are in the contract, not emitted yet. All reason codes
Updated · This page as Markdown · Changelog