Trillboards
shared.backToDevelopers
shared.developerDocs

partnerSdk.heroTitleWhite partnerSdk.heroTitleAccent

partnerSdk.heroSubtitle

partnerSdk.overviewTitle

partnerSdk.overviewDesc

partnerSdk.whatYouGet

    partnerSdk.supportedPlatforms

      partnerSdk.npmTitle

      partnerSdk.npmDesc

      Terminal
      npm install @trillboards/ads-sdk

      partnerSdk.entryPoints

        partnerSdk.hardenedFeatures

          partnerSdk.quickStartTitle

          partnerSdk.registerPartner

          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"
            }'
          partnerSdk.registerPartnerNote

          partnerSdk.registerDevice

          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"
              }
            }'
          partnerSdk.registerDeviceNote

          partnerSdk.loadInWebview

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

          partnerSdk.cmsApiTitle

          partnerSdk.cmsApiDesc

          partnerSdk.resolveScreenId

          Terminal
          curl -s "https://api.trillboards.com/v1/partner/screens/resolve?device_id=YOUR_DEVICE_ID" \
            -H "Authorization: Bearer YOUR_API_KEY"

          partnerSdk.publishDefaultStream

          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"
            }'

          partnerSdk.updateLbar

          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"
              }
            }'

          partnerSdk.createSelfPromo

          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"]
            }'
          partnerSdk.fullApiReference

          partnerSdk.screenSettingsTitle

          partnerSdk.screenSettingsDesc

          partnerSdk.contentPreferences

          partnerSdk.contentPreferencesDesc

          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"}'

          partnerSdk.displaySettings

          partnerSdk.displaySettingsDesc

          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
              }
            }'

          partnerSdk.programmaticSettings

          partnerSdk.programmaticSettingsDesc

          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"]
            }'

          partnerSdk.batchOperations

          partnerSdk.batchOperationsDesc

          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
              }
            }'

          partnerSdk.requestTracking

          partnerSdk.requestTrackingDesc

          partnerSdk.dashboardApiTitle

          partnerSdk.dashboardApiDesc

          partnerSdk.getDashboard

          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)

          partnerSdk.getScreenAnalytics

          partnerSdk.getScreenAnalyticsDesc

          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

          partnerSdk.teamApiTitle

          partnerSdk.teamApiDesc

          partnerSdk.authentication

          partnerSdk.authDesc

            partnerSdk.listTeam

            partnerSdk.listTeamDesc

            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"

            partnerSdk.inviteTeam

            partnerSdk.inviteTeamDesc 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

            partnerSdk.changeMemberRole

            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"}'

            partnerSdk.removeTeamMember

            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"

            partnerSdk.rolePermissions

            partnerSdk.roles.owner

            • partnerSdk.permissions.rotateApiKeys
            • partnerSdk.permissions.manageTeam
            • partnerSdk.permissions.requestPayouts
            • partnerSdk.permissions.viewEarnings
            • partnerSdk.permissions.viewAllScreens

            partnerSdk.roles.admin

            • partnerSdk.permissions.manageTeamShort
            • partnerSdk.permissions.viewEarningsShort
            • partnerSdk.permissions.configureWebhooks
            • partnerSdk.permissions.editScreenSettings
            • partnerSdk.permissions.viewScreensAnalytics

            partnerSdk.roles.viewer

            • partnerSdk.permissions.viewEarningsShort
            • partnerSdk.permissions.editAnything
            • partnerSdk.permissions.viewAnalytics
            • partnerSdk.permissions.viewScreenStatus
            • partnerSdk.permissions.viewScreens

            partnerSdk.earningsApiTitle

            partnerSdk.earningsApiDesc

            partnerSdk.getEarnings

            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": 70,
            #   "payout_threshold_cents": 2500,
            #   "breakdown": { "direct_campaigns": 3000000, ... },
            #   "next_payout_estimate": { "date": "2026-02-01", "amount_cents": 350000 }
            # }

            partnerSdk.getTransactions

            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

            partnerSdk.getBreakdown

            partnerSdk.getBreakdownDesc

            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"

            partnerSdk.requestPayout

            partnerSdk.requestPayoutDesc

            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

            partnerSdk.revenueShare

            partnerSdk.revenueShareDesc

            partnerSdk.platformTitle

            partnerSdk.androidWebview

            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
                    }
                }
            }

            partnerSdk.layoutXml

            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>

            partnerSdk.sdkReferenceTitle

            partnerSdk.events

            EventDataDescription
            ready
            ad_started
            ad_completed
            ad_error
            ad_skipped
            ad_ended
            overlay_clicked
            online
            offline
            error

            partnerSdk.methods

            MethodDescription
            init(options)
            show()
            hide()
            skipAd()
            refresh()
            getState()
            getAds()
            destroy()

            partnerSdk.offlineTitle

            partnerSdk.offlineDesc

            partnerSdk.cacheBehavior

              partnerSdk.impressionSync

                partnerSdk.troubleshootingTitle

                partnerSdk.adsNotLoading

                  partnerSdk.videosNotPlaying

                    partnerSdk.notReceivingEvents

                      partnerSdk.needHelp

                      partnerSdk.needHelpText developers@trillboards.com partnerSdk.needHelpOr partnerSdk.needHelpSupportPage.