Getting started · Wages.software
There is no sign-up form on this page. That is deliberate.
Self-serve onboarding does not exist for this product. We could put a form here and email you afterwards, but a form that does not provision anything is a form that lies about what it does — and on a payroll site, of all places, that is a strange note to open on.
So: a conversation first, and an honest account of what runs today. The calculation engines are written and wired behind a fail-closed finance-officer gate, and twelve gate suites over them run green. What does not exist is a disbursement rail, a filing transmitter, or a set of statutory tax tables.
Before anything else
Three honest uses. If none of them is yours, say so and we will tell you.
This is worth settling before a call rather than during one, because a payroll engine that does not run payroll is useful for a narrower set of reasons than a payroll service is, and the narrow set is real.
Verification. Run your existing provider’s figures through the engines and see whether the per-authority basis, the withholding and the year-end three-way reconcile agree with what you were sent. This is the use that needs the least from you and answers the most: it is the thing you point at a number nobody can explain.
Integration. Each calculation step is its own endpoint, so a finance system can call the piece it needs — the taxable basis, the federal withholding, FICA, the stub composition, the NACHA structural check, the filing reconcile — instead of adopting a whole suite to get one calculation.
Control. The four-eyes approval, the content-hash binding and the change-event hashing are the parts an auditor asks about, and they are enforced in the function that returns the verdict rather than in a policy document. Read the scope bound on that carefully before you count on it: the approval decision is stateless and the change events are not kept, so what exists today is correct control arithmetic without a store behind it.
And the use that is not on the list. If you need the money to move on Friday, you need a full-service payroll provider. We will say that on a call too, and we would rather say it in the first ten minutes than the last.
Who this is for, and who it is not
A business office with a question, not a school without a payroll provider.
It fits a finance officer or business manager who already has payroll running somewhere and wants an independent way to check it — particularly one who has been handed a figure and told it is correct without being shown why. It fits a team building around a finance system that needs one calculation rather than a whole suite. And it fits an organisation whose auditor has asked about segregation of duties and change evidence, provided they read the scope bounds on those controls carefully.
It does not fit a school without a payroll provider. We do not disburse, we do not file, and we ship no statutory tax tables, so we cannot be the thing that pays your staff on Friday. If that is the requirement, buy from a full-service provider — the first three rows of our own comparison table go to them outright for exactly this reason.
It also does not fit an organisation with nobody who can sign for a tax table. The registry ships empty by design, and an unsigned table withholds zero. That is the right behaviour, and it is only useful if there is somebody whose job it is to sign.
And there is a case we would talk you out of: adopting this as a system of record. It is not one. The payroll surfaces persist nothing, five payroll tables exist with no producer, and the module that would create a run has no production caller. Everything here is arithmetic and access control, both of which are real, and none of it is storage.
What actually happens
Four steps, and you can stop after any of them.
-
Tell us which of the three uses is yours
Write to [email protected] with what your business office is actually trying to do — check a provider’s figures, call one calculation from a system you already run, or satisfy a control an auditor asked about. One paragraph is plenty.
If none of the three fits, that is a useful answer and it takes one reply rather than a scheduled call.
-
A walkthrough of what is wired, and what is not
We show the surfaces a registered handler actually calls, and we name the eleven modules that are written and called by nothing. You should leave able to repeat back which is which — that is the whole test of whether the call was honest.
You can do most of this without us first: the reachable surfaces are on the engines page and the eleven are on built, not switched on.
-
One calculation, against numbers you already know the answer to
The right first move is a known-answer comparison, not a pilot. Take a pay period you have already run and already reconciled, and put it through the basis, withholding and FICA endpoints. Either the figures agree with what your provider sent or they do not, and both outcomes are worth the afternoon.
This needs nothing installed and nothing migrated, because the engines hold no state: values go in on the request and a typed result comes back.
-
Widen only if the first answer was useful
Almost nobody should start with the year-end reconcile or the NACHA structural check. Those are the surfaces that pay off once you already trust the per-period arithmetic, and trusting it is what step three is for.
And if the first answer was that your existing provider is right and legible enough, that is a real result. We would rather you reach it in a week than after a procurement.
What step three actually looks like
One pay period, four calls, and a number you already know.
The verification use is the one most business offices should try first, and it is worth describing concretely rather than as a bullet, because the shape of it is unusual: you already know the right answer before you start. That is what makes it cheap.
Take a pay period you have already run and already reconciled. Send the earnings and the deductions for one employee to the taxable-basis endpoint with a signed exemption mask and you get back a basis per authority, each with the amount that reduced it. Compare those to the basis figures on the stub you were sent. If they differ, the difference is almost always a deduction class treated as pre-tax for the wrong authority, and it will be the same on every period since the deduction was set up.
Send the federal basis and a signed bracket table to the federal withholding endpoint and you get the worksheet worked step by step, with the per-period division floored and the dropped sub-cent fraction returned rather than rounded away. Send the FICA basis and the year-to-date wages to the FICA endpoint and you get the employee and employer sides separately, with Social Security capped, Medicare uncapped, and Additional Medicare employee-only.
Then compose the same inputs through the gross-to-net stub endpoint. It uses the same primitives the three individual endpoints expose, so the composed statement and the individual answers cannot disagree — there is no second arithmetic path for the stub version of a number.
Nothing is installed and nothing is migrated for any of this, because the engines hold no state: values arrive on the request and a typed result comes back. The route module says in its own header that there is no persistence, in those words. If the figures agree with your provider, you have an independent check you can repeat at year end. If they do not, you have a specific disagreement on a specific authority, which is a far better thing to take to a provider than a feeling that the number looks wrong.
What starting does not involve
No card, no charge, no contract signed on a web page.
There is no live checkout on this site and no price on any page of it. Money is switched off end to end: there is no charge rail for buying this, and there is no disbursement rail inside it. The disbursement gate returns an honest-off verdict whenever no licensed partner is configured, and nothing in any wired route configures one.
This site has no contact form; contacting us opens ordinary email, so the message is retained in a mailbox to reply. We use no third-party advertising or tracking scripts and build no behavioral profile; basic short-lived operational logs may record page requests.
And starting does not involve a migration. There is nothing to migrate into, because the payroll surfaces persist nothing — which is a real limitation and is also why the verification use above costs you an afternoon rather than a quarter.
Worth asking us
Four questions we would rather you ask early.
“Who signs the tax tables?” You do, or somebody you employ or retain does. The registry ships empty and the engines invent no rate. If there is nobody in your organisation who can sign for a bracket table, a full-service provider that maintains them for you is a better fit than we are.
“What happens the first time something is missing?” It holds and names the reason — no table, ambiguous window, unsigned, malformed — and the withholding falls to zero rather than to a guess. Zero is obviously wrong to anyone who looks at a stub, which is the point: a visible refusal gets fixed on Tuesday and a plausible guess gets discovered in January.
“Can our employees log in?” The self-service lane is built end to end and walled correctly, and it reads pay tables that nothing in production writes, so today an employee would see an honest empty result. A submitted W-4 or direct deposit would be validated, masked, audited and returned, and stored nowhere. We would rather you hear that here than find it in week two.
“Does any of this touch student data?” No. Payroll and HR are staff-coupled: opaque staff and employee references, no student identity, deliberately outside the student census wall. That is not a claim that we hold no data — an employee record is data, and sensitive data. It is a narrower and more checkable claim.
The operating boundary
A wages engine is not a payroll service, and the difference controls every screen.
Wages.software is being built around calculation and validation boundaries. It can take a deliberately scoped set of wage facts, apply a signed and dated ruleset, and return an explainable result in integer cents. It is not the system that moves money, submits a filing, enrolls a worker, chooses a tax treatment, or declares that a payroll is legally complete. Those duties need different authority, different evidence, and different operational controls. Keeping them outside this product is a product decision rather than a missing footnote.
The arithmetic begins with gross wages and an explicit exemption mask. Each authority receives its own taxable basis because a deduction may reduce federal income-tax wages while leaving Social Security or Medicare wages unchanged. A single field called taxable wages would conceal that distinction. The engine therefore returns separate bases, carries the reason for each exclusion, and refuses an unsigned mask. It never guesses a classification from an employee name, job title, school, or employer.
Money is represented as integer cents. Rates that cannot be represented safely as a decimal are evaluated as integer ratios, with rounding performed at the named boundary. Net is floored at zero and over-deduction is flagged; that return does not recover the shortage from a later check. A W-2, W-3, and Form 941 comparison is a reconciliation result, not a filing. A NACHA-shaped output is checked structurally, but the raw bank file remains withheld. These distinctions matter because an attractive page can otherwise turn a calculation claim into a claim that funds moved.
Rules are data with provenance. Wages.software ships no statutory tables today. The registry starts empty, and an unsigned or out-of-period table cannot silently become active. An operator must be able to identify the authority, effective dates, source artifact, signature, and exact version used for a calculation. A future update process must preserve the prior version so a historical result can be explained with the rules that existed when it was made.
The employee-facing seams follow the same narrow posture. A W-4, direct-deposit change, or address change may be validated, masked, and audited by the relevant module, but the marketing surface does not persist it and does not imply that a production workflow consumes it. The built modules and their test gates are named on this site precisely because several have no production caller. A module can exist, compile, and pass focused tests while remaining intentionally unreachable.
How to read status here
Built names code; reachable names a route; enabled names an operational decision.
Those three words are not synonyms. Built means the repository contains an implementation with a stated contract. Reachable means a registered handler calls it after the relevant tenant and finance-role checks. Enabled would mean an operator has supplied current rules, reviewed the surrounding process, and deliberately turned on a use. Wages.software is in early access, money is switched off, and this site provides no checkout or self-serve account creation.
Every calculation request is intended to sit behind tenant isolation and a fail-closed finance-role gate. Public marketing pages cannot run a calculation, accept employee data, or reveal a result. They explain boundaries and provide one mail address. No page sets a marketing cookie, embeds an advertising tracker, or asks a visitor to paste payroll records into a form. Basic short-lived operational request logs may exist at the hosting boundary, as they do for ordinary web service operation.
The product also avoids claims that cannot yet be supported. There are no customer counts, performance percentages, testimonials, certification badges, or statements that a tax authority accepts an output. The absence of those claims is useful evidence: the decision system should earn trust through named inputs, named refusals, reproducible arithmetic, and a visible line between what software calculates and what an authorized person decides.
Where to go next
The rest of this site.
Every page here is its own argument rather than a restatement of the home page. If you would rather ask a person, the address below reaches one.