Skip to main content
All six countries settle a fortnight. Send period.type: "biweekly" and two fortnights add up to the month exactly, line by line.
Prorating is not dividing. The engine settles the full month and splits the payment. It does not re-run the scheme over half a salary.
That distinction sounds semantic. It is the difference between a correct number and one that is wrong by up to 21%.

Why the obvious shortcut is wrong

“Send half the salary and multiply by two” gets the base salary right and gets everything with a floor, a ceiling or a bracket wrong. Measured against the real engine, country by country:
The two most dangerous cases are the ones that come out right. In Brazil the shortcut is exact to the centavo at the minimum wage — it is the only country in the series with no contribution floor. In Argentina it is exact to the peso at 2,000,000.The error shows up at the edges of the payroll: a minority of headcount, a majority of the money. The natural smoke test — settle a minimum wage in two fortnights and check they add up — passes.
Peru gives the cleanest argument, and it is not about brackets. The IR de 5ta categoria is an annual tax, projected and divided by twelve. Recalculating over half a salary does not say “this worker is paid twice a month”. It says “this worker earns half as much per year”, which is simply false. In CO, CL or BR the shortcut misapplies a table. In PE it asserts a false fact about annual income, and SUNAT sees it at the annual reconciliation.

The model: settle the month, split the payment

The dependency graph runs unchanged over the monthly figures, and the split happens afterwards. Everything non-linear is evaluated exactly where the law defines it: over the month. Not one formula in the rule files changed. Mexico is the only native scheme, because its formulas genuinely prorate (salario_base = daily_salary × period_days) and the IMSS charges by real days. But the ISR tariff and the subsidy are tables, not formulas, and a table cannot read period_days — they were being applied to a base that had already been halved. The fix annualises: apply the monthly table to the equivalent monthly base, then scale the result back to the period. At period_days = 30 the expression reduces to the original, so the monthly case is identical by construction, not by test.

The balancing rule — two fortnights add up to the month

CO, CL and AR round to whole units, so 2 × round(month/2) is not month. Every period but the last takes the rounded share, and the last takes what is left:
Q1 + Q2 == month holds by construction, and both are pure functions of the monthly figure — the engine does not need to remember Q1 to compute Q2. It applies per line, and the totals are derived by summing lines that have already been split. A payslip cannot fail to reconcile with itself. This is not accounting aesthetics. PILA, the F.931, Previred, eSocial and the PLAME are all filed monthly. If the two fortnights do not add up to the month’s contribution, you have a per-employee, per-month difference with the authority.

Subtotals are derived, not split

A concept that is the sum of others cannot be split on its own — it has to add up to what its parts already received. Without that rule, 21% of Chilean fortnights produced a payslip whose “Total Cotizaciones Previsionales” differed by one peso from the three lines above it. In Argentina it would have been 63.6%, because its three rates (11%, 3%, 3%) apply to the same base. The month always reconciled (89,250 + 89,250 = 178,500), which is exactly why no monthly reconciliation ever caught it. What did not reconcile was each individual payslip.

Mexico has no balancing rule, and should not

Under native, each period is settled on its own days: a 14-day period and a 16-day period are not two halves of anything. They land within one cent per line of the month (three on aggregates) — a measured, declared tolerance.

The response contract: period_basis

Additive, and emitted on monthly calculations too, so your client never has to branch on periodicity.
A monthly calculation reports sequence: 1, periods_in_month: 1, factor: "1" and a monthly_equivalent equal to its own summary. monthly_equivalent is what you need to reconcile against the monthly filing. Without it, a fortnightly response cannot be audited without recalculating — or worse, by adding up two fortnights and hoping the rounding agreed.

The sequence is derived, not requested

period.start_date on day 1–15 is the first fortnight; day 16 onward is the second. No new request field: the data was already travelling. A company that pays on the 20th and the 5th is classified correctly with nothing to configure.
period.days is inert under split_monthly. The factor comes from period.type, because on a 30-day commercial month a fortnight is half a month whether the stretch is 14, 15 or 16 days.If days is not 15, the response carries a PERIOD_DAYS_IGNORED warning rather than staying silent. Outside Mexico, period.days does not prorate anything — claiming otherwise repeats exactly the misunderstanding this behaviour exists to close.

What a fortnight is not

This is the part that gets misread, and misreading it costs real money. If you pay advances, keep settling monthly and treat the advance as a deduction in your own system. Its amount is set by the employer and its balance carries state between periods, which is exactly what a stateless engine cannot hold.

Weekly is rejected, in all six countries

The argument is arithmetic, not legal: a month does not contain a whole number of weeks, so the balancing rule has nothing to stand on, and four weeks do not add up to a month against the monthly filing. Argentine and Brazilian law do recognise weekly pay. It makes no difference here. A period.type the scheme does not support returns 422 PERIOD_TYPE_NOT_SUPPORTED, with country, scheme, year, period_type and supported_period_types in details. A batch fails whole, not row by row: a period no row can settle is not one row’s error.

Example

Discover what a scheme supports with GET /v1/payroll/schemes/{country}, which reports supported_period_types per scheme.