# Jutera — Monetize with AI Rewards > Jutera's AIRewards SDK adds rewarded AI search to web and mobile apps. End users ask a > question, compare two anonymous AI answers, pick the better one, and earn in the publisher's > own points, coins, or cash. Publishers keep 60% of net ad revenue by default. ## Pages - [Home](https://jutera.com/): product overview for publishers - [Docs](https://jutera.com/docs): complete integration reference - [Create a publisher account](https://jutera.com/dashboard/register) - [Terms of Use](https://jutera.com/terms) - [Privacy Policy](https://jutera.com/privacy) ## AIRewards SDK — integration summary for implementers and agents Product: rewarded AI search widget for third-party publishers. End users ask a question, get two anonymous AI answers, pick one plus at least one reason chip, and that pick creates a reward.earned event. The publisher credits the user from the server webhook. Full human docs: https://jutera.com/docs — implement from there; this file is an index. ## Keys - pk_... publishable: client-safe, identifies the publisher. - sk_... secret: server only. Signs launch tokens; Bearer auth for /v1 APIs. - whsec_... webhook secret: server only. Verifies webhook signatures. ## Flow 1. (Optional, no code) Test: open https://jutera.com/demo-host?pk=&test=1 — pick + chip creates a test event. 2. Server: mint a launch token per user. JWT-shaped HS256: base64url({alg:HS256,typ:JWT}) + "." + base64url({pk, user_id, metadata, test_mode, iat, exp}) signed HMAC-SHA256 with sk_...; exp-iat <= 900s. user_id opaque, never an email. Copy-paste Node/PHP/Python: https://jutera.com/docs#token 3. Browser/native webview: load https://airewards.b-cdn.net/loader@1.js, then AIRewards.init({ publishableKey, launchToken, container, theme, onEarn, onTokenExpired }). Theme tokens: primaryColor, accentColor, background, textColor, fontFamily, borderRadius, elementRadius, colorScheme, showPoweredBy. Saved dashboard Appearance applies automatically when theme is omitted. 4. Earn moment: onEarn / window event "airewards:earned" / native bridge {source:"airewards", type:"reward.earned", event_id, test_mode} — UI hint only. Token expiry: "airewards:token-expired" -> fetch fresh token -> AIRewards.setLaunchToken(t). 5. Server webhook: POST reward.earned JSON, header AIRewards-Signature: t=...,v1=... Verify HMAC-SHA256(secret=whsec_..., t + "." + rawBody), 5-min tolerance, over raw bytes. Any 2xx = delivered. Dedupe on event_id (at-least-once, ~24h retries). Payload: {id, type, created_at, test_mode, publisher_id, user_id, metadata, duel_id, conversation_id, winner, attributes}. No money fields. 6. Optional: GET https://jutera.com/v1/availability?user_id= (Bearer sk_...) -> {eligible, reason: available|daily_cap_reached|publisher_paused|no_fill_expected|user_ineligible, cache_ttl_seconds: 60} ## Reporting API (Bearer sk_...) - GET /v1/reports/daily?from&to[&group_by=metadata.] Zero-filled days: chats, duels, picks, users, earned, earned_test, provisional_cents, payable_cents, gross_cents. - GET /v1/reports/events?from&to&limit&cursor&user_id&test_mode Cursor-paginated events: event_id, user_id, duel_id, winner, attributes, state (provisional|payable|paid|reversed), publisher_cents, floor_applied, webhook status. - GET /v1/reports/events/:event_id — single event, 404 if not yours. ## Rules that matter - Credit users ONLY from the webhook, never from browser/bridge events. - Test mode (unsigned, pk only) always works; test events never pay. - Live mode requires a signed token and an approved (live) publisher account. - Errors: {error:{code}} — unauthorized, invalid_token, token_expired, not_found.