# How to Automatically Obtain a License for an App with IPATool: Complete Guide

> Learn how to automatically obtain an app license with IPATool. Explore the purchase command and download flag for seamless app acquisition. Get the complete guide now.

- Repository: [Majd/ipatool](https://github.com/majd/ipatool)
- Tags: how-to-guide
- Published: 2026-09-01

---

**IPATool provides two methods to automatically obtain a license for an app: the explicit `purchase` command or the `download` command with the `--purchase` flag, both utilizing the `appstore.Purchase` implementation to interact with Apple's private purchase endpoints.**

IPATool is an open-source command-line interface for interacting with Apple's App Store, allowing users to search, purchase, and download iOS applications. When you need to automatically obtain a license for an app with IPATool, the tool handles Apple's authentication flows, token refresh, and purchase API communication through a structured workflow implemented in Go.

## How the Purchase Workflow Works

The license acquisition process follows a six-step execution flow defined in the source code, handling everything from credential retrieval to error management.

### Account Authentication and Token Management

The process begins in [`cmd/purchase.go`](https://github.com/majd/ipatool/blob/main/cmd/purchase.go) by retrieving stored credentials through `AccountInfo`, which fetches the Apple ID and password token from the local keychain. If the subsequent request fails with `appstore.ErrPasswordTokenExpired`, the tool automatically re-authenticates using the `Login` method to obtain a fresh token before retrying the operation.

### App Resolution

Before purchasing, IPATool must resolve the target application. The `Lookup` function (or an explicit App ID) queries Apple's servers to retrieve an `appstore.App` object containing the App Store item ID, as implemented in [`cmd/purchase.go`](https://github.com/majd/ipatool/blob/main/cmd/purchase.go) lines 43-47.

### The Purchase Request

The core purchase logic resides in [`pkg/appstore/appstore_purchase.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_purchase.go). The `appstore.Purchase` function builds a cryptographically signed PLIST request and POSTs it to Apple's private purchase endpoint. This implementation handles the low-level communication protocol required to acquire licenses from Apple's infrastructure.

### Error Handling and Retry Logic

The purchase workflow handles several specific error cases:
- **`ErrLicenseAlreadyExists`** – The app is already owned; treated as success.
- **`ErrPasswordTokenExpired`** – Triggers credential refresh and retry.
- **`ErrLicenseRequired`** – In download flows, triggers automatic purchase when the `--purchase` flag is set.

## Explicit License Acquisition via the Purchase Command

Use the standalone `purchase` command when you need to acquire a license without immediately downloading the application binary.

```bash

# Obtain a license for the app with bundle identifier com.example.myapp

ipatool purchase --bundle-identifier com.example.myapp

```

This command executes the following sequence:
1. Calls `AppStore.Lookup` to resolve the bundle ID to an App Store item.
2. Invokes `AppStore.Purchase` with the resolved `appstore.App` object.
3. If the license already exists, returns success without error (`ErrLicenseAlreadyExists`).

## Automatic License Acquisition During Download

The `download` command supports automatic license acquisition through the `--purchase` flag, streamlining the workflow when you need both the license and the application package.

```bash

# Download the app and acquire a license if needed

ipatool download \
    --bundle-identifier com.example.myapp \
    --output myapp.ipa \
    --purchase

```

When the `--purchase` flag is provided, the download flow implements retry logic in [`cmd/download.go`](https://github.com/majd/ipatool/blob/main/cmd/download.go) (lines 76-84). If the initial download attempt returns `appstore.ErrLicenseRequired`, the tool automatically invokes `Purchase` before retrying the download:

```go
if errors.Is(lastErr, appstore.ErrLicenseRequired) && acquireLicense {
    err := dependencies.AppStore.Purchase(appstore.PurchaseInput{Account: acc, App: app})
    if err != nil && !errors.Is(err, appstore.ErrLicenseAlreadyExists) {
        return err
    }
    purchased = true
}

```

## Programmatic Usage in Go

You can integrate IPATool's license acquisition directly into Go applications using the `pkg/appstore` package.

```go
import (
    "errors"
    "github.com/majd/ipatool/v2/pkg/appstore"
)

func obtainLicense(client *appstore.Client, acc appstore.Account, bundleID string) error {
    // Resolve the app first
    lookup, err := client.Lookup(appstore.LookupInput{
        Account:  acc,
        BundleID: bundleID,
    })
    if err != nil {
        return err
    }

    // Attempt purchase; treat already-owned as success
    err = client.Purchase(appstore.PurchaseInput{
        Account: acc,
        App:     lookup.App,
    })
    if err != nil && !errors.Is(err, appstore.ErrLicenseAlreadyExists) {
        return err
    }
    return nil
}

```

This implementation leverages the same underlying methods used by the CLI, providing programmatic access to Apple's purchase endpoints.

## Key Implementation Files

| File | Purpose |
|------|---------|
| [`cmd/purchase.go`](https://github.com/majd/ipatool/blob/main/cmd/purchase.go) | CLI command implementation for explicit license purchase. |
| [`cmd/download.go`](https://github.com/majd/ipatool/blob/main/cmd/download.go) | Download command with `--purchase` flag and retry logic. |
| [`pkg/appstore/appstore_purchase.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_purchase.go) | Core purchase implementation building PLIST requests. |
| [`pkg/appstore/appstore.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore.go) | High-level interface exposing `Purchase`, `Lookup`, and `Download` methods. |
| [`pkg/appstore/appstore_login.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_login.go) | Token refresh logic for expired credentials. |

## Summary

- **IPATool offers two pathways** to automatically obtain a license for an app with IPATool: the dedicated `purchase` command or the `--purchase` flag with `download`.
- **Both methods use** the `appstore.Purchase` implementation in [`pkg/appstore/appstore_purchase.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_purchase.go) to communicate with Apple's private APIs.
- **The tool handles authentication** automatically, refreshing expired tokens via `Login` when `ErrPasswordTokenExpired` occurs.
- **Error handling treats** `ErrLicenseAlreadyExists` as success, allowing idempotent operations.
- **Programmatic access** is available through the `github.com/majd/ipatool/v2/pkg/appstore` package for Go developers.

## Frequently Asked Questions

### Can I purchase an app without downloading it using IPATool?

Yes. Use the explicit `purchase` command with the `--bundle-identifier` flag. This executes the purchase workflow in [`cmd/purchase.go`](https://github.com/majd/ipatool/blob/main/cmd/purchase.go) without invoking the download logic, allowing you to acquire the license independently of retrieving the application binary.

### What happens if I already own the app when using the purchase command?

IPATool returns success without error. The implementation specifically checks for `ErrLicenseAlreadyExists` in [`pkg/appstore/appstore_purchase.go`](https://github.com/majd/ipatool/blob/main/pkg/appstore/appstore_purchase.go) (lines 60-87) and treats this condition as a successful operation, preventing duplicate purchases while confirming license ownership.

### How does IPATool handle expired authentication tokens during purchase?

The tool implements automatic token refresh. When a purchase request fails with `ErrPasswordTokenExpired`, the code in [`cmd/purchase.go`](https://github.com/majd/ipatool/blob/main/cmd/purchase.go) (lines 31-41) triggers the `Login` flow to obtain fresh credentials before retrying the purchase operation.

### Is the `--purchase` flag required for downloading free apps?

No. Free apps do not require a license acquisition step. However, including the `--purchase` flag ensures the download succeeds even for paid apps by automatically triggering the purchase workflow when `ErrLicenseRequired` is encountered during the initial download attempt in [`cmd/download.go`](https://github.com/majd/ipatool/blob/main/cmd/download.go).