> For the complete documentation index, see [llms.txt](https://docs.perkox.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.perkox.com/getting-started/sdk/perkox-offerwall-sdk-for-ios.md).

# Perkox Offerwall SDK for iOS

The **Perkox Offerwall SDK for iOS** is a lightweight SDK that allows iOS app developers to integrate the Perkox Offerwall directly into their application.

With Perkox, users can earn in-app rewards by completing offers, surveys, and other rewarded engagement activities.

The SDK is designed to provide a simple Swift integration flow while giving publishers access to rewarded monetization, analytics, and secure server-side reward validation.

***

### Requirements

Before integrating the Perkox iOS SDK, make sure your project meets the following requirements:

| Requirement           | Version                                         |
| --------------------- | ----------------------------------------------- |
| iOS Deployment Target | 13.0+                                           |
| Swift                 | 5.7+                                            |
| Xcode                 | 14.0+                                           |
| Architectures         | arm64 for device, arm64 + x86\_64 for simulator |

***

## Installation

### Step 1: Download the SDK

Download the latest iOS SDK release `.zip` file from the official Perkox GitHub Releases page or from the package provided by the Perkox team.

After extracting the `.zip` file, you should see a folder similar to:

```
perkox-ios-sdk-release-{version}/
├── Package.swift
└── PerkoxOfferwall.xcframework/
    ├── Info.plist
    ├── ios-arm64/
    │   └── PerkoxOfferwall.framework/
    └── ios-arm64_x86_64-simulator/
        └── PerkoxOfferwall.framework/
```

The folder contains a local Swift Package and the bundled `PerkoxOfferwall.xcframework`.

***

### Step 2: Add the Package to Your Xcode Project

In Xcode, add the Perkox SDK as a local Swift Package.

Follow these steps:

1. Open your project in Xcode
2. Go to **File → Add Package Dependencies…**
3. In the bottom-left of the dialog, click **Add Local…**
4. Navigate to the extracted folder:

```
perkox-ios-sdk-release-{version}
```

5. Select the folder and click **Add Package**
6. In the next prompt, make sure your app target is checked
7. Click **Add Package** again

***

### Important Installation Tip

Place the extracted SDK folder somewhere stable before adding it to Xcode.

Recommended location:

```
your-ios-app/
├── YourApp.xcodeproj
└── perkox-ios-sdk-release-{version}/
```

Xcode references local Swift Packages by path. If the SDK folder is moved after being added, Xcode may not be able to find the package.

***

## Quick Start

After installing the SDK, you can launch the Perkox Offerwall using your **App ID**, **SDK Key**, and a unique **Player ID**.

You can find your App ID and SDK Key inside the Perkox Publisher Dashboard.

***

### Basic Swift Implementation

```
import UIKit
import PerkoxOfferwall

class ViewController: UIViewController {

    private func showOfferwall() {
        let offerwall = PerkoxOfferwall.create(
            appId: "YOUR_APP_ID",       // Your App ID
            sdkKey: "YOUR_SDK_KEY",     // Your SDK Key
            playerId: "Player_123"      // Unique player ID
        )

        offerwall.launch(viewController: self)
    }
}
```

***

## API Reference

### PerkoxOfferwall

`PerkoxOfferwall` is the main entry point for creating and launching the Perkox Offerwall.

| Method     | Parameters                                            | Returns     | Description                      |
| ---------- | ----------------------------------------------------- | ----------- | -------------------------------- |
| `create()` | `appId: String`, `sdkKey: String`, `playerId: String` | `Offerwall` | Creates a new Offerwall instance |

***

### Offerwall

The `Offerwall` object is used to launch the offerwall and listen to basic offerwall events.

| Method / Property         | Type                          | Description                                                   |
| ------------------------- | ----------------------------- | ------------------------------------------------------------- |
| `launch(viewController:)` | `UIViewController`            | Presents the offerwall modally from the given view controller |
| `onReward`                | `(([String: Any?]) -> Void)?` | Callback triggered when a reward event is received            |
| `onClose`                 | `(() -> Void)?`               | Callback triggered when the offerwall is closed               |

***

## Listening to Events

You can listen to reward and close events by setting callbacks before launching the offerwall.

### Important Reward Handling Notice

Do **not** rely only on SDK reward callbacks to grant rewards to users.

SDK callbacks only work while the offerwall is active inside the app. For accurate and reliable reward processing, rewards should be handled server-side using the **Postback URL** configured in your Perkox dashboard.

Recommended reward flow:

```
User completes offer
→ Perkox validates conversion
→ Perkox sends postback to your server
→ Your backend verifies the event
→ Your backend credits the user
```

Use SDK callbacks mainly for UI feedback, logs, or temporary in-app updates.

The `onReward` callback may be triggered multiple times for the same transaction with different statuses, such as `pending`, `approved`, `rejected`, or `reversed`.

***

### Full Swift Example with Callbacks

```
import UIKit
import PerkoxOfferwall

class ViewController: UIViewController {

    private func showOfferwall() {
        let offerwall = PerkoxOfferwall.create(
            appId: "YOUR_APP_ID",
            sdkKey: "YOUR_SDK_KEY",
            playerId: "Player_123"
        )

        // Handle reward events
        offerwall.onReward = { reward in
            DispatchQueue.main.async {
                let amount = reward["amount"] as? Double ?? 0
                let status = reward["status"] as? String ?? "?"
                let txid = reward["txid"] as? String ?? "?"
                let playerId = reward["player_id"] as? String ?? "?"

                print("Reward received! Amount: \(amount), Status: \(status)")
            }
        }

        // Handle offerwall close event
        offerwall.onClose = {
            DispatchQueue.main.async {
                print("Offerwall closed")
            }
        }

        // Launch the offerwall
        offerwall.launch(viewController: self)
    }
}
```

***

## Reward Data Fields

When a reward event is received, the SDK may return the following fields:

| Field       | Type     | Description                                |
| ----------- | -------- | ------------------------------------------ |
| `amount`    | `Double` | Reward amount                              |
| `txid`      | `String` | Unique transaction ID                      |
| `status`    | `String` | Reward status                              |
| `player_id` | `String` | Player ID passed during SDK initialization |

***

### Reward Statuses

| Status     | Description                             | Recommended Action                              |
| ---------- | --------------------------------------- | ----------------------------------------------- |
| `pending`  | Reward is being reviewed or processed   | Do not grant final reward yet                   |
| `approved` | Reward has been validated               | Credit the user server-side                     |
| `rejected` | Reward was not approved                 | Do not credit the user                          |
| `reversed` | Previously approved reward was reversed | Adjust or remove the reward if already credited |

***

## Player ID

The `playerId` should be a unique and stable identifier for the user inside your app.

Examples:

```
player123
user_98765
account_45678
```

The Player ID is important because it allows your backend to identify which user should receive the reward.

Best practices:

* Use a stable internal user ID
* Do not use random temporary values
* Do not use sensitive personal information
* Make sure the same user keeps the same Player ID across sessions

***

## Reward Validation Best Practice

For production integrations, Perkox recommends using server-side reward validation through postbacks.

The SDK callback is useful for listening to events inside the app, but the final reward credit should happen on your backend.

Recommended production setup:

```
App launches Perkox Offerwall with playerId
→ User completes an offer
→ Perkox validates conversion
→ Perkox sends postback to publisher backend
→ Publisher backend checks txid and status
→ Publisher backend credits the user
```

This helps prevent duplicate rewards, missed rewards, and client-side manipulation.

***

## Troubleshooting

### 1. `No such module 'PerkoxOfferwall'` Build Error

Check the following:

* Make sure you selected your app target when the **Add Package** prompt appeared
* Go to your target settings
* Open **General → Frameworks, Libraries, and Embedded Content**
* Verify that `PerkoxOfferwall` is listed
* Clean the build folder using **Product → Clean Build Folder**
* Rebuild the project

Shortcut:

```
Cmd + Shift + K
```

***

### 2. Xcode Cannot Find the Local Package After Moving Files

Xcode references local Swift Packages by path.

If you move the SDK folder after adding it, the package reference may break.

To fix this:

1. Remove the package from the project
2. Go to **File → Packages → Reset Package Caches**
3. Re-add the package from its new location

Best practice:

Keep the extracted SDK folder next to your `.xcodeproj` file or inside a stable `/SDKs` folder.

***

### 3. Offerwall Not Loading Content

Check the following:

* Verify that your `appId` is correct
* Verify that your `sdkKey` is correct
* Check the device internet connection
* Make sure the `playerId` is not empty
* Make sure the app/property is active inside the Perkox dashboard
* Test on a real device if simulator behavior is inconsistent

***

### 4. Reward Callback Not Triggering

Possible reasons:

* The offerwall was closed before the event was returned
* The conversion is still pending
* The reward was processed server-side through postback
* The user did not complete the offer requirements
* The transaction status has not changed yet

For production reward handling, always rely on server-side postbacks.

***

## Changelog

### v1.0.0

Initial iOS SDK release.

Included:

* Lightweight iOS offerwall integration
* Local Swift Package support
* `PerkoxOfferwall.xcframework`
* Basic Swift implementation
* Reward callback support
* Close callback support
* Server-side postback recommendation

***

## Support

For questions, issues, or feature requests, contact:

```
support@perkox.com
```

When contacting support, include:

* App ID
* SDK version
* iOS version
* Xcode version
* Device model
* Error logs if available
* Description of the issue
* SDK Integration\
  └── iOS SDK
