README.md

# AppleDeveloper

Elixir client for the [App Store Connect API](https://developer.apple.com/documentation/appstoreconnectapi).

It covers the provisioning and App Store Connect surfaces that are most useful in automation scripts and internal tools:

- certificates
- devices
- provisioning profiles
- bundle IDs
- apps

## Installation

Add to your `mix.exs`:

```elixir
defp deps do
  [
    {:apple_developer, "~> 0.1.0"}
  ]
end
```

## Configuration

```elixir
config :apple_developer,
  issuer_id: System.get_env("APPLE_DEVELOPER_ISSUER_ID"),
  key_id: System.get_env("APPLE_DEVELOPER_KEY_ID"),
  private_key_path: System.get_env("APPLE_DEVELOPER_PRIVATE_KEY_PATH")
```

Supported options:

- `issuer_id` - App Store Connect issuer ID
- `key_id` - App Store Connect API key ID
- `private_key` - inline `.p8` contents
- `private_key_path` - path to the `.p8` file
- `base_url` - defaults to `https://api.appstoreconnect.apple.com`
- `token_ttl_seconds` - defaults to `1200`
- `req_options` - forwarded to `Req`

Every public function accepts per-call overrides.

## Quick Start

```elixir
# Access token
{:ok, token} = AppleDeveloper.token()

# Apps
{:ok, apps} = AppleDeveloper.list_apps(limit: 5)

# Certificates
{:ok, certs} = AppleDeveloper.list_certificates(filter_status: "ACTIVE")

# Devices
{:ok, devices} = AppleDeveloper.list_devices(filter_platform: "IOS")

# Profiles
{:ok, profiles} = AppleDeveloper.list_profiles(filter_profile_state: "ACTIVE")
```

## Common Operations

```elixir
# Register a device
AppleDeveloper.register_device(
  "QA iPhone",
  "00008110-001234567890ABCDE",
  "IOS"
)

# Create a development certificate
AppleDeveloper.create_certificate(:ios_development, csr_pem)

# Create a provisioning profile
AppleDeveloper.create_profile(
  "My Development Profile",
  "IOS_APP_DEVELOPMENT",
  bundle_id_id,
  [certificate_id],
  [device_id]
)
```

## Live Testing

A live smoke test is included:

```bash
cd apple_developer
elixir test_live.exs
```

That script verifies token generation and makes a real `list_apps` call.

## Errors

API calls return `{:ok, result}` or `{:error, reason}`.

HTTP failures are wrapped in `AppleDeveloper.Error`.

Typical statuses:

- `401` - invalid key, issuer, or expired token
- `403` - permissions issue
- `404` - resource not found
- `422` - validation failure
- `429` - rate limited

## Notes

- The client uses the JWT directly as the bearer token.
- Tokens are cached in `AppleDeveloper.TokenCache` with a 60-second refresh buffer.
- The package is suitable for CI tooling and one-off release automation scripts.

## License

MIT