# SDK APIs

To work with the DT Offer Wall, you must ensure that you have:

* Successfully [set up your app](https://docs.digitalturbine.com/dt-offer-wall/publishers/app-setup-in-the-web-dashboard)
* Integrated [the DT Offer Wall via the SDK](https://docs.digitalturbine.com/dt-offer-wall/publishers/dt-offer-wall-sdk/sdk-integration) and implemented the APIs

## DT Offer Wall Sample App

If you prefer to jump straight to the code, DT's sample app can assist you in using DT Offer Wall within your app. In addition, use the DT sample app as a reference during implementation to troubleshoot possible integration issues.

To download the app, click on the relevant platform tab.

{% tabs %}
{% tab title="Android" %}
<https://github.com/fyber-engineering/offerwall-sample-app-android>
{% endtab %}

{% tab title="iOS" %}
<https://github.com/fyber-engineering/offerwall-sample-app-ios>
{% endtab %}

{% tab title="Unity" %}
<https://github.com/fyber-engineering/offerwall-sample-app-unity>
{% endtab %}
{% endtabs %}

## Before Starting the SDK

### User ID

DT Offer Wall SDK will generate a unique User ID upon starting the SDK.

If, instead, you want to provide the SDK with your User ID, you will need to use the following API before starting the SDK:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.userId = "userId"
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.setUserId("userId");
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
OfferWall.userId = "userId"
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
OfferWall.setUserId("userId");
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.UserId = "userId";
```

{% endcode %}
{% endtab %}
{% endtabs %}

The User ID is stored across SDK sessions.

This API can be called at any point after starting the SDK. The new user ID will be associated with any future action by the user.

### Privacy and Compliance

#### GDPR

The [General Data Protection Regulation](https://gdpr-info.eu/) requires you to scope your user's consent.

A user is within the GDPR scope for your app when one or all of the following apply:

* The user is currently located in the EU.
* The user has registered with the app as an EU resident.
* The app is specifically targeted to EU users.

Once you have collected the user's consent, you can pass it onto the SDK using the following API:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.setConsent(
    OfferWallPrivacyConsent.GDPR(true)
)
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.setConsent(
    new OfferWallPrivacyConsent.GDPR(true)
);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
let GDPRDataUseConsent = OfferWallDataUseConsent.GDPR(.given)
OfferWall.setConsent(GDPRDataUseConsent)
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
OFWDataUseConsent *gdprConsent = [OFWDataUseConsentGDPR
    dataUseConsentGDPRWithConsent:OFWGDPRConsentGiven];

[OfferWall setConsent:gdprConsent];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.SetConsent(new OfferWallPrivacyConsent.Gdpr(true));
```

{% endcode %}
{% endtab %}
{% endtabs %}

We recommend that the first time you gather the user's consent, you pass it onto the SDK before starting the SDK. The SDK will then consider the user's consent when initializing. In the following sessions, you must only call the API if the user updates their consent.

For more information about DT and GDPR, refer to DT's [GDPR Resource Page](https://docs.digitalturbine.com/dt-offer-wall/publishers/privacy/gdpr).

#### CCPA

The [California Consumer Privacy Act](https://iabtechlab.com/standards/ccpa/) of 2018 (CCPA) is intended to protect the personal information of California residents. CCPA applies to all companies doing business in California. If a California resident uses a mobile app developer's app, CCPA applies to the developer and every company that processes the personal information of the app's users. CCPA came into effect on 1 January 2020.

For more information about DT and CCPA, refer to DT's [CCPA Resource Page](https://docs.digitalturbine.com/dt-offer-wall/publishers/privacy/ccpa-privacy-string).

Once you have collected the user's opt-out, you can pass it onto the SDK using the following API:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.setConsent(
    OfferWallPrivacyConsent.CCPA("1YNN")
)
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.setConsent(
    new OfferWallPrivacyConsent.CCPA("1YNN")
);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
let CCPADataUseConsent = OfferWallDataUseConsent.CCPA(
    privacyString: "1YYN"
)
OfferWall.setConsent(CCPADataUseConsent)
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
OFWDataUseConsent *ccpaConsent = [OFWDataUseConsentCCPA
    dataUseConsentCCPAWithPrivacyString:"1YNN"];
[OfferWall setConsent:ccpaConsent];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.SetConsent(new OfferWallPrivacyConsent.Ccpa("1YNN"));
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Google Play Families Ads Program

To comply with the [Google Play Family Program](https://support.google.com/googleplay/android-developer/answer/9893335?hl=en-GB\&sjid=4842200760787857266-EU), you must instruct the SDK not to track the Google Ad ID in any requests for users covered by the program. By default, the DT Offer Wall SDK includes the Google Ad ID in all communications with our backend; however, to prevent this and align with the Family Program requirements, you can pass an optional boolean parameter when you [start the SDK](#starting-the-sdk).

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.start(activity = activity,
    appId = appId,
    offerWallListener = offerWallListener,
    saltToken = saltToken,
    disableAdvertisingId = true)
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.start(activity,
    appId,
    offerWallListener
    saltToken,
    true);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
This is not available for iOS.
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.StartSDK("app_id", 
     salt_token, 
     security_token, 
     disableAdvertisingId = true);
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Starting the SDK

{% hint style="info" %}
Starting from FairBid 3.63.0, you will need to pass the `saltToken` when starting the SDK. Contact your DT Representative for information on how to set it up.

The SDK will throw a Runtime Exception if the `saltToken` value is null or empty.
{% endhint %}

Start the SDK using the following API to show the Offer Wall or request Virtual currency:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.start(activity = activity,
    appId = appId,
    offerWallListener = offerWallListener,
    saltToken = saltToken)
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.start(activity,
    appId,
    offerWallListener,
    saltToken);
```

{% endcode %}

The `offerWallListener` needs to be defined and passed to the start API.

It will let the integration know when the Offer Wall is opened and closed so you can pause and resume your app accordingly. For more information about these callbacks and how to show the Offer Wall, see [Showing the Offer Wall](#showing-the-offer-wall).
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" overflow="wrap" %}

```swift
/*API parameter updated (from 3.42.0): virtualCurrencyStartOptions -> virtualCurrencySettings */
OfferWall.start(with: appIdText, 
    delegate: self, 
    virtualCurrencySettings: nil,
    saltToken: saltToken) { [self] error in }
```

{% endcode %}

{% code title="Objective-C" overflow="wrap" %}

```objectivec
/*API parameter updated (from 3.42.0): virtualCurrencyStartOptions -> virtualCurrencySettings */
[OfferWall startWithAppId:appId 
    delegate:self 
    virtualCurrencySettings:nil 
    saltToken:saltToken 
    completion:^(OFWError * _Nullable error) {}];
```

{% endcode %}

The `delegate` needs to be defined and passed to the start API.

It will let the integration know when the Offer Wall is opened and closed so you can pause and resume your app accordingly. For more information about these callbacks and how to show the Offer Wall, see [Showing the Offer Wall](#showing-the-offer-wall).
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
// Basic start with salt token
OfferWall.StartSDK(appId, saltToken);

// With virtual currency security token
OfferWall.StartSDK(appId, saltToken, token);

// With disableAdvertisingId for family-friendly apps  
OfferWall.StartSDK(appId, saltToken, null, true);

// Complete example with all parameters
OfferWall.StartSDK(appId, saltToken, token, false);
```

{% endcode %}

Implement lifecycle callbacks to inform the integration when the Offer Wall is opened and closed so you can pause and resume your app accordingly.
{% endtab %}
{% endtabs %}

## Showing the Offer Wall

To Show the Offer Wall, simply use the `OfferWall.show` API:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.show()
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.show();
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
OfferWall.show()
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
[OfferWall show];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.Show();
```

{% endcode %}
{% endtab %}
{% endtabs %}

This will show the Offer Wall for the default placement with the default behavior (keep the Offer Wall open when the user clicks on an offer and gets redirected out of your app).

### Show Options

**Show Options** enables you to specify the placement ID, change the default behavior of the Offer Wall, or introduce tracking parameters.

#### Close on Redirect

You can specify whether the Offer Wall should be closed once a user clicks on an offer. This will determine what the user sees when returning to the app: either the Offer Wall again or your app. This value is false by default, meaning the user will return to the Offer Wall.

Use the `showOptions` API to define the desired behavior:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
val showOptions = ShowOptions(
    closeOnRedirect = true
)
OfferWall.show(showOptions)
```

{% endcode %}

{% code title="Java" %}

```java
boolean closeOnRedirect = true;
ShowOptions showOptions = new ShowOptions(closeOnRedirect);
OfferWall.show(showOptions);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
let showOptions = ShowOptions(
    closeOnRedirect: true,
    viewController: nil,
    animated: true,
    customParams: nil
)
OfferWall.show(with: showOptions)
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
OFWShowOptions *options = [OFWShowOptions optionsWithCloseOnRedirect:YES
    viewController:nil
    animated:NO
    customParams:nil];
[OfferWall showWithOptions:options];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWallShowOptions showOptions = new OfferWallShowOptions(
    closeOnRedirect: true
);
OfferWall.Show(offerWallShowOptions: showOptions);
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Custom Parameters (Server Side Rewarding)

When using Server Side Rewarding (see [Integrating via REST API - Rewards](https://docs.digitalturbine.com/dt-offer-wall/publishers/offer-wall-rest-api-integration)), you may want to associate additional parameters to the Offer Wall being shown for a given user/placement so that you can perform additional tracking. These custom parameters will be passed back to your system during the reward callback.

Note that these parameters' keys are limited to `pub0`, `pub1`, ..., `pub9`

To add these custom parameters when showing the Offer Wall, use the `customParams` API:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
val customParams = mapOf(
    "pub0" to "tracking_value_0",
    "pub1" to "tracking_value_1"
)
val showOptions = ShowOptions(customParams = customParams)

OfferWall.show(showOptions)
```

{% endcode %}

{% code title="Java" %}

```java
boolean closeOnRedirect = false;
Map<String,String> customParams = new HashMap<>();
customParams.put("pub0", "tracking_value_0");
customParams.put("pub1", "tracking_value_1");

ShowOptions showOptions = new ShowOptions(closeOnRedirect, customParams);

OfferWall.show(showOptions);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
let customParams = [
    "pub0": "tracking_value_0",
    "pub1": "tracking_value_1"
]
let showOptions = ShowOptions(
    viewController: nil,
    customParams: customParams
)
OfferWall.show(with: showOptions)
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
NSDictionary *customParams = @{
    @"pub0": @"tracking_value_0",
    @"pub1": @"tracking_value_1"
};
OFWShowOptions *showOptions = [OFWShowOptions
    optionsWithViewController:self
    customParams:customParams];
[OfferWall showWithOptions:showOptions];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" overflow="wrap" %}

```csharp
var customParams = new Dictionary<string, string>
{
    { "pub0", "tracking_value_0" },
    { "pub1", "tracking_value_1" }
};
OfferWallShowOptions showOptions = new OfferWallShowOptions(customParams: customParams);
OfferWall.Show(offerWallShowOptions: showOptions);
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Show With Placement ID

If you're using placements in your integration, you can specify for which placement ID you want to show the Offer Wall:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.show(placementId = "placementId")
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.show(new ShowOptions(), "placementId");
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
OfferWall.show("placementId")
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
[OfferWall showWithPlacementId:@"placementId"];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.Show("placementId");
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Offer Wall Lifecycle Callbacks

Following [Starting the SDK](#starting-the-sdk), you will need to set up a listener to be notified of the following Offer Wall lifecycle events:

* Offer Wall is about to be shown.
* The user closed the Offer Wall.
* Offer Wall was closed unexpectedly due to an error.

Implement the listener with the `OfferWallListener` API:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" overflow="wrap" %}

```kotlin
val offerWallListener = object: OfferWallListener {
    override fun onShowError(placementId: String?, error: OfferWallError) {
        // This is not expected to take place.
        // You can assume the Offer Wall is not being displayed and resume your app.
    }
    override fun onShow(placementId: String?) {
        // You can assume the Offer Wall is being displayed and pause your app.
    }
    override fun onClose(placementId: String?) {
        // You can assume the Offer Wall is not being displayed and resume your app.
    }
}
```

{% endcode %}

{% code title="Java" overflow="wrap" %}

```java
OfferWallListener offerWallListener = new OfferWallListener() {
    @Override
    public void onShowError(@Nullable String placementId, @NonNull OfferWallError error) {
        // Handle the error, assuming Offer Wall not displayed, resume app.
    }
    @Override
    public void onShow(@Nullable String placementId) {
        // Offer Wall shown, pause app here.
    }
    @Override
    public void onClose(@Nullable String placementId) {
        // Offer Wall closed, resume app here.
    }
};
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" overflow="wrap" %}

```swift
class OfferWallListener: OfferWallDelegate {
    func didShow(_ placementId: String?) {
        // You can assume the Offer Wall is being displayed and pause your app.
    }
    func didFailToShow(_ placementId: String?, error: OfferWallError) {
        // This is not expected to take place.
        // You can assume the Offer Wall is not being displayed and resume your app.
    }
    func didDismiss(_ placementId: String?) {
        // You can assume the Offer Wall is not being displayed and resume your app.
    }
}
```

{% endcode %}

{% code title="Objective-C" overflow="wrap" %}

```objectivec
@interface OfferWallListener: NSObject  {
}
@end
@implementation OfferWallListener
- (void)didShow:(NSString * _Nullable)placementId {
    // You can assume the Offer Wall is being displayed and pause your app.
}
- (void)didFailToShow:(NSString * _Nullable)placementId error:(OFWError * _Nonnull)error {
    // This is not expected to take place.
    // You can assume the Offer Wall is not being displayed and resume your app.
}
- (void)didDismiss:(NSString * _Nullable)placementId {
    // You can assume the Offer Wall is not being displayed and resume your app.
}
@end
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.OfferWallShownEvent += OnOfwShown;
OfferWall.OfferWallClosedEvent += OnOfwClosed;
OfferWall.OfferWallFailedToShowEvent += OnOfwFailedToShow;
```

{% endcode %}

Where the events comply with the following delegates:

{% code title="C#" overflow="wrap" %}

```csharp
public delegate void OfferWallShownCallback(string? placementId);
public delegate void OfferWallClosedCallback(string? placementId);
public delegate void OfferWallFailedToShowCallback(string? placementId, OfferWallError error);
```

{% endcode %}
{% endtab %}
{% endtabs %}

See [Errors](#errors) to assess any problems that may occur (typically an integration mistake).

## Rewarding the User

If you are interested in using your server to handle virtual rewards to your users, DT can interact with it after you've set up your server. For further information, see [Server-Side Hosting](https://docs.digitalturbine.com/dt-offer-wall/publishers/task-specific-guides/rewarding-your-users/server-side-rewarding).

[Virtual Currency Settings](#virtual-currency-settings) assumes you do not run your servers and prefer relying on DT's virtual currency hosting. This is the default setting for mobile applications in the developer Dashboard.

### Virtual Currency Settings

First, you must implement a `VirtualCurrencySettings` object and pass it to the SDK start.

The `VirtualCurrencySettings` holds the security token and callbacks that allow for the complete client-side rewarding:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" overflow="wrap" %}

```kotlin
val virtualCurrencySettings = VirtualCurrencySettings(
    "security_token",
    object: VirtualCurrencyListener {
        override fun onVirtualCurrencySuccess(response: VirtualCurrencySuccessfulResponse) {
            val amountReceived = response.deltaOfCoins
            // Reward users accordingly.
        }

        override fun onVirtualCurrencyError(error: VirtualCurrencyErrorResponse) {
            // Something went wrong. Make sure the security token is correct.
        }
    }
)
OfferWall.start(activity = activity,
    appId =  "appId",
    offerWallListener = ofwListener,
    saltToken = saltToken,
    virtualCurrencySettings = virtualCurrencySettings)
```

{% endcode %}

{% code title="Java" overflow="wrap" %}

```java
VirtualCurrencySettings virtualCurrencySettings = new VirtualCurrencySettings(
    "security_token",
    new VirtualCurrencyListener() {
        @Override
        public void onVirtualCurrencySuccess(@NonNull VirtualCurrencySuccessfulResponse response) {
            double amountReceived = response.getDeltaOfCoins();
            // Reward users accordingly.
        }

        @Override
        public void onVirtualCurrencyError(@NonNull VirtualCurrencyErrorResponse error) {
            // Something went wrong. Make sure the security token is correct.
        }
    });

OfferWall.start(activity,
    "appId",
    ofwListener,
    false,
    saltToken,
    virtualCurrencySettings);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" overflow="wrap" %}

```swift
func didReceive(_ response: VirtualCurrencyResponse) {
    let amount = response.deltaOfCoins
    // Reward users accordingly.
}

func didFail(with errorResponse: VirtualCurrencyErrorResponse) {
    // Something went wrong. Make sure the security token is correct.
}
```

{% endcode %}

Start the Offer Wall with a security token and delegate

{% code title="Swift" overflow="wrap" %}

```swift
/* Class name updated (from 3.42.0): VirtualCurrencyStartOptions - VirtualCurrencySettings */
var vcSettings = VirtualCurrencySettings(securityToken:
    "security_token", delegate: self)
OfferWall.start(with: appId, 
    delegate: self,
    virtualCurrencySettings: vcSettings,
    saltToken: saltToken) { [self] error in }
```

{% endcode %}

***

{% code title="Objective-C" overflow="wrap" %}

```objective-c
- (void)didReceiveResponse:(OFWVirtualCurrencyResponse *_Nonnull)response {
    double amount = [response deltaOfCoins];
    // Reward users accordingly.
}

- (void)didFailWithError:(OFWVirtualCurrencyErrorResponse *_Nonnull)errorResponse {
    // Something went wrong. Make sure the security token is correct.
}
```

{% endcode %}

Start the Offer Wall with a security token and delegate.

{% code title="Objective-C" overflow="wrap" %}

```objectivec
/* Class name updated (from 3.42.0): OFWVirtualCurrencyStartOptions - OFWVirtualCurrencySettings */
OFWVirtualCurrencySettings *vcSettings = [OFWVirtualCurrencySettings
    optionsWithSecurityToken:@"security_token"
    delegate:self];
      
[OfferWall startWithAppId:appId 
    delegate:self 
    virtualCurrencySettings:vcSettings 
    saltToken:saltToken 
    completion:^(OFWError * _Nullable error) {
    }];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
The `VirtualCurrencySettings` object is not supported for Unity.

However, you will first need to pass a security token to the SDK start as well as set up the respective virtual currency delegates before you can request virtual currencies:

{% code title="C#" %}

```csharp
OfferWall.VirtualCurrencyResponseEvent += OnVirtualCurrencySuccess;
OfferWall.VirtualCurrencyErrorEvent += OnVirtualCurrencyError;
```

{% endcode %}

Where the events comply to the following delegates (in the same order)

{% code title="C#" overflow="wrap" %}

```csharp
public delegate void VirtualCurrencyResponseHandler(VirtualCurrencySuccessfulResponse response);
public delegate void VirtualCurrencyErrorHandler(VirtualCurrencyErrorResponse response);

OfferWall.StartSDK(appId: "appId", token: "secret_token");
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Requesting Virtual Currency

Run the `requestCurrency` API to request Virtual Currency:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
OfferWall.requestCurrency()
```

{% endcode %}

{% code title="Java" %}

```java
OfferWall.requestCurrency();
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
OfferWall.requestCurrency()
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
[OfferWall requestCurrency];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
OfferWall.RequestCurrency();
```

{% endcode %}
{% endtab %}
{% endtabs %}

This will request the server for the delta (amount since the last transaction) of the default virtual currency the current user is eligible for.

#### Virtual Currency Options

The request may include the following additional configurations:

* Specify the currency ID if using multiple currencies in your app.
* Specify if the SDK should show a Toast notification of the virtual currency amount received (shown by default).

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" %}

```kotlin
val options = VirtualCurrencyRequestOptions(
    toastOnReward = false,
    currencyId = "currency_id"
)

OfferWall.requestCurrency(options)
```

{% endcode %}

{% code title="Java" %}

```java
VirtualCurrencyRequestOptions options = new VirtualCurrencyRequestOptions(
    false,
    "currency_id"
);
        
OfferWall.requestCurrency(options);
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
let options = VirtualCurrencyRequestOptions(
    currencyId: "currency_id",
    toastOnReward: false
)

OfferWall.requestCurrency(withOptions: options)
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
OFWVirtualCurrencyRequestOptions *options = [OFWVirtualCurrencyRequestOptions
    optionsWithCurrencyId:@"currency_id"
    toastOnReward:NO];
        
[OfferWall requestCurrencyWithOptions:options];
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
VirtualCurrencyRequestOptions options = new VirtualCurrencyRequestOptions(
    toastOnReward: true,
    currencyId: "currency_id"
);
        
OfferWall.RequestCurrency(options);
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Handling a Virtual Currency Success Response

You can extract the delta of coins received by the user as well as the currency name and ID from the `VirtualCurrencySuccessfulResponse` object:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" overflow="wrap" %}

```kotlin
override fun onVirtualCurrencySuccess(response: VirtualCurrencySuccessfulResponse) {
    val amountReceived = response.deltaOfCoins
    val currencyId = response.currencyId
    val currencyName = response.currencyName
    // Reward users accordingly.
}
```

{% endcode %}

{% code title="Java" overflow="wrap" %}

```java
@Override
public void onVirtualCurrencySuccess(@NonNull VirtualCurrencySuccessfulResponse response) {
    double amountReceived = response.getDeltaOfCoins();
    String currencyId = response.getCurrencyId();
    String currencyName = response.getCurrencyName();
    // Reward users accordingly.
}
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" %}

```swift
func didReceive(_ response: VirtualCurrencyResponse) {
    let amount = response.deltaOfCoins
    let currencyId = response.currencyId
    let currencyName = response.currencyName
    // Reward users accordingly.
}
```

{% endcode %}

{% code title="Objective-C" %}

```objectivec
- (void)didReceiveResponse:(OFWVirtualCurrencyResponse *_Nonnull)response {
    double amount = [response deltaOfCoins];
    NSString *currencyId = [response currencyId];
    NSString *currencyName = [response currencyName];
    // Reward users accordingly.
}
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
public void OnVirtualCurrencySuccess(VirtualCurrencySuccessfulResponse response) {
    double amountReceived = response.DeltaOfCoins;
    string currencyId = response.CurrencyId;
    string currencyName = response.CurrencyName;
    // Reward users accordingly.
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Virtual Currency Errors

When there is a problem with the request, you can assess what's wrong by inspecting the `VirtualCurrencyErrorResponse` object:

{% tabs %}
{% tab title="Android" %}
{% code title="Kotlin" overflow="wrap" %}

```kotlin
override fun onVirtualCurrencyError(errResponse: VirtualCurrencyErrorResponse) {
    val currencyId = errResponse.currencyId
    val message = errResponse.serverErrorMessage
    val errorDetail = errResponse.error
    // Handle the error appropriately.    
}
```

{% endcode %}

{% code title="Java" overflow="wrap" %}

```java
@Override
public void onVirtualCurrencyError(@NonNull VirtualCurrencyErrorResponse error) {
    String currencyId = error.getCurrencyId();
    String message = error.getServerErrorMessage();
    OfferWallError errorDetail = error.getError();
    // Handle the error appropriately.
}
```

{% endcode %}
{% endtab %}

{% tab title="iOS" %}
{% code title="Swift" overflow="wrap" %}

```swift
func didFail(with errorResponse: VirtualCurrencyErrorResponse) {
    let currencyId = errorResponse.currencyId
    let message = errorResponse.serverErrorMessage
    let errorDetail = errorResponse.error
    // Handle the error appropriately.
}
```

{% endcode %}

{% code title="Objective-C" overflow="wrap" %}

```objectivec
- (void)didFailWithError:(OFWVirtualCurrencyErrorResponse *_Nonnull)errorResponse {
    NSString *currencyId = errorResponse.currencyId;
    NSString *message = errorResponse.serverErrorMessage;
    OFWError *errorDetail = errorResponse.error;
    // Handle the error appropriately.
}
```

{% endcode %}
{% endtab %}

{% tab title="Unity" %}
{% code title="C#" %}

```csharp
public void OnVirtualCurrencyError(VirtualCurrencyErrorResponse errorResponse) {
    string currencyId = errorResponse.CurrencyId;
    string message = errorResponse.ServerErrorMessage;
    OfferWallError errorDetail = errorResponse.Error;
    // Handle the error appropriately.
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Errors

The following table describes some of the possible errors that might occur when you show the Offer Wall or request virtual currency:

| ERROR                                         | DESCRIPTION                                                                                                                                                                                                                                                                          |
| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `CONNECTION_ERROR`                            | It can occur when either showing the Offer Wall or requesting virtual currency when the device is offline.                                                                                                                                                                           |
| `INVALID_VIRTUAL_CURRENCY_RESPONSE`           | If the virtual currency request is successful but not in the expected format, this may be a consequence of an integration mistake or a system problem. If this occurs, please contact an account manager or Solution Engineer.                                                       |
| `INVALID_VIRTUAL_CURRENCY_RESPONSE_SIGNATURE` | If the virtual currency response is incorrectly signed. This may indicate either an interference with the SDK<>backend communication (e.g., a man in the middle) or a system problem. Please contact an account manager or solution engineer if you detect this error in production. |
| `VIRTUAL_CURRENCY_SERVER_RETURNED_ERROR`      | This typically indicates that the backend rejected the virtual currency request due to missing parameters or a wrong signature. Double-check your integration. If the problem persists, contact an account manager or Solution engineer.                                             |
| `DEVICE_NOT_SUPPORTED`                        | Android Only: If you are trying to run the SDK on a device running Android OS lower than 4 (API 16 - Jelly Bean).                                                                                                                                                                    |
| `UNKNOWN_ERROR`                               | The server returned an error that the SDK does not recognize.                                                                                                                                                                                                                        |
