REST API + CLI · free on every account

Push builds from your CI.
One curl.

Every account gets a free REST API. One POST to /upload.php uploads an .ipa, .apk, or .aab and returns the shareable install link. Works with GitHub Actions, GitLab CI, Bitrise, Fastlane, or a raw curl in a shell script.

Sign up free or log in to get your API token.

Endpoint

POST https://apponthego.com/upload.php

Single endpoint. Uploads use multipart/form-data. Same endpoint the browser uses — CI just sends a Bearer token instead of a session cookie.

Authentication

Pass your token in one of three ways (Bearer header preferred):

Authorization: Bearer 0b6079183e35159c4a64169a942e6493fa47ab
curl -F file=@build.ipa "https://apponthego.com/upload.php?token=YOUR_TOKEN"

Get your token from this page (logged in), or regenerate any time. Regenerating invalidates the previous token instantly.

Parameters

FieldTypeRequiredDescription
filefileyes.ipa, .apk, or .aab. AABs are auto-converted server-side via bundletool.
is_public0|1no1 to feature on the public Wall of Apps. Default 1.
passwordstringnoSet an install-page password. Free-tier feature.
stable_slugstringnoRebind the given slug to this build. Slug format: [a-z0-9][a-z0-9\-]{1,30}[a-z0-9].
expires_in_secondsintnoAuto-expiry. 0 = "Never" (paid tiers only). Capped by your plan's link_lifetime_days.

Response

200 OK — body is the plaintext install URL:

https://i.apponthego.com/myapp-beta

Errors — 4xx / 5xx with a plaintext reason. Common codes: 400 (bad params), 409 (slug taken by another user), 413 (too large for your plan), 500 (server error).

curl example

The full example — bearer auth, stable slug, 7-day expiry, Slack-friendly output:

curl -X POST https://apponthego.com/upload.php \
  -H "Authorization: Bearer $AOTG_TOKEN" \
  -F "file=@./build/MyApp.ipa" \
  -F "stable_slug=myapp-beta" \
  -F "expires_in_seconds=604800" \
  -F "is_public=1"

Fastlane lane

Drop this into your Fastfile after gym / build_app:

lane :ship_beta do
  build_app(scheme: "MyApp")
  ipa_path = lane_context[SharedValues::IPA_OUTPUT_PATH]

  response = sh(
    "curl -sf -H 'Authorization: Bearer #{ENV['AOTG_TOKEN']}' " \
    "-F 'file=@#{ipa_path}' " \
    "-F 'stable_slug=myapp-beta' " \
    "-F 'expires_in_seconds=604800' " \
    "https://apponthego.com/upload.php"
  ).strip

  slack(message: "New iOS build ready: #{response}") if response.start_with?("http")
end

GitHub Actions

Add a step to your build workflow (secrets: AOTG_TOKEN):

- name: Push to App On The Go
  run: |
    URL=$(curl -sf -X POST \
      -H "Authorization: Bearer ${{ secrets.AOTG_TOKEN }}" \
      -F "file=@build/MyApp.ipa" \
      -F "stable_slug=myapp-beta" \
      -F "expires_in_seconds=1209600" \
      https://apponthego.com/upload.php)
    echo "INSTALL_URL=$URL" >> $GITHUB_ENV
    echo "::notice::Installable at $URL"

Bitrise step

- script:
    title: Push to App On The Go
    inputs:
    - content: |
        #!/usr/bin/env bash
        set -e
        URL=$(curl -sf -X POST \
          -H "Authorization: Bearer $AOTG_TOKEN" \
          -F "file=@$BITRISE_IPA_PATH" \
          -F "stable_slug=$BITRISE_APP_TITLE-beta" \
          https://apponthego.com/upload.php)
        envman add --key AOTG_INSTALL_URL --value "$URL"

Notifications

Save a Slack / Discord / Teams / generic webhook URL in Settings and every upload (including from the API) automatically posts to your channel. No extra API call needed.

Rate limits

Currently no hard rate limit — but keep uploads reasonable (5+ min between builds of the same app is a normal CI pattern). Persistent abuse of the free tier may get throttled.

Automate your beta shipping
in the next 10 minutes.

Get a token, add one curl to your CI, testers get every build automatically.