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:
This header is only accepted with admin-scoped tokens. Regular tenant tokens cannot impersonate other tenants.