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
- Create an accountand create an app in the console with its bundle ID to get an
App Key. - Wait for the app to be approved: the status changes to "Approved".
- Create ad units in the app details to get a
Unit Key, then add ad sources in "Mediation". - 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
| Callback | When it fires |
|---|---|
onLoaded | Ad loaded and ready to show |
onShown | Ad shown, counted as an impression |
onClicked | User clicked the ad |
onRewarded | Rewarded video finished, grant the reward |
onClosed | Ad closed |
onError | Load 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
consentparameter. - 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
| HTTP | error | Description |
|---|---|---|
| 400 | bad_json / bad_event | Request body is not valid JSON, or a field is invalid |
| 401 | signature_required / bad_signature / stale_timestamp / bad_timestamp / signing_not_enabled | Signature missing or wrong, timestamp more than 5 minutes off, or signature headers sent for an app without signing |
| 409 | replayed | This signature was already used (replay) |
| 403 | app_not_approved | App is not approved yet |
| 404 | app_not_found / unknown_unit | App key, ad unit or ad network does not exist |