La API de reconciliación de hojas de horas permite que los usuarios autorizados creen o corrijan entradas de tiempo de forma masiva. Puede enviar una única corrección o un lote de correcciones en una sola solicitud.
Este artículo explica quién puede usar la API, qué información necesita cada corrección, las reglas que se aplican y cómo interpretar los resultados.
Quién puede usarla
Para enviar correcciones de reconciliación de hojas de horas, debe:
-
Ser Administrador financiero, y
-
Ser Administrador de hoja de horas, y
-
Tener habilitada la función Timesheet Corrections para su organización, y
-
Tener habilitada la función Timesheet Reconciliation Correction para su organización.
Si no se cumple alguna de estas condiciones, la solicitud se rechaza con la respuesta 403 Forbidden y no se guarda ninguna corrección.
Qué puede hacer
-
Enviar una corrección individual – envíe una entrada de corrección y reciba el resultado de esa entrada.
-
Enviar un lote de correcciones – envíe muchas entradas de corrección a la vez y reciba un resultado por fila además de un resumen general.
Cada entrada crea una nueva corrección o actualiza una existente. Para actualizar una corrección existente, incluya su Id de registro. Para crear una nueva corrección, deje el Id de registro vacío (o configúrelo en 0).
Información necesaria para cada corrección
Cada entrada de corrección está compuesta por los siguientes campos.
Obligatorios
Toda entrada debe incluir todo lo siguiente:
-
Fecha – la fecha a la que corresponde el tiempo.
-
Horas – la cantidad de horas que se registran para la corrección.
-
Una forma de identificar el recurso – proporcione una Referencia de recurso o una Referencia externa.
-
Una forma de identificar el trabajo – proporcione al menos uno de Referencia de proyecto, Referencia alternativa de proyecto o Proyecto (nombre) para el trabajo no relacionado con proyectos, como 'Leave' etc.
Opcionales
Estos campos se pueden proporcionar para agregar más detalle o para admitir escenarios específicos:
-
Id de registro – el identificador de una corrección existente que desea actualizar. Para obtener el Id de registro de correcciones existentes, use el endpoint 'Find' para obtener las correcciones de un intervalo de fechas. Omita el Id de registro para crear una nueva corrección.
-
Recurso – el nombre del recurso (persona).
-
Referencia financiera – una referencia financiera asociada con el trabajo.
-
Tarea – la Flex Task a la que se refiere el tiempo.
-
Subactividad – una actividad más específica dentro de la tarea.
-
Valor local – un valor monetario para la entrada, en moneda local.
-
Código de moneda local – la moneda del Valor local.
-
Notas – notas de texto libre sobre la corrección.
Reglas de validación
Las correcciones se verifican en dos etapas.
1. Verificaciones básicas (de la entrada)
Estas se aplican primero a cada entrada:
-
Se debe proporcionar una Fecha.
-
Se deben proporcionar las Horas.
-
El recurso debe poder identificarse mediante una Referencia de recurso o una Referencia externa.
-
El trabajo debe poder identificarse mediante una Referencia de proyecto, una Referencia alternativa de proyecto o un nombre de Proyecto.
-
RecordId debe ser mayor o igual que 0.
Una entrada que no supere alguna de estas verificaciones se marca como no válida y no se procesa más. El motivo se devuelve junto con esa entrada.
2. Verificaciones de negocio
Las entradas que superan las verificaciones básicas se validan luego contra los datos y las reglas de su organización, por ejemplo:
-
El RecordId debe existir en el sistema.
-
El recurso referenciado debe existir.
-
El proyecto o elemento de trabajo referenciado debe existir y ser válido para correcciones de hojas de horas.
-
La fecha debe estar dentro de un período abierto para corrección (los períodos que se hayan bloqueado o que sean anteriores a la Capitalization Lock Date no se pueden corregir).
-
El Proyecto debe ser de un tipo o estado que la Timesheet Configuration marque como excluido de las correcciones.
-
Cualquier moneda proporcionada debe ser válida.
Las entradas que no superan una verificación de negocio se marcan como no válidas y el motivo específico se devuelve junto con la fila correspondiente. Las entradas que superan todas las verificaciones se envían.
Se admite el éxito parcial. Cuando envía un lote, las entradas válidas se aplican aunque otras entradas del mismo lote sean no válidas. No necesita reenviar todo el lote para corregir una sola fila con errores.
Cómo interpretar los resultados
Corrección individual
La respuesta indica si la entrada fue válida o no válida, e incluye los mensajes de validación que expliquen por qué se rechazó una entrada.
Lote de correcciones
La respuesta incluye un resumen general y un desglose por fila:
-
Estado – el resultado general del lote:
-
success – todas las entradas fueron válidas y se aplicaron.
-
partial – algunas entradas fueron válidas y se aplicaron; otras fueron no válidas.
-
failed – ninguna entrada fue válida; no se aplicó nada.
-
-
Cantidad total – la cantidad de entradas enviadas.
-
Cantidad válida – la cantidad de entradas que pasaron la validación y se aplicaron.
-
Cantidad no válida – la cantidad de entradas que no pasaron la validación.
-
Resultados por fila – para cada entrada, si fue válida y los mensajes de validación correspondientes.
-
Id de correlación – una referencia para el lote, útil al revisar o dar seguimiento a un envío.
Consejos para un envío sin errores
-
Incluya siempre la Fecha y las Horas en cada entrada.
-
Proporcione una Referencia de recurso o Referencia externa para que el recurso se pueda identificar sin ambigüedad.
-
Proporcione una Referencia de proyecto, Referencia alternativa de proyecto o nombre de Proyecto para que el trabajo se pueda identificar.
-
Asegúrese de que la Fecha esté dentro de un período que todavía esté abierto para reconciliación.
-
Para actualizar una corrección existente en lugar de crear una nueva, incluya su Id de registro.
-
Al enviar un lote, revise los resultados por fila para poder corregir y reenviar solo las filas que fallaron.
-
URL base
/rest/api/timesheetreconciliation
Límites de tasa
|
Endpoint |
Límite |
|---|---|
|
GET Find |
100 solicitudes cada 10 segundos |
|
POST single |
20 solicitudes cada 5 segundos |
|
POST bulk |
10 solicitudes cada 2 segundos |
El estado del límite de tasa se devuelve en los encabezados de la respuesta:
|
Encabezado |
Descripción |
|---|---|
|
|
Cantidad máxima de solicitudes permitidas en la ventana |
|
|
Capacidad restante |
|
|
Segundos restantes hasta que se reinicie la ventana |
Endpoints
1. Buscar registros de corrección por intervalo de fechas{#find}
Recupera los registros de corrección de reconciliación de hojas de horas para el intervalo de fechas especificado. Tanto startDate como endDate son obligatorios.
Ejemplo HTTP
Endpoint: GET /rest/api/timesheetreconciliation/find
Ejemplo cURL
curl -X GET "https://organisation.fluid.work/rest/api/timesheetreconciliation/find?startDate=2026-07-01&endDate=2026-07-31&version=3.0" \
-H "Authorization: Bearer {your_api_token}" \
-H "Accept: application/json"
Parámetros de consulta:
|
Parámetro |
Tipo |
Obligatorio |
Descripción |
|---|---|---|---|
|
|
DateTime |
Sí |
Inicio del intervalo de fechas (inclusive). Formato ISO 8601 o |
|
|
DateTime |
Sí |
Fin del intervalo de fechas (inclusive). Formato ISO 8601 o |
|
|
string |
No |
Versión de la API (p. ej., |
|
|
string |
No |
Lista de campos a incluir en la respuesta, separados por comas. |
|
|
string |
No |
Lista de expansiones de propiedades personalizadas, separadas por comas. |
|
|
integer |
No |
Cantidad de registros a omitir para la paginación. El valor predeterminado es |
|
|
integer |
No |
Cantidad de registros a devolver. El valor predeterminado es |
Encabezados de respuesta:
|
Encabezado |
Descripción |
|---|---|
|
|
Cantidad de registros devueltos en esta respuesta |
|
|
Cantidad total de registros coincidentes |
Respuesta:
[
{
"fields": {
"recordId": 1042,
"date": "2026-07-01T00:00:00",
"resource": "Henry Rogers",
"resourceRef": "Henry.rogers",
"externalRef": "EMP-001",
"project": "Project Solara",
"projectRef": "ED-EN-1000",
"alternateProjectRef": null,
"financialRef": "FR-JC-01",
"task": null,
"subActivity": null,
"hours": 8.0,
"localValue": 0.0,
"localCurrencyCode": null,
"notes": null
}
}
]
Respuesta (400 Bad Request) — parámetros de fecha faltantes o no válidos:
{
"message": "startDate and endDate are required and must be valid dates."
}
Respuesta (403 Forbidden):
{
"message": "You do not have the required permission to fetch timesheet reconciliation corrections."
}
2. Crear una entrada de corrección individual
Crea o actualiza una única entrada de corrección de reconciliación de hojas de horas.
Ejemplo HTTP
Endpoint: POST /rest/api/timesheetreconciliation
Cuerpo de la solicitud:
{
"fields": {
"recordId": 0,
"date": "2026-07-01T00:00:00Z",
"resourceRef": "Henry.rogers",
"projectRef": "ED-EN-1000",
"financialRef": "FR-JC-01",
"subActivity": "Application Support",
"hours": 8.0,
"localValue": 350.00,
"localCurrencyCode": "GBP",
"notes": "July correction"
}
}
Ejemplo cURL
curl -X POST "https://organisation.fluid.work/rest/api/timesheetreconciliation?version=3.0" \
-H "Authorization: Bearer {your_api_token}" \
-H "Content-Type: application/json" \
-d '{
"fields": {
"recordId": 0,
"date": "2026-07-01T00:00:00Z",
"resourceRef": "Henry.rogers",
"projectRef": "ED-EN-1000",
"financialRef": "FR-JC-01",
"subActivity": "Application Support",
"hours": 8.0,
"localValue": 350.00,
"localCurrencyCode": "GBP",
"notes": "July correction"
}
}'
Respuesta — Entrada válida:
{
"fields": {
"rowIndex": 1,
"isValid": true,
"status": "valid",
"validationMessages": []
}
}
Respuesta — Error de validación:
{
"fields": {
"rowIndex": 1,
"isValid": false,
"status": "invalid",
"validationMessages": [
"This row was skipped as Project 'Vacations' is not a valid Miscellaneous Task as configured in Timesheet Configuration."
]
}
}
Respuesta (403 Forbidden):
{
"message": "You do not have the required permission to create timesheet reconciliation corrections."
}
3. Crear entradas de corrección en lote
Envía varias entradas de corrección de reconciliación de hojas de horas en una sola solicitud. Cada entrada se valida y procesa de forma independiente. Las filas no válidas no impiden que se guarden las filas válidas.
Ejemplo HTTP
Endpoint: POST /rest/api/timesheetreconciliation/bulk
Cuerpo de la solicitud:
[
{
"fields": {
"recordId": 0,
"date": "2026-07-01T00:00:00Z",
"resourceRef": "Henry.rogers",
"projectRef": "ED-EN-1000",
"hours": 8.0
}
},
{
"fields": {
"recordId": 1042,
"date": "2026-07-02T00:00:00Z",
"resourceRef": "Henry.rogers",
"projectRef": "ED-EN-1000",
"financialRef": "FR-JC-01",
"hours": 10.5
}
},
{
"fields": {
"recordId": 0,
"date": "2026-07-03T00:00:00Z",
"resourceRef": "unknown.user",
"projectRef": "ED-EN-1000",
"hours": 8.0
}
}
]
Ejemplo cURL
curl -X POST "https://organisation.fluid.work/rest/api/timesheetreconciliation/bulk?version=3.0" \
-H "Authorization: Bearer {your_api_token}" \
-H "Content-Type: application/json" \
-d '[
{
"fields": {
"recordId": 0,
"date": "2026-07-01T00:00:00Z",
"resourceRef": "Henry.rogers",
"projectRef": "ED-EN-1000",
"hours": 8.0
}
},
{
"fields": {
"recordId": 1042,
"date": "2026-07-02T00:00:00Z",
"resourceRef": "Henry.rogers",
"projectRef": "ED-EN-1000",
"financialRef": "FR-JC-01",
"hours": 10.5
}
}
]'
Respuesta — Éxito parcial:
{
"status": "partial",
"totalCount": 3,
"validCount": 2,
"invalidCount": 1,
"correlationId": "12345678-1234-1234-1234-123456789012",
"results": [
{
"fields": {
"rowIndex": 1,
"isValid": true
"status": "valid",
"validationMessages": [],
}
},
{
"fields": {
"rowIndex": 2,
"isValid": true
"status": "valid",
"validationMessages": [],
}
},
{
"fields": {
"rowIndex": 3,
"isValid": false
"status": "valid",
"validationMessages": [
"Row 3: no resource found matching the Resource Ref 'unknown.user'"
]
}
}
]
}
Modelo de solicitud
El objeto de solicitud de nivel superior encapsula un objeto fields.
{
"fields": { ... }
}
|
Campo |
Tipo |
Obligatorio |
Descripción |
|---|---|---|---|
|
|
integer |
No |
Id de una entrada de corrección existente que se desea actualizar. Use |
|
|
DateTime |
Sí |
Fecha de la entrada de corrección. Debe ser posterior a la Capitalization Lock Date. |
|
|
string |
Sí* |
Id de referencia del recurso (p. ej., |
|
|
string |
Sí* |
Id de empleado del recurso. Alternativa a |
|
|
string |
No |
Nombre para mostrar del proyecto. Se usa para resolver entradas de tareas misceláneas cuando |
|
|
string |
Sí** |
Referencia externa del proyecto (p. ej., |
|
|
string |
Sí** |
Referencia alternativa del proyecto. |
|
|
string |
No |
Referencia financiera para la entrada de tiempo (p. ej., un código de costo o un elemento de la EDT). |
|
|
string |
No |
Título de la tarea de Flex Board. Se usa cuando la corrección se refiere a una entrada de tarea de Flex Board. No se puede combinar con |
|
|
string |
No |
Tipo de subactividad (p. ej., |
|
|
decimal |
Sí |
Horas de la corrección. Debe ser mayor que cero para registros nuevos ( |
|
|
decimal |
No |
Valor monetario de reemplazo en moneda local. Cuando se proporciona junto con |
|
|
string |
No |
Código de moneda para |
|
|
string |
No |
Notas de texto libre adjuntas a la entrada de corrección. |
* Se requiere resourceRef o externalRef.
** Se requiere projectRef o alternateProjectRef (o project para entradas de tareas misceláneas).
Modelos de respuesta
Devuelto tanto por el endpoint de creación individual como por el de creación en lote.
|
Campo |
Tipo |
Descripción |
|---|---|---|
|
|
string |
Estado general del lote: |
|
|
integer |
Cantidad total de registros enviados. |
|
|
integer |
Cantidad de registros que pasaron la validación y se guardaron. |
|
|
integer |
Cantidad de registros que no pasaron la validación. |
|
|
string |
GUID único asignado a esta solicitud para el rastreo y la correlación de registros (logs). |
|
|
array |
Lista de |
status valores
|
Valor |
Significado |
|---|---|
|
|
Todos los registros enviados eran válidos y se guardaron. |
|
|
Algunos registros eran válidos y se guardaron; otros no pasaron la validación. |
|
|
Ningún registro era válido; no se guardó nada. |
|
|
Se produjo un error de procesamiento inesperado. |
Resultado por fila
|
Campo |
Tipo |
Descripción |
|---|---|---|
|
|
integer |
Posición de esta fila dentro de la lista enviada, con base en 1. |
|
|
boolean |
|
|
|
string |
|
|
|
string[] |
Arreglo de mensajes de error de validación. Vacío cuando es válido. |
Respuesta del endpoint 'Find'
Se devuelve por registro en el endpoint GET /find.
|
Campo |
Tipo |
Descripción |
|---|---|---|
|
|
integer |
|
|
|
DateTime |
Fecha de inicio de la hoja de horas para esta entrada de corrección. |
|
|
string |
Nombre completo del recurso. |
|
|
string |
Id de referencia del recurso. |
|
|
string |
Id de empleado del recurso. |
|
|
string |
Nombre para mostrar del proyecto o la tarea. |
|
|
string |
Referencia externa del proyecto. |
|
|
string |
Referencia externa secundaria del proyecto. |
|
|
string |
Referencia financiera para la entrada de tiempo. |
|
|
string |
Título de la tarea de Flex Board, si corresponde. |
|
|
string |
Tipo de subactividad. |
|
|
decimal |
Horas registradas. |
|
|
decimal |
Valor monetario local almacenado. |
|
|
string |
Código de moneda local. |
|
|
string |
Notas adjuntas a la entrada. |
Reglas de validación
La validación se ejecuta en dos fases: a nivel de solicitud (preprocesador) y a nivel de procesador.
Fase 1 — Validación a nivel de solicitud
Se aplica antes de que se ejecute el procesador. Una fila que no supere alguna de estas verificaciones se marca como no válida y se excluye de la ejecución del procesador.
|
Regla |
Mensaje de error |
|---|---|
|
|
|
|
|
|
|
No se proporcionó |
|
|
No se proporcionó ninguno de |
|
Fase 2 — Validación a nivel de procesador
Se aplica a cada entrada que supera la Fase 1.
|
Regla |
Fragmento del mensaje de error |
|---|---|
|
|
|
|
|
|
|
No se encontró el recurso por |
|
|
No se encontró el recurso por |
|
|
El recurso no tiene un plan de recursos para |
|
|
No se encontró el proyecto por |
|
|
El tipo de proyecto está excluido de la reconciliación de hojas de horas |
|
|
El estado del proyecto impide nuevas entradas |
|
|
|
|
|
El valor de |
|
|
No se encontró el nombre de la tarea miscelánea en la configuración |
|
|
No se encontró el título de |
mensaje de tarea no encontrada |
|
Se proporcionaron tanto |
|
|
|
|
|
|
|
|
|
|
|
Fila duplicada dentro del lote (mismo recurso + proyecto + fecha + finRef + subActivity) |
Solo se considera para el envío el registro más reciente de la lista de duplicados; el resto de los registros duplicados se omite con un mensaje de duplicado detectado |
Coincidencia de combinación para actualizaciones (recordId > 0)
Cuando recordId es mayor que cero, el procesador busca el registro de corrección existente por ese Id y compara los siguientes campos con lo que se envió:
|
campo |
|---|
|
|
|
Recurso |
|
Proyecto |
|
|
|
GUID de la tarea |
|
|
Si algún campo no coincide, la fila se rechaza y el registro existente no cambia. Solo hours, localValue, localCurrencyCode y notes pueden diferir de los valores almacenados — todos los demás campos actúan como clave de identidad para confirmar que se está actualizando el registro correcto.
Comportamiento de procesamiento
-
Validación de la solicitud: cada fila se verifica según las reglas de campos obligatorios.
-
Eliminación de duplicados: las filas que comparten la misma clave
(resourceRef, projectRef, date, financialRef, subActivity)dentro de un mismo lote se deduplican. Se conserva la fila que aparece más tarde en la lista de combinaciones duplicadas; los duplicados anteriores se rechazan sin procesarse. -
Ejecución del procesador: se envían todas las entradas válidas.
Control de versiones
La API admite el control de versiones mediante el parámetro de consulta version:
-
version=3oversion=3.0— API V3 (actual) -
Si se omite, se resuelve a la última versión estable (actualmente V3)
POST /rest/api/timesheetreconciliation?version=3.0
Filtrado de campos
Use el parámetro de consulta fields para limitar los campos que aparecen en la respuesta:
GET rest/api/timesheetreconciliation/find?startDate=2026-08-01&endDate=2026-08-30&fields=resourceRef,projectRef,recordid
Mejores prácticas
-
Use el endpoint Find antes de las actualizaciones en lote: llame primero a
GET /rest/api/timesheetreconciliation/findpara obtener los valores actuales derecordIdy los valores exactos de los campos almacenados en la base de datos. Esto garantiza que la verificación de combinación se supere al enviar actualizaciones. -
Trate
recordIdcomo un identificador opaco: obténgalo del endpoint 'Find'. -
Para las actualizaciones, cambie solo
hours,localValue,localCurrencyCodeonotes: cualquier cambio endate,resourceRef,projectRef,financialRef,subActivityotasken una fila conrecordId > 0hará que falle la verificación de combinación y que se rechace la fila. -
Use el endpoint en lote para envíos de varias filas: el endpoint en lote procesa todas las filas en un solo lote y devuelve resultados por fila. Enviar filas de forma individual mediante varias llamadas POST únicas es menos eficiente.
-
Verifique
isValidpor fila: recorraresultsy verifiqueisValidpara identificar las filas rechazadas y susvalidationMessages. -
Gestione el éxito parcial: el campo
statusindica"success","partial"o"failed". -
Respete la Capitalization Lock Date: las entradas con una
dateigual o anterior a la Capitalization Lock Date siempre se rechazan. Verifique la fecha de bloqueo antes de enviar correcciones históricas. -
Entradas de tareas misceláneas: para las entradas dirigidas a una tarea miscelánea en lugar de a un proyecto estándar, establezca el campo
projectcon el nombre para mostrar de la tarea y dejeprojectRefyalternateProjectRefvacíos. No incluyasubActivityen las filas de tareas misceláneas. -
Entradas de tareas de Flex Board: establezca el campo
taskcon el título exacto de la tarea de Flex Board. No combinetaskconfinancialRef. -
Use el filtrado de campos: use el parámetro de consulta
fieldspara reducir el tamaño del payload de la respuesta cuando solo se necesiten campos específicos.