Your API Key Is Your Identity
When you send an email through SMTPfast (or any email API), your API key is the only thing that proves the request is from you. If someone gets your key, they can send emails as your domain, burn through your quota, and damage your sender reputation.
This is entirely preventable.
Rule 1: Never Hardcode API Keys
This is the most common mistake. Keys end up in source code, get committed to git, and become public.
// Never do this
const API_KEY = "sf_live_abc123def456";
// Do this instead
const API_KEY = process.env.SMTPFAST_API_KEY;
Even in private repositories, hardcoded keys are a risk. Anyone with repo access sees them. If the repo ever becomes public, even briefly, the key is compromised.
Rule 2: Use Environment Variables
Store API keys in environment variables, not in code or config files.
Local Development
Use a .env file with a library like dotenv:
# .env (add this to .gitignore!)
SMTPFAST_API_KEY=sf_test_your_test_key
// Load at app startup
require("dotenv").config();
# Python equivalent
from dotenv import load_dotenv
load_dotenv()
import os
api_key = os.environ["SMTPFAST_API_KEY"]
Production
Set environment variables in your hosting platform:
# Vercel
vercel env add SMTPFAST_API_KEY
# Railway
railway variables set SMTPFAST_API_KEY=sf_live_your_key
# Fly.io
fly secrets set SMTPFAST_API_KEY=sf_live_your_key
# Docker
docker run -e SMTPFAST_API_KEY=sf_live_your_key your-app
Never pass secrets as command-line arguments. They show up in process listings and shell history.
Rule 3: Use Separate Keys for Each Environment
Create different API keys for development, staging, and production.
| Environment | Key Prefix | Purpose |
|---|---|---|
| Development | sf_test_ |
Testing locally, no real emails sent |
| Staging | sf_test_ |
Integration testing |
| Production | sf_live_ |
Real email sending |
If your staging key leaks, your production sending is unaffected.
Rule 4: Scope Your Keys
SMTPfast supports key scoping. Limit each key to only the permissions it needs.
| Scope | Allows |
|---|---|
email:send |
Send emails |
email:read |
Read email status |
domain:manage |
Add/verify domains |
webhook:manage |
Configure webhooks |
A key used by your application to send emails should only have email:send scope. It should not be able to manage domains or webhooks.
# Create a scoped key via the API
curl -X POST https://smtpfa.st/api/v1/api-keys \
-H "Authorization: Bearer sf_live_your_admin_key" \
-H "Content-Type: application/json" \
-d '{
"name": "production-sender",
"scopes": ["email:send"]
}'
Rule 5: Rotate Keys Regularly
Even if you follow every best practice, rotate your keys periodically. This limits the blast radius if a key is compromised without your knowledge.
Rotation schedule:
- Production keys: every 90 days
- After any team member leaves
- After any security incident
- After any accidental exposure
Zero-Downtime Rotation
- Create a new API key in the SMTPfast dashboard
- Update your environment variables with the new key
- Deploy the update
- Verify emails are sending with the new key
- Revoke the old key
# Step 1: Create new key
# (do this in the SMTPfast dashboard)
# Step 2: Update env var
export SMTPFAST_API_KEY=sf_live_new_key_here
# Step 3: Deploy
git push heroku main
# Step 4: Verify
curl -X POST https://smtpfa.st/api/v1/emails \
-H "Authorization: Bearer sf_live_new_key_here" \
-H "Content-Type: application/json" \
-d '{"from":"[email protected]","to":"[email protected]","subject":"Key rotation test","html":"<p>Works!</p>"}'
# Step 5: Revoke old key in the dashboard
Rule 6: Add Your .env to .gitignore
This should be the first thing you do in any project:
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
echo ".env.production" >> .gitignore
If a .env file was already committed, removing it from .gitignore is not enough. The key is still in git history. You need to rotate the key immediately.
Rule 7: Use Rate Limiting
Even with good key security, add rate limiting as a defense-in-depth measure. If a key is compromised, rate limits slow down the attacker.
SMTPfast applies rate limits per API key:
| Plan | Rate Limit |
|---|---|
| Free | 10 requests/second |
| Starter | 50 requests/second |
| Growth | 100 requests/second |
| Scale | 500 requests/second |
If you hit a rate limit, you get a 429 response with a Retry-After header.
Rule 8: Monitor Key Usage
Watch for unusual patterns that might indicate a compromised key:
- Sudden spike in email volume
- Emails sent to domains you do not recognize
- Sending outside your normal hours
- High bounce rates (attacker sending to random addresses)
Set up alerts in the SMTPfast dashboard for volume spikes and unusual bounce rates.
Rule 9: Scan for Leaked Keys
Use automated tools to catch accidental key exposure:
# Check git history for leaked keys
git log -p | grep -n "sf_live_"
# Use git-secrets to prevent future commits
git secrets --install
git secrets --add 'sf_live_[a-zA-Z0-9]+'
git secrets --add 'sf_test_[a-zA-Z0-9]+'
GitHub also scans public repositories for known API key patterns and will notify you if it finds one.
What SMTPfast Does on Its Side
- Keys are hashed at rest using bcrypt. We cannot see your full key after creation.
- All API traffic requires HTTPS. Plaintext HTTP requests are rejected.
- Failed authentication attempts are rate-limited to prevent brute force.
- Key creation and revocation events are logged in your audit trail.
Checklist
- API keys stored in environment variables, not code
-
.envfiles in.gitignore - Separate keys for dev, staging, and production
- Keys scoped to minimum required permissions
- Rotation schedule in place (every 90 days)
- Rate limiting configured
- Usage monitoring and alerts set up
- Git history scanned for leaked keys
-
git-secretsor similar tool installed
Ready to get started?
Start sending transactional email today. Free to start, no credit card required.
Get Started for FreeRelated Posts
One approval instead of five DNS records: Domain Connect on SMTPfast
If your domain is on Cloudflare, SMTPfast can publish its sending records, and separately the inbound MX, through Domain Connect. You review each set on Cloudflare's screen, approve, and the records are written for you. Here is how it works, what gets written, and what to do when your DNS lives elsewhere.
Logs API and webhook deliveries: answer 'did it send?' without opening the dashboard
Two additions for the debugging side of email: the event log behind the Logs page is now an API, and every webhook has a delivery log with attempts, responses, automatic retries and a retry button.