Skip to content

Multi-Tenancy & Connected Businesses

Invora supports three deployment models:

Model Description API Surface
Standalone Single business using Invora directly All invoicing + billing APIs
Platform Parent org managing child businesses Identity + Admin + Invoicing + Billing
Reseller Platform that white-labels Invora for its customers Same as Platform, with Connected Business APIs

Tenant Isolation

Every API call is scoped to a single tenant (organization). The tenant is determined by the access token's urn:zitadel:iam:user:resourceowner:id claim.

Data boundaries

  • Documents, parties, settings, and regulation state are fully isolated per tenant
  • No cross-tenant reads or writes via standard APIs
  • Admin APIs (platform operators only) can list across tenants

Tenant hierarchy

flowchart TD
  P["Platform<br/>(parent org)"]
  A["Connected Business A<br/>(child tenant)"]
  B["Connected Business B<br/>(child tenant)"]
  C["Connected Business C<br/>(child tenant)"]
  P --> A
  P --> B
  P --> C

Each connected business: - Has its own Zitadel org ID (tenant_id) - Gets its own OIDC client credentials - Owns its own documents, parties, settings - Shares the parent's billing subscription (costs attributed to parent)

Creating Connected Businesses

Platforms use ConnectedBusinessService to create and manage child tenants:

curl -X POST https://gateway.invora.app/api/v2/identity/connected-businesses \
  -H "Authorization: Bearer $PLATFORM_TOKEN" \
  -d '{
    "name": "Branch Office Riyadh",
    "country": "SA",
    "taxId": "300000000000099",
    "adminEmail": "admin@branch-riyadh.com"
  }'

Response:

{
  "connectedBusiness": {
    "tenantId": "org-xyz-123",
    "name": "Branch Office Riyadh",
    "parentTenantId": "org-abc-parent",
    "active": true
  },
  "clientId": "branch-riyadh-client",
  "clientSecret": "secret-store-securely"
}

The child tenant can now authenticate independently and use all invoicing APIs within its own scope.

Scope Gating

Some operations require specific entitlements on the tenant's subscription plan:

Operation Required Entitlement
CreateConnectedBusiness connected_business capability on plan
LinkBillingCustomer billing capability on plan
Billing APIs (all) billing capability
ZATCA onboarding regulations capability

Tenants on invoicing-only plans get PERMISSION_DENIED for billing and connected business operations.

Platform Admin APIs

Platform administrators (parent org with admin scopes) access cross-tenant management via the admin module:

Tenant Management

Method Path RPC
POST /api/admin/identity/v2/tenants CreateTenant
GET /api/admin/identity/v2/tenants/{id} GetTenant
POST /api/admin/identity/v2/tenants/list ListTenants
POST /api/admin/identity/v2/tenants/{id}/deactivate DeactivateTenant
POST /api/admin/identity/v2/tenants/{id}/reactivate ReactivateTenant

Billing Org Management

Method Path RPC
POST /api/admin/billing/v2/orgs ProvisionOrg
GET /api/admin/billing/v2/orgs/{tenant_id} GetOrgStatus
POST /api/admin/billing/v2/orgs/{tenant_id}/suspend SuspendOrg
POST /api/admin/billing/v2/orgs/{tenant_id}/reactivate ReactivateOrg

Cross-Tenant Invoice Visibility

Method Path RPC
POST /api/admin/invoices/v2/list ListAllInvoices (filter by tenant_id)
GET /api/admin/invoices/v2/{id} GetInvoice (any tenant)
GET /api/admin/invoices/v2/tenants/{id}/usage-stats GetTenantUsageStats

Regulation Management

Method Path RPC
POST /api/admin/regulations/v2/tenants/{id}/enable EnableRegulation
POST /api/admin/regulations/v2/tenants/{id}/disable DisableRegulation
GET /api/admin/regulations/v2/tenants/{id}/regulations ListTenantRegulations

Billing Model for Connected Businesses

Connected businesses share the parent's billing subscription:

  • Parent subscribes to a plan (e.g., "Platform Pro — 50 connected businesses")
  • Usage metering tracks events per connected business
  • Invoices are generated at the parent level
  • Parent can view per-tenant usage via GetTenantUsageStats

Connected businesses do NOT have their own subscriptions, wallets, or payment methods. All billing is parent-scoped.

Suspending a Connected Business

curl -X POST https://gateway.invora.app/api/v2/identity/connected-businesses/org-xyz-123/suspend \
  -H "Authorization: Bearer $PLATFORM_TOKEN" \
  -d '{"reason": "Non-payment"}'

Suspension: - Revokes the child's API access immediately - Preserves all data (documents, parties, settings) - Stops usage metering - Reactivatable at any time

Cross-Tenant Header

For admin operations that need to target a specific tenant:

X-Target-Org-Id: org-xyz-123

This header is only accepted with admin-scoped tokens. Regular tenant tokens cannot impersonate other tenants.