Management API - Applications And Builds
Use these endpoints to list protected application records, inspect build history, upload app artifacts, download protected outputs, and manage signing material used by portal builds.
For simple CI/CD protection jobs, the Automation API is usually easier. Use these Management API endpoints when your integration also needs portal build history, signing-key administration, tenant administration, or reporting.
Integration Notes
| Need | Recommendation |
|---|---|
| Release traceability | Store the AppTego version, platform, original file_name, returned file_path, start_time, protected output name, and your commit SHA together. |
| Upload handling | Upload binaries to the signed URL returned by AppTego. Do not send app binaries directly to /frontend/upload_application_build. |
| Build status | Use success, status_message, error_message, and signing_error_message from build history as release gates. |
| Artifact handling | Download protected artifacts into controlled storage and validate them before distribution. |
| Permissions | Grant the Builds permission only to users or API tokens that need build operations. |
Common Fields
| Field | Description |
|---|---|
version | Configuration version: development, staging, or production. |
platform | android or ios. Android uploads must be .apk or .aab; iOS uploads must be .ipa. |
start_time | Unix timestamp returned when the upload URL is created. It is also the build job identifier used by download, delete, and signing calls. |
file_name | Base filename for the app artifact. Path components are stripped server-side. |
Signed upload and download URLs expire after 3600 seconds.
List Applications
Get application records associated with your tenant.
POST /frontend/get_applications
Permission: None (read-only)
Request Body:
{}
Response:
{
"applications": [
{
"platform": "android",
"build_version": "1.0.0",
"build_id": "build-identifier",
"build_name": "MyApp",
"build_image": "https://example.com/icon.png",
"creation_time": 1700000000,
"application_id": "app-uuid-1234"
}
]
}
List Builds By Configuration Version
Get paginated build history for one configuration version.
POST /frontend/get_application_builds
Permission: None (read-only)
Request Body:
{
"version": "production",
"page": 1,
"page_size": 6
}
| Field | Type | Required | Description |
|---|---|---|---|
version | String | Yes | development, staging, or production. |
page | Integer | No | Page number. Defaults to 1. |
page_size | Integer | No | Number of builds per page. Defaults to 6; maximum is 50. |
Response:
{
"results": [
{
"start_time": 1700000000,
"end_time": 1700000300,
"version": "production",
"name": "app-release.apk",
"platform": "android",
"success": true,
"signed": true,
"error_message": null,
"status_message": "Complete",
"signing_key_id": "key-uuid-1234",
"signing_key_name": "Android release key",
"deleted": false,
"signing_error_message": null
}
],
"total_count": 1,
"page": 1,
"page_size": 6,
"total_pages": 1,
"builds_used_apple": 0,
"builds_used_android": 1,
"still_waiting": false
}
Build Status Interpretation
| Field State | Meaning |
|---|---|
success: null | Build is still processing. Use status_message for the current stage. |
success: true | Build completed successfully and can be downloaded. |
success: false | Build failed or was reset for signing. Review status_message, error_message, and signing_error_message. |
deleted: true | The build record is retained in history but marked deleted. |
In-progress builds older than the worker timeout are automatically marked failed by the listing endpoint.
Request An Upload URL
Create a signed URL for uploading an APK, AAB, or IPA. The protected build is queued after the uploaded object is received. Large files return multipart upload instructions.
POST /frontend/upload_application_build
Permission: Builds
Request Body:
{
"file_name": "app-release.apk",
"platform": "android",
"version": "production",
"file_size": 52428800,
"signing_key_id": "key-uuid-1234"
}
| Field | Type | Required | Description |
|---|---|---|---|
file_name | String | Yes | Base filename ending in .apk, .aab, or .ipa. |
platform | String | Yes | android or ios. |
version | String | Yes | development, staging, or production. |
file_size | Integer | No | Artifact size in bytes. Include this so the API can reject files over 2 GB and return multipart instructions for files 100 MB or larger. |
signing_key_id | String | No | Signing key to use. Omit to use the tenant default key when configured, or set none to skip signing-key metadata. Free tenants always skip signing-key metadata. |
The request is rejected if the tenant has reached build limits or if no protection/detection control is enabled for the selected platform and version.
Single-Part Upload Response
{
"url": "https://apps.apptego.com/signed-upload-url",
"file_path": "tenant-123/uploads/android/production/1700000000/app-release.apk",
"start_time": 1700000000,
"expires_in": 3600,
"signing_key_id": "key-uuid-1234"
}
Upload the binary with PUT to url:
curl -sS -X PUT \
-H "Content-Type: application/octet-stream" \
--data-binary "@app-release.apk" \
"$UPLOAD_URL"
Multipart Upload Response
Files at or above 100 MB return multipart instructions with 10 MB chunks.
{
"multipart": true,
"upload_id": "multipart-upload-id",
"part_urls": [
"https://apps.apptego.com/signed-part-1",
"https://apps.apptego.com/signed-part-2"
],
"chunk_size": 10485760,
"total_parts": 2,
"file_path": "tenant-123/uploads/android/production/1700000000/app-release.apk",
"start_time": 1700000000,
"expires_in": 3600,
"signing_key_id": null
}
Upload each chunk with PUT to the matching part_urls entry and keep the ETag header for each part.
Complete Multipart Upload
Finalize a multipart upload after all parts have been uploaded.
POST /frontend/complete_multipart_upload
Permission: Builds
Request Body:
{
"file_path": "tenant-123/uploads/android/production/1700000000/app-release.apk",
"upload_id": "multipart-upload-id",
"parts": [
{ "PartNumber": 1, "ETag": "\"abc123\"" },
{ "PartNumber": 2, "ETag": "\"def456\"" }
]
}
Response:
{
"message": "Upload completed successfully"
}
file_path must be the tenant-scoped path returned by upload_application_build.
Abort Multipart Upload
Cancel an in-progress multipart upload.
POST /frontend/abort_multipart_upload
Permission: Builds
Request Body:
{
"file_path": "tenant-123/uploads/android/production/1700000000/app-release.apk",
"upload_id": "multipart-upload-id"
}
Response:
{
"message": "Upload aborted successfully"
}
Download A Protected Build
Get a signed download URL for a completed protected build. Use the version, platform, start_time, and name values from build history.
POST /frontend/download_application_build
Permission: None (read-only)
Request Body:
{
"version": "production",
"platform": "android",
"start_time": 1700000000,
"file_name": "app-release.apk"
}
Response:
{
"url": "https://apps.apptego.com/signed-download-url"
}
Delete A Build
Delete the protected build artifact and remove its build-history row.
POST /frontend/delete_application_build
Permission: Builds
Request Body:
{
"version": "production",
"platform": "android",
"start_time": 1700000000,
"file_name": "app-release.apk"
}
Response:
{
"success": true
}
Delete An Application Record
Delete an application record from the tenant. Applications cannot be deleted within 7 days of creation.
POST /frontend/delete_application
Permission: Builds
Request Body:
{
"application_id": "app-uuid-1234"
}
Response:
{
"success": true
}
Use delete_application_build for individual build artifacts and build-history rows.
Code Signing
Signing-key management requires a Team or Enterprise plan. Mutating signing endpoints require the Builds permission.
List Signing Keys
POST /frontend/get_signing_keys
Permission: None (read-only) Plan: Team+
Request Body:
{}
Response:
{
"signing_keys": [
{
"key_id": "key-uuid-1234",
"key_name": "Android release key",
"platform": "android",
"file_name": "release.jks",
"is_default": true,
"uploaded_by": "user@example.com",
"creation_time": 1700000000
}
]
}
Upload A Signing Key
Create a signing-key record and receive a signed URL for uploading the key file.
POST /frontend/upload_signing_key
Permission: Builds Plan: Team+
Request Body:
{
"key_name": "Android release key",
"platform": "android",
"file_name": "release.jks",
"password": "keystore-or-certificate-password",
"alias": "release",
"file_size": 4096,
"is_default": true
}
| Field | Type | Required | Description |
|---|---|---|---|
key_name | String | Yes | Display name for the signing key. |
platform | String | Yes | android or ios. |
file_name | String | Yes | Base filename for the key file. |
password | String | Yes | Password used for the signing key file. It is encrypted before storage. |
alias | String | Android required | Android key alias. |
file_size | Integer | No | Signing-key file size in bytes. Files over 10 MB are rejected. |
is_default | Boolean | No | Set this key as the default for its platform. |
Response:
{
"key_id": "key-uuid-1234",
"url": "https://apps.apptego.com/signed-key-upload-url"
}
Upload the signing key file with PUT to url.
Set Default Signing Key
POST /frontend/set_default_signing_key
Permission: Builds Plan: Team+
Request Body:
{
"platform": "android",
"key_id": "key-uuid-1234"
}
Omit key_id or send it as null to clear the default key for a platform.
Response:
{
"success": true
}
Delete A Signing Key
POST /frontend/delete_signing_key
Permission: Builds Plan: Team+
Request Body:
{
"key_id": "key-uuid-1234"
}
Response:
{
"success": true
}
Upload A Legacy Code-Signing File
This endpoint stores per-application signing metadata and returns a signed URL for uploading the signing artifact. Prefer managed signing keys for new integrations.
POST /frontend/upload_code_signing_file
Permission: Builds Plan: Team+
Request Body:
{
"file": "required-compatibility-field",
"password": "signing-password",
"application_id": "app-uuid-1234",
"platform": "android",
"alias": "release"
}
| Field | Type | Required | Description |
|---|---|---|---|
file | String | Yes | Required compatibility field. Upload the actual signing file to the returned URL. |
password | String | Yes | Signing password. It is encrypted before storage. |
application_id | String | Yes | Application record to associate with the signing file. |
platform | String | Yes | android or ios. |
alias | String | Android required | Android key alias. |
Response:
{
"url": "https://apps.apptego.com/signed-signing-file-upload-url"
}
Sign A Build With A Legacy Code-Signing File
Queue a completed build for signing using the per-application signing file configured above.
POST /frontend/sign_application_build
Permission: Builds Plan: Team+
Request Body:
{
"platform": "android",
"name": "app-release.apk",
"start_time": 1700000000
}
Response:
{
"success": true,
"message": "Build queued for signing"
}
Example: Upload, Poll, Download
import base64
import time
import requests
BASE = "https://app.apptego.com/frontend"
token = base64.b64encode(f"{TOKEN_KEY}:{TOKEN_SECRET}".encode()).decode()
headers = {
"Authorization": f"Bearer {token}",
"tenant": TENANT_ID,
"Content-Type": "application/json",
}
upload = requests.post(f"{BASE}/upload_application_build", headers=headers, json={
"file_name": "app-release.apk",
"platform": "android",
"version": "production",
"file_size": 45_000_000,
}).json()
with open("app-release.apk", "rb") as app_file:
requests.put(upload["url"], data=app_file, headers={
"Content-Type": "application/octet-stream",
})
start_time = upload["start_time"]
while True:
history = requests.post(f"{BASE}/get_application_builds", headers=headers, json={
"version": "production",
"page": 1,
"page_size": 50,
}).json()
build = next((b for b in history["results"] if b["start_time"] == start_time), None)
if build and build["success"] is True:
break
if build and build["success"] is False:
raise RuntimeError(build.get("status_message") or "Build failed")
time.sleep(15)
download = requests.post(f"{BASE}/download_application_build", headers=headers, json={
"version": build["version"],
"platform": build["platform"],
"start_time": build["start_time"],
"file_name": build["name"],
}).json()
protected = requests.get(download["url"])
protected.raise_for_status()
open("app-protected.apk", "wb").write(protected.content)