Trillboards
Back to Developers
Developer Docs

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.

Terminal
npm install @trillboards/ads-sdk

Entry 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

Terminal
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"
  }'
Save the <code>api_key</code> from the response securely β€” it's only shown once!

2. Register Your Device

Terminal
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"
    }
  }'
The response includes an <code>embed_url</code> β€” load this in your WebView.

3. Load in WebView

URL
// The embed_url from device registration looks like:
https://screen.trillboards.com?fp=P_a1b2c3d4e5f6

Partner 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

Terminal
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

Terminal
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

Terminal
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

Terminal
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"]
  }'
Full API reference

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.

Terminal
# 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.

Terminal
# 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.

Terminal
# 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).

Terminal
# 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

Terminal
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.

Terminal
# 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 data

Team 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.

Terminal
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

Terminal
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_at

Change Member Role

Terminal
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

Terminal
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

Terminal
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

Terminal
# 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 pagination

Get Earnings Breakdown

Group earnings by day, week, or screen for detailed analysis.

Terminal
# 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

Terminal
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 payout

Revenue 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)

AdWebViewActivity.kt
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
<!-- 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

EventDataDescription
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

MethodDescription
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.

Ready to start integrating?