Skip to main content

Authorization

This page covers who can access Esper and which workspace they're allowed to operate.

API Key Authentication

API Key Validation

All ingest endpoints require valid API keys for authentication:

  • Header: API keys must be passed in the x-esper-api-key header
  • Validation: Keys are validated against the PostgreSQL database on every request
  • Response: Invalid or missing keys return 401 Unauthorized
  • Scope: API keys are tenant-scoped and tied to a specific source_id

API keys are the primary mechanism for authenticating traffic sources. Each key is bound to a specific tenant and source identifier, ensuring proper isolation and attribution of ingested events. The validation happens synchronously on every request before any processing begins.

Rate Limiting

Beyond basic authentication, the system provides built-in protection against traffic spikes and abuse:

Rate Limiting Configuration

API keys include automatic rate limiting protection:

  • Each key has a configurable per-minute request limit
  • Rate limits are tracked in Redis for fast performance
  • Exceeding limits returns 429 Too Many Requests
  • Configure limits via api_key_rate_limit_per_minute in server config

This rate limiting operates independently per API key, so one source experiencing high traffic won't impact others. The Redis-backed implementation ensures minimal latency even under high load.

Operator authentication

The current dashboard model is bearer-token based.

Hosted browser flow:

  1. The operator starts from an auth route such as /auth/github/login.
  2. The backend issues a JWT after successful callback.
  3. The frontend stores the token as esper.auth_token.
  4. API requests send Authorization: Bearer <token>.

Important backend behavior:

  • The server now has dedicated auth middleware.
  • Dashboard routes require a bearer JWT before tenant membership checks run.
  • Invalid tokens return 401.

Membership management

Memberships are tenant-scoped. The UI supports:

  • Create or update a membership with user_id and role.
  • Remove a membership by user_id.

Endpoints:

GET /tenants/{tenant_id}/memberships
POST /tenants/{tenant_id}/memberships
DELETE /tenants/{tenant_id}/memberships/{user_id}

Supported roles:

RoleCurrent meaning
Ownerhighest tenant role
Adminadministrative operator
Analystanalysis-oriented operator
Viewerread-oriented operator