Documentation

Go to Portal Website

Automation API Reference

Overview

The Automation API lets CI/CD pipelines, release scripts, and internal build systems protect mobile app artifacts programmatically. It is intentionally focused: request a signed upload URL for an APK, AAB, or IPA, upload the artifact, monitor the protection job, and download the protected output from a signed URL.

Use the Automation API when AppTego protection is one step in a larger mobile release pipeline. If your integration needs to manage users, tenant settings, logs, support records, security configuration, signing-key administration, or build reporting, use the Management API instead.

Base URL: https://api.apptego.com or your custom endpoint.

Workflow At A Glance

StepEndpointResult
AuthenticateRequest headerAppTego validates the automation key.
Request uploadPOST /automate/uploadA build job ID and signed upload URL are returned.
Upload binarySigned URL from the upload responseYour pipeline uploads the APK, AAB, or IPA directly to the signed URL.
Complete multipart uploadPOST /automate/upload/completeRequired only when the upload response uses multipart upload.
Abort multipart uploadPOST /automate/upload/abortOptional cleanup if a multipart upload fails.
Check statusGET /automate/status/{jobId}Your pipeline can wait, fail, retry, or continue based on status.
DownloadGET /automate/download/{jobId}A signed download URL is returned when the job completes.

There is no GET /automate/jobs endpoint. Use the Management API when an integration needs broader build history or reporting.

Authentication

All Automation API requests require an automation key in the Authorization header:

Authorization: Bearer <key_id>:<key_secret>

Create automation keys in the AppTego Portal under Automation Keys. Store the full key_id:key_secret value in your CI or release-secret manager. Automation keys require a Team or Enterprise plan, and a disabled key is rejected immediately. Each tenant can have up to 10 automation keys. The secret is shown only when the key is created and cannot be retrieved later.

Automation API keys use the raw key_id:key_secret pair in the Bearer token. Do not Base64-encode automation keys; Base64 encoding is used by Management API tokens instead.

Production Integration Checklist

CheckRecommended practice
Secret storageStore the automation key in a secret manager, not in source control or job output.
EnvironmentUse dev or staging for validation jobs and prod only for approved release candidates.
Artifact metadataSave the source artifact name, protected artifact name, AppTego job ID, commit SHA, configuration version, and release metadata.
Upload handlingUpload the binary to the signed URL returned by AppTego. Do not send the binary directly to /automate/upload.
Timeout handlingTreat processing builds as pending until your pipeline timeout is reached.
Error handlingSurface AppTego error messages in CI logs, but redact secrets, signed URLs, and sensitive paths.
QATest the protected output before publishing it to users.

Request An Upload URL

POST /automate/upload
Content-Type: application/json

Request Body

FieldTypeRequiredDescription
file_nameStringYesBase filename for the APK, AAB, or IPA. Path components are stripped. The filename must use a lowercase .apk, .aab, or .ipa extension.
platformStringYesandroid or ios. Use APK or AAB for Android and IPA for iOS.
versionStringYesConfiguration version. Accepted aliases are case-insensitive and include dev, development, stg, staging, prod, and production. Responses use development, staging, or production.
file_sizeNumberNoArtifact size in bytes. Include this so the API can reject files over 2 GB and return multipart instructions for files 100 MB or larger. If omitted, the API cannot preflight size or switch to multipart upload.
signing_key_idStringNoSigning key to use for this build. Omit it to use the tenant default signing key when one is configured, or set none to skip signing-key metadata.
{
  "file_name": "app-release.apk",
  "platform": "android",
  "version": "prod",
  "file_size": 52428800
}

The upload request validates the tenant plan, active automation key, build limits, enabled controls for the selected platform/version, filename, file size, platform, version, and signing key selection. At least one protection or detection control must be enabled for the selected platform and configuration version before a build can start.

Single-Part Response

For files below the multipart threshold, or when file_size is omitted, the response includes upload_url. Upload the binary with an HTTP PUT to that URL.

{
  "url": "https://apps.apptego.com/signed-upload-url",
  "upload_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": null,
  "job_id": "1700000000"
}

job_id is returned as a string. Pass it exactly as returned to the status and download endpoints.

Upload The Binary

curl -sS -X PUT \
  -H "Content-Type: application/octet-stream" \
  --data-binary "@app-release.apk" \
  "$UPLOAD_URL"

Large File Upload

First-party CI/CD integrations handle large files automatically. Custom integrations should include file_size in the upload request. Files at or above 100 MB return multipart upload instructions with 10 MB chunks.

Multipart Initiation Response

{
  "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,
  "job_id": "1700000000"
}

Upload each chunk with PUT to the matching part_urls entry. Preserve the ETag response header for each part. If any part upload fails, abort the multipart upload before retrying the whole upload. After all parts are uploaded, complete the multipart upload and then poll the same job_id returned by the initiation response.

Complete Multipart Upload

POST /automate/upload/complete
Content-Type: application/json
{
  "file_path": "tenant-123/uploads/android/production/1700000000/app-release.apk",
  "upload_id": "multipart-upload-id",
  "parts": [
    { "ETag": "\"abc123\"", "PartNumber": 1 },
    { "ETag": "\"def456\"", "PartNumber": 2 }
  ]
}

Abort Multipart Upload

POST /automate/upload/abort
Content-Type: application/json
{
  "file_path": "tenant-123/uploads/android/production/1700000000/app-release.apk",
  "upload_id": "multipart-upload-id"
}

Check Job Status

GET /automate/status/{jobId}

Begin polling after the binary upload, or multipart completion, has succeeded. A newly uploaded job can briefly return 404 while the build record is being created; retry during normal polling. A persistent 404 means the job ID does not exist for the authenticated tenant.

Processing Response

{
  "job_id": "1700000000",
  "status": "processing",
  "platform": "android",
  "version": "production",
  "file_name": "app-release.apk",
  "created_at": 1700000000,
  "updated_at": 1700000000,
  "progress": "Queued"
}

Completed Response

{
  "job_id": "1700000000",
  "status": "completed",
  "platform": "android",
  "version": "production",
  "file_name": "app-release.apk",
  "created_at": 1700000000,
  "updated_at": 1700000300
}

Failed Response

{
  "job_id": "1700000000",
  "status": "failed",
  "platform": "android",
  "version": "production",
  "file_name": "app-release.apk",
  "created_at": 1700000000,
  "updated_at": 1700000300,
  "error_message": "Signing failed"
}

Status Values

StatusDescription
processingThe build record exists and AppTego is queued, launching a worker, downloading inputs, applying protection, packaging, signing, or uploading output. Use progress for the current human-readable stage when present.
completedBuild succeeded and is ready for download.
failedBuild failed. Review error_message.

Download Protected App

GET /automate/download/{jobId}

The response returns a signed download URL. The protected binary is not returned directly from /automate/download/{jobId}.

{
  "job_id": "1700000000",
  "file_name": "app-release.apk",
  "download_url": "https://apps.apptego.com/signed-download-url",
  "expires_in": 3600
}

Download links are time-limited. Request a new download URL when a link expires.

Error Responses

CodeDescription
400Invalid JSON, missing or invalid fields, invalid job ID, job not completed, file too large, no enabled controls for the selected platform/version, invalid filename, or invalid signing key selection.
401Authentication failed because the automation key is missing, malformed, unknown, disabled, invalid, or unavailable on the tenant plan.
403Multipart completion or abort was denied because the upload path does not belong to the authenticated tenant.
404Job or endpoint not found.
405HTTP method not allowed for the endpoint.
429Concurrent build or weekly build limit exceeded. Wait for in-progress jobs to finish or reduce pipeline parallelism.
500Internal server error. Retry when appropriate or contact support with the job ID.

Error Response Format

{
  "error": "Description of the error"
}

Rate Limits And Concurrency

Example: Single-Part Workflow

This example covers artifacts below 100 MB. For larger artifacts, follow the multipart response fields described above or use a first-party CI/CD integration.

set -euo pipefail

API_URL="https://api.apptego.com"
APP_FILE="app-release.apk"
PLATFORM="android"
VERSION="prod"
OUTPUT_FILE="app-release-protected.apk"

FILE_SIZE=$(wc -c < "$APP_FILE" | tr -d '[:space:]')

# 1. Request a signed upload URL.
UPLOAD_RESPONSE=$(jq -n \
  --arg file_name "$(basename "$APP_FILE")" \
  --arg platform "$PLATFORM" \
  --arg version "$VERSION" \
  --argjson file_size "$FILE_SIZE" \
  '{file_name: $file_name, platform: $platform, version: $version, file_size: $file_size}' | \
  curl -sS -X POST "$API_URL/automate/upload" \
    -H "Authorization: Bearer $APPTEGO_API_KEY" \
    -H "Content-Type: application/json" \
    --data-binary @-)

JOB_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.job_id')
UPLOAD_URL=$(echo "$UPLOAD_RESPONSE" | jq -r '.upload_url')
IS_MULTIPART=$(echo "$UPLOAD_RESPONSE" | jq -r '.multipart // false')

if [ "$IS_MULTIPART" = "true" ]; then
  echo "This file requires multipart upload. Use the part_urls, upload_id, and file_path fields."
  exit 1
fi

# 2. Upload the app binary to the signed URL.
curl -sS -X PUT \
  -H "Content-Type: application/octet-stream" \
  --data-binary "@$APP_FILE" \
  "$UPLOAD_URL"

# 3. Wait for completion.
while true; do
  STATUS_RESPONSE=$(curl -sS "$API_URL/automate/status/$JOB_ID" \
    -H "Authorization: Bearer $APPTEGO_API_KEY")

  STATUS=$(echo "$STATUS_RESPONSE" | jq -r '.status')

  if [ "$STATUS" = "completed" ]; then
    echo "Build complete"
    break
  elif [ "$STATUS" = "failed" ]; then
    echo "$STATUS_RESPONSE" | jq -r '.error_message // "Build failed"'
    exit 1
  fi

  sleep 15
done

# 4. Request a signed download URL and download the protected app.
DOWNLOAD_RESPONSE=$(curl -sS "$API_URL/automate/download/$JOB_ID" \
  -H "Authorization: Bearer $APPTEGO_API_KEY")

DOWNLOAD_URL=$(echo "$DOWNLOAD_RESPONSE" | jq -r '.download_url')

curl -sS -L "$DOWNLOAD_URL" -o "$OUTPUT_FILE"