> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gameball.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Notes

> Migrate from v2 to v3.1.1

This guide walks you through migrating from **Gameball iOS SDK v2** to **v3.1.1**.

## What's New in v3.1.1

<Info>
  **Guest Mode & Easier Widget Init** — v3.1.1 makes `ShowProfileRequest` non-throwing, allows `customerId` to be optional (guest mode), and keeps all v3+ code compatible.
</Info>

### Highlights in v3.1.1

* **Guest Mode Fix**: Profile widget works without a customer ID.
* **Non-Throwing ShowProfileRequest**: Remove the `try` keyword when creating the request.
* **Optional customerId**: Omit for guest experiences.
* **Session Tokens**: Still supported for secure routing to v4.1.

### Migrate v3.1.0 → v3.1.1 (Non-Breaking)

* Update SPM dependency to `from: "3.1.1"`.
* Drop `try` when creating `ShowProfileRequest` (initializer is non-throwing).
* Use guest mode when `customerId` is not available:
  ```swift theme={null}
  let guestRequest = ShowProfileRequest(showCloseButton: true)
  GameballApp.getInstance().showProfile(guestRequest, presentationStyle: .pageSheet)
  ```
* Authenticated mode stays the same:
  ```swift theme={null}
  let profileRequest = ShowProfileRequest(customerId: "customer_123")
  GameballApp.getInstance().showProfile(profileRequest, presentationStyle: .fullScreen)
  ```

***

## What's New in v3.0.0

<CardGroup cols={2}>
  <Card title="Modern Swift API" icon="code">
    Native Swift API with improved type safety and better Swift idioms
  </Card>

  <Card title="Async/Await Support" icon="bolt">
    Full async/await support alongside traditional callback-based APIs
  </Card>

  <Card title="Enhanced Type Safety" icon="shield">
    Stronger typing and better compile-time checks with Swift generics
  </Card>

  <Card title="Improved Performance" icon="gauge-high">
    Optimized SDK initialization and reduced memory footprint
  </Card>
</CardGroup>

***

## Breaking Changes

### 1. SDK Initialization

**v2:**

```swift theme={null}
Gameball.configure(
    apiKey: "api-key",
    lang: "en",
    platform: "ios",
    shop: "shop-id"
)
```

**v3.1.x:**

```swift theme={null}
let config = GameballConfig(
    apiKey: "api-key",
    lang: "en",
    platform: "ios",
    shop: "shop-id",
    sessionToken: "session-token"  // Optional - New in v3.1.x
)

GameballApp.getInstance().`init`(config: config) { error in
    if let error = error {
        print("SDK init failed: \(error.localizedDescription)")
    }
}
```

***

### 2. Customer Registration

**v2:**

```swift theme={null}
Gameball.registerPlayer(
    customerId: "customer-123",
    attributes: attributes,
    referralCode: "REF123",
    isGuest: false
) { success in
    // Handle response
}
```

**v3.1.x:**

```swift theme={null}
do {
    let request = try InitializeCustomerRequest(
        customerId: "customer-123",
        customerAttributes: attributes,
        referralCode: "REF123",
        isGuest: false
    )

    GameballApp.getInstance().initializeCustomer(request) { response, errorMessage in
        if let errorMessage = errorMessage {
            print("Error: \(errorMessage)")
        } else {
            print("Customer initialized: \(response?.gameballId ?? \"\")")
        }
    }

    // Optional: Override session token for this request
    GameballApp.getInstance().initializeCustomer(
        request,
        sessionToken: "customer-token"
    ) { _, _ in }
} catch {
    print("Validation error: \(error.localizedDescription)")
}
```

***

### 3. Event Tracking

**v2:**

```swift theme={null}
let event = GameballEvent()
event.customerId = "customer-123"
event.eventName = "purchase"
event.metadata = ["amount": 99.99]

Gameball.sendEvent(event) { success in
    // Handle response
}
```

**v3.1.x:**

```swift theme={null}
do {
    let event = try Event(
        events: [
            "purchase": [
                "amount": 99.99
            ]
        ],
        customerId: "customer-123"
    )

    GameballApp.getInstance().sendEvent(event) { success, errorMessage in
        if success {
            print("Event sent")
        } else if let errorMessage = errorMessage {
            print("Error: \(errorMessage)")
        }
    }

    // Optional: Override session token for this request
    GameballApp.getInstance().sendEvent(
        event,
        sessionToken: "customer-token"
    ) { _, _ in }
} catch {
    print("Validation error: \(error.localizedDescription)")
}
```

***

### 4. Method Name Changes

| **v2**                      | **v3.1.x**                                                    |
| :-------------------------- | :------------------------------------------------------------ |
| `Gameball.configure()`      | `GameballApp.getInstance().init(config:)`                     |
| `Gameball.registerPlayer()` | `GameballApp.getInstance().initializeCustomer(_:completion:)` |
| `Gameball.sendEvent()`      | `GameballApp.getInstance().sendEvent(_:completion:)`          |
| `PlayerAttributes`          | `CustomerAttributes`                                          |
| `PlayerRegisterResponse`    | `InitializeCustomerResponse`                                  |

***

### 5. Show Profile Widget

**v2:**

```swift theme={null}
Gameball.showProfile(
    customerId: "customer-123",
    from: self
)
```

**v3.1.x:**

```bash theme={null}
let profileRequest = ShowProfileRequest(
    customerId: "customer-123",
    showCloseButton: true,
    closeButtonColor: "#FF6B6B"
)

GameballApp.getInstance().showProfile(
    profileRequest,
    presentationStyle: .fullScreen
) { _, _ in }

// Optional: Override session token for this request
GameballApp.getInstance().showProfile(
    profileRequest,
    presentationStyle: .fullScreen,
    sessionToken: "customer-token"
) { _, _ in }
```

***

### 6. Error Handling

**v2:**

```swift theme={null}
Gameball.sendEvent(event) { success in
    if success {
        // Success
    } else {
        // Error (no details)
    }
}
```

**v3.1.x:**

```swift theme={null}
GameballApp.getInstance().sendEvent(event) { success, errorMessage in
    if success {
        // Success
    } else if let errorMessage = errorMessage {
        print(errorMessage)
    }
}
```

***

### 7. Session Token Authentication (New in v3.1.x)

```bash theme={null}
// Configure with session token
let config = GameballConfig(
    apiKey: "api-key",
    lang: "en",
    sessionToken: "session-token"  // Global token
)
GameballApp.getInstance().`init`(config: config)

// Per-request token override
GameballApp.getInstance().initializeCustomer(
    request,
    sessionToken: "override-token"
) { _, _ in }
```

<Info>
  Session tokens enable automatic v4.1 endpoint routing and enhanced security. The token is stored in memory with thread-safe access.
</Info>

***

### 8. Async/Await Support (New in v3.0.0)

```swift theme={null}
// Traditional callback
GameballApp.getInstance().initializeCustomer(request) { _, _ in }

// Async/await (v3.0.0+)
Task {
    do {
        let response = try await GameballApp.getInstance().initializeCustomer(request)
        // Handle success
    } catch {
        // Handle error
    }
}

// With session token override (v3.1.x+)
Task {
    do {
        let response = try await GameballApp.getInstance().initializeCustomer(
            request,
            sessionToken: "customer-token"
        )
        // Handle success
    } catch {
        // Handle error
    }
}
```

***

## Migration Steps

### From v3.0.0 to v3.1.x (No Breaking Changes)

<Info>
  v3.1.x is fully backward compatible. Simply update the dependency version. Session Token support is optional.
</Info>

<Steps>
  <Step title="Update Dependency">
    Update your Swift Package Manager dependency to **3.1.1**.
  </Step>

  <Step title="(Optional) Add Session Token">
    If you need enhanced security, add a session token to your configuration:

    ```swift theme={null}
    let config = GameballConfig(
        apiKey: "api-key",
        lang: "en",
        sessionToken: "your-session-token"
    )
    ```
  </Step>

  <Step title="Test">
    Test your integration. All existing v3.0.0 code should work without changes.
  </Step>
</Steps>

***

### From v2.x to v3.1.x

<Steps>
  <Step title="Update Dependency">
    Update your Swift Package Manager dependency to **3.1.1**.
  </Step>

  <Step title="Update Initialization">
    Replace `Gameball.configure()` with `GameballConfig` + `GameballApp.getInstance().init(config:)`.
  </Step>

  <Step title="Update Customer Registration">
    Replace `registerPlayer()` with `initializeCustomer()` using the new request type `InitializeCustomerRequest`.
  </Step>

  <Step title="Update Event Tracking">
    Update event creation to use the `Event` model and pass it to `sendEvent`.
  </Step>

  <Step title="Update Error Handling">
    Replace boolean success handlers with Result-based completion handlers to access detailed error information.
  </Step>

  <Step title="Update Show Profile">
    Use the non-throwing `ShowProfileRequest` (guest mode optional) for displaying the profile widget.
  </Step>

  <Step title="Test Thoroughly">
    Test all Gameball functionality (registration, events, profile, notifications, etc.) to ensure the migration is successful.
  </Step>
</Steps>

***

## Compatibility

* **Minimum iOS**: iOS 12.0+
* **Xcode**: 12.0+
* **Swift**: 5.0+

***

## Additional Resources

* **GitHub Repository:** [https://github.com/gameballers/gameball-ios](https://github.com/gameballers/gameball-ios)
* **Changelog:** [https://github.com/gameballers/gameball-ios/blob/main/CHANGELOG.md](https://github.com/gameballers/gameball-ios/blob/main/CHANGELOG.md)
* **Release Notes:** [https://github.com/gameballers/gameball-ios/blob/main/RELEASE\_NOTES.md](https://github.com/gameballers/gameball-ios/blob/main/RELEASE_NOTES.md)
* **Developer Docs:** [https://developer.gameball.co](https://developer.gameball.co)

<Tip>
  If you encounter issues during migration, check the GitHub repository for known issues and solutions, or contact Gameball support.
</Tip>
