Security Best Practices
Security is a top priority at Notifs. This guide covers best practices for keeping your integration secure.
API Key Management
Store Keys Securely
Never commit API keys to version control. Always use environment variables:
# .env
NOTIFS_API_KEY=notifs_sk_...
// ✅ Good
const notifs = new Notifs({
apiKey: process.env.NOTIFS_API_KEY
})
// ❌ Bad
const notifs = new Notifs({
apiKey: 'notifs_sk_abc123...' // Never hardcode!
})
Rotate Keys Regularly
Rotate your API keys periodically, especially if:
- A team member with access leaves
- You suspect a key has been compromised
- As part of regular security hygiene (every 90 days)
Use Restricted Keys
Create separate API keys for different environments and services:
# Development
NOTIFS_API_KEY=notifs_sk_dev_...
# Production
NOTIFS_API_KEY=notifs_sk_prod_...
Webhook Signature Verification
When you send notifications via the SDK, signatures are generated automatically. This section explains how signature verification works for receiving webhooks from external services.
How Notifs Signatures Work
When sending to POST /webhook/:webhookId:
- The SDK computes an HMAC-SHA256 signature using your webhook secret
- The signature is sent in the
X-Notifs-Signatureheader - Format:
t=<timestamp>,v1=<hash>
Signature Format
X-Notifs-Signature: t=1234567890,v1=abc123def456...
t- Unix timestamp (seconds) when the signature was createdv1- HMAC-SHA256 hex digest of"<timestamp>.<payload>"
Manual Signature Generation
If not using the SDK, generate signatures like this:
import crypto from 'crypto'
function generateSignature(payload: string, secret: string): string {
const timestamp = Math.floor(Date.now() / 1000)
const signaturePayload = `${timestamp}.${payload}`
const hash = crypto
.createHmac('sha256', secret)
.update(signaturePayload)
.digest('hex')
return `t=${timestamp},v1=${hash}`
}
// Usage
const payload = JSON.stringify({ title: 'Test', data: {} })
const signature = generateSignature(payload, process.env.WEBHOOK_SECRET!)
fetch(`https://notifs.io/api/webhook/${webhookId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Notifs-Signature': signature
},
body: payload
})
Signature Validation Rules
- Timestamps must be within 5 minutes of the server time (prevents replay attacks)
- Signatures use constant-time comparison to prevent timing attacks
- Invalid signatures return
401 Unauthorized
Rate Limiting
Notifs implements rate limiting to prevent abuse:
Default Limits
- Free Tier: 10 requests/second, 1,000 requests/month
- Pro Tier: 100 requests/second, 100,000 requests/month
- Enterprise: Custom limits
Handle Rate Limits
Implement exponential backoff when you hit rate limits:
import { Notifs, NotifsError } from '@notifs/sdk'
const notifs = new Notifs({ apiKey: process.env.NOTIFS_API_KEY! })
const webhook = await notifs.webhooks.get('your-webhook-id')
async function sendWithRetry(
payload: { title: string; message?: string; data?: any },
maxRetries = 3
) {
let retries = 0
while (retries < maxRetries) {
try {
return await webhook.send(payload)
} catch (error) {
if (error instanceof NotifsError && error.status === 429) {
const delay = Math.pow(2, retries) * 1000 // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay))
retries++
} else {
throw error
}
}
}
throw new Error('Max retries exceeded')
}
Duplicate Prevention
Notifs automatically prevents duplicate notifications within a 5-minute window based on payload fingerprinting.
If you send an identical payload within 5 minutes, you'll receive a 409 Conflict response:
{
"message": "Duplicate request detected",
"code": "WEBHOOK_2005"
}
To send the same notification again, either:
- Wait 5 minutes
- Add a unique field like a timestamp to your payload
await webhook.send({
title: 'Payment Received',
data: {
paymentId: 'pay_123',
timestamp: new Date().toISOString() // Makes each request unique
}
})
Input Validation
Always validate and sanitize data before sending:
import { z } from 'zod'
import { Notifs } from '@notifs/sdk'
const notifs = new Notifs({ apiKey: process.env.NOTIFS_API_KEY! })
const paymentWebhook = await notifs.webhooks.get('your-payment-webhook-id')
const PaymentSchema = z.object({
userId: z.string(),
amount: z.number().positive(),
currency: z.enum(['USD', 'EUR', 'GBP']),
email: z.string().email()
})
async function sendPaymentNotification(data: unknown) {
// Validate input
const validated = PaymentSchema.parse(data)
// Send notification with validated data
await paymentWebhook.send({
title: 'Payment Received',
message: `Payment of ${validated.amount} ${validated.currency} received`,
data: validated
})
}
HTTPS Only
Notifs only accepts requests over HTTPS. Make sure your webhook endpoints also use HTTPS in production.
// ✅ Good
const webhookUrl = 'https://yourapp.com/webhooks/notifs'
// ❌ Bad (will fail in production)
const webhookUrl = 'http://yourapp.com/webhooks/notifs'
Content Security Policy
Add appropriate CSP headers to your API routes:
export async function POST(request: NextRequest) {
const response = NextResponse.json({ success: true })
response.headers.set(
'Content-Security-Policy',
"default-src 'none'; frame-ancestors 'none'"
)
return response
}
Monitoring and Alerts
Set up monitoring for suspicious activity:
- Failed authentication attempts
- Unusual request patterns
- High error rates
- Rate limit hits
Dashboard Monitoring
Use the Notifs dashboard to track and investigate issues:
- Go to Webhooks → Select your webhook → Logs
- Filter by status (
successorerror) - Review failed requests for error messages
Service Execution Monitoring
Check service execution status in the dashboard:
- Click on any notification to see service executions
- Review
errororskippedstatuses - Use Rerun to retry failed executions
Data Privacy
PII Handling
Be mindful of personally identifiable information (PII):
- Don't include sensitive data in notification payloads unless necessary
- Use references/IDs instead of full user data when possible
- Comply with GDPR, CCPA, and other privacy regulations
// ✅ Good - Use references
await webhook.send({
title: 'Password Reset Requested',
data: {
userId: 'user_123',
event: 'password_reset_requested'
}
})
// ❌ Avoid sensitive data
await webhook.send({
title: 'Account Update',
data: {
email: 'user@example.com',
socialSecurityNumber: '123-45-6789', // Never!
creditCard: '4111111111111111' // Never!
}
})
Compliance
Notifs is compliant with:
- SOC 2 Type II
- GDPR
- CCPA
- HIPAA (Enterprise plan)
For enterprise compliance requirements, contact enterprise@notifs.io.
Security Incident Response
If you suspect a security incident:
- Rotate your API keys immediately
- Review recent logs for suspicious activity
- Contact our security team: security@notifs.io
- Document the incident and affected resources
Bug Bounty Program
We run a bug bounty program. If you discover a security vulnerability, please report it responsibly to security@notifs.io.
Do not:
- Test against production without permission
- Access or modify data that doesn't belong to you
- Perform DoS attacks
- Publicly disclose vulnerabilities before we've had time to patch
Next Steps
- Review the SDK Reference for secure implementation
- Check out Examples for secure integration patterns
- Read about Webhooks for delivery details