Skip to main content
API Documentation

API Integration Guide

Complete developer reference for WAVE Streaming API

Version 1.0Updated November 202545-55 min read

API Overview

Base URLs

EnvironmentBase URLPurpose
Productionhttps://api.wave.av/v1Live production traffic
Staginghttps://api-staging.wave.av/v1Pre-production testing
Sandboxhttps://api-sandbox.wave.av/v1Development and testing

API Characteristics

REST-based

Standard HTTP methods (GET, POST, PUT, PATCH, DELETE) with JSON format

Idempotent

Safe to retry POST/PUT/DELETE operations with idempotency keys

Versioned

API version in URL path (/v1, /v2) ensures backward compatibility

Rate Limited

Tiered rate limits based on plan with burst allowances

Authentication

API Key Authentication

Primary authentication method for server-to-server integrations using Bearer tokens.

# Generate API Key
1. Log in to https://dashboard.wave.av
2. Navigate to Settings > API Keys
3. Click "Create API Key"
4. Copy and store securely (shown only once!)

# Usage: Bearer token (RECOMMENDED)
curl -X GET https://api.wave.av/v1/streams \
  -H "Authorization: Bearer wave_live_abc123xyz789" \
  -H "Content-Type: application/json"

# Alternative: Custom header
curl -X GET https://api.wave.av/v1/streams \
  -H "X-API-Key: wave_live_abc123xyz789"

JavaScript Example

const WAVE_API_KEY = process.env.WAVE_API_KEY;

async function fetchStreams() {
  const response = await fetch('https://api.wave.av/v1/streams', {
    headers: {
      'Authorization': `Bearer ${WAVE_API_KEY}`,
      'Content-Type': 'application/json'
    }
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  const data = await response.json();
  return data.streams;
}

Python Example

import os
import requests

WAVE_API_KEY = os.environ.get('WAVE_API_KEY')

def fetch_streams():
    headers = {
        'Authorization': f'Bearer {WAVE_API_KEY}',
        'Content-Type': 'application/json'
    }

    response = requests.get(
        'https://api.wave.av/v1/streams',
        headers=headers
    )

    response.raise_for_status()
    return response.json()['streams']

Streams API

Create Stream

POST /v1/streams

{
  "title": "Product Launch Event",
  "description": "Live product unveiling",
  "protocol": "webrtc",
  "quality": {
    "resolution": "1080p",
    "bitrate": 5000,
    "frameRate": 30
  },
  "recording": {
    "enabled": true,
    "format": "mp4"
  },
  "privacy": "public"
}

# Response
{
  "stream": {
    "id": "str_abc123",
    "title": "Product Launch Event",
    "status": "ready",
    "ingest": {
      "url": "webrtc://ingest.wave.av/str_abc123",
      "streamKey": "live_xyz789"
    },
    "playback": {
      "url": "https://stream.wave.av/str_abc123",
      "embedCode": "<iframe src=\"...\"></iframe>"
    },
    "createdAt": "2025-11-16T10:00:00Z"
  }
}

List Streams

GET /v1/streams?status=live&limit=20&offset=0

# Response
{
  "streams": [
    {
      "id": "str_abc123",
      "title": "Product Launch Event",
      "status": "live",
      "viewers": 1234,
      "duration": 3600
    }
  ],
  "pagination": {
    "total": 45,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  }
}

Update Stream

PATCH /v1/streams/str_abc123

{
  "title": "Updated Title",
  "privacy": "private"
}

# Response
{
  "stream": {
    "id": "str_abc123",
    "title": "Updated Title",
    "privacy": "private",
    "updatedAt": "2025-11-16T11:00:00Z"
  }
}

Start/Stop Stream

POST /v1/streams/str_abc123/start
POST /v1/streams/str_abc123/stop

# Response
{
  "stream": {
    "id": "str_abc123",
    "status": "live",  // or "ended"
    "startedAt": "2025-11-16T12:00:00Z"
  }
}

Productions API

Multi-camera productions with scene switching, composition, and real-time graphics.

Create Production

POST /v1/productions

{
  "name": "Studio Production",
  "cameras": [
    {
      "id": "cam1",
      "label": "Main Camera",
      "source": "rtmp://input.wave.av/cam1"
    },
    {
      "id": "cam2",
      "label": "Close-up",
      "source": "rtmp://input.wave.av/cam2"
    }
  ],
  "scenes": [
    {
      "id": "scene1",
      "name": "Full Screen Main",
      "layout": "single",
      "cameras": ["cam1"]
    },
    {
      "id": "scene2",
      "name": "Picture-in-Picture",
      "layout": "pip",
      "cameras": ["cam1", "cam2"]
    }
  ],
  "output": {
    "streamId": "str_abc123"
  }
}

# Response
{
  "production": {
    "id": "prod_xyz789",
    "name": "Studio Production",
    "status": "ready",
    "activeScene": "scene1"
  }
}

Switch Scene

POST /v1/productions/prod_xyz789/switch-scene

{
  "sceneId": "scene2",
  "transition": {
    "type": "fade",
    "duration": 500
  }
}

# Response
{
  "production": {
    "id": "prod_xyz789",
    "activeScene": "scene2",
    "previousScene": "scene1"
  }
}

Analytics API

Real-Time Metrics

GET /v1/analytics/streams/str_abc123/realtime

# Response
{
  "metrics": {
    "currentViewers": 1234,
    "peakViewers": 2500,
    "averageBitrate": 4500,
    "bufferRatio": 0.02,
    "qualityScore": 98.5,
    "geographicDistribution": {
      "US": 45.2,
      "EU": 32.8,
      "ASIA": 22.0
    }
  },
  "timestamp": "2025-11-16T12:00:00Z"
}

Historical Analytics

GET /v1/analytics/streams/str_abc123/historical
  ?from=2025-11-01
  &to=2025-11-16
  &granularity=day

# Response
{
  "data": [
    {
      "date": "2025-11-01",
      "totalViewers": 5234,
      "averageWatchTime": 1800,
      "peakConcurrent": 1234,
      "totalWatchHours": 9234
    }
  ],
  "summary": {
    "totalViewers": 45234,
    "totalWatchHours": 123456,
    "averageEngagement": 0.78
  }
}

WebSocket & Real-Time Events

Subscribe to real-time stream events via WebSocket for live updates.

Connect to WebSocket

const ws = new WebSocket('wss://ws.wave.av/v1');

ws.on('open', () => {
  // Authenticate
  ws.send(JSON.stringify({
    type: 'auth',
    token: 'wave_live_abc123xyz789'
  }));

  // Subscribe to stream events
  ws.send(JSON.stringify({
    type: 'subscribe',
    channel: 'stream:str_abc123'
  }));
});

ws.on('message', (data) => {
  const event = JSON.parse(data);

  switch (event.type) {
    case 'viewer.joined':
      console.log('New viewer:', event.data);
      break;
    case 'stream.quality.changed':
      console.log('Quality changed:', event.data);
      break;
    case 'stream.ended':
      console.log('Stream ended');
      break;
  }
});

Event Types

EventDescription
stream.startedStream went live
stream.endedStream stopped
viewer.joinedNew viewer connected
viewer.leftViewer disconnected
stream.quality.changedQuality settings updated

Webhooks

Receive HTTP POST notifications when events occur on your streams.

Configure Webhook

POST /v1/webhooks

{
  "url": "https://yourdomain.com/webhooks/wave",
  "events": [
    "stream.started",
    "stream.ended",
    "stream.error",
    "recording.ready"
  ],
  "secret": "webhook_secret_abc123"
}

# Response
{
  "webhook": {
    "id": "wh_xyz789",
    "url": "https://yourdomain.com/webhooks/wave",
    "events": ["stream.started", "stream.ended", ...],
    "status": "active"
  }
}

Handle Webhook (Node.js)

const crypto = require('crypto');

app.post('/webhooks/wave', (req, res) => {
  // Verify signature
  const signature = req.headers['x-wave-signature'];
  const body = JSON.stringify(req.body);
  const secret = process.env.WEBHOOK_SECRET;

  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');

  if (signature !== expectedSignature) {
    return res.status(401).send('Invalid signature');
  }

  // Handle event
  const { event, data } = req.body;

  switch (event) {
    case 'stream.started':
      console.log('Stream started:', data.streamId);
      break;
    case 'recording.ready':
      console.log('Recording ready:', data.recordingUrl);
      break;
  }

  res.status(200).send('OK');
});

SDKs & Client Libraries

JavaScript/TypeScript SDK

# Installation
npm install @wave/sdk

# Usage
import { WaveClient } from '@wave/sdk';

import { DesignTokens, getContainer, getSection } from '@/lib/design-tokens';
const wave = new WaveClient({
  apiKey: process.env.WAVE_API_KEY,
  environment: 'production'
});

// Create stream
const stream = await wave.streams.create({
  title: 'My Stream',
  protocol: 'webrtc'
});

// Start stream
await wave.streams.start(stream.id);

// Get analytics
const metrics = await wave.analytics.getRealtime(stream.id);

Python SDK

# Installation
pip install wave-sdk

# Usage
from wave import WaveClient

wave = WaveClient(
    api_key=os.environ.get('WAVE_API_KEY'),
    environment='production'
)

# Create stream
stream = wave.streams.create(
    title='My Stream',
    protocol='webrtc'
)

# Start stream
wave.streams.start(stream['id'])

# Get analytics
metrics = wave.analytics.get_realtime(stream['id'])

Integration Best Practices

Security

  • • Never expose API keys in client-side code
  • • Use environment variables for secrets
  • • Rotate API keys regularly (quarterly)
  • • Implement webhook signature verification
  • • Use HTTPS for all API communication

Performance

  • • Implement exponential backoff for retries
  • • Cache API responses when appropriate
  • • Use pagination for large result sets
  • • Batch operations when possible
  • • Monitor rate limit headers

Reliability

  • • Implement comprehensive error handling
  • • Use idempotency keys for critical operations
  • • Set appropriate timeouts (30s for API calls)
  • • Log all API interactions for debugging
  • • Test failure scenarios regularly

Monitoring

  • • Track API latency and success rates
  • • Set up alerts for API errors
  • • Monitor webhook delivery status
  • • Review analytics regularly
  • • Use structured logging

Related Guides

API Integration Guide | WAVE Resources