Listar fichajes
GET
/api/v1/attendance Devuelve una entrada por día natural del rango (ambos extremos incluidos) para un empleado: las marcas del día, los minutos realmente trabajados —los descansos ya van descontados— y el saldo frente a su horario. Se pagina por día, no por marca. El rango no puede superar 366 días. La geolocalización de las marcas nunca se devuelve.
Parámetros de consulta
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
user_id | string | Sí | Id del empleado. |
from | string | Sí | Primer día del rango (YYYY-MM-DD). |
to | string | Sí | Último día del rango (YYYY-MM-DD), incluido. |
tz | string | No | Zona horaria IANA con la que se agrupan las marcas por día. |
page | integer | No | Página (desde 1). |
page_size | integer | No | Días por página (máx. 100). |
Ejemplo
Sustituye db_live_tu_clave por tu clave.
curl -s -H "Authorization: Bearer db_live_tu_clave" \
"https://api.dutybeat.com/api/v1/attendance?user_id=u-delm&from=2026-06-03&to=2026-06-03" | jq Respuesta de ejemplo
Lo que imprime cada snippet al ejecutarlo: cURL devuelve el JSON crudo; los snippets de Python y PowerShell piden campos concretos, así que su salida es la de cada uno.
{
"data": [
{
"user_id": "u-delm",
"date": "2026-06-03",
"is_workday": true,
"holiday": null,
"modality": "remote",
"punches": [
{
"type": "in",
"at": "2026-06-03T07:00:00.000Z",
"edited": false
},
{
"type": "break_start",
"at": "2026-06-03T08:30:00.000Z",
"edited": false
},
{
"type": "break_end",
"at": "2026-06-03T08:45:00.000Z",
"edited": false
},
{
"type": "out",
"at": "2026-06-03T12:00:00.000Z",
"edited": false
},
{
"type": "in",
"at": "2026-06-03T13:00:00.000Z",
"edited": false
},
{
"type": "out",
"at": "2026-06-03T16:00:00.000Z",
"edited": false
}
],
"worked_minutes": 465,
"expected_minutes": 480,
"balance_minutes": -15
}
],
"meta": {
"page": 1,
"page_size": 25,
"total": 1
}
}