SDK reference.
the wire-level api behind the optional sdks. two endpoints, one bearer key. usable from any http client.
What the SDK API is
RevenueHog needs no SDK: revenue, the live feed, metrics and alerts all work server-side from your App Store Connect key. The SDK API adds exactly one capability: user-level attribution, linking purchases to your own user ids so anonymous transaction-derived customers upgrade to real profiles. Two endpoints cover it: identify (who the user is) and attribute (which transaction belongs to them). The SDKs page shows the Swift / React Native / Kotlin call sites.
Authentication
Both endpoints authenticate with your organization's publishable key (pk_live_…, from settings → api) as a bearer token: Authorization: Bearer pk_live_…. The key is public by design: safe to ship in an app binary or call from a browser. It can only write identity/attribution data; it can never read revenue.
POST /api/sdk/v1/identify
Upserts an app user. Repeat calls merge: attributes shallow-merge into what's stored, device fields update, and the user's last-seen timestamp bumps. Anonymous pre-login ids (the SDKs send $anon_<uuid>) are ordinary user ids here.
POST /api/sdk/v1/identify
Authorization: Bearer pk_live_…
Content-Type: application/json
{
"appUserId": "user_42", // required: your user id
"bundleId": "com.example.app", // required
"platform": "ios", // optional: "ios" | "android"
"osVersion": "26.2", // optional
"deviceModel": "iPhone17,2", // optional
"locale": "en_US", // optional
"attributes": { "plan": "pro" } // optional, flat JSON ≤ 8 KB
}
→ 200 { "ok": true, "id": "…" }attributes must be a flat JSON object of at most 8 KB. platform accepts exactly ios or android; anything else is ignored rather than rejected. An unknown bundleId (an app not yet imported) still stores the identity, unscoped.
POST /api/sdk/v1/attribute
Links a store transaction to an app user. One transaction belongs to one user per organization, and re-POSTing the same originalTransactionId with a different appUserId moves it. That upsert is the whole aliasing mechanism: after login, the SDKs re-send earlier anonymous transactions under the real user id and history re-points automatically.
POST /api/sdk/v1/attribute
Authorization: Bearer pk_live_…
Content-Type: application/json
{
"appUserId": "user_42", // required
"bundleId": "com.example.app", // required
"originalTransactionId": "2000000123456789", // required
"productId": "com.example.app.pro.monthly" // optional
}
→ 200 { "ok": true }Android clients send the Google Play purchase token as originalTransactionId; it's stored as-is (RevenueHog ingests Apple revenue today; the mapping is kept for future Play support).
Rate limits, CORS & errors
Writes are limited to 240 requests per minute per organization. Over the limit, responses are 429 with a retry-after header (seconds). Other errors: 400 for malformed JSON or missing required fields, 401 for an invalid key. Both endpoints are idempotent in practice: the official SDKs retry with exponential backoff and queue offline, and re-sends merge rather than duplicate.
CORS is deliberately permissive (* origin, POST + OPTIONS): the publishable key is public, so browser-based callers are expected. Responses are never cached.
Versioning
/v1/). Fields may be added over time; existing fields won't change meaning within v1.