SDK integration docs

How to integrate UV Junction Zone into your app, read config and report data through the open API. Examples use Kotlin; iOS and Unity work the same way.

Quick start

  1. Create an accountand create an app in the console with its bundle ID to get an App Key.
  2. Wait for the app to be approved: the status changes to "Approved".
  3. Create ad units in the app details to get a Unit Key, then add ad sources in "Mediation".
  4. Integrate the SDK, then call initialization, load and show.

Initialization

Initialize as early as possible in Application.onCreate and pass the user consent state.

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        UVJZ.init(this, "YOUR_APP_KEY", consent = userConsent)
    }
}

Load and show

All ad formats use the same "load, then show" flow. Preload the next ad right after showing.

val ad = RewardedAd("YOUR_UNIT_KEY")
ad.listener = object : AdListener {
    override fun onRewarded() { /* grant the reward */ }
    override fun onClosed()   { ad.load() }
    override fun onError(e: AdError) { /* log and fall back */ }
}
ad.load { ok -> if (ok) ad.show(activity) }

Callbacks

CallbackWhen it fires
onLoadedAd loaded and ready to show
onShownAd shown, counted as an impression
onClickedUser clicked the ad
onRewardedRewarded video finished, grant the reward
onClosedAd closed
onErrorLoad or show failed, with an error code

Config endpoint

On start, the SDK fetches the app's ad units and mediation config. Responses can be cached;ttl_seconds is the suggested cache time. Returns 403 if the app is not approved.

GET /api/v1/config?app_key=YOUR_APP_KEY

{
  "app": { "name": "Pixel Racer", "platform": "android" },
  "units": [ { "unit_key": "…", "format": "rewarded", "floor_ecpm": 8.0 } ],
  "waterfall": [ { "network": "pangle", "placement_id": "…", "bidding": true, "priority": 20 } ],
  "ttl_seconds": 300
}

Event reporting

event Allowed: request,fill,impression,click. An impression event can include revenue_usd(revenue for one impression, in USD).

POST /api/v1/events
Content-Type: application/json

{ "app_key": "…", "unit_key": "…", "network": "pangle",
  "country": "US", "event": "impression", "revenue_usd": 0.0123 }

Event signing

On the app page, click Generate signing secret. The SDK computes HMAC-SHA256(secret, timestamp + "." + raw body) for every event and sends it in two headers. The timestamp is in Unix seconds and is rejected if it is more than 5 minutes off the server clock; each signature is accepted once, so retries need a new timestamp and an event_id.

POST /api/v1/events
Content-Type: application/json
X-UVJZ-Timestamp: 1767225600
X-UVJZ-Signature: sha256=9f2c…

# shell example
TS=$(date +%s)
BODY='{"app_key":"…","unit_key":"…","network":"pangle","country":"US","event":"impression","event_id":"e1"}'
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')
curl -X POST https://uvjz.com/api/v1/events -H "Content-Type: application/json"   -H "X-UVJZ-Timestamp: $TS" -H "X-UVJZ-Signature: sha256=$SIG" -d "$BODY"

Suggested rollout: ship an SDK version that signs, wait until the unsigned count on the app page is near 0, then turn on Require signatures. After a rotation the old secret stays valid until you retire it. The secret ships inside the app, so signing stops forged requests from anyone who only knows the App Key, and replays, but it does not replace server-side revenue checks (see Report connections in the console).

Reporting API

Create a token under "API tokens" in the console and call with Bearer auth. How far back you can query depends on your plan; an invalid token returns 401.

GET /api/v1/reports?from=2026-01-01&to=2026-01-07&group=app
Authorization: Bearer ahk_…

{ "group": "app", "rows": [ { "label": "Pixel Racer", "impressions": 3456659, "revenue_usd": 8023.14, "ecpm_usd": 2.32 } ] }

group accepts day,app,unit,country,network.

Auction endpoint

Runs bids against ad sources with "real-time bidding" on and returns the highest bid plus the sources that go through the waterfall. If the user matches a traffic segment, that segment's settings are used. Networks without a bid URL return a simulated bid (simulated: true), for testing and estimates only.

POST /api/v1/auction
{ "app_key": "…", "unit_key": "…", "country": "US" }

{ "segment": "default", "floor_ecpm": 4.0, "winner": { "network": "pangle", "ecpm": 7.1, "simulated": false }, "bids": […], "waterfall": […] }

Event reporting also supports:dau(with count),reward(with txn_id,user_ref), and for A/B tests: ab_id and variant.

Reward callback

If an ad unit has a callback URL (https), when the SDK reports a reward event, the platform sends a GET request to it with the parameters txn,user,unit,ts and sig.sig is the hex HMAC-SHA256 (keyed with the ad unit's signing secret) of txn|user|unit|ts . The same txn_id triggers one callback only; failures are retried 3 times.

Webhook

Add a URL in the console and pick events:app.review,payout.status,alert.fired. Requests include X-UVJZ-Signature: sha256=…, the HMAC-SHA256 of the raw request body. For safety, the URL must be https and cannot point to a private network.

Privacy & compliance

  • In the EU, UK and similar regions, get user consent before initializing the SDK and pass it with the consent parameter.
  • On iOS, request authorization as required by App Tracking Transparency.
  • For child-directed apps, enable child mode and do not serve personalized ads.
  • Disclose ad-related data use accurately in your app store privacy details.

app-ads.txt

Add the authorization line provided by the platform to the app-ads.txtfile at the root of your developer website, and make sure the developer URL in the app store matches it. Otherwise some advertisers will not buy your traffic.

Error codes

HTTPerrorDescription
400bad_json / bad_eventRequest body is not valid JSON, or a field is invalid
401signature_required / bad_signature / stale_timestamp / bad_timestamp / signing_not_enabledSignature missing or wrong, timestamp more than 5 minutes off, or signature headers sent for an app without signing
409replayedThis signature was already used (replay)
403app_not_approvedApp is not approved yet
404app_not_found / unknown_unitApp key, ad unit or ad network does not exist