The Integration Problem

Every HR platform has its own data model. Personio stores a salary in fix_salary. SAP SuccessFactors calls it compensation.basePay. Workday uses worker.compensation.totalBasePayAmount. AFAS labels it SalarisBedrag. For a payroll system that needs to consume data from all of these platforms, the integration surface is enormous — and it multiplies with every country added.

The same field carries different semantic weight in different countries. A "tax class" matters in Germany (Steuerklasse 1–6 drives the entire LSt calculation), is irrelevant in the UK (PAYE uses a tax code instead), and doesn't exist in Singapore (progressive brackets, no classes). A "social security number" is a 12-digit RVNR in Germany, an 11-digit BSN in the Netherlands, a 13-digit NIR in France, and a 9-digit SSN in the US.

The traditional approach is to build point-to-point mappings: Personio→Germany, Personio→Netherlands, SuccessFactors→France, Workday→UK. Each mapping understands both the source system's field model and the target country's case structure. This works, but it creates a combinatorial problem. Ten source systems times eighteen countries equals 180 potential mapping configurations. Adding an eleventh source system requires eighteen new mappings. Adding a nineteenth country requires ten new mappings.

The Global Case Model eliminates this multiplication by introducing an intermediate layer: a single, stable, country-agnostic data contract that all adapters target. The adapter maps source fields to the Global Case Model once. Payroll Engine resolves Global Case domains to country-specific case names at runtime. The two concerns — source mapping and country resolution — are separated.

Twelve Domains, One Bundle

The Global Case Model is implemented as the EmployeeImportBundle — a typed aggregate containing twelve domain-specific DTOs, each representing a distinct functional area of employee payroll data. Together, the twelve domains cover every data category that a payroll calculation can require.

Domain DTO Cluster Tag Example Fields
Employee EmployeeSetupCase GC.Employee FirstName, LastName, DateOfBirth, Nationality
Employment EmploymentSetupCase GC.Employment StartDate, ContractType, WorkSchedule, Probation
Salary SalarySetupCase GC.Salary BaseSalary, PayFrequency, Currency
Tax TaxSetupCase GC.Tax TaxClass, TaxId, FilingStatus
Social Security SocialSecuritySetupCase GC.SocialSecurity SocialSecurityNumber, InsuranceGroup
Banking BankingSetupCase GC.Banking IBAN, BIC, AccountHolder
Pension PensionSetupCase GC.Pension PensionScheme, ContributionRate
Time TimeImportCase GC.Time HoursWorked, OvertimeHours, PeriodStart
Benefits BenefitsSetupCase GC.Benefits BenefitPlan, EmployeeContribution
Garnishment GarnishmentSetupCase GC.Garnishment GarnishmentType, MonthlyAmount, Creditor
Termination TerminationSetupCase GC.Termination TerminationDate, TerminationReason
Leave LeaveSetupCase GC.Leave LeaveType, EntitlementDays

Each domain is independently nullable. An adapter that only provides salary and tax data sets the Salary and Tax properties on the bundle and leaves the other ten as null. The sync engine skips null domains automatically — no empty writes, no placeholder values, no unnecessary case changes in the payroll history.

This is not a lowest-common-denominator approach. The twelve domains are comprehensive enough to express every data category that any of the eighteen supported country regulations can consume. But completeness is optional — a provider imports what it has, and the engine processes what it receives.

Convention over configuration: If a domain property name matches the target PE case field name, no explicit mapping is needed. The Global Case Resolver handles the translation. Explicit FieldMapping entries are only required when the source system's naming diverges from the convention.

Country Resolution at Runtime

The key architectural insight is that country-specific knowledge does not live in the adapter. The adapter produces a country-agnostic bundle. The payroll engine resolves it to country-specific case names at runtime.

This resolution is performed by the GlobalCaseResolver, which uses the regulation's ClusterSet definitions. Each country regulation declares which PE case name corresponds to each Global Case cluster tag. When the BundleSyncEngine processes an EmployeeImportBundle, it queries the payroll's available cases with the GC.All ClusterSet and builds the mapping table.

For example, the same adapter producing a bundle with GC.Employee and GC.Salary data resolves differently depending on the target regulation:

Cluster Tag Germany Netherlands France United Kingdom
GC.Employee DE.Arbeitnehmer NL.Werknemer FR.Salarié UK.Employee
GC.Salary DE.Gehalt NL.Salaris FR.Salaire UK.Salary
GC.Tax DE.Steuer NL.Belasting FR.Impôt UK.Tax
GC.SocialSecurity DE.Sozialversicherung NL.SocialeVerzekering FR.Cotisations UK.NationalInsurance

The adapter code is identical in all four scenarios. Only the target tenant changes. A Personio adapter serving a company with employees in Germany and the Netherlands produces the same bundle structure for both — the GlobalCaseResolver ensures each bundle lands in the correct country-specific case.

Machine-Readable Schemas

The Global Case Model is not just a convention documented in prose. It is published as machine-readable JSON Schema definitions, generated directly from the C# type system using NJsonSchema. These schemas are the canonical contract — they define every property, type constraint, nullability rule, and enumeration value that the data contract supports.

Schema Describes Use Case
provider-configuration Adapter config file Validate adapter configuration in IDE or CI
employee-import-bundle Global Case input Auto-generate iPaaS output shapes, validate import files
field-mapping Field mapping entry Validate custom mapping configurations
result-export-scope Export scope Define outbound export boundaries
forecast-scope Forecast config Configure forecast horizon and parameters

Publishing schemas as machine-readable artifacts creates value at multiple integration points:

  • IDE validation — Reference the schema in a $schema property and get auto-completion, inline documentation, and error highlighting in VS Code, JetBrains, or any JSON Schema-aware editor. Configuration errors surface before deployment, not at runtime.
  • iPaaS integration — Import the employee-import-bundle schema into MuleSoft, Workato, Make, or n8n to auto-generate the output shape for a data mapping step. The integration platform knows the exact structure of the target file — no manual field discovery, no trial-and-error.
  • LLM context — AI assistants working with adapter configurations receive the schema as structured context. The schema tells the LLM what fields exist, what types they expect, and what values are valid — enabling accurate, hallucination-free configuration authoring.
  • CI/CD validation — Validate adapter configuration files against the schema in a CI pipeline before deployment. A misconfigured field mapping fails the build, not the payroll run.

Schemas are generated, not hand-written. Every schema is derived from the authoritative C# type definitions in Adapter.Core using PayrollEngine.JsonSchemaBuilder. When a property is added, renamed, or re-typed in C#, the schema updates automatically on the next build. The schema and the runtime implementation can never diverge.

The iPaaS Integration Pattern

Integration platforms (iPaaS) are the primary beneficiary of machine-readable schemas. A payroll provider using MuleSoft to connect a client's Workday instance to Payroll Engine follows a straightforward pattern:

  1. Import the schema — Load employee-import-bundle.schema.json into the iPaaS platform. The platform generates a typed output shape with all twelve domains and their properties.
  2. Map source fields — Use the iPaaS visual mapper to connect Workday worker fields to the bundle's domain properties. worker.legalName.firstName maps to Employee.FirstName. worker.compensation.basePay maps to Salary.BaseSalary.
  3. Export a JSON file — The iPaaS transform step produces a JSON file conforming to the EmployeeImportBundle schema.
  4. Ingest via JSON adapter — Payroll Engine's file-based JSON adapter reads the file, the BundleSyncEngine resolves Global Case tags to the target country, and the data is written to PE via the REST API.

This pattern decouples the iPaaS platform from Payroll Engine's internal API. The integration contract is a JSON file with a published schema — not a REST endpoint, not an SDK dependency, not a binary protocol. Any system that can produce a conforming JSON file can feed data into Payroll Engine, regardless of whether a native adapter exists for that system.

For source systems without a dedicated adapter — a custom-built HRIS, a niche T&A platform, a government portal — the iPaaS pattern provides a path to integration without writing adapter code. The schema defines the target. The iPaaS handles the source. Payroll Engine handles the payroll.

Compared to Proprietary APIs

Most payroll platforms expose integration through proprietary REST APIs with platform-specific field names, authentication schemes, and versioning strategies. An integration engineer connecting Personio to ADP, Paychex, or SAP must learn each platform's unique API surface — different endpoints, different field models, different error codes.

The Global Case Model takes a different approach:

Aspect Proprietary API Global Case Model
Integration surface Platform-specific endpoints, fields, pagination One JSON Schema, one file contract
Country handling Country-specific API variants or field prefixes Country-agnostic contract, runtime resolution
Schema discovery Documentation pages, trial-and-error Machine-readable JSON Schema, IDE auto-complete
Adding a new source New adapter per source × per country New adapter per source (country-agnostic)
iPaaS compatibility Requires platform-specific connector Any iPaaS that produces JSON files
Contract versioning API version in URL, breaking changes per release Schema generated from types, additive evolution

The key difference is separation of concerns. A proprietary API bundles source mapping, country resolution, and data transport into a single integration point. The Global Case Model separates them: the adapter handles source mapping, the ClusterSet handles country resolution, and the file contract handles transport. Each concern can evolve independently.

Additive Evolution

The Global Case Model evolves additively. When a new domain is needed — a thirteenth DTO for equity compensation, or a fourteenth for expense reimbursement — it is added as a new nullable property on the EmployeeImportBundle. Existing adapters that don't produce the new domain continue to work unchanged. Their bundles simply don't include the new property.

This additive pattern extends to individual domains as well. When a new property is added to SalarySetupCase — say, PaymentMethod — existing adapters that don't set this property produce bundles that remain valid against the schema. The new property is nullable by default. Only adapters that want to provide the new data need updating.

Because schemas are generated from the C# types, the schema file reflects any addition automatically. An iPaaS integration that re-imports the updated schema sees the new field in its mapper. An LLM that receives the updated context knows the field exists. An IDE that validates against the schema accepts the new property. The entire toolchain updates from a single source of truth.

Eighteen countries, one contract. The Global Case Model serves all eighteen country regulations that Payroll Engine supports — from German LSt/SV to Brazilian INSS/FGTS to Singaporean CPF. Each country regulation defines its own ClusterSet mappings, but every adapter targets the same twelve-domain bundle. The contract is universal. The resolution is local.

Explore the data contract

Review the full DTO reference with per-property documentation, download the JSON Schemas, or get in touch to discuss how the Global Case Model fits your integration architecture.

Get in Touch →
← Back
All Articles