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
All webhooks sent from Notifs include HMAC-SHA256 signatures. Always verify these signatures to ensure webhooks are genuine.
How It Works
- Notifs signs each webhook request with your webhook secret
- The signature is sent in the
X-Notifs-Signatureheader - You verify the signature using the same secret
Implementation
import crypto from 'crypto'
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const hmac = crypto.createHmac('sha256', secret)
hmac.update(payload)
const expectedSignature = hmac.digest('hex')
// Use timing-safe comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)
}
// In your webhook handler
app.post('/webhooks/notifs', (req, res) => {
const signature = req.headers['x-notifs-signature']
const payload = JSON.stringify(req.body)
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).json({ error: 'Invalid signature' })
}
// Process webhook...
res.json({ success: true })
})
Next.js App Router Example
// app/api/webhooks/route.ts
import { NextRequest, NextResponse } from 'next/server'
import crypto from 'crypto'
function verifySignature(payload: string, signature: string): boolean {
const hmac = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET!)
hmac.update(payload)
const expectedSignature = hmac.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
)
}
export async function POST(request: NextRequest) {
const signature = request.headers.get('x-notifs-signature')
if (!signature) {
return NextResponse.json({ error: 'Missing signature' }, { status: 401 })
}
const payload = await request.text()
if (!verifySignature(payload, signature)) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 })
}
const data = JSON.parse(payload)
// Process webhook securely...
return NextResponse.json({ success: true })
}
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:
async function sendWithRetry(
webhookId: string,
data: any,
maxRetries = 3
): Promise<WebhookResponse> {
let retries = 0
while (retries < maxRetries) {
try {
return await notifs.webhooks.send(webhookId, data)
} catch (error) {
if (error instanceof RateLimitError) {
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')
}
Idempotency
Use idempotency keys to prevent duplicate webhook sends:
await notifs.webhooks.send('webhook_id', data, {
idempotencyKey: `payment_${paymentId}` // Unique key per operation
})
If the same idempotency key is used within 24 hours, Notifs will return the cached response instead of sending a duplicate webhook.
Input Validation
Always validate and sanitize data before sending:
import { z } from 'zod'
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 notifs.webhooks.send('webhook_id', 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
Use Notifs request logs to track and investigate issues:
const logs = await notifs.logs.list({
status: 'failed',
startDate: new Date(Date.now() - 24 * 60 * 60 * 1000) // Last 24h
})
if (logs.data.length > 10) {
console.warn('High number of failed requests detected!')
}
Data Privacy
PII Handling
Be mindful of personally identifiable information (PII):
- Don't include sensitive data in webhook payloads unless necessary
- Use references/IDs instead of full user data when possible
- Comply with GDPR, CCPA, and other privacy regulations
// ✅ Good
await notifs.webhooks.send('webhook_id', {
userId: 'user_123',
event: 'password_reset_requested'
})
// ❌ Avoid when possible
await notifs.webhooks.send('webhook_id', {
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.dev.
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.dev
- 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.dev.
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