Authentication & API Keys
Manage Skytells API keys securely across dev, staging, and production — environment separation, rotation strategy, and server-side-only patterns.
What you'll be able to do after this module
Set up a bulletproof key management strategy that prevents the most common (and costly) security mistakes: leaked keys, shared keys, and client-side key exposure.
The one rule
Your API key = your billing account. Anyone who has it can generate predictions at your expense. Treat it exactly like a password — or a credit card number.
How authentication works
Every Skytells request requires the x-api-key header:
curl https://api.skytells.ai/v1/predictions \
-H "x-api-key: $SKYTELLS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "truefusion-pro", "input": {"prompt": "test"}}'Environment separation
Create one key per environment
Go to Dashboard → API Keys and create three keys:
| Key name | Used in |
|---|---|
dev-local | Your .env.local |
staging | Your staging server |
production | Your production server only |
If a dev key leaks, your production traffic is unaffected. If staging is breached, production is still safe.
Store each key in the right environment variable
# .env.local — development only, git-ignored
SKYTELLS_API_KEY=sk-dev-...Add .env files to .gitignore
echo ".env*.local" >> .gitignore
echo ".env.staging" >> .gitignore
git add .gitignore && git commit -m "ignore env files"Using os.getenv("KEY") in Python returns None silently if the variable is missing — causing confusing auth errors. Use os.environ["KEY"] instead. It raises KeyError at startup if the variable is absent, which is far easier to debug.
Never expose keys to the browser
If your API key is included in a client-side bundle, anyone with browser DevTools can extract it and use it. Never use API keys in React components, browser fetch calls, or mobile apps.
The correct architecture:
Browser / App → Your API route → Skytells API// app/page.tsx — THIS IS WRONG
// NEXT_PUBLIC_ prefix means this value is embedded in the browser bundle
const prediction = await fetch('https://api.skytells.ai/v1/predictions', {
headers: { 'x-api-key': process.env.NEXT_PUBLIC_SKYTELLS_API_KEY }
});Key rotation
Rotate your API keys at least every 90 days, or immediately after any suspected exposure.
Create a new key
In Dashboard → API Keys, generate a new key with the same name + a version suffix: production-v2.
Update your environment variables
Update the key in your hosting platform's secrets manager (Vercel, AWS Secrets Manager, etc.). Do not deploy yet.
Deploy
Deploy the change. Your app now uses the new key.
Verify
Watch your logs for 5 minutes. Confirm requests succeed with the new key.
Revoke the old key
In the Dashboard, revoke production-v1. Any rogue processes still using the old key will immediately get 401 Unauthorized — which you'll see in your monitoring.
Zero-downtime rotation: Update the secret first, then deploy. At no point is there a gap where no valid key exists. If the deployment fails, roll back — your old key is still active until you explicitly revoke it.
Per-user rate limiting
Your Skytells account has a rate limit. If many users hit your app simultaneously, they compete for that shared quota. Protect yourself with per-user rate limiting in your backend:
import { RateLimiter } from 'limiter';
// 10 predictions per minute per user
const limiters = new Map<string, RateLimiter>();
function getUserLimiter(userId: string) {
if (!limiters.has(userId)) {
limiters.set(
userId,
new RateLimiter({ tokensPerInterval: 10, interval: 'minute' })
);
}
return limiters.get(userId)!;
}
export async function generateForUser(userId: string, prompt: string) {
const remaining = await getUserLimiter(userId).removeTokens(1);
if (remaining < 0) {
throw new Error('Your generation limit (10/min) has been reached. Please wait.');
}
return client.predictions.create({ model: 'truefusion-pro', input: { prompt } });
}Audit logging
Log every prediction your backend creates. This data is essential for debugging, cost attribution, and detecting abuse:
interface PredictionAuditLog {
timestamp: string;
userId: string;
predictionId: string;
model: string;
status: 'created' | 'succeeded' | 'failed';
latencyMs?: number;
costUsd?: number;
ipAddress?: string;
}
// Call this when you create a prediction
function logPrediction(log: PredictionAuditLog) {
// Send to your logging system (Datadog, Logtail, CloudWatch, etc.)
console.log(JSON.stringify({ event: 'prediction', ...log }));
}Security checklist
Summary
Your key management is now hardened against the most common attack vectors.
The five patterns that matter most:
- One key per environment — dev, staging, prod are isolated
- Server-side only — keys never reach the browser
- Environment variables — keys are never in source code
- Per-user rate limits — protect your quota from abuse
- Audit every prediction — logging enables debugging and cost attribution
Next: webhooks — the right way to handle async predictions in production.
Building Production Apps
Everything between "it works on my machine" and "it handles 10,000 users without breaking" — auth, webhooks, rate limits, and the Edge API.
Webhooks
Implement reliable webhook handling — signature verification, idempotency, async processing, and a complete production webhook receiver.