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.

VariableRequiredDescription
DATABASE_URLPostgres connection string. TimescaleDB required.
REDIS_URLRedis connection string. Used by BullMQ.
AUTH_SECRETAuth.js secret. Generate with: npx auth secret
AUTH_URLFull URL of the dashboard. e.g. https://app.quotawatch.app
RESEND_API_KEYRequired for email alerts. Get at resend.com.
RESEND_FROMFrom address for alert emails.
GITHUB_IDGitHub OAuth app client ID (optional).
GITHUB_SECRETGitHub OAuth app client secret (optional).

Email alerts (Resend)

QuotaWatch uses Resend to send threshold alert emails. Free tier: 3,000 emails/month.

  1. Create an account at resend.com
  2. Go to API Keys → Create API Key (Sending access)
  3. Add your domain in Domains and verify the DNS records
  4. Set RESEND_API_KEY and RESEND_FROM
💡
For development, use 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.

LimitFreeProTeam
Projects15Unlimited
Environments per project12Unlimited
APIs per project15Unlimited

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" }
💡
The SDK surfaces 403 responses so you can catch them in application code or set up alerts. Because limits return errors rather than silently dropping events, you'll always know when you've hit a ceiling.