{"openapi":"3.1.0","info":{"title":"API de Harmony","version":"1.0.0","description":"Lectura de los datos de una organización de Harmony. Es de sólo lectura y se autentica con una clave de API que emite un super administrador desde Ajustes → API."},"servers":[{"url":"https://www.harmony.report/api/v1","description":"Producción"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer hk_live_…`"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["missing_authorization","invalid_api_key","revoked_api_key","expired_api_key","missing_parameter","invalid_period","invalid_limit","response_too_large","not_found","rate_limited","method_not_allowed","internal_error"],"description":"Identificador estable del error."},"message":{"type":"string","description":"Explicación en español."}},"required":["code","message"]}},"required":["error"]},"Workspace":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Nombre del espacio."},"active":{"type":"boolean","description":"Si está activo."},"createdAt":{"type":"string","description":"Creación, ISO 8601."}},"required":["id","name","active","createdAt"]},"Customer":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Razón social del cliente."},"identifier":{"type":"string","description":"NIT o documento."},"workspaceId":{"type":"string","description":"Espacio al que pertenece."},"idle":{"type":"boolean","description":"Suspendido temporalmente."},"active":{"type":"boolean","description":"Si está activo."},"hasForm":{"type":"boolean","description":"Tiene ficha de formulario."},"createdAt":{"type":"string","description":"Creación, ISO 8601."}},"required":["id","name","identifier","workspaceId","idle","active","hasForm","createdAt"]},"Area":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Nombre de la sede."},"description":{"type":"string","description":"Descripción libre."},"active":{"type":"boolean","description":"Si está activa."},"customerId":{"type":"string","description":"Cliente al que pertenece."}},"required":["id","name","description","active","customerId"]},"Point":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Nombre del puesto."},"description":{"type":"string","description":"Descripción libre."},"areaId":{"type":["string","null"],"description":"Sede en la que está, si tiene."},"customerId":{"type":"string","description":"Cliente al que pertenece."},"idle":{"type":"boolean","description":"Puesto inactivo."},"active":{"type":"boolean","description":"Si está activo."}},"required":["id","name","description","customerId","idle","active"]},"Worker":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Nombre de la persona."},"identifier":{"type":"string","description":"Documento de identidad."},"group":{"type":["string","null"],"description":"Grupo o cuadrilla."},"customerId":{"type":"string","description":"Cliente al que está adscrita."},"workspaceId":{"type":"string","description":"Espacio al que pertenece."},"idle":{"type":"boolean","description":"Inactiva temporalmente."},"active":{"type":"boolean","description":"Si está activa."},"hasForm":{"type":"boolean","description":"Tiene ficha de formulario."},"createdAt":{"type":"string","description":"Creación, ISO 8601."}},"required":["id","name","identifier","customerId","workspaceId","idle","active","hasForm","createdAt"]},"Assignment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"period":{"type":["string","null"],"description":"Mes, `YYYY-MM`."},"pointId":{"type":"string","description":"Puesto cubierto."},"pointName":{"type":"string","description":"Nombre del puesto al asignar."},"workerId":{"type":"string","description":"Persona asignada."},"workerName":{"type":"string","description":"Nombre al asignar."},"workerIdentifier":{"type":"string","description":"Documento al asignar."},"customerId":{"type":"string","description":"Cliente del puesto."},"skipExtraDays":{"type":"boolean","description":"Excluye los días adicionales del mes."}},"required":["id","pointId","pointName","workerId","workerName","workerIdentifier","customerId","skipExtraDays"]},"Shift":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"date":{"type":["string","null"],"description":"Fecha completa del turno, `YYYY-MM-DD`."},"period":{"type":["string","null"],"description":"Mes, `YYYY-MM`."},"day":{"type":"number","description":"Día del mes."},"description":{"type":"string","description":"«06:00 a 18:00» o «Descanso»."},"color":{"type":"string","description":"`green` turno · `gray` descanso."},"startsAt":{"type":["string","null"],"description":"Inicio con huso, ISO 8601. Nulo en un descanso."},"endsAt":{"type":["string","null"],"description":"Fin con huso, ISO 8601."},"workerId":{"type":"string","description":"Persona que cubre el turno."},"workerName":{"type":"string","description":"Nombre al programar."},"workerIdentifier":{"type":"string","description":"Documento al programar."},"pointId":{"type":["string","null"],"description":"Puesto cubierto."},"positionId":{"type":["string","null"],"description":"Cargo aplicado."},"customerId":{"type":"string","description":"Cliente del turno."},"workspaceId":{"type":"string","description":"Espacio del turno."},"sequenceId":{"type":["string","null"],"description":"Secuencia que lo generó."},"sequenceName":{"type":"string","description":"Nombre de la secuencia."}},"required":["id","day","description","color","workerId","workerName","workerIdentifier","customerId","workspaceId","sequenceName"]},"Incident":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"date":{"type":["string","null"],"description":"Fecha completa, `YYYY-MM-DD`."},"period":{"type":["string","null"],"description":"Mes, `YYYY-MM`."},"day":{"type":"number","description":"Día del mes."},"abbreviation":{"type":"string","description":"Sigla con la que se pinta."},"description":{"type":"string","description":"Descripción de la novedad."},"color":{"type":"string","description":"`sky` · `red` · `yellow`."},"keep":{"type":"boolean","description":"Si cuenta como día trabajado."},"categoryId":{"type":["string","null"],"description":"Categoría aplicada."},"categoryName":{"type":["string","null"],"description":"Nombre al registrar."},"startsAt":{"type":["string","null"],"description":"Inicio con huso, ISO 8601."},"endsAt":{"type":["string","null"],"description":"Fin con huso, ISO 8601."},"workerId":{"type":"string","description":"Persona implicada."},"workerName":{"type":"string","description":"Nombre al registrar."},"workerIdentifier":{"type":"string","description":"Documento al registrar."},"pointId":{"type":["string","null"],"description":"Puesto donde ocurrió."},"positionId":{"type":["string","null"],"description":"Cargo aplicado."},"customerId":{"type":"string","description":"Cliente de la novedad."},"workspaceId":{"type":"string","description":"Espacio de la novedad."}},"required":["id","day","abbreviation","description","color","keep","workerId","workerName","workerIdentifier","customerId","workspaceId"]},"FinancialRecord":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"period":{"type":["string","null"],"description":"Mes, `YYYY-MM`."},"type":{"type":"string","description":"`income` ingreso · `expense` egreso."},"concept":{"type":"string","description":"Concepto del registro."},"amount":{"type":"number","description":"Monto, en pesos."},"customerId":{"type":["string","null"],"description":"Cliente al que se imputa. Nulo en un centro indirecto, cuyo devengo no se factura a ningún cliente."},"costCenterId":{"type":["string","null"],"description":"Centro de costo del registro. Nulo cuando la facturación llega agregada sobre varios centros."},"costCenterCode":{"type":["string","null"],"description":"Código externo del centro."},"costCenterName":{"type":["string","null"],"description":"Nombre del centro."}},"required":["id","type","concept","amount"]},"Position":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Nombre del cargo."},"value":{"type":"number","description":"Valor asociado al cargo."},"year":{"type":"number","description":"Año de vigencia."},"active":{"type":"boolean","description":"Si está activo."}},"required":["id","name","value","year","active"]},"Category":{"type":"object","properties":{"id":{"type":"string","description":"Identificador de Convex."},"name":{"type":"string","description":"Nombre de la categoría."},"abbreviation":{"type":"string","description":"Sigla con la que se pinta."},"color":{"type":"string","description":"`sky` · `red`."},"keep":{"type":"boolean","description":"Si cuenta como día trabajado."},"shouldCount":{"type":"boolean","description":"Si entra en los conteos."}},"required":["id","name","abbreviation","color","keep","shouldCount"]}}},"paths":{"/me":{"get":{"operationId":"get-me","summary":"La clave que estás usando","description":"Devuelve la organización de la clave, su alcance y el límite de peticiones. Útil como primera llamada para comprobar que la clave funciona.","parameters":[],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object"},"example":{"key":{"name":"Integración de nómina","prefix":"hk_live_a1b2c3","createdAt":"2026-09-07T15:04:00.000Z","lastUsedAt":"2026-09-07T15:41:12.000Z","expiresAt":null},"organization":{"id":"p57fazjfjmde4egmkz0xh6b51982enz0","name":"Seguridad Andina"},"scope":{"type":"organization","workspaceIds":null,"unreachableWorkspaceIds":[]},"rateLimit":{"limit":60,"windowSeconds":60}}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces":{"get":{"operationId":"list-workspaces","summary":"Espacios de trabajo","description":"Los espacios que la clave alcanza. Una clave de organización los devuelve todos; una acotada, sólo los suyos.","parameters":[],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Workspace"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j","name":"Operación Bogotá","active":true,"createdAt":"2026-01-15T14:02:11.000Z"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/customers":{"get":{"operationId":"list-customers","summary":"Clientes","description":"Los clientes de la organización. Con una clave acotada a espacios, `workspaceId` es obligatorio: no hay índice que recorra varios espacios en una sola página.","parameters":[{"name":"workspaceId","in":"query","required":false,"schema":{"type":"string"},"description":"Espacio del que listar los clientes. Obligatorio cuando la clave está acotada a espacios concretos."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","name":"Centro Comercial Andino","identifier":"900123456-7","code":"CC-AND","workspaceId":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j","idle":false,"active":true,"hasForm":true,"createdAt":"2026-02-03T09:11:00.000Z"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/customers/{id}":{"get":{"operationId":"get-customer","summary":"Un cliente","description":"Un cliente por su identificador. Responde `404` si no existe o si está fuera del alcance de la clave: no se distingue, para no confirmar la existencia de datos ajenos. Con `include` devuelve la programación del cliente completa —sedes, puestos, personal, turnos y novedades del mes— en una sola petición.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Identificador del cliente."},{"name":"include","in":"query","required":false,"schema":{"type":"string"},"description":"Secciones que añadir a la respuesta, separadas por comas. Sin este parámetro la respuesta no cambia; con él, el recurso pasa a venir dentro de un sobre junto a las secciones pedidas."},{"name":"period","in":"query","required":false,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio en cuanto se expande algo que vive en un mes; sin él esas expansiones responden 400."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"},"example":{"id":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","name":"Centro Comercial Andino","identifier":"900123456-7","code":"CC-AND","workspaceId":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j","idle":false,"active":true,"hasForm":true,"createdAt":"2026-02-03T09:11:00.000Z"}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/areas/{id}":{"get":{"operationId":"get-area","summary":"Una sede","description":"Una sede por su identificador, con lo que cuelga de sus puestos. Los turnos y las novedades cuelgan del puesto y no de la sede, así que expandirlos cuesta una consulta por puesto: una sede de más de 50 responde 400 y hay que pedir sus puestos uno a uno.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Identificador de la sede."},{"name":"include","in":"query","required":false,"schema":{"type":"string"},"description":"Secciones que añadir a la respuesta, separadas por comas. Sin este parámetro la respuesta no cambia; con él, el recurso pasa a venir dentro de un sobre junto a las secciones pedidas."},{"name":"period","in":"query","required":false,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio en cuanto se expande algo que vive en un mes; sin él esas expansiones responden 400."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Area"},"example":{"id":"m9231bc4de5f6g7h8i9j0k1l2m3n4o5p","name":"Torre Norte","description":"Acceso principal y parqueaderos","active":true,"customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1"}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/points/{id}":{"get":{"operationId":"get-point","summary":"Un puesto","description":"Un puesto por su identificador. Es la ruta que resuelve el caso completo: su sede, su cliente, quién está asignado, quién está programado, los turnos y las novedades del mes, y dónde más está esa gente — todo en una petición.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Identificador del puesto."},{"name":"include","in":"query","required":false,"schema":{"type":"string"},"description":"Secciones que añadir a la respuesta, separadas por comas. Sin este parámetro la respuesta no cambia; con él, el recurso pasa a venir dentro de un sobre junto a las secciones pedidas."},{"name":"period","in":"query","required":false,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio en cuanto se expande algo que vive en un mes; sin él esas expansiones responden 400."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Point"},"example":{"id":"n8321cd5ef6g7h8i9j0k1l2m3n4o5p6q","name":"Portería Norte","description":"24 horas","areaId":"m9231bc4de5f6g7h8i9j0k1l2m3n4o5p","customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","idle":false,"active":true}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/areas":{"get":{"operationId":"list-areas","summary":"Sedes de un cliente","description":"Las sedes cuelgan del cliente y ése es su único índice, así que `customerId` es obligatorio.","parameters":[{"name":"customerId","in":"query","required":true,"schema":{"type":"string"},"description":"Cliente del que listar las sedes."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Area"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"m9231bc4de5f6g7h8i9j0k1l2m3n4o5p","name":"Torre Norte","description":"Acceso principal y parqueaderos","active":true,"customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/points":{"get":{"operationId":"list-points","summary":"Puestos de servicio","description":"Se piden por cliente o por sede — uno de los dos, no los dos a la vez.","parameters":[{"name":"customerId","in":"query","required":false,"schema":{"type":"string"},"description":"Cliente del que listar los puestos."},{"name":"areaId","in":"query","required":false,"schema":{"type":"string"},"description":"Sede de la que listar los puestos."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Point"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"n8321cd5ef6g7h8i9j0k1l2m3n4o5p6q","name":"Portería Norte","description":"24 horas","areaId":"m9231bc4de5f6g7h8i9j0k1l2m3n4o5p","customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","idle":false,"active":true}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workers":{"get":{"operationId":"list-workers","summary":"Personal","description":"`workspaceId` es obligatorio: el personal no tiene índice por organización, sólo por espacio y por cliente.","parameters":[{"name":"workspaceId","in":"query","required":true,"schema":{"type":"string"},"description":"Espacio del que listar el personal."},{"name":"customerId","in":"query","required":false,"schema":{"type":"string"},"description":"Acota al personal de un cliente de ese espacio."},{"name":"search","in":"query","required":false,"schema":{"type":"string"},"description":"Búsqueda difusa por nombre. Devuelve los mejores resultados de una vez, con `nextCursor` siempre en `null`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Worker"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"w4412ef6gh7i8j9k0l1m2n3o4p5q6r7s","name":"Ana María Pérez","identifier":"1023456789","group":"Grupo A","customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","workspaceId":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j","idle":false,"active":true,"hasForm":true,"createdAt":"2026-02-10T16:40:00.000Z"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workers/{id}":{"get":{"operationId":"get-worker","summary":"Una persona","description":"Una persona por su identificador, si la clave la alcanza. Con `include` responde a la pregunta girada: no quién cubre un puesto, sino dónde está esta persona este mes.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Identificador de la persona."},{"name":"include","in":"query","required":false,"schema":{"type":"string"},"description":"Secciones que añadir a la respuesta, separadas por comas. Sin este parámetro la respuesta no cambia; con él, el recurso pasa a venir dentro de un sobre junto a las secciones pedidas."},{"name":"period","in":"query","required":false,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio en cuanto se expande algo que vive en un mes; sin él esas expansiones responden 400."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Worker"},"example":{"id":"w4412ef6gh7i8j9k0l1m2n3o4p5q6r7s","name":"Ana María Pérez","identifier":"1023456789","group":"Grupo A","customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","workspaceId":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j","idle":false,"active":true,"hasForm":true,"createdAt":"2026-02-10T16:40:00.000Z"}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/assignments":{"get":{"operationId":"list-assignments","summary":"Asignaciones del mes","description":"Qué persona cubre qué puesto en un mes. Las asignaciones cuelgan del cliente —no del espacio—, así que se piden con `customerId`.","parameters":[{"name":"period","in":"query","required":true,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio: la operación se guarda por período mensual y no hay rango de fechas."},{"name":"customerId","in":"query","required":true,"schema":{"type":"string"},"description":"Cliente cuyas asignaciones se listan."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Assignment"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"a1122gh8ij9k0l1m2n3o4p5q6r7s8t9u","period":"2026-08","pointId":"n8321cd5ef6g7h8i9j0k1l2m3n4o5p6q","pointName":"Portería Norte","workerId":"w4412ef6gh7i8j9k0l1m2n3o4p5q6r7s","workerName":"Ana María Pérez","workerIdentifier":"1023456789","customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","skipExtraDays":false}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/shifts":{"get":{"operationId":"list-shifts","summary":"Turnos del mes","description":"Los turnos programados de un espacio en un mes, descansos incluidos (`color: \"gray\"`).","parameters":[{"name":"period","in":"query","required":true,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio: la operación se guarda por período mensual y no hay rango de fechas."},{"name":"workspaceId","in":"query","required":true,"schema":{"type":"string"},"description":"Espacio cuyos turnos se listan."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Shift"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"s7712ij0kl1m2n3o4p5q6r7s8t9u0v1w","date":"2026-08-12","period":"2026-08","day":12,"description":"06:00 a 18:00","color":"green","startsAt":"2026-08-12T06:00:00-05:00","endsAt":"2026-08-12T18:00:00-05:00","workerId":"w4412ef6gh7i8j9k0l1m2n3o4p5q6r7s","workerName":"Ana María Pérez","workerIdentifier":"1023456789","pointId":"n8321cd5ef6g7h8i9j0k1l2m3n4o5p6q","positionId":"p1122kl2m3n4o5p6q7r8s9t0u1v2w3x","customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","workspaceId":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j","sequenceId":null,"sequenceName":"Rotativa 2x2"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/incidents":{"get":{"operationId":"list-incidents","summary":"Novedades del mes","description":"Faltas, adicionales y seguimientos de un espacio en un mes, con su categoría.","parameters":[{"name":"period","in":"query","required":true,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio: la operación se guarda por período mensual y no hay rango de fechas."},{"name":"workspaceId","in":"query","required":true,"schema":{"type":"string"},"description":"Espacio cuyas novedades se listan."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Incident"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"i9912kl1m2n3o4p5q6r7s8t9u0v1w2x3","date":"2026-08-14","period":"2026-08","day":14,"abbreviation":"FI","description":"Falta injustificada","color":"red","keep":false,"categoryId":"c2231lm2n3o4p5q6r7s8t9u0v1w2x3y4","categoryName":"Falta","startsAt":null,"endsAt":null,"workerId":"w4412ef6gh7i8j9k0l1m2n3o4p5q6r7s","workerName":"Ana María Pérez","workerIdentifier":"1023456789","pointId":"n8321cd5ef6g7h8i9j0k1l2m3n4o5p6q","positionId":null,"customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","workspaceId":"k17fgbsj1hyw66bq5gw5sz2g8s82fs5j"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/financial-records":{"get":{"operationId":"list-financial-records","summary":"Ingresos y egresos del mes","description":"Con una clave de organización se leen todos los del mes; con una acotada, `customerId` es obligatorio.","parameters":[{"name":"period","in":"query","required":true,"schema":{"type":"string"},"description":"Mes a consultar, `YYYY-MM`. Obligatorio: la operación se guarda por período mensual y no hay rango de fechas."},{"name":"customerId","in":"query","required":false,"schema":{"type":"string"},"description":"Cliente cuyos registros se listan. Obligatorio cuando la clave está acotada a espacios concretos."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FinancialRecord"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"f3312mn3o4p5q6r7s8t9u0v1w2x3y4z5","period":"2026-08","type":"income","concept":"Servicio de vigilancia agosto","amount":18500000,"customerId":"j5712xk9qb3v8w1n0m4pz6r2t8s5c7d1","costCenterId":"k9912ab3c4d5e6f7g8h9i0j1k2l3m4n5","costCenterCode":"00201","costCenterName":"CAJAMAG"}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/positions":{"get":{"operationId":"list-positions","summary":"Cargos","description":"Catálogo de cargos de la organización. Es una entidad de organización, así que una clave acotada a espacios lo ve igual.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Position"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"p1122kl2m3n4o5p6q7r8s9t0u1v2w3x","name":"Guarda de seguridad","value":1423500,"year":2026,"active":true}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/categories":{"get":{"operationId":"list-categories","summary":"Categorías de novedad","description":"Catálogo de categorías de la organización, con su sigla y si cuentan como día trabajado.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer"},"description":"Tamaño de página, de 1 a 5.000. Por defecto 50. Para volumen —todas las novedades de un mes— conviene subirlo: son menos peticiones contra el mismo límite por minuto."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"El `nextCursor` de la página anterior."}],"responses":{"200":{"description":"Correcto.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Category"}},"nextCursor":{"type":["string","null"],"description":"Cursor de la página siguiente. `null` en la última página, y es la única señal de fin."}},"required":["data","nextCursor"]},"example":{"data":[{"id":"c2231lm2n3o4p5q6r7s8t9u0v1w2x3y4","name":"Falta","abbreviation":"FI","color":"red","keep":false,"shouldCount":true}],"nextCursor":null}}}},"400":{"description":"Parámetro ausente o mal formado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Clave ausente, inválida, revocada o caducada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No existe o está fuera del alcance de la clave.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Límite de peticiones superado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}