Skip to main content
Contafy’s multi-profile system allows you to manage multiple business entities (companies, subsidiaries, or separate activities) from a single user account, with complete financial separation between profiles.

Profile structure

Each profile represents a distinct business entity:
export interface Profile {
  id: string;
  user_id: string;
  nombre: string;
  rfc: string;
  tipo_persona: 'FISICA' | 'MORAL';
  regimenes_fiscales: string[];
  validaciones_habilitadas: Record<string, unknown>;
  created_at: string;
  updated_at: string;
  frozen?: boolean;
  frozen_reason?: 'plan_limit' | 'user_suspension' | 'payment_issue' | null;
  frozen_at?: string | null;
}

Key profile attributes

  • nombre - Business or entity name
  • rfc - Mexican tax identification number (RFC)
  • tipo_persona - Legal entity type (FISICA for individuals, MORAL for corporations)
  • regimenes_fiscales - Array of applicable tax regimes (catálogo SAT c_RegimenFiscal)
A single profile can have multiple tax regimes. For example, a person might have both “Régimen de Actividades Profesionales” and “Arrendamiento” in their regimenes_fiscales array.

Creating profiles

Profile creation form

When creating a new profile (/dashboard/setup/profiles/new), you configure:
interface CreateProfileRequest {
  nombre: string;
  rfc: string;
  tipo_persona: 'FISICA' | 'MORAL';
  regimenes_fiscales?: string[];
  validaciones_habilitadas?: {
    validarRFCIngresos?: boolean;
    validarRFCGastos?: boolean;
    validarRegimenFiscal?: boolean;
    validarUUIDDuplicado?: boolean;
    bloquearSiRFCNoCoincide?: boolean;
    bloquearSiRegimenNoCoincide?: boolean;
  };
}

Validation rules

Each profile can have custom validation rules:
  • validarRFCIngresos - Verify RFC in incoming invoices
  • validarRFCGastos - Verify RFC in expense receipts
  • validarRegimenFiscal - Verify tax regime matches profile
  • validarUUIDDuplicado - Check for duplicate UUIDs
  • bloquearSiRFCNoCoincide - Reject uploads if RFC doesn’t match
  • bloquearSiRegimenNoCoincide - Reject uploads if regime doesn’t match
When bloquearSiRFCNoCoincide or bloquearSiRegimenNoCoincide are enabled, uploads that fail validation will be completely rejected. Use these settings carefully.

Profile limits by plan

Contafy enforces profile limits based on subscription plan:
  • FREE - Limited number of profiles
  • BASIC - More profiles available
  • PREMIUM/ENTERPRISE - Higher or unlimited profiles
The system tracks:
const { canCreate, remaining, currentCount } = useProfileLimits(subscription);
When you reach your plan limit, the “Create Profile” button is disabled with an upgrade prompt.

Profile freezing

Profiles can be frozen for various reasons:
type FrozenReason = 'plan_limit' | 'user_suspension' | 'payment_issue' | null;

Frozen profile behavior

  • Frozen profiles cannot upload new invoices or expenses
  • Existing data remains viewable
  • Dashboard metrics still include frozen profile data
  • Profile appears with a “frozen” badge in the UI
Profiles are typically frozen when you exceed your subscription’s profile limit. Upgrading your plan will automatically unfreeze the profiles.

Using profiles throughout Contafy

Global profile selector

Most pages include a profile selector dropdown that allows you to:
  • View data for a specific profile
  • View aggregated data across all profiles (“Todas las empresas”)
  • Switch profiles without leaving the current page

Profile-filtered views

When a profile is selected:
  • Dashboard shows metrics for that specific profile
  • Invoice and expense lists filter to that profile’s data
  • Reports generate for that profile only
  • Upload forms pre-select the active profile

Aggregated view

When “Todas las empresas” is selected:
  • Dashboard aggregates metrics across all profiles
  • Lists show invoices/expenses from all profiles with profile badges
  • Charts combine data from all profiles
  • Some features (like manual entry) are disabled in aggregate view
The dashboard greeting changes when viewing all profiles: “Buenos días, [nombre] - Todas las empresas” to make it clear you’re in aggregate view.

Profile management interface

The profiles table (/dashboard/setup/profiles) displays:

Table columns

  • Nombre - Profile name with persona type badge (Física/Moral)
  • RFC - Tax identification number
  • Regímenes fiscales - Badge list of tax regimes (up to 3 visible)
  • Estado - Status (Active/Frozen)
  • Facturas/Gastos - Usage statistics
  • Acciones - Edit and delete actions

Profile actions

  • Edit - Modify profile details and validation settings (/dashboard/setup/profiles/[id])
  • Delete - Remove profile and all associated data (requires confirmation)
  • Export - Export profile list to PDF or Excel

Tax regime display

The table uses the SAT régimen fiscal catalog to display human-readable regime descriptions:
interface RegimenFiscalItem {
  clave: string;
  descripcion: string;
  aplica_persona_fisica: boolean;
  aplica_persona_moral: boolean;
}
Regimes are fetched from /api/sat/regimenes-fiscales and displayed with proper descriptions.

Profile-specific periods

Financial periods are created per profile:
  • Each profile has its own monthly periods
  • Period IDs are UUIDs
  • Manual entries require a valid period_id for the profile
  • Aggregate view uses period_id “aggregated” (special case)
When viewing “Todas las empresas”, the period_id is “aggregated”, which disables manual income/expense entry since these features require a specific profile’s period.

Data isolation

Complete separation

Each profile’s data is fully isolated:
  • Invoices link to profile via profile_id
  • Expenses link to profile via profile_id
  • Metrics calculated separately per profile
  • Reports generated independently

Cross-profile features

Some features work across profiles:
  • Dashboard aggregate view sums all metrics
  • Trend charts can combine data from multiple profiles
  • Global search can find transactions across profiles

Editing profiles

The edit form (/dashboard/setup/profiles/[id]) allows updating:
interface UpdateProfileRequest {
  nombre?: string;
  rfc?: string;
  tipo_persona?: 'FISICA' | 'MORAL';
  regimenes_fiscales?: string[];
  validaciones_habilitadas?: {...};
}
Changing a profile’s RFC or tax regimes may affect existing invoice and expense validations. Existing data is not revalidated after profile changes.

Export capabilities

The profiles table supports data export:

PDF export

exportProfilesToPDF(profiles: Profile[], stats: ProfileStats[]): Promise<void>
Generates a formatted PDF with:
  • Profile details
  • Tax regimes
  • Usage statistics
  • Validation settings

Excel export

exportProfilesToExcel(profiles: Profile[], stats: ProfileStats[]): Promise<void>
Creates a spreadsheet with:
  • All profile fields
  • Statistics columns
  • Filterable and sortable data