AlphaAlpha Docs

Cross-Tenant Worker

Run one worker daemon for all tenants with a cross-tenant API key

Cross-Tenant Worker

By default an API key belongs to exactly one tenant: the worker daemon polling /jobs/next with that key only ever sees that tenant's configuration jobs. A cross-tenant worker key lifts that restriction so a single daemon + Revit machine can serve the job queues of all active tenants.

How it works

  1. Cross-tenant API key: an API key created with isCrossTenant: true. Only super admins can create one (POST /api-key). It still has a home tenant (the creator's organization), which applies whenever no tenant header is sent.
  2. Queue scan across tenants: when a cross-tenant key polls GET /jobs/next, the backend scans the house, block, and option-sales queues of all tenants and returns the highest-priority job. The job payload's tenantId identifies the tenant it belongs to.
  3. X-Tenant-Id header: for every follow-up call (start/status/upload/finish/fail, project lookup, /tenants/me, blob downloads, …) the worker sends the job's tenant as an X-Tenant-Id header. The backend validates the tenant (must exist and be active) and runs the request in that tenant's context, including tenant settings such as coordinate system, Revit template, and default Revit version.
  4. Job dispatch: the daemon passes the job's tenantId to the Revit add-in over the named pipe (configure, configure-block, configure-option-sales). The add-in keeps it as the ambient job tenant and stamps all of its own API calls with the same header until the job ends.

Regular (single-tenant) keys are rejected with 403 if they send an X-Tenant-Id other than their own tenant, and unknown or inactive tenants are rejected with 400. Every applied override is audit-logged on the backend.

Setting it up

  1. As a super admin, create a cross-tenant API key:

    POST /api-key
    {
      "daysTillExpiration": 365,
      "name": "revit-worker-fleet",
      "isCrossTenant": true,
      "permissions": { "configuratorPermissions": ["READ_QUEUEJOBS"] }
    }
  2. Put the key in the worker machine's ~/Alpha/settings.json as usual (apiKey / productionApiKey / …). No other daemon configuration is needed; the tenantId setting is now only a fallback for manual (non-job) runs.

  3. Restart the AlphaWorkerDaemon. The log line Claimed <TYPE> job <id> (tenant=<tenantId>) confirms per-job tenant resolution is active.

Notes

  • Manual runs in Revit (UI or CLI dispatch without a job) are unaffected: no job tenant is set, so calls run against the key's home tenant exactly as before.
  • Revit versions per tenant still resolve per job: project.revitVersion → tenant default (/tenants/me with the job's tenant) → daemon settings.
  • Heartbeat/registration still registers the agent under the tenant from local settings; the queue agent list shows which machine ran which job via worker events on the job itself.

On this page