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.

Shell
pip install requests

Credentials: 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

Python
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 body

2. App ids from package names

Python
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 → appId

API 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

Python
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

Python
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.

Python
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.

Get a free API key

2 apps free. Test keys return sample reviews from every platform.

Next step: read the reviews as JSON with the Huawei AppGallery reviews API, and compare plans on Prisma Reviews pricing.

Get your API key in a minute

Free Spark plan: 2 locations, no card. Test keys return sample data on all 84 platforms, so you can build before connecting a real one.