Contratos y previsualización
REST requiere Starter o Pro activo. contracts:read permite listar, consultar y previsualizar sin persistir; contracts:write permite mutar e incluye lectura. No requiere resources:write para gestionar contratos de un recurso existente.
Endpoints
| Método y ruta | Parámetros | Éxito |
|---|---|---|
GET /api/v1/contracts |
Query opcional resource_id ID positivo, limit entero 1–100 (50), offset entero ≥0 (0) |
200 array data, meta con limit/offset/total |
GET /api/v1/contracts/:id |
ID positivo obligatorio | 200 {"data": contrato} |
POST /api/v1/contracts |
JSON creación | 201 {"data":{"contract": contrato}} |
PATCH /api/v1/contracts/:id |
ID obligatorio, JSON parcial | 200 {"data":{"contract": contrato}} |
PUT /api/v1/contracts/:id |
Igual que PATCH, conserva omitidos | 200 mismo envelope |
DELETE /api/v1/contracts/:id |
ID obligatorio; conflict_policy opcional |
200 {"data":{"contract": contrato}} eliminado |
POST /api/v1/contracts/preview |
JSON con operation: "create" (por defecto sin id) |
200 resultado de preview |
POST /api/v1/contracts/:id/preview |
ID obligatorio; operation: "update" (defecto con id) o "delete" |
200 resultado de preview |
Lista por ID ascendente; no admite filtro de fechas ni nombre. GET individual acepta include=monthly_hours y from/to (ISO juntos, ordenados, ≤3660 días), pero no añade matriz al contrato.
Atributos de contrato
| Campo | Tipo | Crear | Actualizar |
|---|---|---|---|
resource_id |
ID positivo | Obligatorio | Opcional, solo puede ser el mismo recurso |
start_date |
date string YYYY-MM-DD |
Obligatorio | Opcional |
end_date |
date string o null | Opcional, null = indefinido | Opcional; null elimina fecha de fin |
daily_hours |
entero 1–8 | Obligatorio | Opcional |
annual_convention_hours |
entero 1–2500 o null por REST | Opcional | Opcional |
cost_per_hour |
decimal string no negativo | Obligatorio | Opcional |
conflict_policy |
reject o resolve |
Opcional, reject por defecto |
Opcional, reject por defecto |
entry_ids |
array no vacío de IDs positivos | Condicional: resolver conflictos | Condicional: resolver conflictos |
Campos planos, sin attrs, hours ni organization_id. Los omitidos se conservan en actualización. {} es una actualización válida si supera las validaciones/conflictos actuales; no es un preview. Las fechas deben estar ordenadas, sin solapes incompatibles. Un contrato contiguo con misma jornada y convenio puede rechazarse como duplicado: actualiza el existente. El convenio opcional permite usar la configuración de organización cuando corresponde. MCP exige número para jornada/convenio y no admite null en convenio; usa enteros para cumplir el dominio.
Un sucesor de un contrato indefinido anterior cierra automáticamente ese anterior el día previo a start_date. Esta operación es atómica, respeta capacidad del plan y puede afectar asignaciones y costes: previsualiza primero.
Preview de creación, actualización y borrado
Todos los ejemplos llevan Bearer y JSON Content-Type.
POST /api/v1/contracts/preview
Content-Type: application/json
{"operation":"create","resource_id":7,"start_date":"2027-01-01","end_date":null,"daily_hours":6,"annual_convention_hours":1800,"cost_per_hour":"50.00"}
El preview de creación valida el flujo real, incluido cierre de predecesor, y revierte la simulación: no persiste contratos, cierres ni asignaciones y no emite cambios. Con éxito devuelve data.valid: true, closes_contract_id (ID o null) y contract propuesto (id/timestamps pueden ser null). Si encuentra conflictos del predecesor devuelve 200 con valid: false, conflicts (asignaciones) y closes_contract_id.
POST /api/v1/contracts/5/preview
Content-Type: application/json
{"operation":"update","daily_hours":4}
Actualización sin conflictos: {"data":{"valid":true,"conflicts":[]}}. Con conflictos: {"data":{"valid":false,"conflicts":[...]}}, donde cada elemento es una asignación. El preview no resuelve aunque envíes conflict_policy: "resolve".
POST /api/v1/contracts/5/preview
Content-Type: application/json
{"operation":"delete"}
Borrado permitido: {"data":{"valid":true,"id":5}}. Borrado bloqueado devuelve error HTTP, no necesariamente valid: false. operation solo es parámetro de preview. La variante sin ID también acepta id en el cuerpo para update/delete; usa preferentemente la ruta con ID.
Guardar y resolver explícitamente
POST /api/v1/contracts
Content-Type: application/json
{"resource_id":7,"start_date":"2027-01-01","end_date":null,"daily_hours":6,"annual_convention_hours":1800,"cost_per_hour":"50.00"}
PATCH /api/v1/contracts/5
Content-Type: application/json
{"daily_hours":4,"conflict_policy":"resolve","entry_ids":[42]}
reject no autoriza resolver asignaciones. Con resolve, selecciona IDs actualmente conflictivos, obtenidos del preview; el array no puede estar vacío cuando hay conflictos. El resolver solo puede modificar las asignaciones seleccionadas. Si necesita cambiar otras, quedan conflictos, o hay bloqueos archivados, la transacción se revierte. Si no hay conflictos no hace falta selección. El preview no reserva estado: los conflictos se vuelven a comprobar al escribir.
GET /api/v1/contracts?resource_id=7&limit=50&offset=0
GET /api/v1/contracts/5
DELETE /api/v1/contracts/5
DELETE acepta opcionalmente conflict_policy, pero resolve no fuerza el borrado. No admite entry_ids, fechas, jornada ni operation. El borrado debe superar sus comprobaciones y devuelve el contrato eliminado, no deleted: true ni 204.
Representación y errores
Contrato: id, start_date, end_date nullable, daily_hours entero, annual_convention_hours entero nullable, cost_per_hour decimal string, inserted_at, updated_at ISO 8601. Solo listar/GET individual añaden resource_id; el objeto bajo data.contract no lo incluye.
400 invalid_params para parámetros/políticas/selecciones inválidos; 404 not_found; 409 conflict con asignaciones en errors.assignments cuando procede. 422 validation_error (solapes, duplicados, fechas/costes), plan_limit, archived_project_conflict u otros rechazos de dominio. Los errores usan errors.code, errors.detail y detalles adicionales. valid: false de un preview exitoso es HTTP 200, no un error del transporte. También 401/403 comunes.
MCP Pro: kordia_search (entity: "contracts"), kordia_get (entity: "contract"), kordia_manage_contract (action: "create", "update", "delete") y kordia_preview_contract_change (operation). No enviar operation a manage ni filtros ajenos a la operación, aunque aparezcan en el esquema agregado de la herramienta.