SDK Docs
Track 5 events. Voltaire handles the rest.
Quickstart
After signing up, connect your Stripe or RevenueCat account, then add 5 tracking calls to your app. Voltaire's Claude Code plugin installs the SDK automatically — just run:
/voltaire
Voltaire detects your platform, writes the helper, and instruments the 5 events. You can also do it manually — see the platform sections below.
Events reference
Track exactly these 5 events — no more, no less.
| Event | When to fire |
|---|---|
session_started |
App launch or user login — needed to compute session-to-conversion rates |
feature_used |
When the user hits the key feature that leads to the paywall — identifies your value moment |
paywall_shown |
When the paywall UI becomes visible |
paywall_dismissed |
When the user closes the paywall without purchasing — include dismiss_seconds |
paywall_converted |
After a successful purchase or subscription |
JavaScript / TypeScript
No npm package needed — plain fetch. Store your API key in an env variable.
const VOLTAIRE_KEY = process.env.VOLTAIRE_API_KEY const VOLTAIRE_URL = 'https://api.hivoltaire.com/api/events' async function voltaireEvent(type: string, userId: string, extra?: Record) { await fetch(VOLTAIRE_URL, { method: 'POST', headers: { 'X-Api-Key': VOLTAIRE_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify({ event_type: type, user_session_id: userId, ...extra }), }).catch(() => {}) // fire-and-forget, never block the UI } // 1. New session voltaireEvent('session_started', userId) // 2. Key feature used voltaireEvent('feature_used', userId) // 3. Paywall appears — save the timestamp const paywallShownAt = Date.now() voltaireEvent('paywall_shown', userId) // 4a. User closes without buying voltaireEvent('paywall_dismissed', userId, { dismiss_seconds: (Date.now() - paywallShownAt) / 1000 }) // 4b. User subscribes voltaireEvent('paywall_converted', userId)
iOS (Swift)
No SDK to install — uses URLSession which is built into iOS.
// VoltaireTracker.swift — add this file to your project
func voltaireEvent(_ type: String, userId: String, extra: [String: Any] = [:]) {
guard let url = URL(string: "https://api.hivoltaire.com/api/events") else { return }
var req = URLRequest(url: url)
req.httpMethod = "POST"
req.setValue(ProcessInfo.processInfo.environment["VOLTAIRE_API_KEY"], forHTTPHeaderField: "X-Api-Key")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
var body: [String: Any] = ["event_type": type, "user_session_id": userId]
body.merge(extra) { _, new in new }
req.httpBody = try? JSONSerialization.data(withJSONObject: body)
URLSession.shared.dataTask(with: req).resume()
}
// 1. App launch
voltaireEvent("session_started", userId: currentUser.id)
// 2. Key feature used
voltaireEvent("feature_used", userId: currentUser.id)
// 3. Paywall appears
var paywallShownAt = Date()
voltaireEvent("paywall_shown", userId: currentUser.id)
// 4a. User closes without buying
voltaireEvent("paywall_dismissed", userId: currentUser.id,
extra: ["dismiss_seconds": Date().timeIntervalSince(paywallShownAt)])
// 4b. After purchase
voltaireEvent("paywall_converted", userId: currentUser.id)
Store your API key in Info.plist or an xcconfig file — never hardcode it.
Android (Kotlin)
No SDK to install — uses OkHttp, which is already in most Android projects.
// build.gradle.kts (app) — OkHttp is likely already present
dependencies {
implementation("com.squareup.okhttp3:okhttp:4.12.0")
}
// VoltaireTracker.kt import okhttp3.* import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.toRequestBody import org.json.JSONObject fun voltaireEvent(type: String, userId: String, extra: Map= emptyMap()) { val body = JSONObject(mapOf("event_type" to type, "user_session_id" to userId) + extra) .toString().toRequestBody("application/json".toMediaType()) val request = Request.Builder() .url("https://api.hivoltaire.com/api/events") .addHeader("X-Api-Key", BuildConfig.VOLTAIRE_API_KEY) .post(body).build() Thread { OkHttpClient().newCall(request).execute().close() }.start() } // 1. App launch voltaireEvent("session_started", currentUser.id) // 2. Key feature used voltaireEvent("feature_used", currentUser.id) // 3. Paywall appears val paywallShownAt = System.currentTimeMillis() voltaireEvent("paywall_shown", currentUser.id) // 4a. User closes without buying voltaireEvent("paywall_dismissed", currentUser.id, mapOf("dismiss_seconds" to (System.currentTimeMillis() - paywallShownAt) / 1000.0)) // 4b. After purchase voltaireEvent("paywall_converted", currentUser.id)
Store your API key in local.properties and expose via BuildConfig.
Request format
All events go to the same endpoint via HTTP POST.
POST https://api.hivoltaire.com/api/events
X-Api-Key: volt_YOUR_API_KEY
Content-Type: application/json
{
"event_type": "paywall_shown", // required — one of the 5 events above
"user_session_id": "user_abc" // required — your user or device ID
}
Returns {"ok": true, "event_id": "..."} on success. Fire-and-forget — don't block your UI on it.
Optional fields
| Field | Type | When to use |
|---|---|---|
dismiss_seconds |
number | On paywall_dismissed — time user spent on the paywall |
feature |
string | On feature_used — name of the feature (e.g. "export_pdf") |
Claude Code plugin
The plugin installs the SDK, instruments the 5 events, and applies your weekly recommendation — all from the terminal. Install it once:
/plugin install voltaire@voltairehq
A browser window opens to connect your account. No API key to copy. Then run from any project:
/voltaire
Requires Claude Code.