Merchant Warrior Logo

Altima Linux
Payment Gateway

Merchant Warrior Logo

Multi-Tenant Architecture Documentation

A comprehensive guide to implementing secure, scalable payment processing with multi-tenant support, VATU currency conversion, and seamless application integration.

Table of Contents

1. Overview & Features

The Merchant Warrior Payment Gateway Integration is a modern, secure payment processing application that provides comprehensive multi-tenant support, enabling organizations to deploy a single application that serves multiple clients with completely separate configurations.

Production Ready

This application is built with enterprise-grade architecture, supporting unlimited tenants through a single deployment while maintaining complete isolation between tenant configurations and data.

1.1 Live Demo

The application is deployed and available for testing:

AltimaPay Demo Links

Testing Different Tenants

Tenant URL Features
Default /?amount=50.00 Test credentials, basic features
Altima Education /?tenant=altima-education&vatu=5000 VATU converter, education branding
Charity Network /?tenant=charity-donations&amount=25.00 Charity branding, no VATU converter

1.2 Key Features

đŸĸ Multi-Tenant Architecture

Single deployment supporting unlimited organizations with separate configurations, merchant accounts, and branding.

🔒 Secure Payment Processing

Full integration with Merchant Warrior PayFrame for PCI DSS compliant card processing with no card data touching your servers.

💱 Currency Conversion

Real-time VATU to AUD conversion using live exchange rates, configurable per tenant for specific use cases.

📧 Email Notifications

Automated email confirmations for customers and admin notifications with tenant-specific templates and branding.

🔗 URL Parameters

Pre-populate forms via URL parameters for seamless integration with existing applications and workflows.

â†Šī¸ Return to Application

Automatic return to spawning application with payment status, enabling complex multi-application workflows.

🎨 White-Label Solutions

Custom branding per tenant including company names, colors, logos, and feature toggles.

📱 Responsive Design

Works perfectly on desktop and mobile devices with modern React, TypeScript, and Tailwind CSS.

2. Multi-Tenant Architecture

The application supports multiple tenant configurations without requiring separate builds, enabling both hosted multi-tenancy and self-hosting scenarios with complete configuration isolation.

Tenant Detection & Configuration Flow

1. Request
User accesses application
→
2. Detection
System detects tenant
→
3. Config
Load tenant settings
→
4. Render
Apply branding & features

2.1 Tenant Detection Methods

The system detects tenants using multiple methods in priority order:

Priority Method Example Use Case
1 URL Parameter ?tenant=altima-education Dynamic switching, testing
2 URL Path /tenant/charity-donations/ RESTful routing
3 Subdomain altima.gateway.com Multi-tenant hosting
4 Environment Variable VITE_TENANT_ID=altima Self-hosting
5 Local Storage Persisted selection User preference
6 Default Test configuration Fallback

Example Tenant URLs

# URL Parameter Method (Highest Priority)
https://paymentgateway.com/?tenant=altima-education&amount=50.00

# Path Method
https://paymentgateway.com/tenant/charity-donations/?amount=25.00

# Subdomain Method
https://altima.paymentgateway.com/?amount=100.00

# Self-Hosting (Environment Variable)
https://payments.altima-education.org/?amount=75.00
        

2.2 Configuration Structure

Each tenant can have completely different configurations:

đŸĻ Merchant Warrior Accounts

Different merchant UUIDs, API keys, passphrases, and gateway URLs per tenant.

📧 Email Settings

Separate EmailJS configurations, templates, and admin email addresses.

🎨 Branding

Custom company names, colors, logos, and visual identity per tenant.

âš™ī¸ Features

Enable/disable VATU converter, email notifications, and other features per tenant.

Tenant Configuration Example

'altima-education': {
  tenantId: 'altima-education',
  tenantName: 'Altima Education Foundation',
  merchantWarrior: {
    merchantUUID: import.meta.env.VITE_ALTIMA_MW_MERCHANT_UUID,
    apiKey: import.meta.env.VITE_ALTIMA_MW_API_KEY,
    passphrase: import.meta.env.VITE_ALTIMA_MW_PASSPHRASE,
    // ... other config
  },
  email: {
    serviceId: import.meta.env.VITE_ALTIMA_EMAILJS_SERVICE_ID,
    adminEmail: 'admin@altima-education.org',
    // ... email templates
  },
  branding: {
    companyName: 'Altima Education Foundation',
    primaryColor: '#059669',
    secondaryColor: '#047857',
    // ... branding options
  },
  features: {
    vatuConverter: true,
    emailNotifications: true,
    streamlinedFlow: true,
    customReturnUrls: true
  }
}
        

2.3 Adding New Tenants

Simple 3-Step Process

Adding a new tenant requires no code changes to the core application - just configuration and environment variables.

Step 1: Add Tenant Configuration

Add the new tenant configuration in src/config/tenantConfig.ts:

'your-organization': {
  tenantId: 'your-organization',
  tenantName: 'Your Organization Name',
  merchantWarrior: {
    merchantUUID: import.meta.env.VITE_YOUR_MW_MERCHANT_UUID || 'test_fallback',
    apiKey: import.meta.env.VITE_YOUR_MW_API_KEY || 'test_fallback',
    passphrase: import.meta.env.VITE_YOUR_MW_PASSPHRASE || 'test_fallback',
    // ... other merchant warrior config
  },
  branding: {
    companyName: 'Your Organization',
    primaryColor: '#your-primary-color',
    secondaryColor: '#your-secondary-color',
    supportEmail: 'support@yourorganization.com'
  },
  features: {
    vatuConverter: false, // Enable/disable as needed
    emailNotifications: true,
    streamlinedFlow: true,
    customReturnUrls: true
  }
}
        

Step 2: Add Environment Variables

Configure production credentials in your deployment environment:

# Your Organization Configuration
VITE_YOUR_MW_MERCHANT_UUID=live_merchant_uuid
VITE_YOUR_MW_API_KEY=live_api_key
VITE_YOUR_MW_PASSPHRASE=live_passphrase
VITE_YOUR_EMAILJS_SERVICE_ID=your_service_id
VITE_YOUR_EMAILJS_PUBLIC_KEY=your_public_key
VITE_YOUR_ADMIN_EMAIL=admin@yourorganization.com
# ... other variables
        

Step 3: Deploy Once

Deploy the application once - all tenants (existing and new) will use the same build with their respective configurations loaded dynamically.

Zero Downtime

Adding new tenants requires no downtime for existing tenants. The application dynamically loads configurations based on the detected tenant.

3. URL Parameters & Integration

The application supports comprehensive URL parameters for seamless integration with existing applications and workflows.

3.1 Parameter Reference

Tenant Selection Parameters

Parameter Description Example
tenant Select specific tenant configuration ?tenant=altima-education
t Short form tenant parameter ?t=charity-donations

Currency Parameters

Parameter Description Example
amount Pre-fills AUD amount directly (disables VATU converter) ?amount=50.00
vatu Pre-fills VATU amount and shows real-time AUD conversion ?vatu=5000

Customer Information Parameters

Parameter Description Example
name Pre-fills customer name ?name=John%20Doe
email Pre-fills email address ?email=john@example.com
phone Pre-fills phone number ?phone=+61400000000
address Pre-fills street address ?address=123%20Main%20St
city Pre-fills city ?city=Sydney
state Pre-fills state/province ?state=NSW
postcode Pre-fills postal code ?postcode=2000
country Pre-fills country (default: AU) ?country=AU
product Pre-fills product/service description ?product=Computer%20Donation

Return URL Parameters

Parameter Description Example
return_url URL to return to after payment completion ?return_url=https://myapp.com/dashboard
returnUrl Alternative parameter name for return URL ?returnUrl=https://myapp.com/dashboard

3.2 Integration Examples

Multi-Tenant with Direct AUD Payment

https://altimapay.com/demo?tenant=altima-education&amount=75.50&name=John%20Doe&email=john@example.com&product=Computer%20Donation

VATU Conversion Payment

https://altimapay.com/demo?tenant=altima-education&vatu=10000&name=Mary%20Smith&email=mary@example.com&product=Education%20Support

Complete Pre-filled Form (Streamlined Flow)

https://altimapay.com/demo?tenant=altima-education&vatu=5000&name=John%20Doe&email=john@example.com&phone=+61400000000&address=123%20Main%20St&city=Sydney&state=NSW&postcode=2000&country=AU&product=Altima%20Linux%20Computer

With Return URL

https://altimapay.com/demo?tenant=charity-donations&amount=50.00&name=John%20Doe&email=john@example.com&return_url=https://myapp.com/dashboard

JavaScript Integration Example

// From your application - redirect to payment gateway
function initiatePayment(customerData, amount, tenant = 'default') {
  const baseUrl = 'https://altimapay.com/demo';
  const returnUrl = encodeURIComponent(window.location.origin + '/payment-complete');

  const params = new URLSearchParams({
    tenant: tenant,
    amount: amount.toString(),
    name: customerData.name,
    email: customerData.email,
    phone: customerData.phone,
    return_url: returnUrl
  });

  window.location.href = baseUrl + '?' + params.toString();
}

// Handle return from payment gateway
function handlePaymentReturn() {
  const urlParams = new URLSearchParams(window.location.search);
  const paymentStatus = urlParams.get('payment_status'); // 'success' or 'failed'
  const transactionId = urlParams.get('transaction_id');
  const amount = urlParams.get('amount');

  if (paymentStatus === 'success') {
    console.log(`Payment successful! Transaction: ${transactionId}, Amount: $${amount}`);
    // Update UI, redirect to success page, etc.
  } else {
    console.log('Payment failed or was cancelled');
    // Handle failure case
  }
}
        

4. Payment Flow

The application supports two distinct payment flows depending on how much information is provided via URL parameters.

4.1 Standard Flow

Standard Payment Flow

1. Tenant Detection
System detects tenant config
→
2. Customer Form
User fills information
→
3. Currency Conversion
VATU to AUD (if enabled)
→
4. Secure Payment
PayFrame processing
5. Processing
Merchant Warrior gateway
→
6. Confirmation
Success/failure response
→
7. Email Notifications
Customer & admin emails
→
8. Return
Back to application

Standard Flow Features

4.2 Streamlined Flow

When all required parameters are provided via URL, the application automatically enters streamlined mode:

Streamlined Flow Trigger

Activated when URL contains: name, email, phone, address, city, postcode, and (amount OR vatu)

Streamlined Payment Flow

1. Tenant Detection
System detects tenant config
→
2. Direct to Payment
Skip customer form entirely
→
3. Auto Conversion
VATU conversion if provided
→
4. Secure Payment
PayFrame with pre-filled data
5. Processing
Merchant Warrior gateway
→
6. Simple Response
Success/retry buttons
→
7. Email Notifications
Tenant-specific emails
→
8. Auto Return
Automatic return with status

Streamlined Flow Features

5. Security & Configuration

The application implements enterprise-grade security practices with comprehensive environment variable support for sensitive configuration data.

5.1 Environment Variables

Multi-Tenant Environment Structure

Each tenant uses prefixed environment variables to maintain complete isolation:

# Altima Education Tenant
VITE_ALTIMA_MW_MERCHANT_UUID=altima_live_uuid
VITE_ALTIMA_MW_API_KEY=altima_live_key
VITE_ALTIMA_MW_PASSPHRASE=altima_live_passphrase
VITE_ALTIMA_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js
VITE_ALTIMA_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/
VITE_ALTIMA_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/
VITE_ALTIMA_EMAILJS_SERVICE_ID=service_altima
VITE_ALTIMA_EMAILJS_PUBLIC_KEY=altima_public_key
VITE_ALTIMA_EMAILJS_USER_SUCCESS_TEMPLATE_ID=template_altima_success
VITE_ALTIMA_EMAILJS_USER_FAILURE_TEMPLATE_ID=template_altima_failure
VITE_ALTIMA_EMAILJS_ADMIN_NOTIFICATION_TEMPLATE_ID=template_altima_admin
VITE_ALTIMA_ADMIN_EMAIL=admin@altima-education.org
VITE_ALTIMA_EXCHANGE_RATE_API_KEY=altima_fx_api_key

# Charity Network Tenant
VITE_CHARITY_MW_MERCHANT_UUID=charity_live_uuid
VITE_CHARITY_MW_API_KEY=charity_live_key
VITE_CHARITY_MW_PASSPHRASE=charity_live_passphrase
VITE_CHARITY_EMAILJS_SERVICE_ID=service_charity
VITE_CHARITY_EMAILJS_PUBLIC_KEY=charity_public_key
VITE_CHARITY_ADMIN_EMAIL=donations@charity.org
# ... additional charity configuration
        

Self-Hosting Environment Variables

For self-hosting scenarios, set a tenant ID and configure your organization's settings:

# Set tenant ID for self-hosting
VITE_TENANT_ID=your-organization

# Configure your organization's settings
VITE_YOUR_MW_MERCHANT_UUID=your_merchant_uuid
VITE_YOUR_MW_API_KEY=your_api_key
VITE_YOUR_MW_PASSPHRASE=your_passphrase
VITE_YOUR_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js
VITE_YOUR_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/
VITE_YOUR_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/
VITE_YOUR_EMAILJS_SERVICE_ID=service_your_org
VITE_YOUR_EMAILJS_PUBLIC_KEY=your_public_key
VITE_YOUR_ADMIN_EMAIL=admin@yourcompany.com
        

Development vs Production URLs

Environment PayFrame JS URL PayFrame URL Submit URL
Test securetest.merchantwarrior.com/payframe/payframe.js securetest.merchantwarrior.com/payframe/ base.merchantwarrior.com/payframe/
Production secure.merchantwarrior.com/payframe/payframe.js secure.merchantwarrior.com/payframe/ api.merchantwarrior.com/payframe/

5.2 Security Best Practices

Development/Testing Security

Safe Development Environment

Test credentials are safely hardcoded as fallbacks, all URLs point to Merchant Warrior's test environment, and no real payments can be processed.

Production Security

Critical Security Requirements

Never commit .env files containing production credentials. Always use environment variables for sensitive data in production deployments.

Security Implementation Details

Security Layer Implementation Benefit
Payment Processing Merchant Warrior PayFrame PCI DSS compliant, no card data touches application
API Authentication MD5 hash generation with multiple elements Secure API communication with payment gateway
Data Transmission HTTPS/SSL encryption All data encrypted in transit
Configuration Environment variables Sensitive data never exposed in code
Input Validation Client and server-side validation Prevents malicious input and data corruption
Tenant Isolation Dynamic configuration loading Complete separation between tenant data

Credential Management

# Production .env file (NEVER commit this!)
# Altima Education tenant
VITE_ALTIMA_MW_MERCHANT_UUID=your_live_merchant_uuid
VITE_ALTIMA_MW_API_KEY=your_live_api_key
VITE_ALTIMA_MW_PASSPHRASE=your_live_passphrase

# Charity tenant
VITE_CHARITY_MW_MERCHANT_UUID=charity_live_uuid
VITE_CHARITY_MW_API_KEY=charity_live_key
VITE_CHARITY_MW_PASSPHRASE=charity_live_passphrase

# Add to .gitignore
.env
.env.local
.env.production
        

6. Deployment & Hosting

The application supports multiple deployment scenarios, from multi-tenant SaaS platforms to self-hosted single-tenant installations.

6.1 Multi-Tenant Hosting

Host multiple organizations on a single deployment with complete configuration isolation.

DNS Configuration for Subdomains

# DNS CNAME records for subdomain-based tenant detection
altima.yourgateway.com -> yourgateway.com
charity.yourgateway.com -> yourgateway.com
education.yourgateway.com -> yourgateway.com
*.yourgateway.com -> yourgateway.com  # Wildcard for all subdomains
        

Multi-Tenant Deployment Process

Multi-Tenant Deployment Flow

1. Configure Tenants
Add tenant configs to code
→
2. Set Environment Variables
Configure all tenant credentials
→
3. Deploy Once
Single build serves all tenants
→
4. Configure DNS
Set up subdomains/routing

Environment Variable Management

For hosting platforms like Netlify, Vercel, or Heroku:

# Set all tenant environment variables in deployment platform
VITE_ALTIMA_MW_MERCHANT_UUID=altima_live_uuid
VITE_ALTIMA_MW_API_KEY=altima_live_key
VITE_ALTIMA_EMAILJS_SERVICE_ID=service_altima
VITE_ALTIMA_ADMIN_EMAIL=admin@altima-education.org

VITE_CHARITY_MW_MERCHANT_UUID=charity_live_uuid
VITE_CHARITY_MW_API_KEY=charity_live_key
VITE_CHARITY_EMAILJS_SERVICE_ID=service_charity
VITE_CHARITY_ADMIN_EMAIL=donations@charity.org

# Add more tenants as needed...
        

Multi-Tenant Benefits

💰 Cost Effective

Single deployment and maintenance for unlimited tenants reduces operational costs.

🔄 Easy Updates

Deploy once to update all tenants simultaneously with new features and security patches.

đŸĸ Scalable

Add new tenants without additional infrastructure or deployment complexity.

🔒 Isolated

Complete configuration and data isolation between tenants for security and compliance.

6.2 Self-Hosting

Organizations can self-host the application with their own branding and custom domain.

Self-Hosting Setup Process

Simple Self-Hosting

Self-hosting requires only setting a tenant ID environment variable and configuring your organization's credentials.

Step 1: Set Tenant ID

# Force specific tenant configuration
VITE_TENANT_ID=your-organization
        

Step 2: Configure Credentials

# Your organization's Merchant Warrior credentials
VITE_YOUR_MW_MERCHANT_UUID=your_live_uuid
VITE_YOUR_MW_API_KEY=your_live_key
VITE_YOUR_MW_PASSPHRASE=your_live_passphrase

# Your organization's email configuration
VITE_YOUR_EMAILJS_SERVICE_ID=your_service_id
VITE_YOUR_EMAILJS_PUBLIC_KEY=your_public_key
VITE_YOUR_ADMIN_EMAIL=admin@yourcompany.com

# Production URLs
VITE_YOUR_MW_PAYFRAME_JS_URL=https://secure.merchantwarrior.com/payframe/payframe.js
VITE_YOUR_MW_PAYFRAME_URL=https://secure.merchantwarrior.com/payframe/
VITE_YOUR_MW_SUBMIT_URL=https://api.merchantwarrior.com/payframe/
        

Step 3: Deploy to Custom Domain

# Deploy to your organization's domain
payments.yourcompany.com
pay.yourorganization.org
gateway.yourbusiness.net
        

Self-Hosting Benefits

7. Technical Reference

7.1 Architecture Overview

Technology Stack

Layer Technology Purpose
Frontend Framework React 18 + TypeScript Modern, type-safe user interface
Build Tool Vite Fast development and optimized builds
Styling Tailwind CSS Utility-first CSS framework
Payment Processing Merchant Warrior PayFrame PCI DSS compliant card processing
Email Service EmailJS Client-side email notifications
Currency API exchangeratesapi.io Real-time exchange rates
Icons Lucide React Modern icon library
State Management React Hooks Component state and lifecycle

Component Architecture

src/
├── components/
│   ├── CustomerForm.tsx          # Customer information form
│   ├── VatuConverter.tsx         # VATU to AUD conversion
│   ├── PayFrameContainer.tsx     # Merchant Warrior PayFrame integration
│   ├── PaymentResponse.tsx       # Payment result display
│   └── TenantSelector.tsx        # Development tenant switching
├── services/
│   ├── emailService.ts           # Tenant-aware EmailJS integration
│   └── fxService.ts             # Tenant-aware exchange rate API
├── config/
│   ├── tenantConfig.ts          # Multi-tenant configuration system
│   ├── settings.ts              # Legacy settings (backward compatibility)
│   └── merchantWarrior.ts       # Dynamic payment gateway config
├── hooks/
│   └── useUrlParams.ts          # URL parameter handling
└── types/
    └── payment.ts               # TypeScript interfaces
        

State Management Flow

Application State Flow

form
Customer information collection
→
payment
PayFrame integration
→
response
Payment result handling

Multi-Tenant Configuration Loading

Configuration Loading Process

1. Tenant Detection
Multiple detection methods
→
2. Configuration Loading
Dynamic tenant settings
→
3. Environment Resolution
Tenant-prefixed variables
→
4. Fallback Handling
Default for unknown tenants

7.2 API Integration

Payment Status Webhook Integration

For server-side integration, monitor return URLs to detect payment completion:

// Express.js example
app.get('/payment-complete', (req, res) => {
  const { payment_status, transaction_id, amount, tenant } = req.query;

  if (payment_status === 'success') {
    // Update database, send confirmations, etc.
    console.log(`Payment received: ${transaction_id} for $${amount} (${tenant})`);

    // Tenant-specific processing
    switch(tenant) {
      case 'altima-education':
        await processEducationDonation(transaction_id, amount);
        break;
      case 'charity-donations':
        await processCharityDonation(transaction_id, amount);
        break;
    }
  }

  // Redirect user to appropriate page
  res.redirect('/dashboard');
});
        

Frontend Integration

// React component example
function PaymentButton({ customerData, amount, tenant }) {
  const initiatePayment = () => {
    const baseUrl = 'https://altimapay.com/demo';
    const returnUrl = encodeURIComponent(window.location.origin + '/payment-complete');

    const params = new URLSearchParams({
      tenant: tenant,
      amount: amount.toString(),
      name: customerData.name,
      email: customerData.email,
      phone: customerData.phone,
      address: customerData.address,
      city: customerData.city,
      state: customerData.state,
      postcode: customerData.postcode,
      country: customerData.country || 'AU',
      product: customerData.product || 'Purchase',
      return_url: returnUrl
    });

    // Redirect to payment gateway
    window.location.href = baseUrl + '?' + params.toString();
  };

  return (
    <button onClick={initiatePayment} className="payment-button">
      Pay ${amount} AUD
    </button>
  );
}
        

Return URL Parameters

When users return from the payment gateway, these parameters are added to the return URL:

Parameter Description Example Values
payment_status Payment result status success, failed
transaction_id Merchant Warrior transaction ID 12345678
amount Payment amount in AUD 50.00
tenant Tenant that processed the payment altima-education

8. Troubleshooting & Support

Common Integration Issues

Tenant Detection Issues

Issue Cause Solution
Wrong tenant detected Multiple detection methods conflicting Check detection priority order, clear localStorage
Default configuration loading Tenant ID not found in configuration Verify tenant exists in tenantConfig.ts
Subdomain not working DNS configuration incorrect Check CNAME records and wildcard DNS setup
Environment variable not loading Variable name mismatch Verify tenant prefix matches configuration

Payment Processing Issues

Issue Cause Solution
PayFrame not loading Incorrect Merchant Warrior credentials Verify tenant's MW UUID, API key, and passphrase
Payment fails with hash error Incorrect hash generation Check passphrase and hash algorithm implementation
Test payments not working Using production URLs with test credentials Ensure test URLs are used with test credentials
Live payments not working Using test URLs with live credentials Update to production URLs for live processing

Email Notification Issues

Issue Cause Solution
No emails sent EmailJS not configured for tenant Verify tenant's EmailJS service ID and public key
Customer emails not sending Template ID not configured Check tenant's success/failure template IDs
Admin emails not sending Admin email or template not configured Verify admin email and notification template ID
Email template errors Template variables mismatch Ensure template variables match application parameters

Multi-Tenant Troubleshooting

Debugging Multi-Tenant Issues

Use browser developer tools to inspect tenant detection and configuration loading. Check console logs for detailed tenant information.

Configuration Debugging

// Add to browser console for debugging
console.log('Current tenant:', TenantConfigService.detectTenant());
console.log('Tenant config:', TenantConfigService.getConfig());
console.log('Available tenants:', TenantConfigService.getAvailableTenants());

// Check environment variables
console.log('Environment variables:', import.meta.env);
        

Testing Different Tenants

# Test tenant detection methods
# URL Parameter
/?tenant=altima-education&amount=10.00

# Subdomain (requires DNS setup)
https://altima.yourgateway.com/?amount=10.00

# Path-based
/tenant/charity-donations/?amount=25.00

# Environment variable (self-hosting)
VITE_TENANT_ID=altima-education

# Local storage (browser console)
localStorage.setItem('tenantId', 'charity-donations');
        

Support Resources

Documentation

Integration Support

Common Use Cases

Production Ready

This application is designed for secure payment processing with seamless integration capabilities and enterprise-grade multi-tenant architecture. It's particularly well-suited for organizations requiring scalable payment solutions with complete tenant isolation.

Merchant Warrior Payment Gateway - Multi-Tenant Documentation
Generated on
Version 2.0 - Multi-Tenant Architecture