Skip to main content

Tenant Management

Learn how to manage tenants in ConstellationAPI's multi-tenant architecture.

Overview

ConstellationAPI uses a stateless, JWT-based multi-tenant architecture where:

  • Tenants are identified by tenant_id in JWT tokens - No database required
  • Each tenant has isolated connections - Company A and Company B have separate connections
  • Connections are automatically pooled and reused - Better performance through connection caching
  • Complete tenant isolation - No cross-tenant data access possible

How Multi-Tenancy Works

JWT-Based Tenant Identification

Every request includes a JWT token with:

  • tenant_id: Identifies which company/tenant is making the request
  • connections: Contains credentials for each integration (Jira, GitHub, etc.)
{
"tenant_id": "company-a",
"connections": {
"jira": {
"baseUrl": "https://company-a.atlassian.net",
"email": "admin@company-a.com",
"apiToken": "jira-token"
}
}
}

Connection Pooling

When a request arrives:

  1. System extracts tenant_id from JWT
  2. Checks if connection already exists in cache for this tenant
  3. If exists → Reuses connection (fast)
  4. If not → Creates new connection → Caches it

Result: Each tenant (Company A, Company B, etc.) has isolated, cached connections.

See Connection Management for detailed information.

Creating Tenants

Using the API

curl -X POST http://localhost:3007/admin/tenants \
-H "Content-Type: application/json" \
-H "X-API-KEY: your-internal-key" \
-d '{
"id": "my-tenant",
"consumerId": "apideck-consumer-id",
"name": "My Organization",
"description": "My organization tenant"
}'

Tenant ID Rules

  • 3-50 characters
  • Alphanumeric only (a-z, A-Z, 0-9)
  • Must be unique

Storage

Tenants are stored in data/tenants.json:

{
"tenants": {
"my-tenant": {
"consumerId": "apideck-consumer-id",
"name": "My Organization",
"description": "My organization tenant",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
}
}

Using Tenants

All API requests require a JWT token with tenant_id:

curl http://localhost:3007/jira/projects \
-H "X-API-KEY: your-internal-key" \
-H "X-JWT-Token: <jwt-token-with-tenant-id>"

The tenant_id is embedded in the JWT token, not sent as a separate header. This ensures:

  • Security: Tenant ID is cryptographically signed
  • Simplicity: Single token contains all necessary information
  • Isolation: Each tenant's connections are automatically isolated

Generating JWT Tokens

Use the scripts/generate_jwt.py script to generate JWT tokens:

# Edit scripts/generate_jwt.py with your tenant and connection details
python scripts/generate_jwt.py

See Authentication for JWT token structure.

Managing Tenants

List All Tenants

curl http://localhost:3007/admin/tenants \
-H "X-API-KEY: your-internal-key"

Get Tenant Details

curl http://localhost:3007/admin/tenants/my-tenant \
-H "X-API-KEY: your-internal-key"

Update Tenant

curl -X PUT http://localhost:3007/admin/tenants/my-tenant \
-H "Content-Type: application/json" \
-H "X-API-KEY: your-internal-key" \
-d '{
"name": "Updated Name",
"description": "Updated description"
}'

Delete Tenant

curl -X DELETE http://localhost:3007/admin/tenants/my-tenant \
-H "X-API-KEY: your-internal-key"

Best Practices

  1. Naming: Use descriptive tenant IDs (e.g., acme-corp, startup-xyz)
  2. Isolation: Keep tenant data separate and secure
  3. Consumer IDs: Map each tenant to a unique Apideck consumer ID
  4. Backup: Regularly backup data/tenants.json in production

Connection Management

Each tenant's connections are automatically managed:

  • Automatic Pooling: Connections are cached and reused
  • Tenant Isolation: Each tenant has separate connections
  • Connection Stats: View connection statistics per tenant
  • Connection Clearing: Clear connections when needed

See Connection Management for details.