adsGenesys SDK
A client library for integrating with the adsGenesys advertising platform. Available for JavaScript / TypeScript (Node.js 18+) and Java 21+.
The SDK handles authentication, token refresh, and all HTTP communication with
https://api.adsgenesys.com. It exposes focused clients for each
area of the platform: ad delivery, event tracking, frequency capping, video watch
history, and campaign management.
What you can do
- Request HLS chunklist ad blocks for live channels and VOD
- Fetch VAST 4.2 XML for standard video players
- Track ad events — impressions, views, clicks, errors
- Read per-device and cross-device frequency cap data
- Record and query video watch history for idle-based ad scheduling
- Run Dynamic Ad Insertion (DAI) sessions over VOD content
- Manage campaigns, platforms, and audience segments
Installation
JavaScript / TypeScript
Requires Node.js 18 or later. No runtime dependencies.
npm install ads-genesys-sdk
import { AdsGenesysClient } from 'ads-genesys-sdk';
Java
Requires Java 21+. Add to your Maven pom.xml:
<dependency> <groupId>com.vio</groupId> <artifactId>ads-genesys-sdk</artifactId> <version>1.0.0</version> </dependency>
Quick Start
Create a client instance once and reuse it across your application.
import { AdsGenesysClient, impression, viewComplete } from 'ads-genesys-sdk'; const client = new AdsGenesysClient({ apiKey: 'vio_your_api_key', apiSecret: 'your_api_secret', }); // Request an ad block const blocks = await client.chunklist().createChunklist({ platformId: 'platform-1', subscriberId: 'sub-123', deviceType: 'TV', deviceId: 'device-456', channelId: 'channel-789', bids: [{ blockId: 'block-1', duration: 30 }], }); // Track an impression await client.statistics().sendEvent( impression('campaign-1', 'creative-1', 'session-1') );
import com.vio.sdk.AdsGenesysClient; import com.vio.sdk.config.AdsGenesysConfig; import com.vio.sdk.model.AdBlock; import com.vio.sdk.statistics.AdEventRequest; AdsGenesysClient client = AdsGenesysClient.create( AdsGenesysConfig.builder() .apiKey("vio_your_api_key") .apiSecret("your_api_secret") .build() ); // Request an ad block ChunklistRequest req = new ChunklistRequest(); req.setPlatformId("platform-1"); req.setSubscriberId("sub-123"); req.setDeviceType("TV"); req.setChannelId("channel-789"); req.setBids(List.of(new BidRequest("block-1", 30))); List<AdBlock> blocks = client.chunklist().createChunklist(req); // Track an impression client.statistics().sendEvent( AdEventRequest.impression("campaign-1", "creative-1", "session-1") );
Authentication
The SDK exchanges your API key and API secret for a short-lived JWT access token. This happens automatically on the first request and on token expiry — you never manage tokens manually.
/authentication/api-key/exchange
Tokens are cached in memory and refreshed 60 seconds before expiry (~15-minute TTL).
When a 401 or 403 response is received, the token is
invalidated and the request is retried once automatically.
apiSecret server-side only. Never expose it in browser bundles or mobile apps.Configuration
| Field | Type | Description | |
|---|---|---|---|
| apiKey | string | required | Your adsGenesys API key. |
| apiSecret | string | required | Your adsGenesys API secret. |
| baseUrl | string | optional | API base URL. Default: https://api.adsgenesys.com |
| timeoutMs | number | optional | Request timeout in milliseconds. Default: 10000 |
Error Handling
All SDK errors are instances of AdsGenesysError
(JS) or VioSdkException (Java). They carry an HTTP
statusCode when the error originated from an API response.
import { AdsGenesysError } from 'ads-genesys-sdk'; try { const blocks = await client.chunklist().createChunklist(request); } catch (err) { if (err instanceof AdsGenesysError) { console.error(err.statusCode, err.message); } }
try { List<AdBlock> blocks = client.chunklist().createChunklist(request); } catch (VioSdkException e) { System.out.println(e.getStatusCode() + " " + e.getMessage()); }
| statusCode | Meaning |
|---|---|
| 401 / 403 | Invalid or expired credentials. The SDK retries once automatically. |
| 404 | Resource not found. |
| 422 | Validation error. Check request parameters. |
| -1 | Network or timeout error (no HTTP response received). |
Chunklist
Request HLS chunklist ad blocks from the advertisement processor.
Returns one AdBlock per bid, each containing an M3U8
chunklist URL and ad metadata.
/advirtisement/block/chunklist
const blocks = await client.chunklist().createChunklist({ platformId: 'platform-1', channelId: 'channel-live-1', // or vodId for VOD subscriberId: 'sub-123', deviceType: 'TV', deviceId: 'device-456', playingSessionId: 'session-abc', resolution: '1920x1080', ipAddress: '203.0.113.5', bids: [ { blockId: 'mid-1', duration: 30 }, { blockId: 'mid-2', duration: 15 }, ], }); blocks.forEach(block => { console.log(block.blockId, block.chunklist); });
ChunklistRequest req = new ChunklistRequest(); req.setPlatformId("platform-1"); req.setChannelId("channel-live-1"); req.setSubscriberId("sub-123"); req.setDeviceType("TV"); req.setDeviceId("device-456"); req.setPlayingSessionId("session-abc"); req.setIpAddress("203.0.113.5"); req.setBids(List.of( new BidRequest("mid-1", 30), new BidRequest("mid-2", 15) )); List<AdBlock> blocks = client.chunklist().createChunklist(req);
ChunklistRequest fields
| Field | Type | Description | |
|---|---|---|---|
| platformId | string | required | Platform identifier. |
| subscriberId | string | required | Subscriber identifier. |
| deviceType | string | required | TV, MOBILE, or WEB. |
| deviceId | string | required | Device identifier. |
| bids | BidRequest[] | required | List of ad blocks to fill. Each bid specifies a blockId and duration (seconds). |
| channelId | string | optional | Live channel identifier. |
| vodId | string | optional | VOD content identifier. |
| playingSessionId | string | optional | Unique playback session ID. |
| ipAddress | string | optional | Viewer IP for geo-targeting. |
| resolution | string | optional | Screen resolution, e.g. 1920x1080. |
| gender | string | optional | M or F. |
| ar | number | optional | Viewer age for age-restricted ad filtering. |
AdBlock response
| Field | Type | Description |
|---|---|---|
| blockId | string | Matches the bid's blockId. |
| chunklist | string | HLS M3U8 URL to insert into the player. |
| items | AdItem[] | Individual ad segments with tracking URLs. |
| ads | AdMetadata[] | Creative metadata: click-through URL, companion banner, duration. |
VAST
Returns a VAST 4.2 XML string for use with standard video player ad clients (e.g., Google IMA, Video.js, THEOplayer).
/vast/ad
const vastXml = await client.vast().getVastXml({ platformId: 'platform-1', channelId: 'channel-live-1', subscriberId: 'sub-123', deviceType: 'WEB', blockDuration: 30, ipAddress: '203.0.113.5', }); // Pass vastXml to your video player's ad client
VastRequest request = VastRequest.builder() .platformId("platform-1") .channelId("channel-live-1") .subscriberId("sub-123") .deviceType("WEB") .blockDuration(30) .ipAddress("203.0.113.5") .build(); String vastXml = client.vast().getVastXml(request);
Statistics
Send ad lifecycle events to the analytics pipeline and query campaign reports.
Events
The SDK provides factory functions for each event type. All functions accept optional extra fields as a second argument.
/api/v1/events
import { impression, viewStart, viewProgress, viewComplete, click, skip, error } from 'ads-genesys-sdk'; const stats = client.statistics(); await stats.sendEvent(impression('campaign-1', 'creative-1', 'sess-1')); await stats.sendEvent(viewStart('campaign-1', 'creative-1', 'sess-1')); await stats.sendEvent(viewProgress('campaign-1', 'creative-1', 25, 'sess-1')); await stats.sendEvent(viewComplete('campaign-1', 'creative-1', 30000, 'sess-1')); await stats.sendEvent(click('campaign-1', 'creative-1', 'sess-1')); await stats.sendEvent(skip('campaign-1', 'creative-1', 'sess-1')); await stats.sendEvent(error('campaign-1', 'creative-1', 'MEDIA_ERR', 'Failed to load', 'sess-1'));
client.statistics().sendEvent(AdEventRequest.impression("campaign-1", "creative-1", "sess-1")); client.statistics().sendEvent(AdEventRequest.viewProgress("campaign-1", "creative-1", "sess-1", 50)); client.statistics().sendEvent(AdEventRequest.viewComplete("campaign-1", "creative-1", "sess-1", 30000));
| Event type | Description |
|---|---|
| IMPRESSION | Ad was rendered in the player. |
| VIEW_START | Playback of the ad started. |
| VIEW_PROGRESS_25 / 50 / 75 | Quartile progress milestones. |
| VIEW_COMPLETE | Ad played to completion. Include watchTimeMs. |
| CLICK | User clicked the ad. |
| SKIP | User skipped the ad. |
| ERROR | Playback error. Include errorCode and errorMessage. |
Event Batching
Use AdEventBatch to accumulate events and send them as a single
request. Useful for high-traffic players where sending one request per event
is expensive.
Events flush automatically when the buffer reaches maxBatchSize
(default 50) or every flushIntervalMs (default 5 000 ms).
/api/v1/events/batch
const batch = client.statistics().createBatch(); batch.add(impression('campaign-1', 'creative-1', 'sess-1')); batch.add(viewStart('campaign-1', 'creative-1', 'sess-1')); batch.add(viewComplete('campaign-1', 'creative-1', 30000, 'sess-1')); await batch.close(); // final flush + stop timer
try (AdEventBatch batch = client.statistics().createBatch()) { batch.add(AdEventRequest.impression("camp-1", "cre-1", "sess-1")); batch.add(AdEventRequest.viewComplete("camp-1", "cre-1", "sess-1", 30000)); } // auto-closes and flushes
Reports
Query aggregated analytics data by campaign, platform, or creative.
const stats = client.statistics(); const report = await stats.getCampaignReport('campaign-1', { from: '2024-01-01', to: '2024-01-31', }); const creatives = await stats.getCampaignCreatives('campaign-1', { from: '2024-01-01' });
ReportQuery query = ReportQuery.builder() .from("2024-01-01") .to("2024-01-31") .build(); CampaignReport report = client.statistics().getCampaignReport("campaign-1", query);
| Method | Endpoint |
|---|---|
| getCampaignReport(id) | GET /api/v1/reports/campaign/{id} |
| getPlatformReport(id) | GET /api/v1/reports/platform/{id} |
| getCreativeReport(id) | GET /api/v1/reports/creative/{id} |
| getPlatformCampaigns(id) | GET /api/v1/reports/platform/{id}/campaigns |
| getCampaignCreatives(id) | GET /api/v1/reports/campaign/{id}/creatives |
Frequency Cap
Read how many times a subscriber (or a specific device) has seen ads within each campaign period. Used to enforce per-subscriber and per-device view limits.
// Cross-device: combined view counts for the subscriber const history = await client.frequencyCap().getUserViews('sub-123'); // { periodViews: { 'period-abc': 3, 'period-xyz': 1 }, ... } // Per-device view counts const deviceHistory = await client.frequencyCap().getUserViews( 'sub-123', 'device-456', 'TV' );
UserViewHistory history = client.frequencyCap().getUserViews("sub-123"); UserViewHistory deviceHistory = client.frequencyCap().getUserViews( "sub-123", "device-456", "TV" );
| Endpoint | Description |
|---|---|
GET /api/v1/user-views/cross-device |
Aggregated view counts across all devices for a subscriber. |
GET /api/v1/user-views |
View counts for a specific subscriber + device combination. |
Video Watch
Track when subscribers watch video content. This data is used by the idle-based ad scheduling logic inside DAI sessions to decide when to show the first ad.
The SDK caches the last watch time per subscriber in memory for 5 minutes to avoid repeated API calls during a single session.
const watch = client.videoWatch(); // Record that a subscriber started watching await watch.recordWatchSession('sub-123', 'vod-456'); // Query last watch time const lastWatch = await watch.getLastWatchTime('sub-123'); // returns Date | null // Check idle eligibility directly const eligible = await watch.isAdEligibleByWatchHistory('sub-123', 8400, { minContentDurationSeconds: 7200, idleThresholdMinutes: 30, firstAdOffsetMinSeconds: 600, firstAdOffsetMaxSeconds: 900, });
// Record watch session client.videoWatch().recordWatchSession("sub-123", "vod-456"); // Query last watch time Optional<Instant> last = client.videoWatch().getLastWatchTime("sub-123"); VideoWatchConfig cfg = VideoWatchConfig.builder() .minContentDurationSeconds(7200) .idleThresholdMinutes(30) .firstAdOffsetMinSeconds(600) .firstAdOffsetMaxSeconds(900) .build(); boolean eligible = client.videoWatch().isAdEligibleByWatchHistory("sub-123", 8400, cfg);
| Endpoint | Description |
|---|---|
POST /api/v1/video-watch | Record a watch session. Body: { subscriberId, videoId }. |
GET /api/v1/video-watch/last | Returns the last watch record for a subscriber. 404 if none. |
Dynamic Ad Insertion (DAI)
DAI sessions manage ad break scheduling for a single VOD playback. The session calculates break points upfront and tracks which breaks have been served.
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
| firstAdOffsetSeconds | number | 600 | Fallback offset in seconds for the first mid-roll. |
| subsequentIntervalSeconds | number | 3600 | Interval between subsequent mid-rolls. Set to 0 for a single mid-roll. |
| maxAdsPerContent | number | 5 | Maximum total ad breaks (pre + mid + post). |
| defaultBlockDurationSeconds | number | 30 | Duration of each ad block in seconds. |
| skipPreRoll | boolean | false | Skip the pre-roll ad break. |
| skipPostRoll | boolean | true | Skip the post-roll ad break. |
| videoWatchConfig | VideoWatchConfig | null | When set, enables idle-based first-ad scheduling. See below. |
const session = client.createDaiSession( { firstAdOffsetSeconds: 900, subsequentIntervalSeconds: 1800, maxAdsPerContent: 4, defaultBlockDurationSeconds: 30, }, 'vod-123', // vodId 5400, // contentDurationSeconds (90 min) 'platform-1', 'sub-123', 'TV', 'device-456', ); // Inspect planned breaks session.getAdBreaks().forEach(b => console.log(b.offsetSeconds, b.position)); // During playback loop const adBreak = session.checkForAdBreak(currentPositionSeconds); if (adBreak) { const ads = await session.requestAdBlock(adBreak); }
DaiConfig config = DaiConfig.builder() .firstAdOffsetSeconds(900) .subsequentIntervalSeconds(1800) .maxAdsPerContent(4) .build(); DaiSession session = client.createDaiSession( config, "vod-123", 5400, "platform-1", "sub-123", "TV", "device-456" ); Optional<DaiAdBreak> adBreak = session.checkForAdBreak(currentPositionSeconds); adBreak.ifPresent(b -> session.requestAdBlock(b));
Idle-based Scheduling
When videoWatchConfig is set on the DaiConfig,
the first mid-roll offset is determined dynamically:
- If content duration ≥
minContentDurationSeconds(e.g. 120 min), and - the subscriber has not watched in the last
idleThresholdMinutes(e.g. 30 min),
then the first mid-roll is placed at a random time between
firstAdOffsetMinSeconds and firstAdOffsetMaxSeconds
(e.g. 10–15 min). Otherwise, firstAdOffsetSeconds is used as a fallback.
// SDK fetches last watch time automatically and applies the rule const session = await client.createDaiSessionWithWatchCheck( { videoWatchConfig: { minContentDurationSeconds: 7200, // 120 min idleThresholdMinutes: 30, firstAdOffsetMinSeconds: 600, // 10 min firstAdOffsetMaxSeconds: 900, // 15 min }, }, 'vod-123', 8400, // 140 min content — rule applies 'platform-1', 'sub-123', 'TV', 'device-456', ); // Or pass the last watch time manually const lastWatch = await client.videoWatch().getLastWatchTime('sub-123'); const session2 = client.createDaiSession(config, 'vod-123', 8400, 'platform-1', 'sub-123', 'TV', 'device-456', lastWatch);
DaiConfig config = DaiConfig.builder() .videoWatchConfig(VideoWatchConfig.builder() .minContentDurationSeconds(7200) .idleThresholdMinutes(30) .firstAdOffsetMinSeconds(600) .firstAdOffsetMaxSeconds(900) .build()) .build(); // Auto-fetches last watch time DaiSession session = client.createDaiSessionWithWatchCheck( config, "vod-123", 8400, "platform-1", "sub-123", "TV", "device-456" );
Management
Read-only access to campaigns and platforms, plus full CRUD for audience segments.
Campaigns & Platforms
const mgmt = client.management(); const campaigns = await mgmt.getCampaignsByProvider('provider-1'); const campaign = await mgmt.getCampaign('campaign-1', 'provider-1'); const platform = await mgmt.getPlatform('platform-1');
client.management().getCampaignsByProvider("provider-1"); client.management().getCampaign("campaign-1", "provider-1"); client.management().getPlatform("platform-1");
Audience Segments
Audience segments define targeting criteria (age, gender, geo) scoped to a platform. Active segments are applied automatically during ad selection.
const mgmt = client.management(); // Create const segment = await mgmt.createAudienceSegment('platform-1', { name: 'Adults 25-44', ageFrom: 25, ageTo: 44, countries: ['UA', 'PL'], }); // Activate / deactivate await mgmt.activateAudienceSegment('platform-1', segment.uuid); await mgmt.deactivateAudienceSegment('platform-1', segment.uuid); // List const all = await mgmt.getAudienceSegmentsByPlatform('platform-1'); // Delete await mgmt.deleteAudienceSegment('platform-1', segment.uuid);
AudienceSegmentRequest req = new AudienceSegmentRequest(); req.setName("Adults 25-44"); req.setAgeFrom(25); req.setAgeTo(44); req.setCountries(Set.of("UA", "PL")); AudienceSegment seg = client.management().createAudienceSegment("platform-1", req); client.management().activateAudienceSegment("platform-1", seg.getUuid());
| Method | Endpoint |
|---|---|
| createAudienceSegment | POST /api/v1/audience-segments/{platformId} |
| updateAudienceSegment | PUT /api/v1/audience-segments/{platformId}/{uuid} |
| getAudienceSegment | GET /api/v1/audience-segments/{platformId}/{uuid} |
| getAudienceSegmentsByPlatform | GET /api/v1/audience-segments/platform/{platformId} |
| activateAudienceSegment | PUT /api/v1/audience-segments/{platformId}/{uuid}/activate |
| deactivateAudienceSegment | PUT /api/v1/audience-segments/{platformId}/{uuid}/deactivate |
| deleteAudienceSegment | DELETE /api/v1/audience-segments/{platformId}/{uuid} |
Types
All public types are exported from the package root.
import type { // Config AdsGenesysConfig, // Ad delivery ChunklistRequest, BidRequest, AdBlock, AdItem, AdMetadata, AdPosition, VastRequest, // Statistics AdEventType, AdEventRequest, AdEventData, ReportQuery, CampaignReport, // Frequency cap UserViewHistory, // Video watch VideoWatchConfig, VideoWatchRecord, // DAI DaiConfig, // Management AudienceSegment, AudienceSegmentRequest, } from 'ads-genesys-sdk';
Downloads
Download the SDK as a standalone package — no package manager required.
Includes the compiled dist/ folder with .js files and TypeScript declaration files (.d.ts).
Includes the compiled .jar and all runtime dependencies (Jackson, SLF4J).
Prefer a package manager? See Installation for npm and Maven instructions.