Factuarea APIDevelopers
Contracte

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-inoccurred_at, o l’hora del servidor si s’omet.
POST /v1/time-entries/manualstarted_at i ended_at.
POST /v1/time-correctionsL’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}/approveEs 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:

Camptrue quanEfecte en el dia
is_unscheduledEl 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_employmentEl 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_date coincideix amb els camps total_*.
  • Quan encara no s’ha tancat cap dia del mes (el seu primer dia, o un mes futur), through_date és null i 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_correction i approve_time_correction retornen el mateix rebuig clocking_outside_employment_period.
  • get_monthly_time_sheet i get_employee_time_balance retornen les marques diàries; get_monthly_time_sheet i get_team_time_balance_summary retornen to_date.
  • get_employee_work_schedule accepta date, i update_employee accepta hire_date.
  • assign_work_schedule, unassign_work_schedule i close_monthly_time_record segueixen les noves regles d’assignació i de tancament.

Consulta el catàleg de tools MCP.

Endpoints actualitzats13

EndpointDescripció
POST/v1/time-entries/clock-inFitxar l'entrada d'un empleat
POST/v1/time-entries/manualRegistrar una entrada manual retroactiva
POST/v1/time-correctionsSol·licitar una correcció de fitxatge
POST/v1/time-corrections/{time_correction}/approveAprovar una correcció de fitxatge
GET/v1/time-balances/monthly-sheetObtenir 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-summaryObtenir 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}/deactivateDesactivar un empleat
POST/v1/work-schedules/{schedule}/assignAssignar un horari a un empleat
POST/v1/work-schedules/{schedule}/unassignDesassignar un horari d'un empleat
POST/v1/monthly-time-record-closesTancar un registre de jornada mensual

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport