API docs
Resources
Employees
Read records, export ready-to-use payroll files, update fields and sync bidirectionally with your payroll software. Writes never create new employees, they update matched ones (conservative merge).
Canonical model
Internally we keep a single canonical employee model from which all exports are built. Import and PATCH never wipe data, they only fill in empty or changed fields. Creating an employee from scratch happens through a separate onboarding flow.GET/employees
List of the tenant's employees (summary data, without decrypted PII). The response is paginated.
Query parameters
statusstringopcjonalne | filter by onboarding status (e.g. completed). |
companyIduuidopcjonalne | restrict to a single company (payer). |
updatedSinceISO-8601opcjonalne | only records changed since the given moment, for incremental sync. |
pageintegeropcjonalne | page number (default 1). |
pageSizeintegeropcjonalne | page size (default 50, max 200). |
curl -H "Authorization: Bearer onb_..." \
"https://www.onboardly.work/api/v1/employees?updatedSince=2026-07-01&pageSize=50"{
"data": [{
"id": "uuid", "firstName": "Jan", "lastName": "Kowalski",
"email": "jan@example.com", "phone": "+48…", "status": "completed",
"contractType": "zlecenie", "isForeigner": false, "nationalityType": null,
"position": "Kelner", "companyId": "uuid",
"startDate": "2026-06-01", "endDate": null,
"updatedAt": "2026-07-10T12:00:00.000Z"
}],
"page": 1, "pageSize": 50, "total": 130, "totalPages": 3
}GET/employees/{id}
Full canonical record with decrypted personal data. Every call logs the PII access (GDPR art. 30).
{
"data": {
"onboardingId": "uuid", "status": "completed",
"firstName": "Jan", "lastName": "Kowalski", "email": "…", "phone": "…",
"pesel": "86010112345", "birthDate": "1986-01-01", "placeOfBirth": "Warszawa",
"nationality": "PL", "isForeigner": false,
"residenceAddress": { "street": "…", "houseNumber": "…", "postalCode": "00-001", "city": "Warszawa", "country": "PL" },
"contractType": "zlecenie", "position": "Kelner",
"occupationCode": "941201", "startDate": "2026-06-01", "endDate": null,
"hourlyRate": 30.0, "bankAccount": "PL…", "bankName": "mBank",
"insurance": { "code": "041100", "confidence": "low", "requiresZusRegistration": true, "document": "ZUA" },
"nfzCode": "07", "pit2": true, "ppkResign": false,
"employer": { "name": "…", "nip": "…", "regon": "…", "address": "…" }
}
}| HTTP | code | Znaczenie |
|---|---|---|
404 | not_found | no such employee in this tenant. |
410 | pii_deleted | personal data deleted (GDPR). |
GET/employees/{id}/export?format=
Returns a ready-to-use file (not JSON) for your payroll software. The Content-Disposition: attachment header; any warnings in the X-Payroll-Warnings header (URL-encoded JSON).
Query parameter
formatenumopcjonalne | kedu | optima | symfonia | csv | xlsx (default kedu). KEDU is the universal ZUS filing read by Płatnik, Optima, Symfonia, enova and Gratyfikant. |
curl -H "Authorization: Bearer onb_..." \
"https://www.onboardly.work/api/v1/employees/{id}/export?format=kedu" -o kedu.xml| HTTP | code | Znaczenie |
|---|---|---|
400 | — | unknown format. |
422 | incomplete | required fields missing, the body contains { blockers[], warnings[] }. |
501 | format_not_ready | format not yet available for this path. |
PATCH/employees/{id}
Update payroll fields (flat columns). All fields optional. PII and address are not edited this way.
Request body
positionstringopcjonalne | job title. |
salaryNetnumberopcjonalne | net salary. |
hourlyRatenumberopcjonalne | hourly rate. |
startDate / endDateYYYY-MM-DDopcjonalne | employment dates. |
nfzCode / nfzBranchstringopcjonalne | NFZ code and branch. |
usName / usCodestringopcjonalne | tax office name and code. |
bankNamestringopcjonalne | bank name. |
nipstringopcjonalne | employee NIP (B2B / PIT-11). |
pit2 / ppkResignbooleanopcjonalne | PIT-2 declaration / PPK opt-out. |
curl -X PATCH -H "Authorization: Bearer onb_..." -H "Content-Type: application/json" \
-d '{"nfzCode":"07","bankName":"mBank","pit2":true}' \
"https://www.onboardly.work/api/v1/employees/{id}"{ "ok": true, "updated": ["nfzCode", "bankName", "pit2"] }| HTTP | code | Znaczenie |
|---|---|---|
400 | invalid | invalid field value. |
400 | empty | no fields to update. |
404 | not_found | no such employee in this tenant. |
POST/employees/import
Preview of the import, writes nothing. Parses the file and matches records by PESEL (fallback: first name + last name + date of birth).
Request body
formatenumwymagane | kedu | symfonia | optima | csv | xlsx. |
contentstringwymagane | file content (max 5 MB). |
curl -X POST -H "Authorization: Bearer onb_..." -H "Content-Type: application/json" \
-d '{"format":"kedu","content":"<KEDU>...</KEDU>"}' \
"https://www.onboardly.work/api/v1/employees/import"{
"total": 12, "matched": 10, "new": 2,
"rows": [{
"name": "Jan Kowalski", "pesel": "860…",
"matchedOnboardingId": "uuid", "match": "matched"
}]
}| HTTP | code | Znaczenie |
|---|---|---|
422 | parse_failed | the file could not be parsed. |
501 | format_not_ready | format parser not ready. |
POST/employees/import/confirm
Commit the import, conservative merge (fills in only empty or changed fields, never wipes). Upsert exclusively to matched and confirmed identifiers. Does not create new employees.
Request body
formatenumwymagane | as in the preview. |
contentstringwymagane | file content. |
confirmIdsuuid[]wymagane | identifiers of the matched employees to save. |
{
"updated": 2, "skipped": 1,
"updatedDetail": [{ "onboardingId": "uuid", "fields": ["personal.pesel", "nfzCode"] }],
"skippedDetail": [{ "reason": "brak zmian", "pesel": "…" }]
}POST/employees/{id}/zus/deregister
Sets the employment end date and returns a KEDU ZWUA file (ZUS deregistration). Requires a prior registration (ZUA/ZZA).
Request body
endDateYYYY-MM-DDwymagane | employment end date. |
curl -X POST -H "Authorization: Bearer onb_..." -H "Content-Type: application/json" \
-d '{"endDate":"2026-07-31"}' \
"https://www.onboardly.work/api/v1/employees/{id}/zus/deregister" -o zwua.xml| HTTP | code | Znaczenie |
|---|---|---|
409 | not_registered | B2B / specific-task contract, no registration, nothing to deregister. |
410 | pii_deleted | personal data deleted (GDPR). |
Implementation notes
- • KEDU export supports ZUA/ZZA; RUD (specific-task contract) is skipped (filed via PUE ZUS); ZWUA only through the deregistration endpoint.
- • The insurance title code for mandate contracts is sometimes
confidence: "low", confirm it before filing with ZUS. - • Import and PATCH do not create employees from scratch, the onboarding flow is for that.