CONNECT
Integration Platform & Developer APIs
Build custom streaming solutions with comprehensive APIs, SDKs for all platforms, real-time webhooks, and a growing integration marketplace. Extend WAVE to fit your exact needs.
What is CONNECT?
CONNECT is WAVE's integration platform that makes the entire streaming infrastructure programmable
CONNECT provides comprehensive APIs and SDKs that let you build custom streaming applications, integrate with existing systems, and extend WAVE functionality.
Whether you're building a mobile app, integrating with your CRM, creating custom workflows with webhooks, or developing embedded streaming devices, CONNECT gives you the tools to build exactly what you need.
With 500+ REST endpoints, real-time WebSocket API, official SDKs for all major platforms, and a comprehensive event system, CONNECT makes WAVE infinitely extensible.
Official SDKs
SDK Feature Comparison
Comprehensive feature matrix across all supported platforms
| Feature | JavaScript/TS | Python | Go | iOS (Swift) | Android (Kotlin) |
|---|---|---|---|---|---|
| Stream Management | |||||
| Real-time Analytics | |||||
| WebSocket Support | |||||
| Webhook Handling | - | - | |||
| OAuth 2.0 | |||||
| File Upload | |||||
| Video Player | - | - | |||
| Screen Capture | - | - | |||
| Camera Access | - | - | |||
| Background Recording | - | - | - | ||
| Push Notifications | - | - | - | ||
| GraphQL Client | - | - | |||
| Batch Operations | |||||
| TypeScript Support | - | - | - | - | |
| SSR/SSG Support | - | - |
Feature available and production-ready with full documentation
All SDKs are open source on GitHub under MIT license
Regular updates with new features and bug fixes
Key Features
Everything you need to build custom streaming solutions
REST API
500+ endpoints for complete platform control with OAuth 2.0 authentication
WebSocket API
Real-time data streaming with bi-directional communication for live updates
Multi-Platform SDKs
Official SDKs for Web, iOS, Android, Desktop, and Embedded systems
Event System
Comprehensive webhook system for real-time event notifications
Complete API Reference
500+ endpoints for complete programmatic control
Create, manage, and control live streams
Real-time metrics and historical data
Authentication and user management
Schedule streams and automate workflows
Event subscriptions and delivery
Video uploads and transcoding
Subscriptions and payments
Team and org management
Third-party service connections
WebSocket and SSE streams
Get Started with CONNECT
Quick Start Example
// Install WAVE SDK
npm install @wave/sdk
// Initialize client
import { WaveClient } from '@wave/sdk';
const wave = new WaveClient({
apiKey: process.env.WAVE_API_KEY,
webhookSecret: process.env.WAVE_WEBHOOK_SECRET,
});
// Create stream
const stream = await wave.streams.create({
title: 'My Live Stream',
protocol: 'srt',
});
// Listen to events via webhook
wave.webhooks.on('stream.started', (event) => {
console.log('Stream started:', event.streamId);
// Send notification, update database, etc.
});
// Get real-time analytics
const analytics = await wave.analytics.getStreamStats(stream.id);
console.log('Current viewers:', analytics.viewers);
console.log('Avg watch time:', analytics.avgWatchTime);Webhook Events Catalog
15+ real-time events delivered to your endpoint within 100ms
Stream went live and is broadcasting
Stream stopped broadcasting
Stream encountered an error
Viewer connected to stream
Viewer disconnected from stream
Stream recording available for download
Video transcoding finished
Video transcoding encountered error
New customer subscription created
Subscription plan or status changed
Customer subscription cancelled
Payment processed successfully
Payment processing failed
New user account created
New organization created
Metric threshold exceeded
Webhook Security
All webhooks include HMAC-SHA256 signature for verification
Exponential backoff retry up to 3 attempts over 24 hours
Use WAVE CLI to test webhooks locally before deployment
Advanced Integration Examples
Production-ready code for common integration patterns
OAuth 2.0 Authorization Code Flow
// JavaScript - Complete OAuth flow
const express = require('express');
const { WaveClient } = require('@wave/sdk');
const app = express();
const wave = new WaveClient({
clientId: process.env.WAVE_CLIENT_ID,
clientSecret: process.env.WAVE_CLIENT_SECRET,
redirectUri: 'https://yourapp.com/callback'
});
// Step 1: Redirect to authorization
app.get('/auth', (req, res) => {
const authUrl = wave.oauth.getAuthorizationUrl({
scope: ['streams:read', 'streams:write', 'analytics:read'],
state: generateRandomState() // CSRF protection
});
res.redirect(authUrl);
});
// Step 2: Handle callback
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// Verify state for CSRF protection
if (!verifyState(state)) {
return res.status(400).send('Invalid state');
}
// Exchange code for tokens
const tokens = await wave.oauth.exchangeCode(code);
// tokens: { access_token, refresh_token, expires_in }
// Store tokens securely
await saveUserTokens(req.user.id, tokens);
res.redirect('/dashboard');
});
// Step 3: Use access token
app.get('/api/streams', async (req, res) => {
const tokens = await getUserTokens(req.user.id);
const authenticatedWave = new WaveClient({ accessToken: tokens.access_token });
const streams = await authenticatedWave.streams.list();
res.json(streams);
});Webhook Signature Verification
// Node.js - Secure webhook handling
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(payload).digest('hex');
const expectedSignature = `sha256=${digest}`;
// Use timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/wave', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-wave-signature'];
const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WAVE_WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(payload);
// Process event
switch (event.type) {
case 'stream.started':
await handleStreamStarted(event.data);
break;
case 'stream.ended':
await handleStreamEnded(event.data);
break;
// ... handle other events
}
res.json({ received: true });
});
# Python equivalent
import hmac
import hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
expected_signature = hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(
signature,
f"sha256={expected_signature}"
)WebSocket Real-Time Subscription
// Real-time stream metrics via WebSocket
import { WaveWebSocket } from '@wave/sdk';
const ws = new WaveWebSocket({
apiKey: process.env.WAVE_API_KEY
});
// Connect and authenticate
await ws.connect();
// Subscribe to stream events
await ws.subscribe('stream.metrics', { streamId: 'stream_abc123' });
// Listen for real-time updates
ws.on('stream.metrics', (data) => {
console.log('Current viewers:', data.viewers);
console.log('Current bitrate:', data.bitrate);
console.log('Dropped frames:', data.droppedFrames);
// Update UI in real-time
updateDashboard(data);
});
// Subscribe to chat messages
await ws.subscribe('stream.chat', { streamId: 'stream_abc123' });
ws.on('stream.chat', (message) => {
console.log(`${message.user}: ${message.text}`);
displayChatMessage(message);
});
// Handle errors and reconnection
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
ws.on('close', () => {
console.log('Connection closed, attempting reconnect...');
setTimeout(() => ws.connect(), 5000);
});Pagination Pattern for Large Datasets
// Efficient pagination through large result sets
async function fetchAllStreams(wave) {
const allStreams = [];
let cursor = null;
do {
const response = await wave.streams.list({
limit: 100, // Fetch 100 items per page
cursor: cursor // Continue from last position
});
allStreams.push(...response.data);
cursor = response.pagination.nextCursor;
console.log(`Fetched ${allStreams.length} of ${response.pagination.total} streams`);
} while (cursor); // Continue until no more pages
return allStreams;
}
// Usage
const wave = new WaveClient({ apiKey: process.env.WAVE_API_KEY });
const streams = await fetchAllStreams(wave);
console.log(`Total streams: ${streams.length}`);Batch Operations API
// Create multiple streams efficiently
const wave = new WaveClient({ apiKey: process.env.WAVE_API_KEY });
const streamConfigs = [
{ title: 'Stream 1', protocol: 'srt', quality: '1080p' },
{ title: 'Stream 2', protocol: 'webrtc', quality: '4k' },
{ title: 'Stream 3', protocol: 'rtmp', quality: '720p' }
];
// Batch create (single API call)
const result = await wave.streams.batchCreate(streamConfigs);
console.log(`Created ${result.successful.length} streams`);
console.log(`Failed ${result.failed.length} streams`);
// Process results
result.successful.forEach(stream => {
console.log(`✓ Created stream: ${stream.id}`);
});
result.failed.forEach(error => {
console.error(`✗ Failed: ${error.message}`);
});
// Batch update streams
const updates = [
{ id: 'stream_1', title: 'Updated Title 1' },
{ id: 'stream_2', title: 'Updated Title 2' }
];
await wave.streams.batchUpdate(updates);Error Handling with Retry Logic
// Robust error handling with exponential backoff
async function retryableRequest(fn, maxRetries = 3) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error;
// Don't retry client errors (4xx)
if (error.status >= 400 && error.status < 500) {
throw error;
}
// Check if we should retry
if (attempt < maxRetries - 1) {
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
console.log(`Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError;
}
// Usage
const wave = new WaveClient({ apiKey: process.env.WAVE_API_KEY });
try {
const stream = await retryableRequest(() =>
wave.streams.create({
title: 'My Stream',
protocol: 'srt'
})
);
console.log('Stream created:', stream.id);
} catch (error) {
console.error('Failed after retries:', error.message);
// Handle failure (notify user, log to monitoring, etc.)
}Rate Limit Handling
// Respect rate limits with automatic backoff
class RateLimitedClient {
constructor(wave) {
this.wave = wave;
this.queue = [];
this.processing = false;
}
async request(fn) {
return new Promise((resolve, reject) => {
this.queue.push({ fn, resolve, reject });
this.processQueue();
});
}
async processQueue() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
const { fn, resolve, reject } = this.queue.shift();
try {
const result = await fn();
resolve(result);
} catch (error) {
if (error.status === 429) {
// Rate limited - respect Retry-After header
const retryAfter = parseInt(error.headers['retry-after']) || 60;
console.log(`Rate limited. Retrying after ${retryAfter}s`);
// Re-queue the request
this.queue.unshift({ fn, resolve, reject });
// Wait before processing next request
await new Promise(r => setTimeout(r, retryAfter * 1000));
} else {
reject(error);
}
}
this.processing = false;
this.processQueue();
}
}
// Usage
const wave = new WaveClient({ apiKey: process.env.WAVE_API_KEY });
const rateLimited = new RateLimitedClient(wave);
// All requests automatically respect rate limits
const stream1 = await rateLimited.request(() => wave.streams.create({...}));
const stream2 = await rateLimited.request(() => wave.streams.create({...}));GraphQL Complex Query
# Fetch nested stream data with analytics
query GetStreamWithAnalytics($streamId: ID!, $period: TimePeriod!) {
stream(id: $streamId) {
id
title
status
protocol
settings {
quality
bitrate
latency
}
# Current viewers
viewers {
total
byCountry {
country
count
}
}
# Analytics for specified period
analytics(period: $period) {
viewers {
peak
average
total
}
watchTime {
total
average
}
engagement {
likes
comments
shares
}
}
# Recording info
recordings {
id
duration
size
downloadUrl
createdAt
}
}
}
# JavaScript usage
const { GraphQLClient } = require('@wave/sdk');
const client = new GraphQLClient({
apiKey: process.env.WAVE_API_KEY
});
const data = await client.query(query, {
streamId: 'stream_abc123',
period: 'LAST_7_DAYS'
});
console.log('Stream:', data.stream.title);
console.log('Peak viewers:', data.stream.analytics.viewers.peak);
console.log('Total watch time:', data.stream.analytics.watchTime.total);Mobile SDK Initialization
// iOS - Swift
import WaveSDK
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Initialize WAVE SDK
Wave.configure(
apiKey: "your_api_key",
environment: .production,
options: WaveOptions(
enableAnalytics: true,
enableDebugLogging: false,
autoReconnect: true
)
)
return true
}
}
// Create and start stream
let streamManager = Wave.streams()
streamManager.create(
title: "My iOS Stream",
protocol: .webrtc,
quality: .hd1080p
) { result in
switch result {
case .success(let stream):
print("Stream created: \(stream.id)")
// Start broadcasting
streamManager.start(streamId: stream.id) { startResult in
if case .success = startResult {
print("Stream started successfully")
}
}
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}
// Android - Kotlin
import com.wave.sdk.Wave
import com.wave.sdk.WaveOptions
import com.wave.sdk.models.StreamProtocol
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize WAVE SDK
Wave.configure(
context = this,
apiKey = "your_api_key",
options = WaveOptions(
enableAnalytics = true,
enableDebugLogging = false,
autoReconnect = true
)
)
// Create stream
val streamManager = Wave.streams()
streamManager.create(
title = "My Android Stream",
protocol = StreamProtocol.WEBRTC,
quality = StreamQuality.HD_1080P
).subscribe { stream ->
println("Stream created: ${stream.id}")
// Start broadcasting
streamManager.start(stream.id).subscribe {
println("Stream started successfully")
}
}
}
}Server-Side Rendering Integration (Next.js)
// app/streams/[streamId]/page.tsx
import { WaveClient } from '@wave/sdk';
import { StreamPlayer } from '@/components/StreamPlayer';
import { DesignTokens, getContainer, getSection } from '@/lib/design-tokens';
// Server Component - fetch data at build/request time
export default async function StreamPage({
params
}: {
params: { streamId: string }
}) {
const wave = new WaveClient({
apiKey: process.env.WAVE_API_KEY
});
// Fetch stream data on server
const stream = await wave.streams.get(params.streamId);
if (!stream) {
notFound();
}
// Pre-fetch analytics for better UX
const analytics = await wave.analytics.getStreamStats(params.streamId);
return (
<div>
<h1>{stream.title}</h1>
{/* Player component (Client Component) */}
<StreamPlayer
streamId={stream.id}
playbackUrl={stream.playbackUrl}
protocol={stream.protocol}
/>
{/* Pre-rendered analytics */}
<div className="analytics">
<p>Current Viewers: {analytics.viewers}</p>
<p>Peak Viewers: {analytics.peakViewers}</p>
</div>
</div>
);
}
// Generate static params for ISR
export async function generateStaticParams() {
const wave = new WaveClient({ apiKey: process.env.WAVE_API_KEY });
const streams = await wave.streams.list({ limit: 100 });
return streams.data.map((stream) => ({
streamId: stream.id,
}));
}
// Revalidate every 60 seconds
export const revalidate = 60;Developer Resources
Everything you need to build with WAVE CONNECT
Interactive API Playground
Test API endpoints directly in your browser with live responses
Try Before You Integrate
Explore our complete API with an interactive playground. No setup required - authenticate with your API key and start making requests instantly.
Execute real API calls and see responses in real-time
Auto-generate code snippets in your preferred language
Test with your API key in a secure sandbox environment
Review and replay previous API calls for debugging
{
"data": [...],
"pagination": {
"total": 42,
"nextCursor": "..."
}
}Try our comprehensive API using cURL, Postman, or any HTTP client. All 500+ endpoints are documented with examples.
Frequently Asked Questions
Everything you need to know about CONNECT
Why do I need CONNECT if PIPELINE supports protocols?
CONNECT adds advanced protocol interoperability, programmatic API access, webhooks for automation, and custom application development. While PIPELINE handles the streaming infrastructure, CONNECT lets you build custom experiences on top. Create your own player UI, integrate with existing apps, automate workflows with webhooks, and access detailed control that is not available in the dashboard. Think of PIPELINE as the engine and CONNECT as the steering wheel for developers.
What programming languages do you support?
We provide official SDKs for JavaScript/TypeScript, Python, Go, Swift (iOS), and Kotlin (Android). Our REST API works with any language that supports HTTP. Community SDKs exist for PHP, Ruby, C#, and Rust. GraphQL endpoint available for flexible querying. WebSocket API for real-time bidirectional communication. All SDKs are open-source on GitHub with comprehensive documentation and examples.
What's the API rate limit?
Starter plans: 100 requests/minute. Professional plans: 1000 requests/minute. Enterprise plans: custom limits (10K+ req/min available). Rate limits apply per API key. Burst protection allows temporary spikes. WebSocket connections count separately (unlimited messages per connection). Contact sales if you need higher limits. All plans include unlimited webhook deliveries. Rate limit headers included in every response.
Can I build my own streaming UI?
Yes, CONNECT provides complete SDK for custom player and producer interfaces. Build web players with our JavaScript SDK. Create native mobile players with iOS/Android SDKs. Customize every aspect of the viewing experience. Add your branding, custom controls, and features. Player SDK handles all protocol complexity (HLS, DASH, WebRTC). Includes support for DRM, analytics tracking, quality selection, and more. White-label solution available for Enterprise.
Do you support webhooks for automation?
Yes, CONNECT provides 15+ webhook events including stream.started, stream.ended, stream.error, viewer.joined, viewer.left, recording.ready, transcode.completed, and more. Webhooks deliver JSON payloads to your endpoint within 100ms of events. Automatic retry with exponential backoff. Signature verification for security. Test webhooks with our CLI tool. Perfect for triggering notifications, updating databases, or integrating with other services.
What's the difference between REST API and WebSocket?
REST API is for configuration and control operations (create/update/delete streams, fetch analytics, manage users). Use REST for CRUD operations and data retrieval. WebSocket API is for real-time events and bidirectional communication (live viewer counts, chat messages, real-time quality adjustments). WebSocket maintains persistent connection for instant updates. Both APIs use the same authentication. Choose REST for occasional operations, WebSocket for continuous real-time data.
What Developers Say About CONNECT
Build anything with WAVE CONNECT
TechCorp Global
Enterprise Integration
“CONNECT APIs let us integrate WAVE into our enterprise portal seamlessly. The SDK saved us months of development time building custom video features.”
Lisa Anderson
VP of IT Infrastructure
Control Everything
CONNECT provides API access to the entire WAVE platform
PIPELINE
Control PIPELINE streams programmatically. Create, start, stop, and monitor streams via API.
View Stream Control APIsVAULT
Manage VAULT content via API. Upload, transcode, organize, and deliver videos programmatically.
Explore Content Management APIsPULSE
Access PULSE analytics via API. Build custom dashboards, reports, and data integrations.
View Analytics APIsReady to Build with WAVE?
Get your API key and start building in minutes