Skip to content

Impersonation (Cross-Tenant Access) ​

Resellers can access their managed teams' data in three ways:

  1. X-Tenant-Id header — Use your own token with a tenant context header (simple, stateless)
  2. Impersonation tokens — Create short-lived tokens scoped to the target tenant (for automation, no header needed)
  3. SSO login links — Generate one-click login URLs that authenticate users into the dashboard (for end-user access, no password needed)

Method 1: X-Tenant-Id Header ​

Resellers can access their managed teams' data by setting the X-Tenant-Id header on any API request. This switches the database context so all queries are scoped to the target tenant.

How It Works ​

  1. You authenticate with your own credentials and receive a Bearer token
  2. You add X-Tenant-Id: {managed-tenant-uuid} to your API requests
  3. The API validates that you manage the target tenant
  4. Data isolation is enforced at the infrastructure level for the target tenant
  5. All data returned (and created) belongs to the target tenant
┌─────────────┐     ┌──────────────────┐     ┌─────────────┐
│   Reseller   │────>│  Tenant Context  │────>│   Isolated   │
│   Request    │     │   Middleware      │     │   Data       │
│              │     │                  │     │              │
│ Auth: Bearer │     │ 1. Verify token  │     │ Scoped to    │
│ X-Tenant-Id  │     │ 2. Check owner   │     │ target team  │
│              │     │ 3. Set context   │     │              │
└─────────────┘     └──────────────────┘     └─────────────┘

Who Can Impersonate ​

RoleBehavior
Super adminCan set X-Tenant-Id to any tenant
ResellerCan only set X-Tenant-Id to tenants in their managed_tenants list
Admin / MemberX-Tenant-Id header is silently ignored; requests always use own tenant

Request Examples ​

List Monitors in a Managed Team ​

bash
curl https://app.hoppla.dev/api/v1/monitors \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000"

Create a Monitor in a Managed Team ​

bash
curl -X POST https://app.hoppla.dev/api/v1/monitors \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer Website",
    "url": "https://customer.com",
    "type": "uptime",
    "interval": 60,
    "is_enabled": true
  }'

View Incidents in a Managed Team ​

bash
curl https://app.hoppla.dev/api/v1/incidents \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Tenant-Id: 550e8400-e29b-41d4-a716-446655440000"

Finding the Tenant ID ​

The tenant_id for each managed team is returned in several places:

  • POST /auth/token response (in the managed_teams array)
  • GET /reseller/managed-teams response (the tenant_id field on each team)
  • POST /reseller/managed-teams response (when creating a new team)

Dashboard: "View as This Team" ​

In the dashboard, impersonation works via the team selector:

  1. Go to Teams in the sidebar
  2. Click View as this team on any managed team
  3. The dashboard switches context — all pages now show the team's data
  4. Click the team selector dropdown and choose Back to my account to return

Security Model ​

  • Ownership verified on every request: Every API call verifies that you manage the target tenant. There is no caching — the check is performed live.
  • Infrastructure-level isolation: Data isolation is enforced at the infrastructure level, not just in application code. Even in the event of application bugs, cross-tenant data access is prevented.
  • Audit trail: All actions performed while impersonating are attributed to the reseller's user ID, not the managed team's users.
  • No privilege escalation: Impersonation does not grant super admin access. You can perform standard API operations (CRUD monitors, view incidents, etc.) but cannot modify tenant settings or user roles within the managed team.

Error Responses ​

StatusScenario
403X-Tenant-Id points to a tenant you do not manage
403X-Tenant-Id is a valid UUID but the tenant does not exist
400X-Tenant-Id is not a valid UUID format

Example error:

json
{
  "message": "You do not manage this tenant."
}

Caveats ​

  • Notification rules and channels are not shared across tenants. If you create a notification channel while impersonating, it belongs to the managed team.
  • Reseller webhook events always go to the reseller's notification channels, not the managed team's.
  • Rate limits are counted per token, not per tenant context. Impersonating multiple teams does not give you additional rate limit quota.
  • Branding is per-tenant. Use GET/PATCH /reseller/branding with X-Tenant-Id to manage a managed team's branding. SMTP config (/smtp-config) is similarly scoped to the impersonated tenant.

Method 2: Impersonation Tokens ​

For automated workflows (CI/CD, provisioning scripts), you can create short-lived tokens that are pre-scoped to a managed team's tenant. These tokens work as standard Bearer tokens without needing the X-Tenant-Id header.

How It Works ​

  1. You call POST /reseller/managed-teams/{id}/impersonation-tokens with a TTL (1–15 minutes; default and maximum 15)
  2. The API creates a service user in the target tenant (if one doesn't already exist)
  3. A token is created for that service user with read + write scopes
  4. You use the returned plain_text_token as a regular Bearer token
  5. The token automatically operates in the managed team's tenant context
  6. The token expires after the specified TTL
┌─────────────┐     ┌────────────────┐     ┌─────────────┐
│   Reseller   │────>│   Create       │────>│  Service     │
│   Account    │     │   Impersonation│     │  User Token  │
│              │     │   Token        │     │  (in target  │
│ POST /reseller│    │                │     │   tenant)    │
│ /managed-teams│    │ 1. Find team   │     │              │
│ /{id}/imperf- │    │ 2. Create svc  │     │ Expires in   │
│ sonation-tokens│   │    user        │     │ N minutes    │
└──────────────┘    │ 3. Issue token │     └──────────────┘
                    │ 4. Audit log   │
                    └────────────────┘

Create an Impersonation Token ​

bash
curl -X POST https://app.hoppla.dev/api/v1/reseller/managed-teams/mt-uuid-.../impersonation-tokens \
  -H "Authorization: Bearer $RESELLER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ttl_minutes": 10}'

Response:

json
{
  "data": {
    "id": "token-uuid-...",
    "managed_team_id": "mt-uuid-...",
    "managed_tenant_id": "tenant-uuid-...",
    "scopes": ["read", "write"],
    "expires_at": "2026-03-10T14:10:00.000000Z",
    "ttl_minutes": 10
  },
  "plain_text_token": "ik-9xKsecretImpersonationToken..."
}

Use the Impersonation Token ​

No X-Tenant-Id header needed — the token is already scoped:

bash
# List monitors in the managed team
curl https://app.hoppla.dev/api/v1/monitors \
  -H "Authorization: Bearer ik-9xKsecretImpersonationToken..."

# Create a monitor in the managed team
curl -X POST https://app.hoppla.dev/api/v1/monitors \
  -H "Authorization: Bearer ik-9xKsecretImpersonationToken..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Customer Website",
    "url": "https://customer.com",
    "type": "uptime",
    "interval": 60,
    "is_enabled": true
  }'

List Active Tokens ​

bash
curl https://app.hoppla.dev/api/v1/reseller/managed-teams/mt-uuid-.../impersonation-tokens \
  -H "Authorization: Bearer $RESELLER_TOKEN"

Revoke a Token Early ​

bash
curl -X DELETE https://app.hoppla.dev/api/v1/reseller/managed-teams/mt-uuid-.../impersonation-tokens/token-uuid-... \
  -H "Authorization: Bearer $RESELLER_TOKEN"

Limits and Security ​

  • TTL: 1–15 minutes (default and maximum 15) — tokens cannot be extended, only re-created. They cannot be made persistent.
  • Max active tokens: 5 per managed team at any time
  • Audit trail: Every impersonation token creation is logged on both the reseller's and the managed team's audit trail, with the reseller's user ID and the target team
  • Auto-expiry: Expired tokens are automatically rejected
  • Service user: A dedicated service user is created in the target tenant for token ownership

Generate one-click login URLs that authenticate managed team users directly into the Hoppla dashboard. This is the simplest way to provide single sign-on for your customers.

How It Works ​

  1. You call POST /reseller/managed-teams/{id}/sso-link with the target user's email
  2. The API generates a signed JWT (HS256) and returns a full login URL
  3. The user clicks the link and is authenticated into the dashboard — no password needed
  4. The link expires after 5 minutes and can only be used once
┌─────────────┐     ┌────────────────┐     ┌─────────────┐
│   Reseller   │────>│   Generate     │────>│  SSO URL     │
│   Platform   │     │   SSO Link     │     │              │
│              │     │                │     │ /sso/partner  │
│ POST /reseller│    │ 1. Auto-config │     │ ?token=JWT    │
│ /managed-teams│    │ 2. Sign JWT    │     │ &tenant=slug  │
│ /{id}/sso-link│   │ 3. Return URL  │     │              │
└──────────────┘    └────────────────┘     │ User clicks → │
                                            │ Authenticated │
                                            └──────────────┘
bash
curl -X POST https://app.hoppla.dev/api/v1/reseller/managed-teams/mt-uuid-.../sso-link \
  -H "Authorization: Bearer $RESELLER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"user_email": "[email protected]", "user_name": "Alice"}'

Response:

json
{
  "data": {
    "sso_url": "https://monitoring.acme.com/sso/partner?token=eyJ...&tenant=acme-corp",
    "expires_in_seconds": 300,
    "user_email": "[email protected]",
    "user_exists": true
  }
}

Share the sso_url with your user, embed it in your dashboard, or redirect to it.

Portal-aware URLs: The generated URL automatically uses the best available portal domain (managed team's domain > reseller's domain > app.hoppla.dev). This keeps the session cookie on the correct domain so users stay authenticated.

Auto-provisioning ​

You do not need to manually configure Partner SSO before using login links. The endpoint automatically:

  • Generates a shared secret (if none exists)
  • Enables Partner SSO on the managed team
  • Enables auto-registration (new users are created on first login)
  • Enables account linking (existing password users are linked to SSO)

Auto-registration only creates people who don't have an account yet. If user_email already belongs to an account elsewhere, the login is refused. Invite that person to the team first; after they accept, login links work for them.

A session opened through a login link is limited to that team. It cannot switch to the person's other teams, and it cannot change their password, two-factor settings or passkeys. For those they sign in with their own password or passkey.

Parameters ​

FieldTypeRequiredDescription
user_emailemailyesEmail of the user to log in
user_namestringnoDisplay name (used if auto-registering a new user)
redirect_tostringnoDashboard path to redirect to after login, e.g. /dashboard/monitors

Security ​

  • Links expire after 5 minutes
  • Each link can only be used once (JWT replay prevention via jti claim)
  • All generated links are logged to the managed team's audit trail
  • The underlying Partner SSO mechanism uses HS256 JWT signing
  • When hide_password_login is enabled, password-based login is blocked server-side (not just hidden in the UI) — API calls to /auth/login and /auth/token are rejected for users in that tenant

When to Use Which Method ​

ScenarioRecommended Method
Interactive dashboard browsingX-Tenant-Id header
Quick one-off API callsX-Tenant-Id header
CI/CD pipeline automationImpersonation tokens
Provisioning scriptsImpersonation tokens
Delegating access to a serviceImpersonation tokens
Long-running operations (>15 min)X-Tenant-Id header
End-user login from your platformSSO login links
Customer self-service dashboard accessSSO login links
Embedding Hoppla in your productSSO login links + hide password login