Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.streampixel.io/llms.txt

Use this file to discover all available pages before exploring further.

The outcome: a Streampixel deployment where your API keys aren’t on a Pastebin, your stream isn’t being embedded by random sites, your webhook endpoint isn’t being spoofed, and a leaked credential is contained in minutes instead of months. This recipe assumes you have already shipped a working integration. It walks through the threats you should care about and the controls that mitigate each.

Threat model

The realistic risks for a typical Streampixel deployment:
ThreatImpactMitigation
API key leaked in client code or git historyAttacker uploads/distributes builds, runs up your billServer-side only, rotate immediately
Stream embedded on unauthorized sitesBrand misuse, traffic costsDomain whitelisting
Webhook spoofingAttacker triggers your downstream actionsSecret-token URL, payload validation
Unbounded session usageBill shock, worker exhaustionSession limits, rate limiting your endpoint
Stale team members with admin accessInsider risk after departuresPeriodic role audits
Credentials shoulder-surfed in screen-shared logsSubtle but commonMask in CI logs, env vars
The rest of the recipe walks through controls in order of impact.

API key hygiene

Keep keys server-side

API keys must never appear in any code that ships to a browser, mobile app, or anywhere a user can crack open dev tools. The Web SDK does not need an API key to render a stream — it uses your appId. Only server-to-server calls (upload, distribute, webhooks) use the API key.
Browser  ->  appId only  ->  Streampixel
Server   ->  apiKey      ->  Streampixel
If you find yourself writing apiKey: "sk_..." in a .html, .jsx, or anything bundled to the client, stop and rotate.

Use environment variables

# .env (gitignored)
STREAMPIXEL_API_KEY=...
STREAMPIXEL_USER_ID=...
STREAMPIXEL_PROJECT_ID=...
// server.js
const apiKey = process.env.STREAMPIXEL_API_KEY;
if (!apiKey) throw new Error('STREAMPIXEL_API_KEY not set');
Never commit .env. Add it to .gitignore on day one. Use a secret manager (AWS Secrets Manager, GCP Secret Manager, Vault, Doppler) for production.

Rotation

Treat key rotation as a fire drill you should be able to run in under five minutes:
1

Generate a new key

In the API Keys dashboard, create a fresh key.
2

Roll out the new value

Update your secret manager / env vars. Restart workers so they pick up the new key.
3

Revoke the old key

Once you’ve confirmed the new key is in use (one successful upload or distribute call), revoke the old one in the dashboard.
4

Audit

Check recent build uploads / distribute calls for any activity you don’t recognize.
If you ever push a key to a public repo, rotate first, scrub history second. Bots scrape new commits within minutes — assume the key is already compromised.
Force-pushing to overwrite history does not retroactively unbreach a leaked secret. GitHub’s secret scanning, third-party caches, and search engines may have already indexed it. Rotate, then clean up.

Project-level access control

Streampixel projects have built-in access controls. See Security control for the full settings reference. The two most useful settings:
  • Allowed domains — only the domains you list can host the stream. This is the single most effective control against unauthorized embedding.
  • Password protection — gate the stream behind a project password, useful for private demos.
Set both for any project not intended for fully public access.

Domain whitelisting for embeds

The Web SDK validates window.location.origin against the project’s allowed URLs list. Misconfigured domains are the #1 reason “the stream works locally but not in production” support tickets get filed.
PatternMatches
https://app.example.comExactly that host
*.example.comAny subdomain of example.com
localhostAlways allowed for development
Add staging domains separately from production. staging.example.com is not the same as example.com.

Webhook security

Streampixel webhooks do not currently include a signature header. There is no HMAC, no shared secret in headers, no signed token. If your webhook URL is https://example.com/streampixel-webhook, anyone who guesses that URL can POST a fake build.approved event. Treat this seriously. Mitigations:

1. Use a long random token in the URL path

Make the URL itself the secret. Generate 16+ random bytes, hex-encode, and include in the path:
openssl rand -hex 24
# 9f3a4c1ee21b4f2c8d76b0a3e9f128cc4a1b7d9e5f0c2a83
Register the URL with that token in the dashboard:
https://example.com/webhooks/streampixel/9f3a4c1ee21b4f2c8d76b0a3e9f128cc4a1b7d9e5f0c2a83
In your handler, only accept POSTs to that exact path. Any request to /webhooks/streampixel or to a wrong-token path returns 404. This makes the webhook URL effectively a shared secret — keep it out of logs and chat messages.

2. Validate the payload matches what you expect

const KNOWN_PROJECT_IDS = new Set([process.env.STREAMPIXEL_PROJECT_ID]);

app.post(WEBHOOK_PATH, (req, res) => {
  res.status(200).end();

  const { event, data } = req.body || {};
  if (!event || !data) return;

  // Ignore events for projects this server doesn't own.
  if (!KNOWN_PROJECT_IDS.has(data.projectId)) {
    console.warn('Unexpected projectId:', data.projectId);
    return;
  }

  // Ignore events with unknown event names.
  const VALID = new Set([
    'build.uploaded', 'build.downloading', 'build.extracting',
    'build.saving', 'build.distributing', 'build.approved', 'build.rejected',
  ]);
  if (!VALID.has(event)) return;

  handleEvent(event, data);
});
If a forged request arrives, the projectId check stops it from triggering downstream actions even if the URL token leaked.

3. Don’t log the webhook URL

Audit your logging. Many frameworks log the full request URL by default; if your webhook URL contains the secret token, that token ends up in log aggregators, error monitoring services, and screen captures.
// Express example: replace req.url in logs
app.use((req, res, next) => {
  if (req.path.startsWith('/webhooks/streampixel/')) {
    res.locals.loggedPath = '/webhooks/streampixel/[redacted]';
  }
  next();
});

4. Respond fast, work async

Streampixel webhook delivery times out at 10 seconds and does not retry. If your handler does heavy work synchronously and exceeds that window, the event is lost. Always:
app.post(WEBHOOK_PATH, (req, res) => {
  res.status(200).end();         // ack immediately
  enqueueAsync(req.body);         // process in background
});

Rate limiting your own endpoints

Any endpoint you expose that triggers Streampixel calls (say, “Reset my project” buttons in your admin UI) should be rate-limited. Otherwise a misbehaving script or a bored user can hammer Streampixel APIs and exhaust your quotas.
import rateLimit from 'express-rate-limit';

app.use('/api/admin', rateLimit({
  windowMs: 60 * 1000,
  max: 30,
  standardHeaders: true,
}));
The distribute endpoint already enforces 1 call per 2 minutes per user; surface that limit gracefully to your admins instead of letting them retry into errors.

TLS everywhere

There is no good reason to run any part of this over HTTP in production:
  • The Web SDK requires HTTPS for getUserMedia (microphone, camera) and WebXR.
  • API calls go to https://api.streampixel.io/... regardless.
  • Webhook listeners must be HTTPS — Streampixel will not deliver to plain HTTP URLs.
Use Let’s Encrypt, Cloudflare, or your platform’s automatic TLS. There is no excuse.

Content Security Policy for embeds

If you embed Streampixel via iframe, set a CSP that allows the player and nothing else:
Content-Security-Policy: default-src 'self';
  frame-src https://streampixel.io https://*.streampixel.io;
  connect-src 'self' https://api.streampixel.io https://*.streampixel.io wss://*.streampixel.io;
  media-src 'self' blob:;
If you serve the SDK from your own page (not iframe), add script-src and the relevant SDK origins. Test thoroughly — a too-restrictive CSP breaks WebRTC media in non-obvious ways.

Auditing team members

Regularly review who has access to your Streampixel account:
1

List active members

Open the team / members page in the dashboard. Note everyone with admin or developer roles.
2

Reconcile against your HR list

Anyone who left the company in the last 90 days should not be there.
3

Reduce privileges

Apply least-privilege: people who only need to view stats don’t need keys.
4

Rotate keys after offboarding

If a departed member ever had access to API keys, rotate them.
A quarterly cadence is a sensible minimum.

Compliance

Streampixel encrypts data in transit (HTTPS / DTLS-SRTP for WebRTC). For compliance work — SOC 2, GDPR, processing agreements — contact the Streampixel team directly; this recipe is engineering-focused and intentionally avoids making compliance claims.

Pre-flight checklist

Before going to production, confirm:
  • No API key exists in any client-side code, including JS bundles served to browsers.
  • .env is in .gitignore. Run git log -p -- .env and git log --all -p -S "STREAMPIXEL_API_KEY" to confirm none has ever been committed.
  • Allowed domains list in the dashboard contains only your real production and staging hosts.
  • Webhook URL contains a 24+ byte random token in the path.
  • Webhook handler validates projectId and event name.
  • Webhook handler returns 200 within ~1 second.
  • All endpoints are HTTPS.
  • Team member list reviewed in the last 90 days.
  • You have a documented runbook for “API key leaked, what now.”

Next steps

API keys

Manage and rotate your API keys.

Security control

Project-level password and domain restrictions.

Webhooks

All seven events and payload shapes.

CI/CD pipeline

A reference webhook listener with the patterns above.