Rovenue SDK
Getting Started

Installation

Add the Rovenue SDK to your React Native, iOS, or Android app in three steps.

The Rovenue SDK shares a single Rust core (librovenue) across all three platforms. Native billing — StoreKit 2 on iOS, Play Billing 6 on Android — is handled by the platform-specific façade. Pick your platform path and follow the steps below.

Types on this page

type RovenueConfig = {
  apiKey: string;      // public SDK key — prefix rov_pub_
  baseUrl?: string;    // API endpoint — defaults to https://api.rovenue.io
  debug?: boolean;     // verbose log output; default false
  appVersion?: string; // override version reported to the server
};
FieldTypeDescription
apiKeystringPublic SDK key from the Rovenue dashboard. Prefix rov_pub_.
baseUrlstring?Optional. API endpoint; defaults to https://api.rovenue.io. Override only when self-hosting.
debugboolean?Enables verbose SDK logging. Keep false in production.
appVersionstring?App version string reported to the server. Defaults to the OS-reported value.

Swift and Kotlin mirror this with platform-idiomatic parameters. See Types.

The rov_pub_ key is safe to ship in client code — it can only read public project data. Never embed your secret API key (rov_sec_...) in a mobile binary.


Add the package

Install with your package manager (works with bare React Native and Expo). Your choice is remembered across the whole site:

npm install @rovenue/react-native-sdk

Peer dependencies: React Native ≥ 0.76, React ≥ 18.3, Expo ≥ 52 — in an Expo app, the React Native version your Expo SDK pins (npx expo install --check). The Nitro module bundles the prebuilt librovenue dylib — no separate native install is needed.

In Xcode: File → Add Package Dependencies and enter:

https://github.com/broverse/rovenue-ios

Or add to your Package.swift:

dependencies: [
  .package(
    url: "https://github.com/broverse/rovenue-ios",
    from: "0.16.0"
  )
],
targets: [
  .target(
    name: "YourTarget",
    dependencies: ["Rovenue"]
  )
]

Supported platforms: iOS 16.0+ (device and simulator) and macOS 12.0+.

Add to your Podfile:

pod 'Rovenue'

Then run:

pod install

In build.gradle.kts (module level):

dependencies {
  implementation("io.rovenue:sdk:0.16.0")
}

Make sure mavenCentral() is in your settings.gradle.kts repository list.

Wire up native entry points

Expo (recommended): Add the config plugin so expo prebuild auto-wires the native layer:

app.json
{
  "expo": {
    "plugins": ["@rovenue/react-native-sdk/app.plugin"]
  }
}

Then run prebuild:

npx expo prebuild

Bare React Native: Link native modules (React Native ≥ 0.76 auto-links via the Nitro module spec — no manual react-native link needed). For Android, ensure minSdkVersion is 24 or higher in android/build.gradle; on iOS the deployment target must be 16.0 or higher.

No additional wiring is needed beyond adding the package. The SDK hooks into StoreKit 2 automatically at runtime.

If you are using UIKit (non-SwiftUI), ensure your AppDelegate does not override application(_:open:options:) in a way that swallows deep links — the SDK uses SKPaymentQueue for fallback receipt handling on older OS versions.

The SDK requires the BILLING permission. Confirm your AndroidManifest.xml includes it (the AAR ships with a merged manifest, so it is usually added automatically):

AndroidManifest.xml
<uses-permission android:name="com.android.vending.BILLING" />

Ensure your app targets minSdk 24 or higher. Initialize the SDK from your Application subclass, not from an Activity, to avoid lifecycle issues (see Step 3).

Call configure() once at startup

configure() must be called before any other SDK method. It initialises the Rust core, opens the SQLite cache, and starts the background poller.

Call it at the top of your app entry file, before the component tree renders:

index.ts
import { Rovenue } from '@rovenue/react-native-sdk';

Rovenue.configure({
  apiKey: 'rov_pub_your_key_here',
});

With Expo Router, put this in app/_layout.tsx before the <Stack /> render, or in a dedicated app/init.ts that is imported first.

Call from application(_:didFinishLaunchingWithOptions:) (UIKit) or the @main struct init() (SwiftUI):

AppDelegate.swift
import Rovenue

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    Rovenue.configure(
      apiKey: "rov_pub_your_key_here"
    )
    return true
  }
}

SwiftUI @main:

YourApp.swift
import SwiftUI
import Rovenue

@main
struct YourApp: App {
  init() {
    Rovenue.configure(
      apiKey: "rov_pub_your_key_here"
    )
  }

  var body: some Scene {
    WindowGroup { ContentView() }
  }
}

Call from your Application.onCreate():

App.kt
import android.app.Application
import dev.rovenue.sdk.Rovenue

class App : Application() {
  override fun onCreate() {
    super.onCreate()
    Rovenue.configure(
      context = this,
      apiKey = "rov_pub_your_key_here"
    )
  }
}

Register App in AndroidManifest.xml:

AndroidManifest.xml
<application android:name=".App" ...>

Self-hosting? Pass baseUrl to point the SDK at your own deployment, e.g. RN Rovenue.configure({ apiKey: 'rov_pub_...', baseUrl: 'https://api.acme.com' }), Swift Rovenue.configure(apiKey: "rov_pub_...", baseUrl: "https://api.acme.com"), Kotlin Rovenue.configure(apiKey = "rov_pub_...", baseUrl = "https://api.acme.com"). The host must use https:// — plain http:// is accepted only for localhost during local development.

Call configure() once at app startup, before any other Rovenue call. Calling it again later is supported on every platform — it replaces the shared instance rather than throwing — so if you need to change the key (e.g. in a multi-tenant app), you can call configure() again directly; shutdown() first is not required. What is a real hazard is the other ordering mistake: calling any method other than configure() before the first configure() call. That's a programming error to fix at the call site — see Calling the SDK before configure() for what actually happens per platform (a hard crash on iOS, not a catchable error).

Verify the installation

After configure(), call getVersion() to confirm the SDK is wired correctly. The version string is also logged at info level on startup.

import { Rovenue } from '@rovenue/react-native-sdk';

console.log('Rovenue SDK', Rovenue.getVersion());
// → "Rovenue SDK 0.2.0"
import Rovenue

print("Rovenue SDK", Rovenue.shared.getVersion())
// → "Rovenue SDK 0.6.0"
import dev.rovenue.sdk.Rovenue

println("Rovenue SDK ${Rovenue.shared.getVersion()}")
// → "Rovenue SDK 0.6.0"

If configure() was skipped or ran after this code, this step will not fail gracefully: on iOS it crashes outright (the console/crash log shows "Rovenue: must call Rovenue.configure(apiKey:baseUrl:) before accessing shared" just before the process terminates), and on Android it throws an uncaught IllegalStateException carrying the same intent, worded for Kotlin's call syntax ("Rovenue: must call Rovenue.configure(apiKey, baseUrl) before accessing shared"). Neither is a catchable "NotConfigured" error — see Calling the SDK before configure(). If you hit either, double-check configure() actually ran first — see App lifecycle for the correct startup order.

Next step: Continue to the Quick Start to check your first entitlement and make a test purchase. For platform-specific details — Expo plugin options, AppDelegate wiring, Gradle flavours — see the per-platform guides: React Native, iOS Swift, Android Kotlin.

On this page