Skip to main content
← Back to Quickstart Guides

API Authentication

Secure access with API keys, OAuth 2.0, and JWT tokens

10 minutes
Beginner to Advanced
Security
3
Auth Methods
15+
API Scopes
4
Rate Limit Tiers
256-bit
Encryption

Choose Your Authentication Method

Select the method that best fits your use case and security requirements

API Keys

Security: High

Server-to-server authentication for backend applications

Best for:
Backend services
CI/CD pipelines
Server scripts
Scheduled jobs
Expiration: Configurable (30-365 days)

OAuth 2.0

Security: Very High

User-delegated access for third-party applications

Best for:
Third-party integrations
User-facing apps
Mobile applications
Partner APIs
Expiration: Access: 1h, Refresh: 30d

JWT Tokens

Security: High

Short-lived tokens for session-based authentication

Best for:
Web applications
Single-page apps
Real-time features
WebSocket connections
Expiration: 15 minutes - 24 hours

API Key Authentication

Generate and manage API keys for server-to-server communication

1Generate API Key

POST https://api.wave.inc/v1/auth/keys
Authorization: Bearer <your-session-token>
Content-Type: application/json

{
  "name": "Production API Key",
  "scopes": ["streams:read", "streams:write", "analytics:read"],
  "expires_in_days": 90,
  "allowed_ips": ["192.168.1.0/24"],  // Optional IP allowlist
  "metadata": {                        // Optional custom metadata
    "environment": "production",
    "service": "stream-manager"
  }
}

Response:
{
  "api_key": {
    "id": "key_abc123xyz789",
    "key": "wave_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "name": "Production API Key",
    "scopes": ["streams:read", "streams:write", "analytics:read"],
    "rate_limit_tier": "pro",
    "expires_at": "2026-02-01T00:00:00Z",
    "created_at": "2025-11-01T00:00:00Z",
    "last_used_at": null
  },
  "warning": "Save this API key securely - it will not be shown again!"
}

2Use API Key in Requests

# Include in Authorization header
Authorization: Bearer wave_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

# Example request
curl -X GET "https://api.wave.inc/v1/streams" \
  -H "Authorization: Bearer wave_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json"

Key Rotation

# Rotate a key (creates new key, marks old as deprecated)
POST https://api.wave.inc/v1/auth/keys/{key_id}/rotate
Authorization: Bearer <session-token>

{
  "grace_period_hours": 24  // Old key works for 24h
}

Response:
{
  "new_key": {
    "id": "key_new123xyz",
    "key": "wave_live_newkeyxxxxxxxxxxxxxxxxxx"
  },
  "old_key": {
    "id": "key_abc123xyz789",
    "deprecated_at": "2025-11-01T00:00:00Z",
    "expires_at": "2025-11-02T00:00:00Z"  // 24h grace period
  }
}

OAuth 2.0 Authentication

Implement user-delegated access for third-party applications

1Register Application

Create an OAuth application in the WAVE Developer Portal

// Application configuration
{
  "name": "My Integration",
  "redirect_uris": [
    "https://myapp.com/callback",
    "http://localhost:3000/callback"  // For development
  ],
  "scopes": ["streams:read", "streams:write", "analytics:read"]
}

2Authorization Request

Redirect users to WAVE authorization endpoint

const authUrl = new URL('https://auth.wave.inc/oauth/authorize');
authUrl.searchParams.set('client_id', CLIENT_ID);
authUrl.searchParams.set('redirect_uri', 'https://myapp.com/callback');
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'streams:read streams:write');
authUrl.searchParams.set('state', generateSecureState());

// For mobile apps, use PKCE
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
authUrl.searchParams.set('code_challenge', codeChallenge);
authUrl.searchParams.set('code_challenge_method', 'S256');

window.location.href = authUrl.toString();

3Handle Callback

Exchange authorization code for tokens

// User redirected to: https://myapp.com/callback?code=xxx&state=xxx

// Verify state to prevent CSRF
if (params.state !== savedState) {
  throw new Error('Invalid state parameter');
}

// Exchange code for tokens
const response = await fetch('https://auth.wave.inc/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET,
    code: params.code,
    redirect_uri: 'https://myapp.com/callback',
    code_verifier: codeVerifier  // For PKCE
  })
});

const { access_token, refresh_token, expires_in } = await response.json();

4Refresh Tokens

Use refresh token to get new access tokens

// Before access token expires, refresh it
const response = await fetch('https://auth.wave.inc/oauth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'refresh_token',
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET,
    refresh_token: savedRefreshToken
  })
});

const { access_token, refresh_token, expires_in } = await response.json();
// Store new tokens securely

API Scopes Reference

Granular permissions for controlling API access

Streams Scopes

ScopeDescriptionEndpointsRisk
streams:readView stream configurations and statusGET /v1/streams, GET /v1/streams/:id
Low
streams:writeCreate, update, and delete streamsPOST /v1/streams, PUT /v1/streams/:id, DELETE /v1/streams/:id
Medium
streams:broadcastStart and stop live broadcastsPOST /v1/streams/:id/start, POST /v1/streams/:id/stop
Medium
streams:recordingsAccess and manage stream recordingsGET /v1/recordings, DELETE /v1/recordings/:id
Medium

Analytics Scopes

ScopeDescriptionEndpointsRisk
analytics:readView streaming analytics and metricsGET /v1/analytics/*
Low
analytics:exportExport analytics data in bulkPOST /v1/analytics/export
Low
analytics:realtimeAccess real-time viewer statisticsWS /v1/analytics/realtime
Low

Users Scopes

ScopeDescriptionEndpointsRisk
users:readView user profiles and preferencesGET /v1/users, GET /v1/users/:id
Low
users:writeUpdate user profilesPUT /v1/users/:id
Medium
users:adminManage team members and permissionsPOST /v1/users, DELETE /v1/users/:id
High

Billing Scopes

ScopeDescriptionEndpointsRisk
billing:readView invoices and usageGET /v1/billing/*
Low
billing:writeUpdate payment methods and subscriptionsPUT /v1/billing/*
High

Webhooks Scopes

ScopeDescriptionEndpointsRisk
webhooks:readView webhook configurationsGET /v1/webhooks
Low
webhooks:writeCreate and manage webhooksPOST /v1/webhooks, PUT /v1/webhooks/:id
Medium
Special Scopes
  • *All permissions (admin only, use with caution)
  • offline_accessIssue refresh tokens for long-lived access (OAuth only)
  • openid profile emailOpenID Connect scopes for user identity

Rate Limits

Request limits by subscription tier with burst and concurrent limits

TierRequests/minBurst/secConcurrentBandwidth
Free60/min10/sec5100 GB/month
Pro300/min50/sec251 TB/month
Business1,000/min100/sec10010 TB/month
Enterprise10,000/min500/sec500Unlimited
Rate Limit Headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 298
X-RateLimit-Reset: 1699876543
X-RateLimit-Retry-After: 45
X-RateLimit-Policy: "300;w=60"
Handling 429 Responses
// Implement exponential backoff
const retryAfter = response.headers
  .get('X-RateLimit-Retry-After');
await sleep(parseInt(retryAfter) * 1000);

// Or use the SDK (handles automatically)
const wave = new WaveClient({
  apiKey: KEY,
  retryConfig: {
    maxRetries: 3,
    backoff: 'exponential'
  }
});

SDK Authentication Examples

Quick start examples for popular programming languages

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

// Initialize with API key
const wave = new WaveClient({
  apiKey: process.env.WAVE_API_KEY,
  // Optional: specify region for lower latency
  region: 'us-east-1',
});

// All requests are automatically authenticated
const streams = await wave.streams.list();
const stream = await wave.streams.create({
  name: 'My Live Stream',
  protocol: 'webrtc',
});

// For user-context operations (OAuth)
const waveUser = new WaveClient({
  accessToken: userAccessToken,
  refreshToken: userRefreshToken,
  onTokenRefresh: (tokens) => {
    // Store refreshed tokens
    saveTokens(tokens);
  },
});

Security Best Practices

Essential security guidelines for API authentication

Key Management

Use environment variables

Never hardcode API keys in source code. Use environment variables or secret managers.

process.env.WAVE_API_KEY
"wave_live_abc123..."
Separate keys per environment

Use different keys for development, staging, and production.

WAVE_API_KEY_PROD, WAVE_API_KEY_STAGING
Same key in all environments
Rotate keys regularly

Generate new keys every 90 days and revoke old ones.

Automated rotation with overlap period
Using same key for years

Scope Management

Minimal permissions

Request only the scopes your application needs.

["streams:read", "analytics:read"]
["*"] (all permissions)
Scope segregation

Use different keys for different parts of your application.

Read-only key for dashboard, write key for admin
One key with all permissions everywhere

Transport Security

Always use HTTPS

All API requests must use HTTPS. HTTP requests are rejected.

https://api.wave.inc/v1/streams
http://api.wave.inc/v1/streams
Validate TLS certificates

Never disable certificate verification in production.

Default TLS verification
NODE_TLS_REJECT_UNAUTHORIZED=0

Error Handling

Never expose keys in errors

Sanitize error messages before logging or displaying.

Log "Authentication failed" without key
Log full request including Authorization header
Handle 401/403 gracefully

Implement proper token refresh and re-authentication flows.

Automatic retry with refreshed token
Crash or expose error to user

Troubleshooting

Common authentication errors and how to resolve them

401 Unauthorized
invalid_token
Possible Causes:
  • API key is invalid or revoked
  • Token has expired
  • Missing Authorization header
Solutions:
  • Verify the API key is correct and active
  • Refresh the access token if using OAuth
  • Ensure header format is "Bearer <token>"
403 Forbidden
insufficient_scope
Possible Causes:
  • Key does not have required scope
  • Resource belongs to different organization
  • IP allowlist restriction
Solutions:
  • Check key scopes in Developer Portal
  • Use a key with appropriate permissions
  • Verify IP is in allowlist if enabled
429 Too Many Requests
rate_limit_exceeded
Possible Causes:
  • Exceeded requests per minute limit
  • Burst limit exceeded
  • Concurrent request limit hit
Solutions:
  • Implement exponential backoff
  • Check X-RateLimit-Reset header
  • Upgrade to higher tier if needed
400 Bad Request
invalid_grant
Possible Causes:
  • Authorization code expired (10 min)
  • Code already used
  • Redirect URI mismatch
Solutions:
  • Start OAuth flow again
  • Verify redirect_uri matches exactly
  • Check PKCE code_verifier is correct

API Key Management

Manage your API keys in the Developer Portal dashboard

Your API Keys
Production API Key
key_abc...7893 scopes
Last used: 2 hours ago
active
Staging API Key
key_stg...4565 scopes
Last used: 1 day ago
active
Old Production Key
key_old...1232 scopes
Last used: 30 days ago
deprecated
WAVE - Enterprise Live Streaming Platform