Prisma Reviews / Guides / Huawei AppGallery reviews API in Python
Huawei AppGallery reviews API in Python: Connect API client, Comments API, replies
AppGallery is the third app store that matters for Android outside Google Play, and its Comments API is complete: reviews by country, developer replies, and tokens that last two days. It is also the most particular: four regional hosts, 6-month query windows, no author or title in the data, and a requestId header on every reply. This guide does it with requests, following developer.huawei.com as Prisma’s AppGallery connector does (in beta, built from the docs). The mobile picture is on app reviews API.
pip install requestsCredentials: an API client from AppGallery Connect (Users and permissions → API key → Connect API → API client; project N/A; Administrator or Operations role) with its client id and key, the apps’ package names, the countries to read (ISO codes) and the data site of the apps: cn, de, sg or ru.
1. Token on the right host
import os, time, uuid, requests
HOSTS = {"cn": "connect-api.cloud.huawei.com", "de": "connect-api-dre.cloud.huawei.com", "sg": "connect-api-dra.cloud.huawei.com", "ru": "connect-api-drru.cloud.huawei.com"}
SITE = os.environ.get("AG_SITE", "de")
BASE = f"https://{HOSTS[SITE]}"
CLIENT_ID, CLIENT_SECRET = os.environ["AG_CLIENT_ID"], os.environ["AG_CLIENT_SECRET"]
r = requests.post(f"{BASE}/api/oauth2/v1/token", json={"grant_type": "client_credentials", "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET}, timeout=30)
r.raise_for_status()
TOKEN = r.json()["access_token"] # valid 48 hours
H = {"client_id": CLIENT_ID, "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
def ok(body):
ret = body.get("ret") or {}
code = ret.get("rtnCode", ret.get("code", 0))
if code != 0:
raise RuntimeError(f"AppGallery {code}: {ret.get('rtnDesc') or ret.get('msg')}")
return body2. App ids from package names
PACKAGES = ["com.example.app"]
apps = ok(requests.get(f"{BASE}/api/publish/v2/appid-list", headers=H, params={"packageName": ",".join(PACKAGES)}, timeout=30).json())
APP_IDS = {a["key"]: a["value"] for a in apps.get("appids", [])} # package name → appIdAPI clients can’t list a team’s apps, which is why the package names are an input.
3. Reviews in 6-month windows, by country
COUNTRIES = ["DE", "ES", "FR"]
WINDOW = 180 * 86400 * 1000
def reviews(app_id, begin_ms, end_ms):
page = 1
while True:
q = {"appId": app_id, "beginTime": begin_ms, "endTime": end_ms, "countries": ",".join(COUNTRIES), "sort": 0, "page": page, "limit": 100}
body = ok(requests.get(f"{BASE}/api/reviews/v1/manage/dev/reviews", headers=H, params=q, timeout=30).json())
data = body.get("data") or {}
for rv in data.get("reviewList", []):
yield rv
if data.get("hasNext") != 1:
return
page += 1
now = int(time.time() * 1000)
for pkg, app_id in APP_IDS.items():
for rv in reviews(app_id, now - WINDOW, now): # last 6 months; loop 4 windows for the full 2-year history
print(pkg, rv.get("countryCode"), rv["reviewId"], rv.get("rating"), time.strftime("%Y-%m-%d", time.gmtime(rv["dateline"] / 1000)), rv.get("apkVersion"), (rv.get("content") or "")[:80], "| replied" if (rv.get("devReplyContent") or "").strip() else "")Fields: reviewId, rating (1 to 5), content, dateline (epoch milliseconds), countryCode, phoneType, apkVersion and devReplyContent. No reviewer name, no title, no language. Review ids repeat across countries, so key them as country:reviewId.
4. Reply, 800 characters, once per review
LANGS = {"DE": "de_DE", "ES": "es_ES", "FR": "fr_FR", "GB": "en_GB", "CN": "zh_CN"}
country, review_id = rv.get("countryCode", COUNTRIES[0]), rv["reviewId"]
ok(requests.post(f"{BASE}/api/reviews/v1/manage/dev/reviews", headers={**H, "requestId": str(uuid.uuid4())},
json={"lang": LANGS.get(country, "en_US"), "appId": app_id, "reviewId": review_id, "countryCode": country, "devReplyContent": "Thanks for the feedback. Version 4.3 fixes the login loop on EMUI 12."}, timeout=30).json())Huawei wants a language with each reply and a unique requestId; a second POST on the same review replaces the first. Error 50010028 means the app isn’t in the API client’s team.
5. The same job through Prisma
Prisma connects an AppGallery team with the API client, package names, countries and site (checked by listing the app ids before storing, encrypted), reads reviews in the 6-month windows with a month of look-back, keys them by country, and publishes replies with a fresh requestId per request. One key covers AppGallery plus the App Store, Google Play, Microsoft Store and 50+ more.
H = {"Authorization": f"Bearer {os.environ['PRISMA_API_KEY']}"}
r = requests.get("https://api.prismareviews.com/v1/reviews", headers=H, params={"platform": "appgallery", "has_reply": "false", "limit": 100}, timeout=30)
for rev in r.json()["data"]:
print(rev["rating"], rev["text"], rev["url"])
requests.post(f"https://api.prismareviews.com/v1/reviews/{rev['id']}/reply", headers=H, json={"text": "Thanks for the feedback. Version 4.3 fixes the login loop on EMUI 12."}, timeout=30).raise_for_status()AppGallery is in beta in Prisma, with replies live. Connection fields: Platforms. A test key returns sample reviews so the code runs now.
FAQ
What credentials does the AppGallery reviews API need?
An API client created by the team account holder in AppGallery Connect (Users and permissions → API key → Connect API → API client, project N/A, Administrator or Operations role): its client id and key, exchanged for a 48-hour token with POST /api/oauth2/v1/token on the data site’s host (China, Germany, Singapore or Russia).
Why do I have to query AppGallery reviews in 6-month windows?
The Comments API accepts beginTime and endTime at most 6 months apart, and Huawei keeps about two years of comments, so a first full read is four windows. After that, one window from your last sync minus a month is enough.
Can I reply to AppGallery reviews by API?
Yes, once per review: POST /api/reviews/v1/manage/dev/reviews with appId, reviewId, countryCode, a lang and devReplyContent up to 800 characters, plus a unique requestId header. Huawei keeps the developer’s reply; a second POST replaces it.
AppGallery, App Store, Google Play and Microsoft Store, one key.
2 apps free. Test keys return sample reviews from every platform.