AppZone Store API
Read-only discovery plus download, review and report endpoints. Everything a Flutter or native Android client needs to browse the store and keep installed apps up to date.
https://apkzone.in/api/v1
Response envelope
Every response uses the same shape, success or failure.
{
"status": true,
"message": "Apps fetched successfully",
"data": []
}
{
"status": false,
"message": "App not found"
}
{
"status": false,
"message": "Validation failed",
"errors": { "rating": "Rating must be at least 1." }
}
Authentication
Discovery endpoints are public. Posting a review requires a user bearer token; downloads and reports accept one optionally so the action can be attributed.
Authorization: Bearer <token>
Tokens are stored only as SHA-256 digests, can carry an expiry, and are revocable. A token belonging to a suspended user stops working immediately.
Pagination
https://apkzone.in/api/v1/apps?page=2&limit=20
Default page size 20, maximum 100.
List responses carry a pagination block with
total, per_page, current_page,
last_page, from, to and has_more.
Rate limits
| Bucket | Limit | Window |
|---|---|---|
| General API | 120 requests | 60 s |
| Downloads | 30 requests | 1 hour |
| Review posting | 10 requests | 1 hour |
| Reporting | 10 requests | 1 hour |
Responses carry X-RateLimit-Limit and X-RateLimit-Remaining.
On 429 a Retry-After header states how many seconds to wait.
Error codes
| Code | Meaning |
|---|---|
200 | Success. |
201 | Resource created (review, report). |
400 | Malformed request. |
401 | Authentication required — send a valid bearer token. |
403 | Not permitted — the app is suspended, removed or unpublished. |
404 | Endpoint or resource not found. |
409 | Conflict — for example, you already reviewed this app. |
422 | Validation failed. An errors object lists each field. |
429 | Rate limit exceeded. Check the Retry-After header. |
500 | Server error. Details are logged, never returned in production. |
Discovery
Lists every available endpoint and the API version.
{
"status": true,
"message": "AppStore API",
"data": { "version": "v1", "endpoints": [ ... ], "docs": "..." }
}
curl 'https://apkzone.in/api/v1/'
Authentication
Creates a store-user account and returns a bearer token. Send the token as "Authorization: Bearer <token>" on endpoints that act on behalf of a person. Rate limited to 5 registrations per IP per hour.
| Name | Type | Notes |
|---|---|---|
name |
string | Required. 2-120 characters. |
email |
string | Required. Must be unique. |
password |
string | Required. Minimum 10 characters, letters and digits. |
mobile |
string | Optional mobile number. |
device_name |
string | Optional label shown in the user's device list. |
platform |
string | android (default) | ios | web | other |
{
"status": true,
"message": "Account created successfully.",
"data": {
"token": "IVpqj1hfelkCzusGQ7ZQ…",
"token_type": "Bearer",
"expires_at": "2026-10-31 16:49:25",
"user": { "id": 4, "name": "Flutter User", "email": "user@example.com" }
}
}
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/auth/register'
Exchanges e-mail and password for a bearer token. Subject to the same lockout as the web panels: after 5 failed attempts the account is locked and the endpoint answers 429. Unknown accounts and wrong passwords return an identical message so accounts cannot be enumerated.
| Name | Type | Notes |
|---|---|---|
email |
string | Required. |
password |
string | Required. |
device_name |
string | Optional label for this token. |
platform |
string | android (default) | ios | web | other |
{
"status": true,
"message": "Signed in successfully.",
"data": {
"token": "CWCuoWd2yL3JV7wqJd2pF05uAv…",
"token_type": "Bearer",
"expires_at": "2026-10-31 16:49:40",
"user": { "id": 4, "name": "Flutter User", "email": "user@example.com" }
}
}
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/auth/login'
Returns the profile behind the presented token. Useful on app start to confirm a stored token is still valid.
{
"status": true,
"message": "Profile fetched successfully",
"data": {
"id": 4, "name": "Flutter User", "email": "user@example.com",
"mobile": null, "avatar": null, "created_at": "2026-08-02 16:49:25"
}
}
curl 'https://apkzone.in/api/v1/auth/me'
Revokes only the token used for this call, so other devices stay signed in. Revoked and expired tokens are removed by cron/cleanup.php.
{
"status": true,
"message": "Signed out."
}
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/auth/logout'
Apps
Paginated list of published apps.
| Name | Type | Notes |
|---|---|---|
page |
int | Page number. Default 1. |
limit |
int | Items per page. Default 20, max 100. |
category |
int | Filter by category id. |
platform |
string | android | ios. Omit for both. Every listing endpoint accepts this. |
sort |
string | popular (default) | new | rating | updated | name |
{
"status": true,
"message": "Apps fetched successfully",
"data": [
{
"id": 11,
"name": "PAN MITRA",
"slug": "pan-mitra",
"package_name": "com.example.app",
"short_description": "…",
"icon": "https://…/uploads/icons/…png",
"category": "Business",
"developer": { "name": "Acme", "slug": "acme", "verified": true },
"version": "1.4.0",
"version_code": 15,
"size": 13831254,
"size_human": "13.2 MB",
"min_sdk": 21,
"min_android": "5.0",
"rating": 4.5,
"rating_count": 128,
"downloads": 5210,
"published_at": "2026-08-01 23:04:04",
"url": "https://…/app/pan-mitra",
"download_url": "https://…/api/v1/apps/11/download"
}
],
"pagination": {
"total": 42, "per_page": 20, "current_page": 1,
"last_page": 3, "from": 1, "to": 20, "has_more": true
}
}
curl 'https://apkzone.in/api/v1/apps'
Full detail for one app, including screenshots, permissions and the current release.
| Name | Type | Notes |
|---|---|---|
id |
int | App id (path parameter). |
{
"status": true,
"message": "App fetched successfully",
"data": {
"id": 11, "name": "…", "full_description": "…",
"screenshots": [ "https://…/1.png", "https://…/2.png" ],
"current_release": {
"version_name": "1.4.0", "version_code": 15,
"size": 13831254,
"sha256": "ea9d559de7c0…",
"min_sdk": 21, "target_sdk": 34,
"abis": ["arm64-v8a"],
"release_notes": "…",
"published_at": "2026-08-01 23:04:04"
},
"permissions": [
{ "name": "android.permission.CAMERA", "dangerous": true }
]
}
}
curl 'https://apkzone.in/api/v1/apps/{id}'
Every published release of an app, newest first. Pending and rejected releases are never returned.
| Name | Type | Notes |
|---|---|---|
id |
int | App id. |
{
"status": true,
"message": "Versions fetched successfully",
"data": [
{
"version_name": "1.4.0", "version_code": 15,
"size": 13831254, "size_human": "13.2 MB",
"sha256": "ea9d559de7c0…",
"min_sdk": 21, "target_sdk": 34,
"release_notes": "…", "published_at": "…", "downloads": 5210
}
]
}
curl 'https://apkzone.in/api/v1/apps/{id}/versions'
Discovery lists
Apps an administrator has marked as featured, in curated order.
| Name | Type | Notes |
|---|---|---|
page |
int | |
limit |
int |
Same envelope and item shape as GET /apps.
curl 'https://apkzone.in/api/v1/featured'
Ordered by total downloads, then rating.
| Name | Type | Notes |
|---|---|---|
page |
int | |
limit |
int |
Same envelope and item shape as GET /apps.
curl 'https://apkzone.in/api/v1/popular'
Ordered by first publication date.
| Name | Type | Notes |
|---|---|---|
page |
int | |
limit |
int |
Same envelope and item shape as GET /apps.
curl 'https://apkzone.in/api/v1/new'
Apps with the most recent releases.
| Name | Type | Notes |
|---|---|---|
page |
int | |
limit |
int |
Same envelope and item shape as GET /apps.
curl 'https://apkzone.in/api/v1/updates'
Categories
All active categories with a live published-app count.
{
"status": true,
"message": "Categories fetched successfully",
"data": [
{ "id": 1, "name": "Games", "slug": "games", "icon": "bi-controller",
"description": null, "app_count": 12, "url": "https://…/category/games" }
]
}
curl 'https://apkzone.in/api/v1/categories'
Published apps inside one category.
| Name | Type | Notes |
|---|---|---|
id |
int | Category id. |
page |
int | |
limit |
int |
Same envelope and item shape as GET /apps.
curl 'https://apkzone.in/api/v1/categories/{id}/apps'
Search
Searches app name, package name, short description, publisher name and category.
| Name | Type | Notes |
|---|---|---|
q |
string | Required. 1-100 characters. |
page |
int | |
limit |
int |
{
"status": true,
"message": "Search completed successfully",
"query": "photo",
"data": [ … ],
"pagination": { … }
}
curl 'https://apkzone.in/api/v1/search'
Downloads
Authorises a download. With Accept: application/json it returns metadata plus a URL; without it (or via GET) the APK bytes are streamed directly. The download is recorded once per client per 24 hours; obvious bots are logged but never counted. Android only. For an iOS listing this answers 409 with {"platform":"ios","store_url":"…"} — open that App Store URL instead, because Apple does not permit a third party to host or install iOS builds.
| Name | Type | Notes |
|---|---|---|
id |
int | App id (path parameter). |
version |
int | Optional. A specific published version id; defaults to the latest. |
{
"status": true,
"message": "Download authorised",
"data": {
"app_id": 11,
"package_name": "com.example.app",
"version": "1.4.0",
"version_code": 15,
"size": 13831254,
"sha256": "ea9d559de7c0…",
"file_name": "com.example.app_1.4.0.apk",
"download_url": "https://…",
"expires_in": null
}
}
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/apps/{id}/download'
Update check
The endpoint an installed Android app calls to discover updates. Only published, non-blocked releases are ever returned.
| Name | Type | Notes |
|---|---|---|
package_name |
string | Required. The applicationId of the installed app. |
version_code |
int | Required. The versionCode currently installed. |
{
"package_name": "com.example.app",
"version_code": 10
}
{
"status": true,
"update_available": true,
"message": "An update is available.",
"app_id": 11,
"app_name": "Example",
"package_name": "com.example.app",
"latest_version": "2.0",
"latest_version_code": 15,
"apk_size": 25000000,
"sha256": "ea9d559de7c0…",
"min_sdk": 21,
"release_notes": "Performance improvements",
"published_at": "2026-08-01 23:04:04",
"download_url": "https://…/api/v1/apps/11/download"
}
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/check-update'
Reviews
Approved reviews for an app, newest first.
| Name | Type | Notes |
|---|---|---|
id |
int | App id. |
page |
int | |
limit |
int |
{
"status": true,
"message": "Reviews fetched successfully",
"data": [
{ "rating": 5, "title": "Great", "review": "…", "created_at": "…",
"developer_reply": null, "user_name": "Asha" }
],
"pagination": { … }
}
curl 'https://apkzone.in/api/v1/apps/{id}/reviews'
Post a review. One review per user per app. Rate limited to 10 per hour.
| Name | Type | Notes |
|---|---|---|
rating |
int | Required. 1-5. |
title |
string | Optional. Max 150 characters. |
review |
string | Optional. Max 5000 characters. |
{ "rating": 5, "title": "Works well", "review": "Fast and stable." }
{ "status": true, "message": "Review submitted and awaiting moderation." }
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/apps/{id}/reviews'
Reports
Report an app. Malware reports are automatically raised to critical priority. Rate limited to 10 per hour per client.
| Name | Type | Notes |
|---|---|---|
reason |
string | Required. malware | fake_app | copyright | privacy | inappropriate | other |
details |
string | Optional. Max 5000 characters. |
reporter_email |
string | Optional contact address for anonymous reports. |
{ "reason": "malware", "details": "Requests SMS access with no reason." }
{ "status": true, "message": "Report submitted. Our team will review it." }
curl -X POST \
-H 'Content-Type: application/json' \
'https://apkzone.in/api/v1/apps/{id}/report'
Flutter client example
Minimal update check from an installed Android app.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:package_info_plus/package_info_plus.dart';
Future<Map<String, dynamic>?> checkForUpdate() async {
final info = await PackageInfo.fromPlatform();
final response = await http.post(
Uri.parse('https://apkzone.in/api/v1/check-update'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'package_name': info.packageName,
'version_code': int.parse(info.buildNumber),
}),
);
if (response.statusCode != 200) return null;
final data = jsonDecode(response.body) as Map<String, dynamic>;
if (data['update_available'] != true) return null;
// data['download_url'], data['latest_version'], data['sha256'],
// data['apk_size'] and data['release_notes'] are all present here.
return data;
}
sha256. Hash the downloaded file and compare
before handing it to the package installer — this is what makes a self-hosted store
safe to update from.