Authentication
Everything about API keys, scopes, sandbox keys, rate limits and security best practices.
Authentication
All API requests require authentication via an API key in the X-Api-Key header.
Create an API key
- Go to Settings → API Keys in your OptimoCMS dashboard
- Click Create API Key
- Give the key a descriptive name (e.g. "Production Backend", "CI/CD Pipeline")
- Select the desired scopes
- Copy the key — it is only shown once
Using your API key
REST API
curl https://api.optimocms.com/v1/sites \
-H "X-Api-Key: optimo_live_abc123def456"TypeScript SDK
import { OptimoCMS } from '@optimocms/sdk';
const cms = new OptimoCMS({
apiKey: process.env.OPTIMOCMS_API_KEY!,
});MCP configuration
{
"mcpServers": {
"optimocms": {
"command": "npx",
"args": ["-y", "@optimocms/mcp-server"],
"env": {
"OPTIMOCMS_API_KEY": "optimo_live_abc123def456"
}
}
}
}Scopes
Scopes control what an API key is allowed to do. Always use the minimum set of scopes you need.
| Scope | Description |
|---|---|
sites:read | List and retrieve sites |
sites:write | Create and update sites |
pages:read | List and retrieve pages |
pages:write | Create, update and delete pages |
media:read | List and retrieve media files |
media:write | Upload and delete media |
analytics:read | Retrieve analytics data |
ai:write | AI generation, translation and content assist |
publish:write | Publish sites |
ecommerce:read | Read products, orders and coupons |
ecommerce:write | Manage products and coupons |
booking:read | Retrieve bookings and availability |
booking:write | Create and manage bookings |
loyalty:read | Retrieve loyalty points |
loyalty:write | Earn and redeem points |
webhooks:read | Retrieve webhook configuration |
webhooks:write | Create and manage webhooks |
forms:read | Retrieve form submissions |
push:write | Send push notification campaigns |
Example: a key for read-only content access:
Scopes: sites:read, pages:read, media:readExample: a key for a CI/CD pipeline that deploys:
Scopes: sites:read, pages:write, media:write, publish:writeSandbox vs. Live keys
| Sandbox | Live | |
|---|---|---|
| Prefix | optimo_sandbox_ | optimo_live_ |
| Data | Test data, no real deployments | Production data |
| Rate limits | Same as your tier | Same as your tier |
| Cost | Free (AI calls don't count) | Normal |
| Publishing | No effect (dry-run) | Site is actually published |
Use sandbox keys for development and testing. Switch to live keys for production.
const cms = new OptimoCMS({
apiKey: process.env.NODE_ENV === 'production'
? process.env.OPTIMOCMS_LIVE_KEY!
: process.env.OPTIMOCMS_SANDBOX_KEY!,
});Rate limits
Rate limits depend on your tier:
| Tier | Requests/min | Burst (per second) | Daily maximum |
|---|---|---|---|
| Free | 60 | 10 | 5,000 |
| Pro | 600 | 50 | 100,000 |
| Enterprise | 6,000 | 200 | Unlimited |
Rate limit headers
Every API response includes rate limit information:
HTTP/1.1 200 OK
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 594
X-RateLimit-Reset: 1748260860| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests in the current window |
X-RateLimit-Remaining | Remaining requests |
X-RateLimit-Reset | Unix timestamp when the window resets |
429 Too Many Requests
When you exceed the limit, you receive a 429 response:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 45 seconds.",
"details": { "retryAfter": 45 }
},
"meta": { "requestId": "req_abc123", "timestamp": "2026-05-26T12:00:00Z" }
}SDK: The SDK has built-in retry with exponential backoff. See SDK error handling.
curl:
# Retry-After header contains the wait time in seconds
curl -i https://api.optimocms.com/v1/sites \
-H "X-Api-Key: your_api_key"
# → Retry-After: 45MCP: The MCP server handles rate limits automatically with retry.
Security best practices
1. Use environment variables
# .env (NEVER commit to git)
OPTIMOCMS_API_KEY=optimo_live_abc123def456// ✅ Good
const cms = new OptimoCMS({ apiKey: process.env.OPTIMOCMS_API_KEY! });
// ❌ Bad — hardcoded key
const cms = new OptimoCMS({ apiKey: 'optimo_live_abc123def456' });2. Minimal scopes
Give each key only the scopes it needs. A frontend integration doesn't need publish:write.
3. Separate keys per environment
Create separate keys for development, staging and production. This way you can revoke individual keys without breaking everything.
4. Rotate keys periodically
Rotate your API keys every quarter. Old keys can be revoked in the dashboard.
5. Monitor usage
Monitor API usage via Settings → API Keys → Usage. Set up alerts for unexpected spikes.
6. Never client-side
Never use API keys in client-side code (browser, mobile app). Create a backend proxy that makes the calls.
Error codes
| Status | Code | Description |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid API key |
403 | FORBIDDEN | Key does not have the required scope |
429 | RATE_LIMIT_EXCEEDED | Too many requests |
{
"error": {
"code": "FORBIDDEN",
"message": "API key does not have scope: pages:write"
},
"meta": { "requestId": "req_err123", "timestamp": "2026-05-26T12:00:00Z" }
}Next steps
- Quickstart — Your first API call
- SDK error handling — Automatic retry on 429
- API Reference — All endpoints