Trillboards
Back to Developers
Developer Docs

TypeScript SDK.

Type-safe API client for Node.js and TypeScript

Terminal
$ npm install @trillboards/api-client

Overview

The Trillboards TypeScript SDK is a fully typed API client that wraps every Trillboards REST endpoint with a clean, discoverable interface. Built for Node.js backends, serverless functions, and CLI tools β€” with first-class TypeScript support, canonical error classes, and webhook verification.

  • 11 resource namespaces β€” screens, devices, impressions, analytics, earnings, errors, webhooks, fleet, audience, data, billing
  • Full TypeScript types for every request and response
  • Canonical error class hierarchy with .code, .type, .requestId, .docsUrl
  • Webhook signature verification with constant-time comparison
  • Automatic retry with exponential backoff on 429 and 5xx
  • Request ID propagation for end-to-end tracing
  • Tree-shakeable β€” import only the resource clients you need

Quick Start

Installation

Terminal
npm install @trillboards/api-client

Basic Usage

app.ts
import { TrillboardsClient } from '@trillboards/api-client';

const client = new TrillboardsClient({
  apiKey: process.env.TRILLBOARDS_API_KEY!,
});

// List all screens the partner has access to
const screens = await client.screens.list();
console.log(screens.data.length, 'screens');

// Get earnings summary for the current week
const earnings = await client.earnings.get({ period: 'week' });
console.log(
  'Total earnings:', earnings.data.total_earnings,
  'across', earnings.data.total_impressions, 'impressions'
);

// Get analytics
const analytics = await client.analytics.get({
  start_date: '2026-04-01',
  end_date: '2026-04-18',
});
console.log(analytics);

Reporting impressions

report-impression.ts
// Single impression
await client.impressions.create({
  screen_id: 'scr_abc123',
  ad_id: 'ad_xyz789',
  completed_at: new Date().toISOString(),
});

// Or batch a full minute of impressions
await client.impressions.createBatch({
  impressions: buffered.map((i) => ({
    screen_id: i.screenId,
    ad_id: i.adId,
    completed_at: i.completedAt.toISOString(),
  })),
});

Resource Clients

Every API domain is exposed as a typed namespace on the client instance.

  • client.screensβ€” List, get, update, delete screens. Watch for status changes.
  • client.devicesβ€” Register, pair, unpair, and manage physical devices.
  • client.impressionsβ€” Query impression logs with filtering and pagination.
  • client.analyticsβ€” Aggregated metrics β€” fill rate, CPM, audience, revenue.
  • client.earningsβ€” Revenue summary, transaction history, payout requests.
  • client.errorsβ€” Error catalog lookup β€” cause, fix, and documentation URL.
  • client.webhooksβ€” Create, list, update, and delete webhook subscriptions.
  • client.fleetβ€” Bulk operations across screen groups and tags.
  • client.audienceβ€” Real-time audience sensing data and aggregations.
  • client.dataβ€” Data export and reporting endpoints.
  • client.billingβ€” Invoice history, payment methods, and Stripe Connect.

Error Handling

Every API error is an instance of TrillboardsError with structured metadata for programmatic handling.

error-handling.ts
import { TrillboardsClient, TrillboardsError } from '@trillboards/api-client';

const client = new TrillboardsClient({ apiKey: 'trb_partner_...' });

try {
  const screen = await client.screens.get('scr_nonexistent');
} catch (err) {
  if (err instanceof TrillboardsError) {
    console.error(err.code);       // "SCREEN_NOT_FOUND"
    console.error(err.type);       // "validation"
    console.error(err.statusCode); // 404
    console.error(err.requestId);  // "req_abc123"
    console.error(err.docsUrl);    // "https://api.trillboards.com/docs/errors#SCREEN_NOT_FOUND"
  }
}

Error Fields

  • .codeβ€” Machine-readable error code (e.g., SCREEN_NOT_FOUND)
  • .typeβ€” Error category (authentication, validation, rate_limit, server)
  • .statusCodeβ€” HTTP status code
  • .requestIdβ€” Unique request ID for support tickets and tracing
  • .docsUrlβ€” Direct link to error documentation

Webhook Verification

Verify incoming webhook signatures with constant-time comparison to prevent timing attacks.

webhook-handler.ts
import { Webhooks } from '@trillboards/api-client';
// or: import { constructEvent } from '@trillboards/api-client';

// Express webhook handler.
// IMPORTANT: use express.raw() so req.body is the exact signed bytes.
app.post('/webhooks/trillboards', express.raw({ type: 'application/json' }), (req, res) => {
  const secret = process.env.TRILLBOARDS_WEBHOOK_SECRET!;

  try {
    // 0.3.0+ β€” pass the full headers object. The SDK reads the compound
    // X-Trillboards-Signature header (t=<ts>,v0=<hex>,v1=<hex>) and enforces
    // a 300-second replay window by default. Override via opts.tolerance.
    const event = Webhooks.constructEvent(req.body, req.headers, secret);

    switch (event.type) {
      case 'impression.recorded':
        console.log('Impression:', event.data.impression_id);
        break;
      case 'device.offline':
        console.log('Screen went offline:', event.data.device_id);
        break;
      case 'payout.processed':
        console.log('Payout:', event.data.amount);
        break;
    }

    res.json({ received: true });
  } catch (err) {
    // TrillboardsError with code "webhook_signature_invalid"
    console.error('Signature verification failed:', (err as Error).message);
    res.status(401).end();
  }
});

Upgrading from 0.2.0? The 0.2.0 call shape constructEvent(payload, sig, secret) failed verification against production deliveries because the server signs `${timestamp}.${payload}` while the 0.2.0 verifier signed only payload. The 0.3.0 verifier handles both formats AND adds replay protection. The 0.2.0 shape is preserved as Webhooks.constructEventLegacy for one minor version (with a deprecation warning). Full contract.

Need Help?

Contact our developer support at developers@trillboards.com or visit the Support page.

Type-safe DOOH automation.

npm install, import, build. Full API coverage with TypeScript types.