Agency Features
White-label branding, client management, portal configuration, and infrastructure topologies.
oCore's agency features transform your installation into a white-label platform for managing multiple clients. Enable agency mode to create client organizations, configure branded portals, manage infrastructure topologies, and use instance templates for consistent provisioning.
Agency Dashboard
Manage clients, branding, and agency-level configuration.
Agency Mode Overview
Agency mode extends oCore with multi-tenant capabilities designed for Odoo service providers, consultancies, and hosting agencies.
Enabling Agency Mode
Navigate to Agency in the sidebar.
Click Enable Agency Mode to activate agency features for your organization.
curl -X POST https://ocore.example.com/api/agency/enable \
-H "Authorization: Bearer $TOKEN"Agency Mode is Per-Organization
Agency mode is enabled at the organization level. Your personal organization can be the agency org, and you create separate client organizations for each customer.
What Agency Mode Provides
| Feature | Description |
|---|---|
| Client Organizations | Create and manage separate orgs for each client |
| White-Label Branding | Custom logo, colors, fonts, and CSS for client portals |
| Portal Domains | Custom subdomains or domains for client access |
| Portal Configuration | Control which features clients can see and use |
| Infrastructure Topologies | Design multi-server architectures for clients |
| Instance Templates | Standardized instance configurations for quick provisioning |
Client Management
Creating Client Organizations
Create a client organization that the agency manages:
curl -X POST https://ocore.example.com/api/agency/clients \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"slug": "acme-corp"
}'ocore agency client create --name "Acme Corp" --slug acme-corpEach client organization includes:
- Name and slug -- Client identification
- Logo -- Client's branding
- Member count -- How many users the client has
- Instance count -- How many Odoo instances are deployed
Listing Clients
curl https://ocore.example.com/api/agency/clients \
-H "Authorization: Bearer $TOKEN"Deleting a Client Organization
Permanent Action
Deleting a client organization removes all their resources, members, and data. This cannot be undone.
curl -X DELETE https://ocore.example.com/api/agency/clients/{clientOrgId} \
-H "Authorization: Bearer $TOKEN"White-Label Configuration
Branding Settings
Customize the visual appearance of client portals:
curl -X PUT https://ocore.example.com/api/agency/branding \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"logoUrl": "https://cdn.example.com/agency-logo.png",
"primaryColor": "#2563eb",
"accentColor": "#7c3aed",
"fontFamily": "Inter",
"fromEmail": "support@agency.com",
"footerText": "Powered by Agency Inc."
}'ocore agency branding update \
--logo-url "https://cdn.example.com/agency-logo.png" \
--primary-color "#2563eb"Branding Options
| Field | Description |
|---|---|
logoUrl | Custom logo URL for the portal header |
primaryColor | Primary brand color (hex) |
accentColor | Accent/secondary color (hex) |
fontFamily | Font family for the portal UI |
customCss | Custom CSS injected into the portal |
faviconUrl | Custom favicon URL |
loginBgUrl | Background image for the login page |
fromEmail | Email address for transactional emails |
footerText | Footer text displayed in the portal |
Portal Domains
Configure custom domains for client portal access:
Creating a Portal Domain
curl -X POST https://ocore.example.com/api/agency/portal-domains \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"subdomain": "acme",
"customDomain": "erp.acme.com"
}'ocore agency portal-domain create --subdomain acme --domain erp.acme.comPortal Domain Properties
| Field | Description |
|---|---|
subdomain | Subdomain on the agency's domain (1-63 chars) |
customDomain | Optional custom domain (max 255 chars) |
dnsVerificationToken | Token for DNS TXT record verification |
dnsVerified | Whether DNS has been verified |
sslStatus | SSL certificate status |
isActive | Whether the portal domain is active |
Verifying DNS
After adding a custom domain, verify DNS ownership:
curl -X POST https://ocore.example.com/api/agency/portal-domains/{domainId}/verify \
-H "Authorization: Bearer $TOKEN"Add a TXT record to your DNS with the dnsVerificationToken value to prove ownership.
Managing Portal Domains
# List portal domains
curl https://ocore.example.com/api/agency/portal-domains \
-H "Authorization: Bearer $TOKEN"
# Delete a portal domain
curl -X DELETE https://ocore.example.com/api/agency/portal-domains/{domainId} \
-H "Authorization: Bearer $TOKEN"Portal Configuration
Control which features are visible to clients in their portal:
curl -X PUT https://ocore.example.com/api/agency/portal-config \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"featureTerminal": true,
"featureFileEditor": true,
"featureOdooShell": false,
"featureMonitoring": true,
"featureBackups": true,
"featureDomains": true,
"featureLogs": true,
"featureDatabases": false,
"teamManagementEnabled": true,
"infrastructureVisibility": "limited"
}'Feature Toggles
| Feature | Default | Description |
|---|---|---|
featureTerminal | true | Client access to web terminal |
featureFileEditor | true | Client access to file editor |
featureOdooShell | true | Client access to Odoo shell |
featureMonitoring | true | Client access to monitoring dashboards |
featureBackups | true | Client access to backup management |
featureDomains | true | Client access to domain management |
featureLogs | true | Client access to operation logs |
featureDatabases | true | Client access to database management |
teamManagementEnabled | true | Client can manage their own team members |
infrastructureVisibility | full | How much server detail clients see: full, limited, none |
Client Autonomy
These settings control the client's self-service capabilities. Disabling features hides them from the client portal but the agency can still perform those operations on behalf of the client.
Infrastructure Topologies
Design and deploy multi-server architectures for complex client setups:
Creating a Topology
curl -X POST https://ocore.example.com/api/topologies \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "HA Production Setup",
"description": "High-availability production topology with load balancing",
"topologyData": {
"nodes": [...],
"edges": [...]
}
}'ocore topology create --name "HA Production Setup"High Availability Configuration
Configure HA settings for a topology:
curl -X PUT https://ocore.example.com/api/topologies/{topologyId}/ha-config \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"lbType": "traefik",
"lbServerId": "SERVER_UUID",
"filestoreType": "shared_nfs",
"redisEnabled": true,
"redisServerId": "REDIS_SERVER_UUID",
"pgFailoverEnabled": true
}'HA Configuration Options
| Field | Description |
|---|---|
lbType | Load balancer type: traefik, haproxy, nginx |
lbServerId | Server hosting the load balancer |
filestoreType | Shared filestore: shared_nfs, s3, local |
redisEnabled | Enable Redis for session storage |
pgFailoverEnabled | Enable PostgreSQL failover |
Topology Operations
# Validate a topology
curl -X POST https://ocore.example.com/api/topologies/{topologyId}/validate \
-H "Authorization: Bearer $TOKEN"
# Deploy a topology
curl -X POST https://ocore.example.com/api/topologies/{topologyId}/deploy \
-H "Authorization: Bearer $TOKEN"
# Check node status
curl -X POST https://ocore.example.com/api/topologies/{topologyId}/nodes/{nodeId}/status \
-H "Authorization: Bearer $TOKEN"Template Management
Instance templates provide standardized configurations for quick provisioning:
Creating a Template
curl -X POST https://ocore.example.com/api/templates \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Standard Odoo 18 CE",
"description": "Standard Community Edition setup for small businesses",
"odooVersion": "18.0",
"odooEdition": "ce",
"defaultWorkers": 4,
"defaultEnvVars": {"PROXY_MODE": "True"},
"moduleList": ["sale", "purchase", "stock", "account"],
"isPublic": false
}'Provisioning from a Template
Create an instance using a template's preconfigured settings:
curl -X POST https://ocore.example.com/api/templates/{templateId}/provision \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"templateId": "TEMPLATE_UUID",
"serverId": "SERVER_UUID",
"overrides": {
"WORKERS": "6"
}
}'Saving a Template from an Instance
Capture an existing instance's configuration as a reusable template:
curl -X POST https://ocore.example.com/api/templates/from-instance/{instanceId} \
-H "Authorization: Bearer $TOKEN"Required Permissions
| Action | Permission |
|---|---|
| Enable agency mode | manage:agency |
| View clients | view:agency |
| Manage clients | manage:agency |
| Update branding | manage:agency |
| Manage portal domains | manage:agency |
| Update portal config | manage:agency |
| Manage topologies | manage:topologies |
| View topologies | view:topologies |
| Manage templates | manage:templates |
| View templates | view:templates |
Troubleshooting
Agency mode not available
- Ensure your subscription includes agency features
- Verify you have the
manage:agencypermission - Check that agency mode has been enabled for your organization
Client portal not loading
- Verify the portal domain DNS is configured correctly
- Check that SSL certificates are provisioned
- Ensure the portal domain is set to
isActive: true - Verify the client organization has not been deleted
Template provisioning fails
- Check that the template's Odoo version is supported
- Verify the target server has sufficient capacity
- Ensure the template's Docker image is accessible
Topology validation errors
- Check that all referenced servers are in
activestatus - Verify network connectivity between topology nodes
- Ensure load balancer and Redis server configurations are valid