Partner SDK
Complete integration guide for vending machines, kiosks, and digital displays
Overview
The Trillboards Partner SDK is a lightweight (~50KB) JavaScript library that runs in a WebView to display ads on your devices. It handles ad fetching, display, impression tracking, and offline caching automatically.
What You Get
- Real-time analytics dashboard
- Video and image ad support
- Offline ad caching (10 ads)
- Automatic impression tracking
- Competitive revenue share via Stripe Connect
Supported Platforms
- React Native WebView
- Electron apps
- Any modern web browser
- iOS WKWebView (iOS 11+)
- Android WebView (API 21+)
NPM Installation
Install the official TypeScript SDK from NPM for type-safe integration with tree-shaking support.
npm install @trillboards/ads-sdkEntry Points
@trillboards/ads-sdk/serverβ Node.js partner client@trillboards/ads-sdk/react-nativeβ React Native WebView@trillboards/ads-sdk/reactβ React hooks & components@trillboards/ads-sdkβ Core browser SDK
Hardened Features
- NativeBridge (10 platform types)
- IndexedDB offline caching
- Real-time telemetry tracking
- Waterfall engine (3 ad source modes)
- Circuit breaker with half-open recovery
Quick Start
1. Register as a Partner
curl -X POST https://api.trillboards.com/v1/partner/register \
-H "Content-Type: application/json" \
-d '{
"name": "Your Company Name",
"slug": "yourcompany",
"contact_email": "developer@yourcompany.com",
"partner_type": "vending_machine"
}'2. Register Your Device
curl -X POST https://api.trillboards.com/v1/partner/device \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"device_id": "machine-001",
"device_type": "vending_machine",
"name": "Mall of America - Floor 2",
"display": {
"width": 1920,
"height": 1080,
"orientation": "landscape"
},
"location": {
"lat": 44.8537,
"lng": -93.2428,
"venue_type": "mall",
"venue_name": "Mall of America"
}
}'3. Load in WebView
// The embed_url from device registration looks like:
https://screen.trillboards.com?fp=P_a1b2c3d4e5f6Partner CMS API (Full Embed Content)
Use the Partner CMS API to push background streams, L-bar content, and self-promo ads to screens running the full embed. Resolve the screen_id once per device, then post content by screen.
Resolve screen_id
curl -s "https://api.trillboards.com/v1/partner/screens/resolve?device_id=YOUR_DEVICE_ID" \
-H "Authorization: Bearer YOUR_API_KEY"Publish a default stream
curl -s -X POST "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/default-streams" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Store TV Loop",
"video_url": "https://cdn.example.com/store-loop.mp4"
}'Update L-bar content
curl -s -X PUT "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/l-bar" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_preferences": {
"display_mode": "l-bar",
"l_bar_position": "bottom",
"l_bar_ads_enabled": true
},
"l_bar_content": {
"enabled": true,
"business_name": "My Store",
"current_promotion": "Buy 1 Get 1"
}
}'Create a self-promo ad
curl -s -X POST "https://api.trillboards.com/v1/partner/ads/self-promo" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Store Special",
"image_url": "https://cdn.example.com/special.jpg",
"screen_ids": ["SCREEN_ID"]
}'Screen Settings APIs
Programmatically control screen content preferences, display settings, and programmatic advertising. All responses include a <code>request_id</code> for debugging.
Content Preferences
Control what types of ads can appear on your screens. Filter by category, age rating, and content type.
# Get content preferences
curl -s "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/content-preferences" \
-H "Authorization: Bearer YOUR_API_KEY"
# Update content preferences (partial)
curl -s -X PATCH "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/content-preferences" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"preference_level": "moderate",
"allow_alcohol": false,
"allow_gambling": false,
"max_age_rating": "PG-13",
"blocked_categories": ["politics", "tobacco"]
}'
# Apply a preset (family-friendly, bar-restaurant, retail, etc.)
curl -s -X POST "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/apply-preset" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"preset_id": "family-friendly"}'Display Settings
Configure screen orientation, ad intervals, L-bar, and Picture-in-Picture display modes.
# Get display settings
curl -s "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/display-settings" \
-H "Authorization: Bearer YOUR_API_KEY"
# Update display settings
curl -s -X PATCH "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/display-settings" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_mode": "l-bar",
"screen_orientation": "landscape",
"ad_interval_seconds": 60,
"l_bar": {
"enabled": true,
"position": "bottom",
"size_percent": 20,
"ads_enabled": true
}
}'Programmatic Settings
Configure header bidding, floor prices, and blocked advertisers for programmatic ads.
# Get programmatic settings
curl -s "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/programmatic-settings" \
-H "Authorization: Bearer YOUR_API_KEY"
# Update programmatic settings
curl -s -X PATCH "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/programmatic-settings" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"floor_price_cpm": 2.50,
"currency": "USD",
"programmatic_allocation_percent": 30,
"blocked_advertisers": ["competitor.com"],
"blocked_iab_categories": ["IAB25-3"]
}'Batch Operations
Update settings for multiple screens in a single request (up to 100 screens).
# Batch update content preferences
curl -s -X POST "https://api.trillboards.com/v1/partner/screens/batch/content-preferences" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"screen_ids": ["SCREEN_1", "SCREEN_2", "SCREEN_3"],
"preset_id": "retail"
}'
# Batch update display settings
curl -s -X POST "https://api.trillboards.com/v1/partner/screens/batch/display-settings" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"screen_ids": ["SCREEN_1", "SCREEN_2"],
"settings": {
"ad_interval_seconds": 45,
"sound_enabled": false
}
}'Request Tracking
All API responses include a <code>request_id</code> field. Include this ID when contacting support for faster debugging. You can also pass your own <code>X-Request-Id</code> header.
Partner Dashboard API
Access comprehensive dashboard data including screen stats, earnings overview, and recent activity. Perfect for building partner portals or monitoring dashboards.
Get Dashboard Overview
curl "https://api.trillboards.com/v1/partner/dashboard" \
-H "Authorization: Bearer YOUR_API_KEY"
# Response includes:
# - partner info (name, slug, status)
# - stats (total_screens, active_screens, impressions today/week/month)
# - earnings (total, available for payout, revenue share %)
# - top_screens (best performing screens)
# - recent_activity (latest events)
# - stripe_status (payout account status)Get Screen Analytics
Get detailed analytics for a specific screen with configurable time periods.
# Get 7-day analytics (default)
curl "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/analytics" \
-H "Authorization: Bearer YOUR_API_KEY"
# Get 30-day analytics
curl "https://api.trillboards.com/v1/partner/screens/SCREEN_ID/analytics?period=30d" \
-H "Authorization: Bearer YOUR_API_KEY"
# Available periods: 7d, 30d, 90d
# Response includes impressions, daily averages, trends, and timeline dataTeam Management API
Invite team members to your partner organization with role-based access control. Team members can access the partner portal and view screens based on their role.
Authentication
Team management write operations require dual authentication:
- X-User-Token: β Owner's JWT token
- Authorization: Bearer trb_partner_xxx β Partner API key
List Team Members
API key only β no user token required for read operations.
curl "https://api.trillboards.com/v1/partner/team" \
-H "Authorization: Bearer YOUR_API_KEY"
# Optional: Filter by status
curl "https://api.trillboards.com/v1/partner/team?status=active" \
-H "Authorization: Bearer YOUR_API_KEY"Invite Team Member
Requires owner role. Available roles: admin, viewer
curl -X POST "https://api.trillboards.com/v1/partner/team/invite" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-User-Token: OWNER_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "teammate@company.com",
"role": "admin",
"name": "Jane Doe"
}'
# Response includes membership_id, status: "pending", expires_atChange Member Role
curl -X PATCH "https://api.trillboards.com/v1/partner/team/USER_ID/role" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-User-Token: OWNER_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "viewer"}'Remove Team Member
curl -X DELETE "https://api.trillboards.com/v1/partner/team/USER_ID" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "X-User-Token: OWNER_JWT_TOKEN"Role Permissions
Owner
- Rotate API keys
- Manage team members
- Request payouts
- View earnings & payouts
- View all screens & analytics
Admin
- Manage team
- View earnings
- Configure webhooks
- Edit screen settings
- View screens & analytics
Viewer
- View earnings
- Edit anything
- View analytics
- View screen status
- View screens
Earnings API
Track your revenue, view transaction history, and request payouts via Stripe Connect.
Get Earnings Summary
curl "https://api.trillboards.com/v1/partner/earnings" \
-H "Authorization: Bearer YOUR_API_KEY"
# Response:
# {
# "total_lifetime_cents": 4500000,
# "this_month_cents": 450000,
# "available_for_payout_cents": 350000,
# "revenue_share_percent": "negotiated",
# "payout_threshold_cents": 2500,
# "breakdown": { "direct_campaigns": 3000000, ... },
# "next_payout_estimate": { "date": "2026-02-01", "amount_cents": 350000 }
# }Get Transaction History
# Get paginated transaction history
curl "https://api.trillboards.com/v1/partner/earnings/transactions?limit=50&offset=0" \
-H "Authorization: Bearer YOUR_API_KEY"
# Response includes earnings and payout transactions with paginationGet Earnings Breakdown
Group earnings by day, week, or screen for detailed analysis.
# Daily breakdown (default)
curl "https://api.trillboards.com/v1/partner/earnings/breakdown" \
-H "Authorization: Bearer YOUR_API_KEY"
# Weekly breakdown
curl "https://api.trillboards.com/v1/partner/earnings/breakdown?group_by=week" \
-H "Authorization: Bearer YOUR_API_KEY"
# By screen
curl "https://api.trillboards.com/v1/partner/earnings/breakdown?group_by=screen" \
-H "Authorization: Bearer YOUR_API_KEY"
# Custom date range
curl "https://api.trillboards.com/v1/partner/earnings/breakdown?start_date=2026-01-01&end_date=2026-01-31" \
-H "Authorization: Bearer YOUR_API_KEY"Request Payout
Requires Stripe Connect account. Minimum payout: $25.00
curl -X POST "https://api.trillboards.com/v1/partner/earnings/payout" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{}' # Defaults to full available balance
# Or specify amount
curl -X POST "https://api.trillboards.com/v1/partner/earnings/payout" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount_cents": 100000}' # Request $1,000 payoutRevenue Share
Partners earn competitive revenue share on all ad impressions. Revenue is calculated based on impressions x CPM rate x your revenue share percentage. Connect your Stripe account in the partner portal to receive payouts.
Platform Integration
Android WebView Setup (Kotlin)
class AdWebViewActivity : AppCompatActivity() {
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ad_webview)
webView = findViewById(R.id.adWebView)
// Configure WebView settings
webView.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true // Required for IndexedDB caching
mediaPlaybackRequiresUserGesture = false // Auto-play videos
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
}
// Add JavaScript interface for events
webView.addJavascriptInterface(
TrillboardsBridge(this),
"TrillboardsNative"
)
// Handle overlay button clicks
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
return false
}
}
// Load the SDK
webView.loadUrl("https://screen.trillboards.com?fp=DEVICE_FINGERPRINT")
}
override fun onBackPressed() {
// Optionally ignore or handle differently
}
}
// JavaScript bridge to receive SDK events
class TrillboardsBridge(private val activity: Activity) {
@JavascriptInterface
fun onAdStarted(adId: String, type: String) {
Log.d("Trillboards", "Ad started: $adId ($type)")
}
@JavascriptInterface
fun onAdCompleted(adId: String) {
Log.d("Trillboards", "Ad completed: $adId")
}
@JavascriptInterface
fun onOverlayClicked() {
activity.runOnUiThread {
// Show your vending machine UI
}
}
}Layout XML
<!-- activity_ad_webview.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/adWebView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Optional: Your custom overlay button -->
<Button
android:id="@+id/orderButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="32dp"
android:text="TAP TO ORDER"
android:visibility="gone" />
</FrameLayout>SDK Reference
Events
| Event | Data | Description |
|---|---|---|
ready | {deviceId, adCount} | SDK initialized and ads loaded |
ad_started | {type, url} | Ad began playing |
ad_completed | {type, url, completed} | Ad finished playing |
ad_error | {type, error} | Ad playback error |
ad_skipped | {type} | User skipped the ad |
ad_ended | {} | SDK advanced to the next ad |
overlay_clicked | {} | User tapped the overlay button |
online | {} | Device came online |
offline | {} | Device went offline |
error | {message} | Initialization error (e.g., missing device ID) |
Methods
| Method | Description |
|---|---|
init(options) | Initialize the SDK with deviceId and partnerId |
show() | Display the ad player and play the next ad |
hide() | Hide the ad player |
skipAd() | Skip the current ad |
refresh() | Force refresh ads from server |
getState() | Get current SDK state (isPlaying, adCount, etc.) |
getAds() | Get list of currently loaded ads |
destroy() | Clean up SDK resources |
Offline Caching
The SDK automatically caches ads in IndexedDB for offline playback. When the device goes offline, cached ads continue to play and impressions are queued for sync.
Cache Behavior
- Oldest ads evicted when cache is full
- Uses ETag for bandwidth efficiency
- Refreshes every 5 minutes when online
- Caches last 10 ads automatically
Impression Sync
- Queue cleared after successful sync
- Timestamps preserved for accurate reporting
- Batch synced when connection restored
- Impressions queued in IndexedDB when offline
Troubleshooting
Ads not loading?
- Verify the device fingerprint in the URL is correct
- Check that your partner account is active (not pending)
- Enable DOM storage for IndexedDB caching
- Ensure JavaScript is enabled in your WebView
Videos not auto-playing?
- Videos are muted by default (unmute on user interaction)
- iOS: Set mediaTypesRequiringUserActionForPlayback = []
- Android: Set mediaPlaybackRequiresUserGesture = false
Not receiving events?
- If you're using an iframe, events fire inside the iframe; use trillboards-embed.js or load the Lite SDK directly
- Events are also dispatched as DOM CustomEvents on window
- Check JavaScript interface is properly registered
Need Help?
Contact our developer support at developers@trillboards.com or visit the Support page.