License: Apache 2.0
The Appning API enables developers to interact with Appning services from their own systems (server-to-server). This client library is focused on Android Publisher with custom endpoints.
All Appning endpoints are authenticated using JWT Bearer tokens signed locally with RS256. This library is based on the Google API Python Client and is adapted for use with Appning services.
This library is an unofficial fork of Googleβs
google-api-python-clientlibrary and is maintained independently by Appning. It is not an official Google product and is provided under the same Apache License 2.0 terms as the upstream project.
The preferred method is via pip. From the project root:
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -e .Or install the published package:
pip install appning-api-python-clientThis library relies on google-auth and google-auth-httplib2 for authentication and HTTP transport. They are installed automatically as dependencies.
Obtain API access credentials from the Developer Portal:
From there you can download a credentials file (e.g. serviceAccount.json) with this structure:
{
"kid": "the-key-id",
"privateKeyPem": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"clientId": "the-client-id"
}privateKeyPemis private and must remain local (never sent to the server).kididentifies the key used to sign the JWT.clientIdidentifies the client and must be used as the JWTissandsubclaims.
- Required claims: The JWT must include
issandsub, both set to the clientβsclientId. - Token validity: The server only accepts tokens with a maximum validity of 15 minutes (
exp - iat <= 900seconds). The JWT must includeiatandexp(Unix epoch seconds). The library handles this when you useJwtBearerCredentialswith the credentials file.
For full details (clock skew, error responses), see Service Account Authentication.
See samples/androidpublisher/example_custom_endpoint.py for a complete example.
import json
import os
import time
import google_auth_httplib2
import httplib2
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import set_user_agent
from googleapiclient.jwt_bearer_credentials import JwtBearerCredentials
service_account_file = 'serviceAccount.json'
package_name = "com.example.app"
if not os.path.exists(service_account_file):
raise FileNotFoundError("serviceAccount.json not found. Obtain credentials from the developer portal.")
with open(service_account_file, 'r') as f:
data = json.load(f)
cred_kwargs = {'kid': data['kid'], 'private_key_pem': data['privateKeyPem']}
if data.get('clientId'):
cred_kwargs['client_id'] = data['clientId']
credentials = JwtBearerCredentials(**cred_kwargs)
custom_endpoint = 'https://product.faa.faurecia-aptoide.com/api/8.20200601/'
base_http = set_user_agent(httplib2.Http(timeout=30), 'appning-api-python-client/androidpublisher')
authorized_http = google_auth_httplib2.AuthorizedHttp(credentials, http=base_http)
service = build('androidpublisher', 'v3', http=authorized_http, client_options={'api_endpoint': custom_endpoint})
batch_request_body = {
"requests": [
{
"oneTimeProduct": {
"packageName": package_name,
"productId": f"coin_pack_etc_{int(time.time())}",
"listings": [
{
"languageCode": "pt-BR",
"title": "300 Moedas",
"description": "Receba 300 moedas instantaneamente"
},
{
"languageCode": "en-US",
"title": "300 Coins",
"description": "Receive 300 coins instantly"
}
],
"purchaseOptions": [
{
"purchaseOptionId": "default",
"buyOption": {
"legacyCompatible": True,
"multiQuantityEnabled": False
},
"regionalPricingAndAvailabilityConfigs": [
{
"regionCode": "US",
"price": {
"currencyCode": "USD",
"units": "1",
"nanos": 880000000
},
"availability": "AVAILABLE"
}
]
}
]
},
"updateMask": "listings,purchaseOptions",
"allowMissing": True,
"latencyTolerance": "PRODUCT_UPDATE_LATENCY_TOLERANCE_LATENCY_TOLERANT",
"regionsVersion": {
"version": "2025/03"
}
}
]
}
response = service.monetization().onetimeproducts().batchUpdate(
packageName=package_name, body=batch_request_body
).execute()| Service | Method | Description |
|---|---|---|
| Android Publisher | POST | Batch create/update one-time products (monetization): applications/{packageName}/oneTimeProducts:batchUpdate |
The base URL for the Appning product API is typically https://product.faa.faurecia-aptoide.com/api/8.20240517 (or the version your account uses). Set it via client_options={'api_endpoint': '...'} when building the service.
- Android Publisher batch update: samples/androidpublisher/example_custom_endpoint.py β JWT Bearer auth and batch updates of one-time products (monetization).
-
Use a virtual environment (recommended):
python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate
-
Install the package in editable mode and test dependencies:
The test suite requires several dependencies (e.g.
pytest,parameterized,mox,webtest). Install them all with:pip install -e . pip install -r dev-requirements.txtWithout
dev-requirements.txt, collection may fail withModuleNotFoundError(e.g.No module named 'parameterized'). -
Run the test suite:
From the project root:
pytest tests/
Or with Python module (if
pytestis not on your PATH):python -m pytest tests/
Optional: run with coverage:
pytest tests/ --cov=googleapiclient --cov-report=term-missing
-
Run the Android Publisher sample (manual/integration):
Requires a valid
serviceAccount.jsonin the project root (or path used by the sample). This calls a real or custom endpoint:cd samples/androidpublisher python example_custom_endpoint.py
- Unit tests (
tests/) β Core client library (discovery, HTTP, auth, mocks). No live API calls. - Android Publisher sample β Manual verification against a real or custom endpoint; not run in CI unless configured with credentials.
Credential-related deprecation warnings from dependencies (e.g. credentials_file) are suppressed in tests. For Appning, obtain credentials from the Developer Portal (JWT Bearer / serviceAccount.json), not via Application Default Credentials or credentials_file.
flake8 googleapiclient/ tests/
autopep8 --in-place --recursive googleapiclient/ tests/- 200 OK β Request processed successfully.
- 400 Bad Request β Invalid payload or validation failure (missing required fields, invalid types).
- 401 Unauthorized β Authentication failure: missing or malformed
Authorizationheader, malformed JWT, invalid signature, unknown/revokedkid, expired token, or token validity > 15 minutes. Ensureissandsubequal yourclientId. - 403 Forbidden β Token valid but caller lacks permission for this operation; check permissions for your
clientIdat developers.appning.com. - 404 Not Found β Resource not found (e.g. package not available for monetization or not under your account).
See Service Account Authentication for more detail.
The docs/ folder contains Getting Started, Installation, Service Account Authentication.
See CONTRIBUTING.md. Pull requests are welcome.
For issues with the library, open an issue in the projectβs issue tracker with a minimal example and error details. For API-specific questions, refer to the relevant API documentation.