Employment Records
Keep the employment and working-time records the law asks for
Record each employment, what the person did each day and how long to keep each record. The rules come from the person's jurisdiction, not your company address.
Add your first employment recordFree account, no card needed. The Payroll pack is €19.99/month, excluding VAT, and you add it in the app.
THE EMPLOYMENT RECORD
Everything starts from the employment record
Everything else hangs off it: the contract, the working-time record, the payslips.
An employment record says who works for you, under what kind of arrangement, in which country, in which time zone, and from when.
Working-time days, and payslips linked to an employment, take their rules from the employment, not from your organization.
A Romanian company with a remote employee in Spain gets Spanish rules for that person, automatically, everywhere the rules are consulted.
-
Jurisdiction splits by concern:
the country governing working time is not always the one governing payroll, social security or tax, so each is named separately rather than assumed.
-
Down to the subdivision:
a US state or a Spanish autonomous community can be named, and is checked against the country it is claimed to belong to.
-
Seven kinds of engagement
Permanent, fixed-term, part-time, day laborer, copyright, contractor and internship.
-
Its own timezone
Anchored per employment, not per company, so a distributed team does not share one clock.
-
Where the facts came from
A start date carries its source, so an inferred date never reads as a confirmed one.
-
Official registration, stated
Every employment says where it stands with the official registry: unknown, not required, required or confirmed. It is never quietly implied to be done.
-
Agreements on record
Opt-outs and exemptions, such as the UK 48-hour opt-out, are kept with their date, their evidence and their end date.
-
Survives the person leaving
The identity is kept encrypted on the employment, so the record outlives the user account being removed.
The questions arrive years after the work
An inspection, a dispute, a former employee asking for proof.
-
The timesheet lives in a spreadsheet
Without Enlivy: One file per month, on somebody's drive, with no history of who changed what. When a month is questioned, there is no way to show it was not edited afterwards.
With Enlivy: Every change keeps the previous state and who made the change, and an hourly scan checks for anything that changed without going through the app.
-
Nobody signed anything
Without Enlivy: The record says a person worked those hours, but nothing shows anyone ever confirmed it was right.
With Enlivy: A second person in your organization can confirm a month, and correcting a confirmed day voids that confirmation rather than hiding it.
-
A remote hire breaks the rules you built
Without Enlivy: You set the company up for one country's labor rules, then hired someone who lives under another set entirely.
With Enlivy: Rules are resolved from the employment, and the country governing working time is named separately from the ones governing payroll, social security and tax.
-
Nobody knows what can be deleted
Without Enlivy: Data you are required to keep sits beside data you are required to remove, and nobody wants to be the one who guesses wrong.
With Enlivy: Each retention rule cites its law, the clean-up lists what it would remove before it deletes anything, and nothing with an unconfirmed retention period can be deleted.
THE DAILY RECORD
A month at a time, filled in by your team
One row per day, saying what the person actually did.
A whole month is written in a single pass.
Each day states its disposition: worked, absent, a rest day, a public holiday, a scheduled non-working day, or honestly not recorded.
Days that carry hours can carry the interval instead, and the hours are calculated from it. A record that can disagree with itself is not a record.
-
Enlivy never fills in a day:
an empty day stays empty until someone on your team records it. Filling it in automatically would mean making up evidence.
-
Romania asks for start and end:
where the local rules require the times, any day carrying hours has to supply both, and the record enforces it.
-
Ten absence reasons
Annual, paid event, unpaid, sick, work accident, maternity, paternity, parental, carers leave and unexcused absence.
-
Overtime, night and weekend
Counted in their own buckets, so premiums can be worked out from the record.
-
Hours you cannot double-state
A day that records an interval may not also assert its own hour count. The span minus the break is the answer.
-
Health detail stays private
The reason behind a sickness absence is visible only with its own permission, which no integration can be given.
-
Work site per day
Where the work happened is part of what the day asserts, not a property of the company.
-
A timesheet your accountant can read
Through the API, export the month in the shape the person doing the payroll actually wants.
Getting the record started
Four steps, and the record is ready when someone asks for it.
No scheduled job fills in a day. You state what happened, Enlivy keeps every version of what you stated, and your team confirms it.
-
Create the employment
The person, the kind of engagement, the country and timezone, the job title, and the contract it was agreed under. This is the row everything else hangs off.
-
Set the working-time terms
The agreed norm, in hours or in days, and from when it applies. Terms change over time, and the record keeps every version.
-
Record the month
Fill the grid: what each day was, the hours or the interval behind them, and the reason for any absence. Save the month in one pass.
-
Confirm and keep
Confirm the month in the app. Where the employment’s country has a retention rule, the rule states how long the month must be kept and which law requires it.
Employment and working-time records
The answer is already in the record
When an inspection asks who worked when, on what terms, and what they were paid, the answer is in one place and it is already written down.
- Free account, no card
- Payroll pack €19.99/month
- Prices exclude VAT
EVIDENCE, HANDLED HONESTLY
Your team confirms the month, and Enlivy checks it for changes
A record only helps if you can say who wrote it, who confirmed it, and whether it changed since.
A second person in your organization can confirm the month.
Before a change to a day is saved, Enlivy keeps the previous content, a fingerprint of it, its version number and who made the change.
Every hour, Enlivy recomputes those fingerprints and reports any day that no longer matches to the Enlivy team. It never repairs a mismatch: repairing legal evidence would falsify it.
-
We say tamper-evident, not tamper-proof:
the fingerprint covers what the day says happened. Anyone who can write to the database could recompute it. This catches accidental and casual changes, and we would rather say so than imply a seal we do not have.
-
Correcting a confirmed day withdraws the confirmation:
and what was confirmed is kept, so nobody can quietly amend a month somebody already signed off.
-
Every day shows where it stands
Each recorded day in the grid reads Confirmed, Not Confirmed or Confirmation Withdrawn.
-
Only a complete month can be confirmed
A month can only be confirmed once the employment's own window inside it is actually complete.
-
Enlivy records who entered each day
Who recorded a day, when, and how it was confirmed are set by Enlivy, never typed in. An API call that tries to set them is refused.
-
Every prior version is kept
Each correction keeps the day's previous content, its version and who replaced it.
-
Confirming is not changing
The fingerprint covers what the day records, not the confirmation details around it, so confirming a day never looks like a change to it.
-
Never repaired automatically
The scan only reads the days it checks. No automatic correction, ever.
HOW LONG YOU MUST KEEP IT
Retention that names the law it comes from
A retention rule is not a number of years in a settings screen. It is a document class, in a jurisdiction, over an effective window, with a condition and a citation.
- The clock is pinned to the statute With the law named, not a rule of thumb.
- Romania: the daily record is kept five years from the end of the financial year
- Legea 82/1991 art. 25, as amended by Legea 36/2023
- Never shortened by counting from the day itself
- Unknown means undeletable A rule we have not verified cannot authorize a deletion.
- A retention period we have not confirmed blocks deletion
- Nothing is removed on an assumption
- A protected record is refused outright
- A clean-up that lists before it deletes Each day it only lists what it would remove. Deleting takes a separate, deliberate run.
- Lists only, by default
- Skips anything protected or with an unconfirmed retention period
- Counts what would go before anything does
What we do, and what we do not
Two boundaries worth stating plainly, because a payroll product that leaves them vague is a product that will disappoint you later.
We keep, we never file. Enlivy produces documents and retains records. It does not transmit anything to a tax or labor authority. Romania’s employment registry is authoritative and ours is operational: where they disagree, the registry is right, which is exactly why every employment states its own registry status instead of implying the filing was done.
We do not calculate payroll. Your accountant remains the calculation engine. Enlivy holds, structures, validates and retains the result.
There is also no clock-in. The daily record is an authored grid, one row per day, not a stream of punches, and we would rather say that than sell you a time clock we have not built.
What the record gives you
The duty to keep these records is yours, which is why Data Export stays available even if a subscription lapses.
- Write a whole month in one pass
Open the grid, state what each day was, and save the month in a single save. No day-by-day data entry.
- Confirm a month once it is complete
Confirm the month from the grid once every day in it is recorded.
- Export the timesheet your accountant wants
Take the month out through the API, in the shape the person doing the payroll actually asked for.
- Keep every prior version of every day
Every change keeps what it replaced and who replaced it.
API reference
Employment and working time from the API
Read and write the employment record programmatically: the employments themselves, the working-time terms behind them, and the month grid that says what each person actually did.
The month is written in one call, not day by day. Provenance fields are refused from the request on purpose: origin, version and content hash are set by the system, so nothing that proves a record can be supplied by the caller.
List the employments in your organization with pagination and navigation metadata. Each row carries the kind of engagement, the job title, the jurisdiction and subdivision that govern it, its own timezone, and where it stands with the official registry.
/organizations/<organization_id>/employments curl -G 'https://api.enlivy.com/organizations/<organization_id>/employments' \
--data-urlencode 'page=1' \
--data-urlencode 'limit=20' \
--data-urlencode 'include_meta=navigation' \
-H "Authorization: Bearer $ENLIVY_API_TOKEN" \
-H 'Accept: application/json' const baseUrl = "https://api.enlivy.com" ;
const token = process.env.ENLIVY_API_TOKEN;
const organizationId = "<organization_id>";
const query = new URLSearchParams({
page: "1",
limit: "20",
include_meta: "navigation",
});
const result = await fetch(`${baseUrl}/organizations/${organizationId}/employments?${query}` , {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/json" ,
},
}).then((response) => response.json());Create the row everything else hangs off. The jurisdiction and timezone are set per employment, not per company, so a Romanian organization hiring in Spain sends `ES` and `Europe/Madrid` here and every later rule resolves from that.
/organizations/<organization_id>/employments curl -X POST 'https://api.enlivy.com/organizations/<organization_id>/employments' \
-H "Authorization: Bearer $ENLIVY_API_TOKEN" \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"organization_user_id": "<user_id>",
"organization_contract_id": "<contract_id>",
"type": "permanent",
"job_title": "Software Engineer",
"jurisdiction_code": "ES",
"timezone": "Europe/Madrid",
"start_date": "2026-09-01"
}' const baseUrl = "https://api.enlivy.com" ;
const token = process.env.ENLIVY_API_TOKEN;
const organizationId = "<organization_id>";
const result = await fetch(`${baseUrl}/organizations/${organizationId}/employments` , {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/json" ,
"Content-Type": "application/json" ,
},
body: JSON.stringify({
organization_user_id: "<user_id>",
organization_contract_id: "<contract_id>",
type: "permanent",
job_title: "Software Engineer",
jurisdiction_code: "ES",
timezone: "Europe/Madrid" ,
start_date: "2026-09-01",
}),
}).then((response) => response.json());Read one employment's month as a grid. Every day states its disposition (worked, absent, a rest day, a public holiday, a scheduled non-working day, or not recorded), with the hours or the interval behind it, and its own version and content hash.
/organizations/<organization_id>/working-time-days/month curl -G 'https://api.enlivy.com/organizations/<organization_id>/working-time-days/month' \
--data-urlencode 'organization_employment_id=<employment_id>' \
--data-urlencode 'month=2026-09' \
-H "Authorization: Bearer $ENLIVY_API_TOKEN" \
-H 'Accept: application/json' const baseUrl = "https://api.enlivy.com" ;
const token = process.env.ENLIVY_API_TOKEN;
const organizationId = "<organization_id>";
const query = new URLSearchParams({
organization_employment_id: "<employment_id>",
month: "2026-09",
});
const result = await fetch(`${baseUrl}/organizations/${organizationId}/working-time-days/month?${query}` , {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/json" ,
},
}).then((response) => response.json());Write the whole month in a single call. A day may carry an interval or its own hour counts, never both, and `expected_version` lets you refuse to overwrite a day somebody else changed while you were working.
/organizations/<organization_id>/working-time-days/month curl -X PUT 'https://api.enlivy.com/organizations/<organization_id>/working-time-days/month' \
-H "Authorization: Bearer $ENLIVY_API_TOKEN" \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"organization_employment_id": "<employment_id>",
"month": "2026-09",
"days": [
{
"date": "2026-09-01",
"disposition": "worked",
"started_at": "2026-09-01T09:00:00+03:00",
"ended_at": "2026-09-01T17:30:00+03:00",
"break_minutes": 30
},
{
"date": "2026-09-02",
"disposition": "absent",
"absence_reason": "annual_leave"
},
{
"date": "2026-09-05",
"disposition": "rest_day"
}
]
}'const baseUrl = "https://api.enlivy.com" ;
const token = process.env.ENLIVY_API_TOKEN;
const organizationId = "<organization_id>";
const result = await fetch(`${baseUrl}/organizations/${organizationId}/working-time-days/month` , {
method: "PUT",
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/json" ,
"Content-Type": "application/json" ,
},
body: JSON.stringify({
organization_employment_id: "<employment_id>",
month: "2026-09",
days: [
{
date: "2026-09-01",
disposition: "worked",
started_at: "2026-09-01T09:00:00+03:00",
ended_at: "2026-09-01T17:30:00+03:00",
break_minutes: 30,
},
{
date: "2026-09-02",
disposition: "absent",
absence_reason: "annual_leave",
},
{ date: "2026-09-05", disposition: "rest_day" },
],
}),
}).then((response) => response.json());Attest a completed month. This endpoint takes second-party methods only, such as `supervisor_approved`: a worker's own confirmation is first-party and comes from the portal, so nobody can confirm a month on someone else's behalf through here.
/organizations/<organization_id>/working-time-days/month/attest curl -X POST 'https://api.enlivy.com/organizations/<organization_id>/working-time-days/month/attest' \
-H "Authorization: Bearer $ENLIVY_API_TOKEN" \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"organization_employment_id": "<employment_id>",
"month": "2026-09",
"attestation_method": "supervisor_approved"
}'const baseUrl = "https://api.enlivy.com" ;
const token = process.env.ENLIVY_API_TOKEN;
const organizationId = "<organization_id>";
const result = await fetch(`${baseUrl}/organizations/${organizationId}/working-time-days/month/attest` , {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/json" ,
"Content-Type": "application/json" ,
},
body: JSON.stringify({
organization_employment_id: "<employment_id>",
month: "2026-09",
attestation_method: "supervisor_approved",
}),
}).then((response) => response.json());Works together with
- Payslips Your accountant works out the figures, and you record each amount in Enlivy on its own line, under your country's payroll code. Enlivy checks that the lines match the payslip's totals.
- Contracts Write a contract, or let Enlivy draft it from your package's template when a client accepts your proposal. You send it, and your client signs online with an optional email or SMS code.
- Users Clients, suppliers, and colleagues share one list in Enlivy. Open anyone's record to see what they owe you or you owe them, their documents, reports, and proposals, as far as your role allows.
- Customer Portal Your clients accept the proposal and sign the contract from the links in your emails, and pay an invoice from the payment link you send. In a portal with your logo, they find their invoices, contracts and subscriptions, and sign in with an email code instead of a password.
- Data Export Choose the period and the record types, and download one archive for your accountant, with a summary spreadsheet for each type if you want one. Free on every plan.
- MCP Connect Claude, ChatGPT, Cursor, or another MCP-compatible assistant to work with your invoices, contracts, and pipeline, within your own permissions.