El control horari respecta el període d’alta
Canvi que trenca: fitxar abans de la data d’alta d’un empleat o després de la seva data de baixa respon ara 422 amb el subcode clocking_outside_employment_period. Els saldos diaris afegeixen is_unscheduled i is_outside_employment, el full mensual i el resum d’equip afegeixen un bloc to_date amb els dies tancats, l’horari de l’empleat accepta una data, hire_date passa a ser editable, i reassignar o desassignar un horari que encara no ha començat l’anul·la.
El registre de jornada respecta ara el període d’alta de cada empleat: des
de hire_date fins a termination_date, tots dos dies inclosos. Fins ara l’API
acceptava fitxatges en qualsevol data, el full mensual amagava els minuts
fitxats en dies sense horari, una hire_date errònia no es podia corregir i el
saldo del mes en curs barrejava els dies tancats amb els que encara falten.
Aquesta publicació tanca aquests buits.
Canvi que trenca: fitxar fora del període d’alta respon 422
Tota escriptura que crea o mou un fitxatge comprova ara la seva data amb el
període d’alta de l’empleat. Si la data cau abans de hire_date o després de
termination_date, la petició es rebutja i no s’escriu res.
| Operació | Data que es comprova |
|---|---|
POST /v1/time-entries/clock-in | occurred_at, o l’hora del servidor si s’omet. |
POST /v1/time-entries/manual | started_at i ended_at. |
POST /v1/time-corrections | L’hora proposada d’una correcció add_missing_entry (inici i final) o adjust_time. No es crea cap sol·licitud. |
POST /v1/time-corrections/{time_correction}/approve | Es torna a comprovar en aprovar, amb el període d’alta vigent en aquell moment. La sol·licitud continua pending. |
{
"error": {
"type": "invalid_request_error",
"code": "business_rule_violation",
"subcode": "clocking_outside_employment_period",
"message": "No se puede fichar el 04/05/2026: el empleado está de alta desde el 11/05/2026.",
"param": "occurred_at",
"doc_url": "https://docs.factuarea.com/guides/errors#business_rule_violation",
"request_id": "req_01HKQS5NTIMEOUTSIDEMPLOY01"
}
}La regla compara la data de calendari de l’instant en el seu propi desfasament
UTC, la mateixa data a la qual el full horari imputa el fitxatge. Pausar,
reprendre i fitxar la sortida d’un tram ja obert mai no es bloquegen, i tampoc
les correccions remove_entry ni els rebuigs.
Què cal fer. Si la teva integració fitxa empleats abans de la seva data
d’alta, per exemple perquè els crea amb una data provisional, corregeix abans
hire_date amb PUT /v1/employees/{employee} (consulta
hire_date editable) i després envia els fitxatges. Ramifica segons
error.subcode; el message és text en castellà orientat a persones que indica
la data d’alta o de baixa. Consulta
clocking_outside_employment_period.
Marques diàries: is_unscheduled i is_outside_employment
Cada element de days[] a GET /v1/time-balances/monthly-sheet i
GET /v1/time-balances/employee/{employee} guanya dos booleans:
| Camp | true quan | Efecte en el dia |
|---|---|---|
is_unscheduled | El dia és dins del període d’alta però no té cap horari de treball vigent. | worked_minutes són els minuts realment fitxats; expected_minutes, balance_minutes i overtime_minutes valen 0. |
is_outside_employment | El dia és anterior a hire_date o posterior a termination_date. | expected_minutes val 0 encara que una assignació d’horari cobreixi el dia; el saldo i les hores extra valen 0. Els fitxatges registrats abans d’aquesta publicació continuen comptant com a minuts treballats. |
Les dues marques mai no són true alhora. Abans d’aquesta publicació, un període
sense cap horari mostrava 0 minuts treballats, i els minuts fitxats en un dia
sense horari podien comptar com a hores extra. Ara aquests minuts sempre
apareixen com a treballats i mai no compten com a hores extra. Per això
total_balance_minutes és la suma dels saldos diaris i pot diferir de
total_worked_minutes − total_expected_minutes quan hi ha minuts fitxats en
aquests dies.
El detall diari congelat de l’informe de tancament mensual no inclou aquestes marques, i els tancaments ja congelats conserven les seves xifres.
to_date davant dels camps total_*
Els camps total_* de GET /v1/time-balances/monthly-sheet i de cada fila de
GET /v1/time-balances/team-summary conserven el seu significat: cobreixen el
mes complet. Per això, en el mes en curs són una projecció que ja resta els
minuts esperats d’avui i dels dies que falten, i total_balance_minutes mostra
un dèficit fins que acaba el mes.
Totes dues respostes afegeixen ara un bloc to_date amb l’acumulat dels dies
tancats, és a dir, tots els anteriors a avui:
"to_date": {
"through_date": "2026-05-24",
"expected_minutes": 7200,
"worked_minutes": 7290,
"balance_minutes": 90,
"overtime_minutes": 60
}through_dateés l’últim dia tancat inclòs, normalment ahir. Avui queda fora perquè la seva jornada encara està en curs.- En un mes acabat,
to_datecoincideix amb els campstotal_*. - Quan encara no s’ha tancat cap dia del mes (el seu primer dia, o un mes
futur),
through_dateésnulli les quatre xifres valen 0. - El bloc és sempre present a totes dues respostes.
GET /v1/time-balances/employee/{employee}no l’inclou.
Mostra to_date.balance_minutes com el saldo fins a la data i reserva els camps
total_* per a la projecció del mes.
Horari de l’empleat en una data
GET /v1/work-schedules/employee/{employee} accepta un query param opcional
date (Y-m-d, avui per defecte) i retorna l’horari vigent aquell dia.
Fes-lo servir per llegir un horari que comença en el futur, com el que s’ha
assignat des d’una data d’alta pendent:
curl "https://api.factuarea.com/v1/work-schedules/employee/01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c?date=2026-10-12" \
-H "Authorization: Bearer $FACTUAREA_API_KEY"Si no hi ha horari vigent aquell dia continua responent
404 schedule_assignment_not_found. Un date que no és una data Y-m-d
vàlida respon 422.
hire_date editable
PUT /v1/employees/{employee} accepta hire_date (Y-m-d). Si s’omet, no
canvia. No pot ser posterior a la termination_date de l’empleat: en aquest cas
la resposta és 422 parameter_invalid_value amb subcode invalid_hire_date i
param termination_date. Una data mal formada també respon 422.
curl -X PUT https://api.factuarea.com/v1/employees/01931b3e-7c4a-7f2e-9a8b-4d6e7f8a9b0c \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 01928f10-7c0e-7c4a-9b7d-2f8a6e3c1d4c" \
-d '{ "hire_date": "2026-09-01" }'Canviar-la mai no esborra res. Els fitxatges i les assignacions d’horari
existents es conserven, i els fitxatges que queden fora del nou període d’alta
continuen al registre, marcats amb is_outside_employment.
El catàleg d’errors inclou ara invalid_hire_date. Tant
PUT /v1/employees/{employee} com POST /v1/employees/{employee}/deactivate
el documenten amb un exemple 422; la baixa ja el retornava quan la
termination_date era anterior a la hire_date. Consulta
invalid_hire_date.
Anul·lar una assignació que encara no ha començat
POST /v1/work-schedules/{schedule}/assign i
POST /v1/work-schedules/{schedule}/unassign responien 422 quan l’assignació
oberta de l’empleat començava en el futur i la nova data era anterior o igual al
seu inici, per exemple en avançar un horari assignat des d’una data d’alta
errònia. Ara aquesta assignació s’anul·la: es tanca com a tram buit
(effective_to igual al seu effective_from), es conserva a l’històric i mai
no és vigent. Una desassignació sense effective_to, que pren per defecte la
data d’avui, també l’anul·la.
Retrotreure l’inici d’una assignació que ja és vigent, és a dir, que va començar
avui o abans, continua responent 422.
Tancament mensual
POST /v1/monthly-time-record-closes inclou ara tot empleat el període d’alta
del qual se solapa amb el mes (donat d’alta fins al seu últim dia i sense baixa
anterior al seu primer dia), sigui quin sigui el seu estat actual. Un empleat que
causa baixa durant el mes apareix a l’informe i a l’exportació de nòmina
d’aquell mes; un de donat d’alta després del mes en queda fora. La resposta i el
format del segell no canvien.
MCP
Les tools comparteixen les mateixes regles:
clock_in,record_manual_time_entry,request_time_correctioniapprove_time_correctionretornen el mateix rebuigclocking_outside_employment_period.get_monthly_time_sheetiget_employee_time_balanceretornen les marques diàries;get_monthly_time_sheetiget_team_time_balance_summaryretornento_date.get_employee_work_scheduleacceptadate, iupdate_employeeacceptahire_date.assign_work_schedule,unassign_work_scheduleiclose_monthly_time_recordsegueixen les noves regles d’assignació i de tancament.
Consulta el catàleg de tools MCP.
Endpoints actualitzats13
| Endpoint | Descripció |
|---|---|
POST/v1/time-entries/clock-in | Fitxar l'entrada d'un empleat |
POST/v1/time-entries/manual | Registrar una entrada manual retroactiva |
POST/v1/time-corrections | Sol·licitar una correcció de fitxatge |
POST/v1/time-corrections/{time_correction}/approve | Aprovar una correcció de fitxatge |
GET/v1/time-balances/monthly-sheet | Obtenir el full horari mensual d'un empleat |
GET/v1/time-balances/employee/{employee} | Obtenir el saldo horari d'un empleat per a un període |
GET/v1/time-balances/team-summary | Obtenir el resum de saldo horari de l'equip |
GET/v1/work-schedules/employee/{employee} | Obtenir l'horari d'un empleat en una data |
PUT/v1/employees/{employee} | Actualitzar un empleat |
POST/v1/employees/{employee}/deactivate | Desactivar un empleat |
POST/v1/work-schedules/{schedule}/assign | Assignar un horari a un empleat |
POST/v1/work-schedules/{schedule}/unassign | Desassignar un horari d'un empleat |
POST/v1/monthly-time-record-closes | Tancar un registre de jornada mensual |