Documentation

Go to Portal Website

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

NeedRecommendation
Release traceabilityStore the AppTego version, platform, original file_name, returned file_path, start_time, protected output name, and your commit SHA together.
Upload handlingUpload binaries to the signed URL returned by AppTego. Do not send app binaries directly to /frontend/upload_application_build.
Build statusUse success, status_message, error_message, and signing_error_message from build history as release gates.
Artifact handlingDownload protected artifacts into controlled storage and validate them before distribution.
PermissionsGrant the Builds permission only to users or API tokens that need build operations.

Common Fields

FieldDescription
versionConfiguration version: development, staging, or production.
platformandroid or ios. Android uploads must be .apk or .aab; iOS uploads must be .ipa.
start_timeUnix timestamp returned when the upload URL is created. It is also the build job identifier used by download, delete, and signing calls.
file_nameBase 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
}
FieldTypeRequiredDescription
versionStringYesdevelopment, staging, or production.
pageIntegerNoPage number. Defaults to 1.
page_sizeIntegerNoNumber 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 StateMeaning
success: nullBuild is still processing. Use status_message for the current stage.
success: trueBuild completed successfully and can be downloaded.
success: falseBuild failed or was reset for signing. Review status_message, error_message, and signing_error_message.
deleted: trueThe 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"
}
FieldTypeRequiredDescription
file_nameStringYesBase filename ending in .apk, .aab, or .ipa.
platformStringYesandroid or ios.
versionStringYesdevelopment, staging, or production.
file_sizeIntegerNoArtifact 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_idStringNoSigning 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
}
FieldTypeRequiredDescription
key_nameStringYesDisplay name for the signing key.
platformStringYesandroid or ios.
file_nameStringYesBase filename for the key file.
passwordStringYesPassword used for the signing key file. It is encrypted before storage.
aliasStringAndroid requiredAndroid key alias.
file_sizeIntegerNoSigning-key file size in bytes. Files over 10 MB are rejected.
is_defaultBooleanNoSet 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"
}
FieldTypeRequiredDescription
fileStringYesRequired compatibility field. Upload the actual signing file to the returned URL.
passwordStringYesSigning password. It is encrypted before storage.
application_idStringYesApplication record to associate with the signing file.
platformStringYesandroid or ios.
aliasStringAndroid requiredAndroid 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)