Skip to content

Impersonating Tenants

Impersonation lets platform administrators perform operations within a tenant’s organization without needing that tenant’s credentials. Every impersonated request is recorded in the audit trail.


  • Debugging — inspect a tenant’s functions, runs, or events
  • Support — fix configuration issues on behalf of a tenant
  • Provisioning — set up initial resources in a newly created tenant

Add --as-org <org_id> to an Ironflow command to run it as the specified tenant:

Terminal window
# List a tenant's environments
ironflow --as-org org_x1y2z3w4 env list
# List a tenant's projects
ironflow --as-org org_x1y2z3w4 project list

The --as-org flag requires platform credentials (from ironflow platform login).

--as-org is a persistent root flag, so every command accepts it, but only the commands that reach the server over the REST API act on it: apikey, circuit-breaker, debounce, env, org, outbox, policy, project, role, secret, tenant and webhook. The ConnectRPC commands — run, function, emit, invoke, sql, stream, projection, subscribe — accept the flag and ignore it, running against your own organization. Use the HTTP form below to reach those resources in a tenant.

Two more commands send the header but gain nothing from it. platform is the surface you impersonate from, not into. capacity serves a global cross-tenant view filtered by --env / --function alone, so the org never narrows it.


For direct API calls, set the X-Ironflow-Org header to the target organization ID:

Terminal window
# List a tenant's functions
curl -H "Content-Type: application/json" -d '{}' http://localhost:9123/ironflow.v1.IronflowService/ListFunctions \
-H "Authorization: Bearer $PLATFORM_TOKEN" \
-H "X-Ironflow-Org: org_x1y2z3w4"

By default, impersonated requests target the tenant’s env_default environment. To target a different environment, add the X-Ironflow-Environment header or ?env query parameter:

Terminal window
curl -H "Content-Type: application/json" -d '{}' http://localhost:9123/ironflow.v1.IronflowService/ListFunctions \
-H "Authorization: Bearer $PLATFORM_TOKEN" \
-H "X-Ironflow-Org: org_x1y2z3w4" \
-H "X-Ironflow-Environment: env_staging"

The environment must belong to the impersonated organization.


Impersonation has two permission levels:

PermissionApplies toDescription
platform:impersonate:readEndpoints whose RBAC action is a read (:read, :list, :subscribe)Read-only access to tenant data
platform:impersonateEvery other endpointWrite access (create, update, delete) to tenant data

The endpoint’s RBAC action decides, not the HTTP method. Every ConnectRPC call is a POST, so ListFunctions (functions:list) needs only read impersonation, while GET /api/v1/export (org:export) needs write. An endpoint with no RBAC action falls back to the method: GET, HEAD and OPTIONS count as reads. HEAD on a mapped route is a rough edge — the action map has no HEAD arm, so it resolves to the resource’s write action and needs full impersonation.

Built-in role assignments:

RoleReadWrite
platform_adminYesYes
platform_operatorYesYes
platform_viewerYesNo

Every impersonated request generates a platform.impersonated audit event containing:

  • The platform user or key that initiated the request
  • The target organization ID
  • The HTTP method and path

Query impersonation events:

Terminal window
ironflow platform audit --event-type platform.impersonated

Filter by target tenant (via HTTP API — this filter is not available in the CLI):

Terminal window
curl "http://localhost:9123/api/v1/platform/audit?impersonated_org_id=org_x1y2z3w4" \
-H "Authorization: Bearer $PLATFORM_TOKEN"

See Platform Architecture for details on how the dual audit model works.