Understanding how Appizer authenticates and authorizes API requests.
Authentication Overview
Appizer uses Bearer token authentication with API keys.
<DiagramWrapper
title="Authentication Process"
description="How API keys are validated"
chart={`
sequenceDiagram
participant Client
participant Gateway as API Gateway
participant Cache as Key Cache
participant DB as Key Database
participant RateLimit as Rate Limiter
Client->>Gateway: Request + API Key
Gateway->>Cache: Lookup Key
alt Key in Cache
Cache-->>Gateway: Key Details
else Key not in Cache
Gateway->>DB: Query Key
DB-->>Gateway: Key Details
Gateway->>Cache: Store in Cache
end
Gateway->>Gateway: Validate Key Status
Gateway->>Gateway: Check Permissions
Gateway->>RateLimit: Check Rate Limit
RateLimit-->>Gateway: Limit Status
alt Valid & Within Limits
Gateway-->>Client: 200 OK + Response
else Invalid Key
Gateway-->>Client: 401 Unauthorized
else Rate Limited
Gateway-->>Client: 429 Too Many Requests
end
`}
relatedLinks={[
{ label: 'Authentication Docs', href: '/docs/api/authentication' },
{ label: 'Rate Limits', href: '/docs/api/rate-limits' }
]}
/>
API Key Types
Secret Keys (Server-Side)
Format: sk_live_ or sk_test_
Permissions: Full access to all API operations
Usage: Server-side applications only
// Server-side
const appizer = new Appizer({
apiKey: process.env.APPIZER_API_KEY // sk_live_...
})
Never Expose
Public Keys (Client-Side)
Format: pk_live_ or pk_test_
Permissions: Limited to client-safe operations (track, identify)
Usage: Browser and mobile applications
// Client-side
const appizer = new AppizerClient({
publicKey: process.env.NEXT_PUBLIC_APPIZER_PUBLIC_KEY // pk_live_...
})
Key Validation Flow
<DiagramWrapper
title="Key Validation Steps"
description="Multi-stage validation process"
chart={`
flowchart TD
Start([Receive Request])
Extract[Extract API Key]
Format{Valid Format?}
Exists{Key Exists?}
Active{Key Active?}
Perms{Has Permission?}
RateLimit{Within Rate Limit?}
Allow[Allow Request]
Deny401_1[401: Invalid Format]
Deny401_2[401: Key Not Found]
Deny401_3[401: Key Inactive]
Deny403[403: Forbidden]
Deny429[429: Rate Limited]
Start --> Extract
Extract --> Format
Format -->|No| Deny401_1
Format -->|Yes| Exists
Exists -->|No| Deny401_2
Exists -->|Yes| Active
Active -->|No| Deny401_3
Active -->|Yes| Perms
Perms -->|No| Deny403
Perms -->|Yes| RateLimit
RateLimit -->|No| Deny429
RateLimit -->|Yes| Allow
style Allow fill:#e8f5e9,stroke:#388e3c
style Deny401_1 fill:#ffebee,stroke:#c62828
style Deny401_2 fill:#ffebee,stroke:#c62828
style Deny401_3 fill:#ffebee,stroke:#c62828
style Deny403 fill:#fff3e0,stroke:#f57c00
style Deny429 fill:#fff3e0,stroke:#f57c00
`}
relatedLinks={[
{ label: 'Error Codes', href: '/docs/api/errors' }
]}
/>
Permission Model
Role-Based Access Control
API keys have associated roles with specific permissions:
<DiagramWrapper
title="Permission Hierarchy"
description="Role-based access control"
chart={`
graph TD
Admin[Admin Role]
Write[Write Role]
Read[Read Role]
AdminPerms[All Operations]
WritePerms[Track Events<br/>Identify Users<br/>Send Notifications]
ReadPerms[Query Analytics<br/>List Resources]
Admin --> AdminPerms
Write --> WritePerms
Read --> ReadPerms
AdminPerms -.includes.-> WritePerms
WritePerms -.includes.-> ReadPerms
style Admin fill:#e3f2fd,stroke:#1976d2
style Write fill:#e8f5e9,stroke:#388e3c
style Read fill:#fff3e0,stroke:#f57c00
`}
/>
Permission matrix:
| Operation | Read | Write | Admin |
|---|---|---|---|
| Track events | ❌ | ✅ | ✅ |
| Query analytics | ✅ | ✅ | ✅ |
| Identify users | ❌ | ✅ | ✅ |
| Send notifications | ❌ | ✅ | ✅ |
| Manage API keys | ❌ | ❌ | ✅ |
| Delete data | ❌ | ❌ | ✅ |
Request Authentication
Header Format
POST /v1/events/track HTTP/1.1
Host: api.appizer.com
Authorization: Bearer sk_live_abc123...
Content-Type: application/json
Authentication Examples
cURL:
curl -X POST https://api.appizer.com/v1/events/track \
-H "Authorization: Bearer sk_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"event":"page_view","userId":"user_123"}'
JavaScript:
const response = await fetch('https://api.appizer.com/v1/events/track', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.APPIZER_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'page_view',
userId: 'user_123'
})
})
Python:
response = requests.post(
'https://api.appizer.com/v1/events/track',
headers={
'Authorization': f'Bearer {os.environ["APPIZER_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'event': 'page_view',
'userId': 'user_123'
}
)
Security Best Practices
Key Management
- Use Environment VariablesStore keys in environment variables, never hardcode
- Separate Keys Per EnvironmentUse different keys for dev, staging, and production
- Rotate RegularlyGenerate new keys periodically and revoke old ones
- Monitor UsageTrack API key usage and set up alerts for anomalies
Key Rotation
<DiagramWrapper
title="Key Rotation Process"
description="Zero-downtime key rotation"
chart={`
sequenceDiagram
participant Admin
participant Dashboard
participant Apps as Applications
participant API
Admin->>Dashboard: Generate New Key
Dashboard-->>Admin: New Key Created
Admin->>Apps: Deploy New Key
Apps->>API: Requests with New Key
API-->>Apps: ✓ Accepted
Note over Apps,API: Both keys work during transition
Admin->>Apps: Verify New Key Works
Apps-->>Admin: ✓ Confirmed
Admin->>Dashboard: Revoke Old Key
Dashboard->>API: Deactivate Old Key
API-->>Dashboard: ✓ Revoked
`}
/>
Monitoring
Track authentication metrics:
// Metrics to monitor
{
totalRequests: 10000,
authenticatedRequests: 9950,
failedAuth: 50,
rateLimited: 25,
byKey: {
'sk_live_abc123': {
requests: 5000,
errors: 10,
lastUsed: '2024-01-15T10:30:00Z'
}
}
}
Error Responses
401 Unauthorized
Missing or invalid API key:
{
"error": "Unauthorized",
"code": "invalid_api_key",
"message": "The API key provided is invalid or has been revoked"
}
403 Forbidden
Valid key but insufficient permissions:
{
"error": "Forbidden",
"code": "insufficient_permissions",
"message": "This API key does not have permission to perform this operation"
}
429 Too Many Requests
Rate limit exceeded:
{
"error": "Too Many Requests",
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Retry after 60 seconds",
"retryAfter": 60
}