Saltar al contenido principal

Tareas — Listado y detalle

Lee tareas con filtrado completo y paginación, elegí cuánto detalle recibir y expandí los bloques pesados (eventos, formularios, adjuntos, pausas, cercas) solo cuando los necesites. Un único recurso de lectura cubre tanto las tareas activas como las finalizadas; nunca te acoplás a dónde vive físicamente la tarea.

Requisitos previos

Todos los endpoints requieren un token JWT válido, una clave de API y el encabezado tenant. Consultá Autenticación.

Alcance de visibilidad

Tener el permiso de lectura no da acceso a todo el tenant. Tanto el listado como el detalle aplican las mismas limitaciones de visibilidad de tu usuario técnico (el usuario atado a tu clave de API): acceso por tarea, aislamiento de procedencia y visibilidad por grupo. Un filtro vacío significa "todo lo que tu usuario técnico puede ver", nunca "todo lo de la compañía". Para ampliar lo que devuelve la API, ampliá la visibilidad del usuario técnico, no el permiso del endpoint.


Niveles de detalle

El recurso de listado expone tres niveles mediante flags de consulta, no tres endpoints distintos:

NivelCómo se pideQué devuelve
EstándarGET /apidev/v1/tasks sin flagsCampos base de la tarea + dynamic_fields[] (campos dinámicos)
ProGET /apidev/v1/tasks?include=...Base + campos dinámicos + bloques pesados opt-in
PersonalizadoGET /apidev/v1/tasks?fields=...Solo los campos pedidos (whitelist cerrada) + campos dinámicos puntuales

include y fields son mutuamente excluyentes: enviar ambos devuelve INCLUDE_FIELDS_CONFLICT. El endpoint de detalle (GET /apidev/v1/tasks/{id}) acepta los mismos flags include/fields.


Listar tareas

Obtiene una lista paginada de tareas con filtrado extenso. Los tres identificadores — serid, service_number, assistance_number — están siempre presentes en cada ítem, incluso en el nivel personalizado.

GET/apidev/v1/tasks
PermisoAPICLI_TASKS_READ
Límite de solicitudes30 solicitudes/min (ventana deslizante)
CachéNinguna

Parámetros de consulta — Paginación y ventana temporal

ParámetroTipoRequeridoPor defectoDescripción
limitintegerNo20Tamaño de página. Mín: 1, Máx: 100 (se recorta con include pesado, ver abajo)
offsetintegerNo0Número de página, 0-based (el servicio aplica OFFSET = offset × limit)
date_typeenumNocreatedQué columna de fecha se filtra: created | scheduled | finished
startdatestringCondicional¹ISO YYYY-MM-DDTHH:MM:SS (sin zona horaria). El rango startdate..enddate debe ser ≤ 31 días
enddatestringCondicional¹Mismo formato; enddate debe ser ≥ startdate

¹ startdate + enddate son obligatorios cuando no filtrás por un identificador puntual (task_ids / external_ids / service_number). Sin un rango de fechas ni un identificador, la solicitud devuelve 400 DATE_RANGE_REQUIRED (protección de rendimiento).

Parámetros de consulta — Filtros por catálogo

Todos los filtros de catálogo son multi-select, enviados como CSV de ids (p. ej. statuses=SA,ASI). Los ids son strings opacos. Un filtro vacío o ausente significa sin filtro; no existe un centinela [Todos].

ParámetroTipoDescripción
statusesCSVCada valor ∈ SA,ASI,ACE,INI,USU,FIN,CAN. Incluir FIN/CAN lee del almacén histórico
procedenciasCSVIds de procedencia
productosCSVIds de producto (línea)
procedence_product_pairsCSVTuplas proid o proid|protipclilin para pareo real padre→hijo
provisionsCSVIds de prestación
causesCSVIds de causa
subcausesCSVIds de subcausa (línea)
provision_cause_pairsCSVTuplas prestaid | prestaid|cauid | prestaid|cauid|causubcaulin
coveragesCSVIds de cobertura (línea)
motivesCSVIds de motivo
end_reasonsCSVIds de fin de servicio
comm_mediaCSVIds de medio de comunicación / plantilla
devicesCSVIds de vehículo
driversCSVIds de conductor / personal
providersCSVIds de prestador
shiftsCSVIds de turno
routesCSVIds de ruta fija
telephonistsCSVIds de telefonista
operatorsCSVIds de operador
reserved_driversCSVIds de conductor reservado
reserved_devicesCSVIds de vehículo reservado
reserved_usersCSVIds de usuario reservado
countrystringId de país (valor único)
departmentsCSVIds de departamento (línea)
account_idstringId de cuenta

Parámetros de consulta — Identificadores y texto libre

ParámetroTipoDescripción
task_idsCSVValores de serid (strings opacos). Máx 200
external_idsCSVIds externos del cliente. Máx 200
service_numberstringNúmero de servicio. Longitud máxima 80
assistance_numberstringNúmero de asistencia. Longitud máxima 80
tracking_numberstringNúmero de tracking. Longitud máxima 120
qstringBúsqueda de texto libre sobre contacto / cuenta / documento. Longitud máxima 200

Parámetros de consulta — Flags de nivel

ParámetroTipoDescripción
includeCSVActiva el nivel Pro. Cada token ∈ forms,events,attachments,invoices,pauses,cercas,dynamic_fields. Token desconocido → 400 INVALID_INCLUDE
fieldsCSVActiva el nivel Personalizado. Cada token de la whitelist de campos. Token desconocido → 400 INVALID_FIELD. dynamic_fields.<label> siempre se acepta
Los bloques pesados necesitan un filtro acotado

include=events, include=forms o include=attachments requieren task_ids / external_ids o un rango de fechas corto; de lo contrario, la solicitud devuelve 400 INCLUDE_REQUIRES_NARROWER_FILTER. Cuando se pide un bloque pesado, el limit efectivo se recorta (menor con events/forms, mayor con solo attachments); el recorte aplicado se informa en meta.capped y meta.limit.

Campos de la respuesta — Nivel estándar

El conjunto de campos del nivel estándar es fijo y estable. Todos los ids son strings opacos. Todas las fechas se serializan crudas del row (timestamp sin zona horaria) o como string vacío ""; nunca se emite null dentro del payload de la tarea.

CampoTipoDescripción
seridstringIdentificador único de la tarea (siempre presente)
service_numberstringNúmero de servicio (siempre presente)
assistance_numberstringNúmero de asistencia (siempre presente)
external_idstringIdentificador externo del cliente
statusstringCódigo de estado: SA,ASI,ACE,INI,USU,FIN,CAN
status_labelstringEstado en forma legible
prioritynumberPrioridad de la tarea
detailstringDetalle de texto libre
tracking_numberstringNúmero de tracking
created_atstringMarca de tiempo de llamada/creación
scheduled_atstringMarca de tiempo agendada
scheduled_untilstringMarca de tiempo agendada-hasta
computesbooleanSi la tarea computa para facturación/métricas
contactobject{ name, phone, phone_mobile }
accountobject{ name, external_code, document, policy }
classificationobjectprocedence{id,name}, product{id,line,name}, coverage{name}, provision{name}, motive{name}, cause{name}, subcause{name}
originobjectcountry, department, city, zone, street, corner, door_number, apt, special_place, lat, lng
destinationobjectMisma forma que origin (espejo)
vehicleobject{ plate, brand, model, year, color }
assignmentobjectdevice, device_imei, device_type, driver, driver_external_code, provider, operator, telephonist, communication_medium
reserveobject{ driver, provider, mobile, user }
loadobjectDatos de carga { weightKg?, volumeM3?, packages?, requiresCold?, requiresFragile?, requiresHeavy? }. Solo aparecen las dimensiones que el producto habilita; se omite entero cuando el producto no tiene perfil de carga
dynamic_fieldsarrayCampos dinámicos como [{ label, value }] (ver Campos dinámicos)

Ejemplo de código

curl -s "https://$TENANT/apidev/v1/tasks?date_type=created&startdate=2026-06-24T00:00:00&enddate=2026-06-24T23:59:59&statuses=ASI,INI&limit=2" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"

Respuesta de ejemplo

{
"success": true,
"data": [
{
"serid": "920183744012",
"service_number": "103878",
"assistance_number": "44021",
"external_id": "OT-2026-0099",
"status": "INI",
"status_label": "Iniciado",
"priority": 2,
"detail": "Cliente reporta auto sin arranque.",
"tracking_number": "TRK-9981",
"created_at": "2026-06-24T09:12:00",
"scheduled_at": "2026-06-24T11:00:00",
"scheduled_until": "",
"contact": { "name": "Ana Pérez", "phone": "099111222", "phone_mobile": "" },
"account": { "name": "Ana Pérez", "external_code": "CLI-55", "document": "1.234.567-8", "policy": "POL-77" },
"classification": {
"procedence": { "id": "12", "name": "Seguros del Sur" },
"product": { "id": "12", "line": "3", "name": "Auxilio Mecánico" },
"coverage": { "name": "Cobertura Total" },
"provision": { "name": "Remolque" },
"motive": { "name": "" },
"cause": { "name": "No arranca" },
"subcause": { "name": "Batería descargada" }
},
"origin": {
"country": "Uruguay", "department": "Montevideo", "city": "Montevideo", "zone": "Centro",
"street": "18 de Julio", "corner": "Ejido", "door_number": "1234", "apt": "5",
"special_place": "", "lat": "-34.90547800000000", "lng": "-56.18815900000000"
},
"destination": {
"country": "", "department": "", "city": "", "zone": "",
"street": "", "corner": "", "door_number": "", "apt": "",
"special_place": "", "lat": "", "lng": ""
},
"vehicle": { "plate": "SAB1234", "brand": "Ford", "model": "Fiesta", "year": 2018, "color": "Gris" },
"assignment": {
"device": "Móvil 12", "device_imei": "352093081234567", "device_type": "Grúa liviana",
"driver": "Juan Gómez", "driver_external_code": "COND-3",
"provider": "Grúas del Este", "operator": "mesa1", "telephonist": "mesa1",
"communication_medium": "Teléfono"
},
"reserve": { "driver": "", "provider": "", "mobile": "", "user": "" },
"computes": true,
"load": { "weightKg": 320, "volumeM3": 1.5, "packages": 4 },
"dynamic_fields": [
{ "label": "Póliza", "value": "POL-77" },
{ "label": "Kilometraje", "value": "84210" }
]
}
],
"meta": { "total": 47, "limit": 2, "offset": 0, "count": 2 }
}
Marcas de tiempo

Todas las marcas de tiempo se devuelven sin zona horaria (p. ej. "2026-06-24T09:12:00"). El valor representa la zona horaria configurada de la compañía. No agregues Z ni apliques conversión a UTC; mostralo tal cual.


Nivel Pro — bloques include

Agregá include para expandir bloques pesados en cada ítem. Cada bloque se compone con su servicio interno, agrupado (batched) por los serid de la página (sin N+1).

TokenCampoNotas
dynamic_fieldsdynamic_fields[]Ya presente en el nivel estándar; aceptado en include por simetría
eventsevents[]Bloque pesado — necesita un filtro acotado
pausespauses[]Sale del mismo origen que los eventos
formsforms[]El PDF del formulario no va inline — obtenelo por el endpoint de PDF del formulario
attachmentsattachments[]Solo metadatos + handle. Nunca base64 inline
cercascercas{origin[],destination[]}Listas de nombres de cerca de origen/destino
invoicesinvoices[]Diferido — devuelve [] con meta.deferred: ["invoices"]

Sub-formas de los bloques

Ítem de events[]: id, at (datetime), status, status_label, lat, lng, user, device, driver, driver_external_code, provider, odometer, address, parameters[] ({ name, value }).

Ítem de pauses[]: started_at, ended_at, user, driver, device, reason, notes.

Ítem de forms[]: form_id, name, driver, device, filled_at, sections[] ({ name, order, fields[] } donde cada campo es { name, order, value }), attachments[].

Ítem de attachments[]: name, type, size, date, notes, task_id, form_id ("" si es suelto), media_id, provider.

Los adjuntos son referencias, no archivos

Tomá attachments[].media_id (o attachments[].name) y pasalo al endpoint de descarga de adjuntos para obtener un link firmado. El listado y el detalle nunca devuelven base64; solo metadatos y un handle.

Ejemplo de código

curl -s "https://$TENANT/apidev/v1/tasks/920183744012?include=events,forms,attachments,pauses,cercas" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"

Respuesta de ejemplo

{
"success": true,
"data": {
"serid": "920183744012",
"service_number": "103878",
"assistance_number": "44021",
"external_id": "OT-2026-0099",
"status": "FIN",
"status_label": "Finalizado",
"dynamic_fields": [ { "label": "Póliza", "value": "POL-77" } ],
"events": [
{ "id": "5512", "at": "2026-06-24T09:30:00", "status": "ASI", "status_label": "Asignado",
"lat": "-34.90500000000000", "lng": "-56.18800000000000", "user": "mesa1",
"device": "Móvil 12", "driver": "Juan Gómez", "driver_external_code": "COND-3",
"provider": "Grúas del Este", "odometer": "84200", "address": "18 de Julio 1234",
"parameters": [ { "name": "Observación", "value": "En camino" } ] },
{ "id": "5518", "at": "2026-06-24T10:25:00", "status": "FIN", "status_label": "Finalizado",
"lat": "-34.90600000000000", "lng": "-56.18900000000000", "user": "mesa1",
"device": "Móvil 12", "driver": "Juan Gómez", "driver_external_code": "COND-3",
"provider": "Grúas del Este", "odometer": "84210", "address": "18 de Julio 1234",
"parameters": [] }
],
"pauses": [
{ "started_at": "2026-06-24T09:45:00", "ended_at": "2026-06-24T09:55:00",
"user": "mesa1", "driver": "Juan Gómez", "device": "Móvil 12",
"reason": "Corte de tránsito", "notes": "" }
],
"forms": [
{ "form_id": "771", "name": "Checklist de Auxilio", "driver": "Juan Gómez", "device": "Móvil 12",
"filled_at": "2026-06-24T10:20:00",
"sections": [
{ "name": "Datos del vehículo", "order": 1,
"fields": [ { "name": "Kilometraje", "order": 1, "value": "84210" } ] }
],
"attachments": [
{ "name": "771_foto_frente.jpg", "type": "image/jpeg", "size": 142233,
"date": "2026-06-24T10:21:00", "notes": "", "task_id": "920183744012",
"form_id": "771", "media_id": "88231", "provider": "azure" }
] }
],
"attachments": [
{ "name": "920183744012_remito.pdf", "type": "application/pdf", "size": 90122,
"date": "2026-06-24T10:25:00", "notes": "Remito firmado", "task_id": "920183744012",
"form_id": "", "media_id": "88240", "provider": "azure" }
],
"cercas": { "origin": ["Zona Sur"], "destination": [] }
},
"meta": { "source": "historic", "includes": ["events","forms","attachments","pauses","cercas"] }
}

Nivel personalizado — fields

Usá fields para recibir solo los campos que pidas (más los tres identificadores forzados serid, service_number, assistance_number). La whitelist de alias es cerrada: un alias fuera de ella devuelve 400 INVALID_FIELD.

id (=serid), external_id, service_number, assistance_number,
status, status_label, priority, detail, tracking_number, computes,
created_at, scheduled_at, scheduled_until,
contact.name, contact.phone, contact.phone_mobile,
account.name, account.external_code, account.document, account.policy,
classification.procedence.id, classification.procedence.name,
classification.product.id, classification.product.line, classification.product.name,
classification.coverage.name, classification.provision.name,
classification.motive.name, classification.cause.name, classification.subcause.name,
origin.country, origin.department, origin.city, origin.zone, origin.street,
origin.corner, origin.door_number, origin.apt, origin.special_place, origin.lat, origin.lng,
destination.country, destination.department, destination.city, destination.zone, destination.street,
destination.corner, destination.door_number, destination.apt, destination.special_place,
destination.lat, destination.lng,
vehicle.plate, vehicle.brand, vehicle.model, vehicle.year, vehicle.color,
assignment.device, assignment.device_imei, assignment.device_type,
assignment.driver, assignment.driver_external_code, assignment.provider,
assignment.operator, assignment.telephonist, assignment.communication_medium,
reserve.driver, reserve.provider, reserve.mobile, reserve.user,
load.weightKg, load.volumeM3, load.packages,
load.requiresCold, load.requiresFragile, load.requiresHeavy,
dynamic_fields, (todo el array)
dynamic_fields.<label> (un campo dinámico por etiqueta; sin distinguir mayúsculas)
  • dynamic_fields.<label> (p. ej. dynamic_fields.Póliza) resuelve el valor del campo dinámico cuya etiqueta coincide (con trim y sin distinguir mayúsculas). Si no existe → string vacío "", no un 400. Cuando pedís campos dinámicos puntuales, el resultado se devuelve como un objeto { "Póliza": "POL-77" }.
  • fields no habilita bloques pesados (events / forms / attachments / invoices); para eso usá include. Pedir un alias de bloque pesado en fields devuelve 400 INVALID_FIELD.

Respuesta de ejemplo

{
"success": true,
"data": [
{ "serid": "920183744012", "service_number": "103878", "assistance_number": "44021",
"external_id": "OT-2026-0099", "status": "FIN", "scheduled_at": "2026-06-24T11:00:00",
"dynamic_fields": { "Póliza": "POL-77" } }
],
"meta": { "total": 1, "limit": 20, "offset": 0, "count": 1,
"fields": ["id","external_id","status","scheduled_at","dynamic_fields.Póliza"] }
}

Campos dinámicos

Los campos dinámicos (dynamic_fields) provienen de una fuente única tanto en el listado como en el detalle, así el mismo campo dinámico se ve idéntico en cualquiera de las respuestas. Cada entrada es { label, value }:

  • En los niveles estándar y pro, dynamic_fields es un array [{ label, value }].
  • Con fields=dynamic_fields.<label> puntual, es un objeto { label: value }.
  • Una <label> desconocida resuelve a "", nunca a un 400.

Detalle de la tarea

Perfil completo de una única tarea. Misma forma de ítem que el listado, expandida según include/fields.

GET/apidev/v1/tasks/{id}
PermisoAPICLI_TASKS_READ
Límite de solicitudes30 solicitudes/min (ventana deslizante)
CachéNinguna

Parámetros de ruta

ParámetroTipoRequeridoDescripción
idstringIdentificador de la tarea (serid). La identidad se resuelve solo por serid

Parámetros de consulta

Los mismos flags include y fields que el endpoint de listado.

Ejemplo de código

curl -s "https://$TENANT/apidev/v1/tasks/920183744012" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT"

Respuesta de ejemplo

{
"success": true,
"data": {
"serid": "920183744012",
"service_number": "103878",
"assistance_number": "44021",
"external_id": "OT-2026-0099",
"status": "INI",
"status_label": "Iniciado",
"priority": 2,
"detail": "Cliente reporta auto sin arranque.",
"tracking_number": "TRK-9981",
"created_at": "2026-06-24T09:12:00",
"scheduled_at": "2026-06-24T11:00:00",
"scheduled_until": "",
"contact": { "name": "Ana Pérez", "phone": "099111222", "phone_mobile": "" },
"account": { "name": "Ana Pérez", "external_code": "CLI-55", "document": "1.234.567-8", "policy": "POL-77" },
"classification": {
"procedence": { "id": "12", "name": "Seguros del Sur" },
"product": { "id": "12", "line": "3", "name": "Auxilio Mecánico" },
"coverage": { "name": "Cobertura Total" },
"provision": { "name": "Remolque" },
"motive": { "name": "" },
"cause": { "name": "No arranca" },
"subcause": { "name": "Batería descargada" }
},
"vehicle": { "plate": "SAB1234", "brand": "Ford", "model": "Fiesta", "year": 2018, "color": "Gris" },
"assignment": {
"device": "Móvil 12", "device_imei": "352093081234567", "device_type": "Grúa liviana",
"driver": "Juan Gómez", "driver_external_code": "COND-3",
"provider": "Grúas del Este", "operator": "mesa1", "telephonist": "mesa1",
"communication_medium": "Teléfono"
},
"reserve": { "driver": "", "provider": "", "mobile": "", "user": "" },
"computes": true,
"load": { "weightKg": 320, "volumeM3": 1.5, "packages": 4 },
"dynamic_fields": [ { "label": "Póliza", "value": "POL-77" } ]
},
"meta": { "source": "active" }
}
meta.source

data es un único objeto (no un array). meta.source informa qué almacén resolvió la tarea (active, historic o despacho) y es solo para depuración; no acoples tu integración al origen físico. Una tarea que no existe para tu compañía devuelve 404 TASK_NOT_FOUND.


Referencia de meta

CampoTipoCuándoSignificado
totalnumberlistado (siempre)Total de coincidencias en todas las páginas
limitnumberlistado (siempre)Tamaño de página aplicado (puede ser menor al pedido por un recorte)
offsetnumberlistado (siempre)Número de página aplicado
countnumberlistado (siempre)Ítems en esta página
includesarraynivel proBloques efectivamente expandidos
fieldsarraynivel personalizadoCampos efectivamente proyectados
deferredarraysi se pidió un bloque diferidoBloques no implementados aún (p. ej. ["invoices"])
sourcestringdetalle (depuración)Almacén que resolvió la tarea
cappedobjectsi se aplicó un recorte{ field, requested, applied } (p. ej. limit recortado por un include pesado)

Errores

Todos los endpoints de esta página pueden devolver estos errores. Consultá Manejo de errores para la referencia completa.

CódigoHTTPDescripción
DATE_RANGE_REQUIRED400Se pidieron tareas sin un rango de fechas ni un identificador puntual
DATE_RANGE_TOO_WIDE400El rango supera el máximo de 31 días
DATE_RANGE_INVALID400enddate anterior a startdate, o un formato de fecha inválido
INVALID_STATUS400Un valor de statuses no es un estado de tarea válido
INVALID_INCLUDE400Un token de include no está en la lista
INVALID_FIELD400Un alias de fields no está en la whitelist
INCLUDE_FIELDS_CONFLICT400Se enviaron include y fields juntos
LIMIT_OUT_OF_RANGE400limit fuera de 1..100
INCLUDE_REQUIRES_NARROWER_FILTER400Se pidió un bloque pesado sin un filtro suficientemente acotado
UNAUTHORIZED401tenant / Authorization / X-API-Key ausente, inválido o expirado
FORBIDDEN403El usuario no tiene APICLI_TASKS_READ
TASK_NOT_FOUND404El {id} no existe para tu compañía
RATE_LIMITED429Se superaron 30 solicitudes/min
INTERNAL_ERROR500Error inesperado del servidor