Ask your admin to create a token from the admin dashboard, or create one yourself if you have admin access.
Tokens are shown only once — copy it immediately after creation.
Install the dist-ant command:
curl -fsSL https://dist.ant.sh/install.sh | bash
Then configure your credentials:
export DIST_ANT_URL=https://dist.ant.sh
export DIST_ANT_TOKEN=your-token-here
Add the exports to your ~/.bashrc or ~/.zshrc to persist them.
# Upload an APK
dist-ant app-release.apk
# Upload with notes and custom expiration
dist-ant app-release.apk --notes "v1.2.0 beta" --expires 7d
# Upload an iOS IPA
dist-ant MyApp.ipa --notes "TestFlight alternative"
# Get JSON output (for CI parsing)
dist-ant app-release.apk --json
-n, --notes "text" | Release notes |
-e, --expires "30d" | Expiration: 7d, 14d, 30d, 90d, never |
-s, --server URL | Server URL (overrides DIST_ANT_URL) |
-t, --token TOKEN | API token (overrides DIST_ANT_TOKEN) |
-j, --json | Output raw JSON response |
-c, --chunked | Force chunked upload (auto for >95MB) |
Add this task to your app/build.gradle.kts:
tasks.register("uploadApk") {
dependsOn("assembleRelease")
group = "distribution"
description = "Upload release APK to dist-ant"
doLast {
val apkDir = layout.buildDirectory
.dir("outputs/apk/release").get().asFile
val apk = apkDir.listFiles()
?.firstOrNull { it.extension == "apk" }
?: error("No APK found in ${apkDir.absolutePath}")
val serverUrl = project.findProperty("distAntUrl") as? String
?: System.getenv("DIST_ANT_URL")
?: error("Set distAntUrl property or DIST_ANT_URL env var")
val token = project.findProperty("distAntToken") as? String
?: System.getenv("DIST_ANT_TOKEN")
?: error("Set distAntToken property or DIST_ANT_TOKEN env var")
val process = ProcessBuilder(
"curl", "-s", "-X", "POST",
"$serverUrl/api/upload",
"-H", "X-Auth-Token: $token",
"-F", "file=@${apk.absolutePath}",
"-F", "notes=CI build ${project.version}"
).redirectErrorStream(true).start()
val output = process.inputStream.bufferedReader().readText()
val exitCode = process.waitFor()
if (exitCode == 0) {
println("Upload successful: $output")
} else {
error("Upload failed: $output")
}
}
}
# With environment variables
export DIST_ANT_URL=https://dist.ant.sh
export DIST_ANT_TOKEN=your-token-here
./gradlew uploadApk
# Or with Gradle properties
./gradlew uploadApk \
-PdistAntUrl=https://dist.ant.sh \
-PdistAntToken=your-token-here
- name: Build & Upload APK
env:
DIST_ANT_URL: https://dist.ant.sh
DIST_ANT_TOKEN: ${{ secrets.DIST_ANT_TOKEN }}
run: ./gradlew uploadApk
If you prefer not to install anything:
# Upload
curl -X POST https://dist.ant.sh/api/upload \
-H "X-Auth-Token: your-token-here" \
-F "file=@app-release.apk" \
-F "notes=Manual upload" \
-F "expires_in=30d"
# Simple upload (returns just the install URL)
curl -X POST https://dist.ant.sh/upload \
-H "X-Auth-Token: your-token-here" \
-F "file=@app-release.apk"
# Delete a release
curl -X DELETE https://dist.ant.sh/api/delete/RELEASE_ID \
-H "X-Auth-Token: your-token-here"
# List releases
curl https://dist.ant.sh/api/releases
# Latest release for a package
curl https://dist.ant.sh/api/bundle/com.example.app/latest