Configuration
Environment variables, alert setup, and self-hosting options.
Environment variables
The QuotaWatch server (ingest API + dashboard) reads these variables. The SDK only needs apiKey passed programmatically.
| Variable | Required | Description |
|---|---|---|
| DATABASE_URL | ✅ | Postgres connection string. TimescaleDB required. |
| REDIS_URL | ✅ | Redis connection string. Used by BullMQ. |
| AUTH_SECRET | ✅ | Auth.js secret. Generate with: npx auth secret |
| AUTH_URL | ✅ | Full URL of the dashboard. e.g. https://app.quotawatch.app |
| RESEND_API_KEY | — | Required for email alerts. Get at resend.com. |
| RESEND_FROM | — | From address for alert emails. |
| GITHUB_ID | — | GitHub OAuth app client ID (optional). |
| GITHUB_SECRET | — | GitHub OAuth app client secret (optional). |
Email alerts (Resend)
QuotaWatch uses Resend to send threshold alert emails. Free tier: 3,000 emails/month.
- Create an account at resend.com
- Go to API Keys → Create API Key (Sending access)
- Add your domain in Domains and verify the DNS records
- Set
RESEND_API_KEYandRESEND_FROM
RESEND_FROM=onboarding@resend.dev — no domain verification needed. If RESEND_API_KEY is not set, alerts are silently skipped.Self-hosted ingest
By default the SDK sends events to https://ingest.quotawatch.app. To use a self-hosted instance, override ingestUrl:
QuotaWatch.init({
apiKey: 'qw_live_...',
ingestUrl: 'https://your-domain.com', // points to your ingest API
apis: [...],
});QuotaWatch.init(QuotaWatchConfig(
api_key="qw_live_...",
ingest_url="https://your-domain.com",
apis=[...],
))Multiple environments
Pass environment to tag all events. The dashboard shows prod/staging/dev separately.
QuotaWatch.init({
apiKey: 'qw_live_...',
environment: process.env.NODE_ENV ?? 'production', // 'production' | 'staging' | 'development'
apis: [...],
});Plan limits
Each plan enforces hard limits on projects, environments, and APIs. When a limit is exceeded, the ingest API returns HTTP 403 — events are never silently dropped, so SDK users can detect and handle limit hits.
| Limit | Free | Pro | Team |
|---|---|---|---|
| Projects | 1 | 5 | Unlimited |
| Environments per project | 1 | 2 | Unlimited |
| APIs per project | 1 | 5 | Unlimited |
When a limit is hit, the ingest API responds with a 403 and a JSON body describing which limit was exceeded:
{
"error": "API limit reached",
"message": "Your plan allows 1 API(s) per project. Upgrade to track more.",
"code": "API_LIMIT"
}Other possible code values:
{ "code": "ENVIRONMENT_LIMIT" }