Timesheet

Correcciones de reconciliación de hojas de horas

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

RateLimit-Limit

Cantidad máxima de solicitudes permitidas en la ventana

RateLimit-Remaining

Capacidad restante

RateLimit-Reset

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

startDate

DateTime

Inicio del intervalo de fechas (inclusive). Formato ISO 8601 o yyyy-MM-dd.

endDate

DateTime

Fin del intervalo de fechas (inclusive). Formato ISO 8601 o yyyy-MM-dd.

version

string

No

Versión de la API (p. ej., "3" o "3.0"). Usa la última versión estable de forma predeterminada.

fields

string

No

Lista de campos a incluir en la respuesta, separados por comas.

expand

string

No

Lista de expansiones de propiedades personalizadas, separadas por comas.

skip

integer

No

Cantidad de registros a omitir para la paginación. El valor predeterminado es 0.

take

integer

No

Cantidad de registros a devolver. El valor predeterminado es 50 (máx. 50).

Encabezados de respuesta:

Encabezado

Descripción

Item-Count

Cantidad de registros devueltos en esta respuesta

Total-Count

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

recordId

integer

No

Id de una entrada de corrección existente que se desea actualizar. Use 0 (u omítalo) para crear una nueva entrada. No puede ser negativo.

date

DateTime

Fecha de la entrada de corrección. Debe ser posterior a la Capitalization Lock Date.

resourceRef

string

Sí*

Id de referencia del recurso (p. ej., "Henry.rogers"). Obligatorio a menos que se proporcione externalRef.

externalRef

string

Sí*

Id de empleado del recurso. Alternativa a resourceRef.

project

string

No

Nombre para mostrar del proyecto. Se usa para resolver entradas de tareas misceláneas cuando projectRef está ausente.

projectRef

string

Sí**

Referencia externa del proyecto (p. ej., "ED-EN-1000").

alternateProjectRef

string

Sí**

Referencia alternativa del proyecto.

financialRef

string

No

Referencia financiera para la entrada de tiempo (p. ej., un código de costo o un elemento de la EDT).

task

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 financialRef.

subActivity

string

No

Tipo de subactividad (p. ej., "Application Support"). Obligatorio para entradas que no son de proyecto; debe coincidir con los valores de subactividad configurados en los metadatos.

hours

decimal

Horas de la corrección. Debe ser mayor que cero para registros nuevos (recordId = 0).

localValue

decimal

No

Valor monetario de reemplazo en moneda local. Cuando se proporciona junto con localCurrencyCode, omite la conversión por tabla de tarifas.

localCurrencyCode

string

No

Código de moneda para localValue (p. ej., "GBP", "USD"). Debe ser un código de moneda válido configurado en el sistema.

notes

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

status

string

Estado general del lote: "success", "partial", "failed" o "error".

totalCount

integer

Cantidad total de registros enviados.

validCount

integer

Cantidad de registros que pasaron la validación y se guardaron.

invalidCount

integer

Cantidad de registros que no pasaron la validación.

correlationId

string

GUID único asignado a esta solicitud para el rastreo y la correlación de registros (logs).

results

array

Lista de Fields, una por cada fila enviada.

status valores

Valor

Significado

"success"

Todos los registros enviados eran válidos y se guardaron.

"partial"

Algunos registros eran válidos y se guardaron; otros no pasaron la validación.

"failed"

Ningún registro era válido; no se guardó nada.

"error"

Se produjo un error de procesamiento inesperado.

Resultado por fila

Campo

Tipo

Descripción

rowIndex

integer

Posición de esta fila dentro de la lista enviada, con base en 1.

isValid

boolean

true si el registro pasó todas las validaciones y se guardó.

status

string

"valid" o "invalid".

validationMessages

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

recordId

integer

TimeActual.Id — use este valor como recordId al enviar una actualización para este registro.

date

DateTime

Fecha de inicio de la hoja de horas para esta entrada de corrección.

resource

string

Nombre completo del recurso.

resourceRef

string

Id de referencia del recurso.

externalRef

string

Id de empleado del recurso.

project

string

Nombre para mostrar del proyecto o la tarea.

projectRef

string

Referencia externa del proyecto.

alternateProjectRef

string

Referencia externa secundaria del proyecto.

financialRef

string

Referencia financiera para la entrada de tiempo.

task

string

Título de la tarea de Flex Board, si corresponde.

subActivity

string

Tipo de subactividad.

hours

decimal

Horas registradas.

localValue

decimal

Valor monetario local almacenado.

localCurrencyCode

string

Código de moneda local.

notes

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

date falta

"Date is required"

hours falta

"Hours is required"

No se proporcionó resourceRef ni externalRef

"Resource Ref or External Ref is required"

No se proporcionó ninguno de projectRef, alternateProjectRef o project

"Project Ref, Alternate Project Ref, or Project is required"

Fase 2 — Validación a nivel de procesador

Se aplica a cada entrada que supera la Fase 1.

Regla

Fragmento del mensaje de error

recordId es negativo

"Record Id is not valid"

date es igual o anterior a la Capitalization Lock Date

"must be later than the Capitalization Lock Date"

No se encontró el recurso por resourceRef

"no resource found matching the Resource Ref"

No se encontró el recurso por externalRef

"no resource found matching the External Ref"

El recurso no tiene un plan de recursos para date

"resource does not have a valid resourceplan for date"

No se encontró el proyecto por projectRef ni alternateProjectRef

"no project found matching the Project Ref"

El tipo de proyecto está excluido de la reconciliación de hojas de horas

"project type is excluded from corrections"

El estado del proyecto impide nuevas entradas

"project status"is excluded from corrections

subActivity está en blanco en entradas que la requieren

"the subactivity value '' is invalid"

El valor de subActivity no está en la lista configurada

"the subactivity value '...' is invalid"

No se encontró el nombre de la tarea miscelánea en la configuración

"is not a valid Miscellaneous Task as configured in Timesheet Configuration"

No se encontró el título de task en las tareas de Flex Board

mensaje de tarea no encontrada

Se proporcionaron tanto task como financialRef

"Task and Financial Ref cannot both be specified"

hours es cero para un registro nuevo (recordId = 0)

"Hours must be greater than zero"

localCurrencyCode no es una moneda válida del sistema

"is not a valid currency code"

recordId > 0 y la combinación enviada no coincide con el registro en la base de datos

"No record found matching."

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

date

Recurso

Proyecto

subActivity

GUID de la tarea

financialRef

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

  1. Validación de la solicitud: cada fila se verifica según las reglas de campos obligatorios.

  2. 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.

  3. 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=3 o version=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

  1. Use el endpoint Find antes de las actualizaciones en lote: llame primero a GET /rest/api/timesheetreconciliation/find para obtener los valores actuales de recordId y 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.

  2. Trate recordId como un identificador opaco: obténgalo del endpoint 'Find'.

  3. Para las actualizaciones, cambie solo hours, localValue, localCurrencyCode o notes: cualquier cambio en date, resourceRef, projectRef, financialRef, subActivity o task en una fila con recordId > 0 hará que falle la verificación de combinación y que se rechace la fila.

  4. 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.

  5. Verifique isValid por fila: recorra results y verifique isValid para identificar las filas rechazadas y sus validationMessages.

  6. Gestione el éxito parcial: el campo status indica "success", "partial" o "failed".

  7. Respete la Capitalization Lock Date: las entradas con una date igual o anterior a la Capitalization Lock Date siempre se rechazan. Verifique la fecha de bloqueo antes de enviar correcciones históricas.

  8. 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 project con el nombre para mostrar de la tarea y deje projectRef y alternateProjectRef vacíos. No incluya subActivity en las filas de tareas misceláneas.

  9. Entradas de tareas de Flex Board: establezca el campo task con el título exacto de la tarea de Flex Board. No combine task con financialRef.

  10. Use el filtrado de campos: use el parámetro de consulta fields para reducir el tamaño del payload de la respuesta cuando solo se necesiten campos específicos.

Was this article helpful?