Authentication
All API requests to the MLM Platform require authentication using a tenant API key.
API keys are passed in the x-tenant-api-key HTTP header:
x-tenant-api-key: mlm_live_abc123...
Key Types
| Prefix | Environment | Usage |
|---|
mlm_live_ | LIVE | Production data |
mlm_sandbox_ | SANDBOX | Testing and development |
Never use LIVE keys in development or testing environments.
Creating API Keys
- Navigate to Settings > API Keys in the Admin Dashboard
- Click Create API Key
- Select the environment (LIVE or SANDBOX)
- Add an optional description
- Click Create
API keys are shown only once at creation. Store them securely.
Security Best Practices
Never Expose Keys Client-Side
API keys should only be used in server-side code:
// BAD - Never do this in browser code
const response = await fetch('/api/users', {
headers: {
'x-tenant-api-key': 'mlm_live_abc123' // Exposed to users!
}
});
// GOOD - Use a server-side proxy
// Client calls your backend
const response = await fetch('/api/proxy/users');
// Your backend adds the API key
// server.js
app.post('/api/proxy/users', async (req, res) => {
const response = await fetch('https://api.mlm-platform.example.com/functions/v1/users', {
headers: {
'x-tenant-api-key': process.env.MLM_API_KEY // Secure!
},
body: JSON.stringify(req.body)
});
res.json(await response.json());
});
Use Environment Variables
Store API keys in environment variables:
# .env (never commit this file)
MLM_API_KEY=mlm_live_abc123...
MLM_SANDBOX_API_KEY=mlm_sandbox_xyz789...
// Use environment variables
const apiKey = process.env.NODE_ENV === 'production'
? process.env.MLM_API_KEY
: process.env.MLM_SANDBOX_API_KEY;
Rotate Keys Regularly
- Create a new API key
- Update your application to use the new key
- Verify the new key works
- Revoke the old key
Monitor Key Usage
Review API key usage in the Admin Dashboard:
- Request counts
- Error rates
- Last used timestamp
Environment Detection
Every API response includes an X-Environment header:
or
Use this to verify you’re hitting the correct environment:
const response = await fetch('/api/users', {
headers: { 'x-tenant-api-key': apiKey }
});
const environment = response.headers.get('X-Environment');
if (environment !== expectedEnvironment) {
console.warn(`Unexpected environment: ${environment}`);
}
Error Responses
Missing API Key
{
"error": "Missing API key",
"code": "UNAUTHORIZED"
}
Invalid API Key
{
"error": "Invalid API key",
"code": "UNAUTHORIZED"
}
Revoked API Key
{
"error": "API key has been revoked",
"code": "UNAUTHORIZED"
}
Rate Limiting
API keys are subject to rate limiting:
| Response Header | Description |
|---|
X-RateLimit-Limit | Maximum requests per window |
X-RateLimit-Remaining | Requests remaining |
X-RateLimit-Reset | Unix timestamp when limit resets |
When rate limited, you’ll receive a 429 Too Many Requests response:
{
"error": "Rate limit exceeded. Try again in 60 seconds.",
"code": "RATE_LIMITED"
}
Handle rate limits gracefully:
async function makeRequest(url, options, retries = 3) {
const response = await fetch(url, options);
if (response.status === 429 && retries > 0) {
const retryAfter = response.headers.get('Retry-After') || 60;
await new Promise(r => setTimeout(r, retryAfter * 1000));
return makeRequest(url, options, retries - 1);
}
return response;
}