API Keys¶
User API keys provide secure authentication for scripts, integrations, and automated workflows across all your topics.
API Keys vs Topic Access Tokens
Confused about which to use?
- User API Keys (
noti_...) - Work across all your topics, for broader automation - Topic Access Tokens (
tk_...) - Scoped to one topic, recommended for integrations
Overview¶
Why use API keys?
- Authenticate scripts and automation
- Avoid exposing user credentials
- Track API usage per key
- Scope permissions (publish, subscribe, manage)
- Set expiration dates
Creating API Keys¶
Via Web Dashboard¶
- Go to Settings → API Keys
- Click "Create API Key"
- Enter name and description
- Select scopes (permissions)
- Optionally set expiration date
- Copy the generated key (shown only once!)
Via CLI¶
notifer keys create my-script-key \
--description "Automation script" \
--scopes "publish,subscribe"
Via API¶
curl -X POST https://app.notifer.io/api/keys \
-H "Authorization: Bearer your_jwt_token" \
-H "Content-Type: application/json" \
-d '{
"name": "my-script-key",
"description": "Automation script",
"scopes": ["publish", "subscribe"]
}'
Response:
{
"id": "key_abc123",
"name": "my-script-key",
"key": "noti_1234567890abcdefghijklmnopqrstuv",
"scopes": ["publish", "subscribe"],
"created_at": "2025-11-02T10:00:00Z"
}
Save Your Key
The API key is shown only once during creation. Save it securely! If you lose it, you'll need to create a new key.
Using API Keys¶
In HTTP Requests¶
Use the X-API-Key header:
In Python¶
import requests
headers = {
"X-API-Key": "noti_your_key_here"
}
response = requests.post(
"https://app.notifer.io/my-topic",
data="Automated message",
headers=headers
)
In JavaScript¶
fetch('https://app.notifer.io/my-topic', {
method: 'POST',
headers: {
'X-API-Key': 'noti_your_key_here',
'Content-Type': 'text/plain'
},
body: 'Automated message'
});
In CLI¶
# Set in config file
notifer config set api-key noti_your_key_here
# Or pass as option
notifer publish my-topic "Message" --api-key noti_your_key_here
Key Scopes¶
Control what each API key can do:
| Scope | Description | Example Use Case |
|---|---|---|
* (all) |
Full access | Development and testing |
publish |
Publish messages to topics | CI/CD notifications |
subscribe |
Subscribe to topics | Log aggregation |
topics:read |
List and view topics | Monitoring dashboard |
topics:write |
Create and manage topics | Automation scripts |
keys:read |
View API keys | Audit scripts |
keys:write |
Manage API keys | Admin automation |
Scope Best Practices¶
Key Management¶
List All Keys¶
Revoke a Key¶
Temporarily disable a key (can be re-enabled):
Delete a Key¶
Permanently delete a key (cannot be undone):
Key Expiration¶
Set expiration dates for temporary access:
Expired keys:
- Automatically stop working at expiration time
- Can be viewed in the dashboard (marked as "expired")
- Cannot be re-enabled (create a new key instead)
Usage Tracking¶
Monitor API key usage in the dashboard:
- Request count - Total requests made with this key
- Last used - Timestamp of most recent use
- Usage by endpoint - Breakdown of API calls
- Rate limit status - Current rate limit usage
Security Best Practices¶
Storage¶
Do:
- Store keys in environment variables
- Use secret managers (AWS Secrets Manager, HashiCorp Vault)
- Use CI/CD secret storage (GitHub Secrets, GitLab CI Variables)
- Rotate keys periodically
Don't:
- Commit keys to version control
- Share keys in plain text (email, chat)
- Use the same key across multiple services
- Grant more permissions than needed
Environment Variables¶
# Store in .env file (don't commit!)
NOTIFER_API_KEY=noti_your_key_here
# Load in script
source .env
curl -H "X-API-Key: $NOTIFER_API_KEY" \
https://app.notifer.io/my-topic
GitHub Actions Secrets¶
- name: Publish notification
run: |
curl -d "Deploy completed" \
-H "X-API-Key: ${{ secrets.NOTIFER_API_KEY }}" \
https://app.notifer.io/deployments
Docker Secrets¶
# Create secret
echo "noti_your_key_here" | docker secret create notifer_key -
# Use in service
docker service create \
--name app \
--secret notifer_key \
myapp
Rate Limits¶
API keys inherit rate limits from your account tier:
| Tier | Rate Limit | Burst |
|---|---|---|
| Free | 10/min | 20 |
| Pro | 100/min | 200 |
| Business | 1000/min | 2000 |
Rate limit headers in response:
Response:
Troubleshooting¶
401 Unauthorized¶
Cause: Invalid or missing API key
Solution:
- Check key is correct (no extra spaces)
- Verify key hasn't been revoked or deleted
- Ensure using correct header:
X-API-Key
403 Forbidden¶
Cause: Insufficient permissions
Solution:
- Check key scopes include required permission
- Verify topic access (private topics require ownership)
- Check rate limits
429 Too Many Requests¶
Cause: Rate limit exceeded
Solution:
- Implement exponential backoff
- Upgrade to higher tier
- Spread requests over time
- Check
X-RateLimit-Resetheader for reset time
Examples¶
Shell Script with Error Handling¶
#!/bin/bash
API_KEY="${NOTIFER_API_KEY}"
TOPIC="server-alerts"
send_notification() {
local message="$1"
local priority="${2:-3}"
response=$(curl -s -w "\n%{http_code}" \
-d "$message" \
-H "X-API-Key: $API_KEY" \
-H "X-Priority: $priority" \
"https://app.notifer.io/$TOPIC")
http_code=$(echo "$response" | tail -n1)
if [ "$http_code" -eq 200 ] || [ "$http_code" -eq 201 ]; then
echo "✓ Notification sent"
return 0
else
echo "✗ Failed with code $http_code"
return 1
fi
}
# Usage
send_notification "Server backup completed" 3
Python with Retry Logic¶
import os
import time
import requests
from typing import Optional
API_KEY = os.getenv("NOTIFER_API_KEY")
BASE_URL = "https://app.notifer.io"
def publish_with_retry(
topic: str,
message: str,
max_retries: int = 3
) -> Optional[dict]:
"""Publish message with exponential backoff retry."""
headers = {"X-API-Key": API_KEY}
url = f"{BASE_URL}/{topic}"
for attempt in range(max_retries):
try:
response = requests.post(
url,
data=message,
headers=headers,
timeout=10
)
if response.status_code in [200, 201]:
return response.json()
if response.status_code == 429:
# Rate limited - wait and retry
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
# Other error - don't retry
response.raise_for_status()
except requests.RequestException as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt) # Exponential backoff
return None
# Usage
publish_with_retry("alerts", "Test message")
Comparison with Topic Access Tokens¶
Understanding when to use each authentication method:
| Feature | User API Key (noti_...) |
Topic Access Token (tk_...) |
|---|---|---|
| Scope | All your topics | Single topic only |
| Prefix | noti_... |
tk_... |
| Header | X-API-Key |
X-Topic-Token |
| Permissions | Global scopes | Per-token (publish/subscribe) |
| Best for | Multi-topic automation | Topic-specific integrations |
| Sharing | ❌ Risky (full access) | ✅ Safe (limited scope) |
| Revocation impact | Affects all integrations | Only affects one topic |
| Created via | Account settings | Topic settings |
| Example use | Admin scripts, dashboards | CI/CD for one topic |
When to Use API Keys¶
✅ Use API keys when:
- Building automation that works across multiple topics
- Creating admin scripts or dashboards
- You control the entire integration
- You need topic management permissions (create, delete topics)
- You need global access to your account
When to Use Topic Access Tokens¶
✅ Use topic access tokens when:
- Integrating with external services (GitHub Actions, monitoring tools)
- Each integration should only access one topic
- You want to share access without sharing account credentials
- You need fine-grained permission control per topic
- You want to easily revoke access for one integration
👉 Learn more about Topic Access Tokens
Next Steps¶
- Topic Access Tokens - Topic-scoped authentication
- Private Topics - Secure your notifications
- HTTP Publishing - Publishing examples
- CLI Tool - Manage keys from command line
- Authentication - Authentication overview