Skip to main content
These endpoints allow you to upload mobile app builds or web app URLs programmatically. For most use cases, we recommend using our GitHub Action instead. All requests require an API key in the X-API-Key header. See API Reference for authentication details.

Endpoints Overview

EndpointPlatformDescription
Start UploadiOS, AndroidGet a presigned URL to upload a build file
Confirm UploadiOS, AndroidFinalize a mobile build upload

Start Upload

Initiate an app build upload and get a presigned URL for uploading your build file.
POST /api/ci/start-upload — Returns 200 OK

Request Body

bundle_id
string
required
Your app’s bundle identifier (e.g., com.company.app)
platform
string
required
Target platform: ios or android
filename
string
required
Name of the build file (e.g., app-release.apk or MyApp.zip)
environment
string
Environment name to associate this app with (e.g., staging, production). Apps with the same bundle ID but different environments are treated as separate apps. Must match an existing environment in your organization. If omitted, the app is assigned to your default environment.

Example Request

curl -X POST https://backend.autosana.ai/api/ci/start-upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_id": "com.company.app",
    "platform": "android",
    "filename": "app-release.apk"
  }'

Response Fields

upload_url
string
Presigned URL for uploading your build file via PUT request. Valid for 1 hour.
file_path
string
Storage path of the uploaded file. Pass this to the confirm-upload endpoint.

Example Response

{
  "upload_url": "https://storage.supabase.co/...",
  "file_path": "app-uuid/android/app-release-20250115T103000.apk"
}
After receiving the response, upload your build file to the upload_url using a PUT request:
curl -X PUT "UPLOAD_URL_FROM_RESPONSE" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @./path/to/your/app.apk

Confirm Upload

After uploading your build file, call this endpoint to finalize the upload and trigger any configured automations.
POST /api/ci/confirm-upload — Returns 200 OK

Request Body

bundle_id
string
required
Your app’s bundle identifier (must match the one used in start-upload)
platform
string
required
Target platform: ios or android
uploaded_file_path
string
required
The file_path returned from the start-upload response
name
string
Display name for your app (e.g., “My Android App”). If the app already exists and the name differs, it will be updated.
environment
string
Environment name (must match the value used in start-upload). Used to look up the correct app when multiple apps share the same bundle ID.
commit_sha
string
Git commit SHA for tracking which commit this build came from.
branch_name
string
Git branch name. Displayed in the Autosana UI for build identification.
variables
string | object
Key-value variables to attach to this build. Available in flow instructions via ${env:KEY}. Accepts a string ("KEY1=VALUE1,KEY2=VALUE2") or a JSON object ({"KEY1": "VALUE1"}). See Build Variables.

Example Request

curl -X POST https://backend.autosana.ai/api/ci/confirm-upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_id": "com.company.app",
    "platform": "android",
    "uploaded_file_path": "app-uuid/android/app-release-20250115T103000.apk",
    "name": "My Android App",
    "environment": "staging",
    "commit_sha": "abc123def456",
    "branch_name": "feature/new-login",
    "variables": "PR_NUMBER=42,BRANCH=feature/new-login"
  }'

Response Fields

status
string
Result status: success or error
message
string
Human-readable description of the result
triggered_flows
integer
Number of automations triggered by this upload (based on your Automations configuration).

Example Response

{
  "status": "success",
  "message": "App build uploaded successfully",
  "triggered_flows": 3
}

Upload Workflow

Here’s the complete workflow for uploading a build via the API:
1

Start Upload

Call /api/ci/start-upload with your app details to get a presigned upload URL.
2

Upload File

PUT your build file (.apk for Android, .zip for iOS) to the presigned URL.
3

Confirm Upload

Call /api/ci/confirm-upload to finalize the upload and trigger automations.

Build Requirements

iOS Builds

Upload a .zip file containing a simulator-compatible .app bundle. See App Build Guide for details.

Android Builds

Upload a universal .apk file (not AAB). The APK must be compatible with arm64 emulators.

Example: Upload from EAS Build Hooks

If you use Expo EAS, you can upload to Autosana directly from an EAS build hook instead of using the GitHub Action. This avoids keeping a GitHub Actions runner idle while waiting for the EAS build to finish, saving CI minutes.
Create an eas-build-on-success.sh file in your project root (next to package.json). EAS automatically runs this script when a build completes successfully.
Replace com.example.myapp with your bundle ID, MyApp.app with your .app bundle name, and "My App" with your app’s display name.
eas-build-on-success.sh
#!/usr/bin/env bash
set -euo pipefail

upload_to_autosana() {
  if [[ -z "${AUTOSANA_API_KEY:-}" ]]; then
    echo "AUTOSANA_API_KEY is not set, skipping upload."
    return 0
  fi

  local platform="$EAS_BUILD_PLATFORM"
  local commit_sha="${EAS_BUILD_GIT_COMMIT_HASH:-unknown}"
  local bundle_id="com.example.myapp"
  local app_name="My App"

  if [[ "$platform" == "ios" ]]; then
    local app_path
    app_path=$(find . -name "MyApp.app" -type d 2>/dev/null | head -1)
    if [[ -z "$app_path" ]]; then
      echo "Error: Could not find .app bundle"
      return 1
    fi

    local filename="app-simulator.zip"
    local artifact="/tmp/${filename}"
    pushd "$(dirname "$app_path")"
    zip -r "$artifact" "$(basename "$app_path")"
    popd
  elif [[ "$platform" == "android" ]]; then
    local artifact
    artifact=$(find . -name "*.apk" -type f 2>/dev/null | head -1)
    if [[ -z "$artifact" ]]; then
      echo "Error: Could not find .apk file"
      return 1
    fi
    local filename=$(basename "$artifact")
  else
    echo "Unsupported platform: $platform"
    return 1
  fi

  local start_response
  start_response=$(curl -sf -X POST https://backend.autosana.ai/api/ci/start-upload \
    -H "X-API-Key: $AUTOSANA_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"bundle_id\": \"$bundle_id\",
      \"platform\": \"$platform\",
      \"filename\": \"$filename\"
    }")

  local upload_url file_path
  upload_url=$(echo "$start_response" | jq -r '.upload_url')
  file_path=$(echo "$start_response" | jq -r '.file_path')

  if [[ -z "$upload_url" || "$upload_url" == "null" ]]; then
    echo "Error: Failed to get presigned URL"
    echo "Response: $start_response"
    return 1
  fi

  if ! curl -sf -X PUT "$upload_url" \
    -H "Content-Type: application/octet-stream" \
    --data-binary "@$artifact"; then
    echo "Error: Failed to upload file to presigned URL"
    return 1
  fi

  if ! curl -sf -X POST https://backend.autosana.ai/api/ci/confirm-upload \
    -H "X-API-Key: $AUTOSANA_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{
      \"bundle_id\": \"$bundle_id\",
      \"platform\": \"$platform\",
      \"uploaded_file_path\": \"$file_path\",
      \"name\": \"$app_name\",
      \"commit_sha\": \"$commit_sha\"
    }"; then
    echo "Error: Failed to confirm upload"
    return 1
  fi

  echo "Uploaded to Autosana successfully"
}

upload_to_autosana || echo "Warning: Autosana upload failed, continuing..."
Make the script executable and commit it to your repo:
chmod +x eas-build-on-success.sh
Then add your API key as an EAS secret:
eas secret:create --name AUTOSANA_API_KEY --value your-api-key-here --scope project
When you trigger a build (eas build --platform ios --profile preview-simulator --non-interactive), EAS runs the hook automatically after the build succeeds — no --wait flag or GitHub runner required.