{"openapi":"3.1.0","info":{"title":"API de Vialo","version":"1.1.0","description":"Lectura y carga de los datos de un laboratorio. Cada token actúa en nombre de la persona que lo creó, solo en su laboratorio y con su rol máximo: un token de Consulta solo lee, uno de Colaborador también carga y modifica. Todo cambio queda en el historial del registro como «vía API». Límites: 60 pedidos por minuto para leer y 20 para escribir, por token."},"servers":[{"url":"https://vialolab.com/api/v1"}],"security":[{"token":[]}],"components":{"securitySchemes":{"token":{"type":"http","scheme":"bearer","description":"Token de Vialo (trz_…), creado en Configuración › Acceso por API."}}},"paths":{"/history":{"get":{"tags":["Laboratorio"],"summary":"Historial de cambios del laboratorio","description":"Todo lo que se cargó, cambió o borró en el laboratorio, con quién lo hizo y cuándo, de lo más nuevo a lo más viejo. Se pagina con un cursor: si next_before no es null, pasalo en before para traer lo anterior. Sin los campos secretos.\n\nPide un token con rol Coordinación.","parameters":[{"name":"module","in":"query","required":false,"description":"Solo de un módulo; core son los cambios del laboratorio (personas, módulos, campos) y places, los lugares y su plano.","schema":{"description":"Solo de un módulo; core son los cambios del laboratorio (personas, módulos, campos) y places, los lugares y su plano.","type":"string","enum":["core","places","biobank","equipment","reagents","monitoring","services","budget","protocols","safety"]}},{"name":"person","in":"query","required":false,"description":"Solo lo que hizo esta persona: me, su id, nombre o email.","schema":{"description":"Solo lo que hizo esta persona: me, su id, nombre o email.","type":"string"}},{"name":"action","in":"query","required":false,"description":"insert (alta), update (cambio), move (movimiento), status_change (cambio de estado), soft_delete (borrado), restore (restauración) o delete (eliminación).","schema":{"description":"insert (alta), update (cambio), move (movimiento), status_change (cambio de estado), soft_delete (borrado), restore (restauración) o delete (eliminación).","type":"string","enum":["insert","update","move","status_change","soft_delete","restore","delete"]}},{"name":"from","in":"query","required":false,"description":"Desde esta fecha (AAAA-MM-DD, en la zona del laboratorio).","schema":{"description":"Desde esta fecha (AAAA-MM-DD, en la zona del laboratorio).","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"to","in":"query","required":false,"description":"Hasta esta fecha, incluida.","schema":{"description":"Hasta esta fecha, incluida.","type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"}},{"name":"before","in":"query","required":false,"description":"Cursor: el next_before de la página anterior.","schema":{"description":"Cursor: el next_before de la página anterior.","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"description":"Cambios por página: hasta 100.","schema":{"default":50,"description":"Cambios por página: hasta 100.","type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"at":{"type":"string"},"entity":{"type":"string","description":"Tipo de registro (biobank.sample…)."},"entity_label":{"type":"string"},"record_id":{"type":"string"},"record":{"description":"Con qué nombre se reconoce el registro, si tiene uno.","type":["string","null"]},"action":{"type":"string","enum":["insert","update","move","status_change","soft_delete","restore","delete"]},"actor":{"type":"string"},"via":{"description":"Si no vino de la web: por la API o un asistente de IA.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["id","at","entity","entity_label","record_id","record","action","actor","via","changed_fields","old","new"],"additionalProperties":false}},"next_before":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["data","next_before"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/lab":{"get":{"tags":["Laboratorio"],"summary":"Laboratorio del token","description":"El laboratorio (con su logo), sus módulos habilitados, su plan y qué puede hacer el token. Sirve para probar que el token anda y para saber si el laboratorio puede cargar datos (can_write: false = solo lectura).","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"timezone":{"type":"string"},"logo_url":{"description":"URL pública del logo; null si el laboratorio no subió uno.","type":["string","null"]},"modules":{"type":"array","items":{"type":"string"}},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"additionalProperties":false},{"type":"null"}],"description":"Si es un sub-laboratorio: el laboratorio general de la institución. null si no."},"sub_labs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"],"additionalProperties":false},"description":"Si es el laboratorio general: sus sub-laboratorios (cada uno tiene sus propios datos y personas; para trabajar en uno hace falta un token de ese laboratorio)."},"subscription":{"anyOf":[{"type":"object","properties":{"plan":{"type":"string","enum":["basico","laboratorio","instituto"]},"status":{"type":"string","enum":["trialing","active","past_due","read_only","canceled"],"description":"trialing (en prueba), active, past_due (pago atrasado: se sigue cargando), read_only o canceled."},"trial_ends_at":{"description":"Hasta cuándo dura la prueba (si está en prueba).","type":["string","null"]},"current_period_end":{"description":"Hasta cuándo está pago el plan, si se sabe.","type":["string","null"]},"can_write":{"type":"boolean","description":"false: solo lectura (prueba vencida, sin plan o dado de baja). Se puede leer y exportar, pero cargar responde 403 read_only."}},"required":["plan","status","trial_ends_at","current_period_end","can_write"],"additionalProperties":false},{"type":"null"}]},"token":{"type":"object","properties":{"name":{"type":"string"},"role":{"type":"string","enum":["viewer","editor","admin"]},"role_label":{"type":"string"},"expires_at":{"type":"string"},"scopes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Acceso parcial de la persona del token: por módulo, los ids de lo único que ve (budget.accounts: cuentas del presupuesto; services.services: servicios del catálogo). Sin la clave, el módulo entero. Lo elige la administración desde Vialo."}},"required":["name","role","role_label","expires_at","scopes"],"additionalProperties":false}},"required":["id","name","slug","timezone","logo_url","modules","parent","sub_labs","subscription","token"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/support":{"get":{"tags":["Soporte"],"summary":"Mis consultas de soporte","description":"Las consultas que la persona dueña del token escribió al equipo de Vialo desde este laboratorio (por la Ayuda, la API o el MCP), con su estado. Las más nuevas primero; hasta 50.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"created_at":{"type":"string"},"category":{"type":"string","enum":["question","problem","idea","billing"]},"subject":{"type":"string"},"message":{"type":"string"},"status":{"type":"string","enum":["new","answered","closed"],"description":"new (recibida), answered (respondida por mail) o closed (cerrada)."},"via":{"type":"string","enum":["web","api","mcp"]}},"required":["id","created_at","category","subject","message","status","via"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Soporte"],"summary":"Escribir una consulta de soporte","description":"Le manda una consulta al equipo de Vialo (no a la administración del laboratorio), igual que el formulario «Escribinos» de la Ayuda: llega por mail y al panel de la plataforma, y se responde por mail a la persona dueña del token. Hasta 5 por hora por persona. Funciona aunque el laboratorio esté en solo lectura.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"category":{"type":"string","enum":["question","problem","idea","billing"],"description":"question (una duda), problem (algo no anda), idea (una idea o pedido) o billing (plan y facturación)."},"subject":{"type":"string","minLength":3,"maxLength":160,"description":"Asunto corto, de 3 a 160 caracteres."},"message":{"type":"string","minLength":10,"maxLength":4000,"description":"Qué se quería hacer, en qué pantalla y qué pasó; de 10 a 4000 caracteres."},"locale":{"default":"es","description":"En qué idioma responder: es (por defecto) o en.","type":"string","enum":["es","en"]}},"required":["category","subject","message"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"created_at":{"type":"string"},"notified":{"type":"boolean","description":"Si salió el aviso por mail. Aunque sea false, la consulta quedó guardada y el equipo la ve."}},"required":["id","created_at","notified"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/audience":{"get":{"tags":["Laboratorio"],"summary":"Quién va a ver lo que se carga","description":"Antes de cargar algo: quiénes lo van a ver. Lo ve la gente del laboratorio que usa el módulo (la administración siempre) y, si va dentro de un recurso restringido (un equipo, un lugar, un documento de Protocolos, un servicio del catálogo o una cuenta de Presupuesto), solo quienes también ven ese recurso. Con varios recursos (los servicios de un pedido), quienes ven todos.","parameters":[{"name":"module","in":"query","required":true,"description":"Módulo donde se va a cargar (budget, equipment…).","schema":{"type":"string","enum":["biobank","equipment","reagents","monitoring","services","budget","protocols","safety"],"description":"Módulo donde se va a cargar (budget, equipment…)."}},{"name":"kind","in":"query","required":false,"description":"Si va dentro de un recurso: equipment, place, protocols_document, service o budget_account.","schema":{"description":"Si va dentro de un recurso: equipment, place, protocols_document, service o budget_account.","type":"string","enum":["equipment","place","protocols_document","service","budget_account"]}},{"name":"ids","in":"query","required":false,"description":"Ids de esos recursos, separados por coma (hasta 50).","schema":{"description":"Ids de esos recursos, separados por coma (hasta 50).","type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"module":{"type":"string","description":"Nombre del módulo."},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Personas activas del laboratorio."},"everyone":{"type":"boolean","description":"true: lo va a ver todo el laboratorio."},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"admin":{"type":"boolean","description":"Es de la administración."}},"required":["id","name","admin"],"additionalProperties":false},"description":"Quiénes lo van a ver."}},"required":["module","total","everyone","people"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reminders":{"get":{"tags":["Recordatorios"],"summary":"Recordatorios","description":"Los recordatorios y pendientes del Calendario. Cada persona ve solo los recordatorios que anotó y los que son para ella: el token ve los de su dueño/a. Pendientes: primero los más próximos (los que ya llegaron, antes). Hechos: primero los últimos que se hicieron. Hasta 200.","parameters":[{"name":"status","in":"query","required":false,"description":"pending (por defecto), done o all.","schema":{"default":"pending","description":"pending (por defecto), done o all.","type":"string","enum":["pending","done","all"]}},{"name":"scope","in":"query","required":false,"description":"all (todos los que ve), mine (los que son para la persona dueña del token) o created (los que anotó).","schema":{"default":"all","description":"all (todos los que ve), mine (los que son para la persona dueña del token) o created (los que anotó).","type":"string","enum":["all","mine","created"]}},{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD, inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde este día (AAAA-MM-DD, inclusive)."}},{"name":"to","in":"query","required":false,"description":"Hasta este día (AAAA-MM-DD, inclusive).","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta este día (AAAA-MM-DD, inclusive)."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"notes":{"type":"string"},"due_date":{"type":"string","description":"Día, AAAA-MM-DD, en la zona del laboratorio."},"due_time":{"description":"Hora, HH:MM; null = todo el día (avisa a las 9:00).","type":["string","null"]},"due_at":{"type":"string","description":"Cuándo avisa (instante ISO 8601)."},"assignees":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"description":"Para quién es: lo ven y reciben el aviso."},"notify_app":{"type":"boolean","description":"Avisa en Vialo y en el navegador."},"notify_email":{"type":"boolean","description":"Avisa también por mail."},"notify_before":{"type":"number","description":"Cuántos minutos antes de due_at avisa (0 = en el momento)."},"repeat":{"type":"string","enum":["none","daily","weekly","monthly"],"description":"none, daily, weekly o monthly. Uno que se repite, al marcarlo como hecho, pasa a la próxima fecha."},"repeat_until":{"description":"Hasta qué día se repite (AAAA-MM-DD); null = sin fin.","type":["string","null"]},"done_at":{"type":["string","null"]},"done_by_name":{"type":["string","null"]},"last_done_at":{"description":"La última vez que se hizo uno que se repite.","type":["string","null"]},"last_done_by_name":{"type":["string","null"]},"created_by":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"can_edit":{"type":"boolean","description":"Lo anotó la persona dueña del token: lo puede cambiar y borrar. Si no, solo marcarlo como hecho."},"overdue":{"type":"boolean","description":"Ya llegó el momento y sigue pendiente."},"version":{"type":"number"}},"required":["id","title","notes","due_date","due_time","due_at","assignees","notify_app","notify_email","notify_before","repeat","repeat_until","done_at","done_by_name","last_done_at","last_done_by_name","created_by","can_edit","overdue","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Recordatorios"],"summary":"Anotar un recordatorio","description":"Anota un recordatorio o un pendiente para la persona dueña del token o para otras personas del laboratorio. Cuando llega el momento, Vialo les avisa en la app (y en el navegador si lo activaron) y, con notify_email, por mail. A quienes se lo asignan les llega además un aviso en la app al guardarlo.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Qué hay que hacer: «Pedir nitrógeno líquido»."},"notes":{"default":"","type":"string","maxLength":2000,"description":"Detalles (opcional)."},"due_date":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día, AAAA-MM-DD, en la zona del laboratorio."},"due_time":{"default":null,"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}],"description":"Hora, HH:MM, en la zona del laboratorio. null o sin mandar = todo el día (avisa a las 9:00)."},"assignees":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":254},"description":"Para quién es: «me» (la persona dueña del token), el id, el nombre o el email de cada persona del laboratorio. Vacío o sin mandar = para la persona dueña del token."},"notify_app":{"default":true,"type":"boolean","description":"Avisar en Vialo (Notificaciones) y en el navegador. Por defecto, sí."},"notify_email":{"default":false,"type":"boolean","description":"Avisar también por mail cuando llega el momento. Por defecto, no."},"notify_before":{"default":0,"type":"integer","minimum":0,"maximum":10080,"description":"Cuántos minutos antes avisar: 0 en el momento (por defecto), 60 una hora antes, 1440 un día antes. Hasta 10080."},"repeat":{"default":"none","type":"string","enum":["none","daily","weekly","monthly"],"description":"none (por defecto), daily, weekly o monthly, contando desde due_date. Al marcarlo como hecho pasa a la próxima fecha."},"repeat_until":{"default":null,"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta qué día se repite (opcional; null = sin fin). Solo con repeat."},{"type":"null"}]}},"required":["title","due_date"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"notes":{"type":"string"},"due_date":{"type":"string","description":"Día, AAAA-MM-DD, en la zona del laboratorio."},"due_time":{"description":"Hora, HH:MM; null = todo el día (avisa a las 9:00).","type":["string","null"]},"due_at":{"type":"string","description":"Cuándo avisa (instante ISO 8601)."},"assignees":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"description":"Para quién es: lo ven y reciben el aviso."},"notify_app":{"type":"boolean","description":"Avisa en Vialo y en el navegador."},"notify_email":{"type":"boolean","description":"Avisa también por mail."},"notify_before":{"type":"number","description":"Cuántos minutos antes de due_at avisa (0 = en el momento)."},"repeat":{"type":"string","enum":["none","daily","weekly","monthly"],"description":"none, daily, weekly o monthly. Uno que se repite, al marcarlo como hecho, pasa a la próxima fecha."},"repeat_until":{"description":"Hasta qué día se repite (AAAA-MM-DD); null = sin fin.","type":["string","null"]},"done_at":{"type":["string","null"]},"done_by_name":{"type":["string","null"]},"last_done_at":{"description":"La última vez que se hizo uno que se repite.","type":["string","null"]},"last_done_by_name":{"type":["string","null"]},"created_by":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"can_edit":{"type":"boolean","description":"Lo anotó la persona dueña del token: lo puede cambiar y borrar. Si no, solo marcarlo como hecho."},"overdue":{"type":"boolean","description":"Ya llegó el momento y sigue pendiente."},"version":{"type":"number"}},"required":["id","title","notes","due_date","due_time","due_at","assignees","notify_app","notify_email","notify_before","repeat","repeat_until","done_at","done_by_name","last_done_at","last_done_by_name","created_by","can_edit","overdue","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reminders/{id}":{"get":{"tags":["Recordatorios"],"summary":"Un recordatorio","description":"","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"notes":{"type":"string"},"due_date":{"type":"string","description":"Día, AAAA-MM-DD, en la zona del laboratorio."},"due_time":{"description":"Hora, HH:MM; null = todo el día (avisa a las 9:00).","type":["string","null"]},"due_at":{"type":"string","description":"Cuándo avisa (instante ISO 8601)."},"assignees":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"description":"Para quién es: lo ven y reciben el aviso."},"notify_app":{"type":"boolean","description":"Avisa en Vialo y en el navegador."},"notify_email":{"type":"boolean","description":"Avisa también por mail."},"notify_before":{"type":"number","description":"Cuántos minutos antes de due_at avisa (0 = en el momento)."},"repeat":{"type":"string","enum":["none","daily","weekly","monthly"],"description":"none, daily, weekly o monthly. Uno que se repite, al marcarlo como hecho, pasa a la próxima fecha."},"repeat_until":{"description":"Hasta qué día se repite (AAAA-MM-DD); null = sin fin.","type":["string","null"]},"done_at":{"type":["string","null"]},"done_by_name":{"type":["string","null"]},"last_done_at":{"description":"La última vez que se hizo uno que se repite.","type":["string","null"]},"last_done_by_name":{"type":["string","null"]},"created_by":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"can_edit":{"type":"boolean","description":"Lo anotó la persona dueña del token: lo puede cambiar y borrar. Si no, solo marcarlo como hecho."},"overdue":{"type":"boolean","description":"Ya llegó el momento y sigue pendiente."},"version":{"type":"number"}},"required":["id","title","notes","due_date","due_time","due_at","assignees","notify_app","notify_email","notify_before","repeat","repeat_until","done_at","done_by_name","last_done_at","last_done_by_name","created_by","can_edit","overdue","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Recordatorios"],"summary":"Cambiar un recordatorio o marcarlo como hecho","description":"Quien lo anotó cambia cualquier dato; las personas asignadas solo pueden marcarlo como hecho o volverlo a pendiente (done). Si cambian el día o la hora, vuelve a avisar en el momento nuevo.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":200,"description":"Qué hay que hacer: «Pedir nitrógeno líquido»."},"notes":{"type":"string","maxLength":2000,"description":"Detalles (opcional)."},"due_date":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día, AAAA-MM-DD, en la zona del laboratorio."},"due_time":{"anyOf":[{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},{"type":"null"}],"description":"Hora, HH:MM, en la zona del laboratorio. null o sin mandar = todo el día (avisa a las 9:00)."},"assignees":{"maxItems":20,"type":"array","items":{"type":"string","minLength":1,"maxLength":254},"description":"Para quién es: «me» (la persona dueña del token), el id, el nombre o el email de cada persona del laboratorio. Vacío o sin mandar = para la persona dueña del token."},"notify_app":{"type":"boolean","description":"Avisar en Vialo (Notificaciones) y en el navegador. Por defecto, sí."},"notify_email":{"type":"boolean","description":"Avisar también por mail cuando llega el momento. Por defecto, no."},"notify_before":{"type":"integer","minimum":0,"maximum":10080,"description":"Cuántos minutos antes avisar: 0 en el momento (por defecto), 60 una hora antes, 1440 un día antes. Hasta 10080."},"repeat":{"type":"string","enum":["none","daily","weekly","monthly"],"description":"none (por defecto), daily, weekly o monthly, contando desde due_date. Al marcarlo como hecho pasa a la próxima fecha."},"repeat_until":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta qué día se repite (opcional; null = sin fin). Solo con repeat."},{"type":"null"}]},"done":{"description":"true lo marca como hecho (si se repite, pasa a la próxima fecha); false lo vuelve a dejar pendiente. Lo pueden hacer también las personas asignadas.","type":"boolean"},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"notes":{"type":"string"},"due_date":{"type":"string","description":"Día, AAAA-MM-DD, en la zona del laboratorio."},"due_time":{"description":"Hora, HH:MM; null = todo el día (avisa a las 9:00).","type":["string","null"]},"due_at":{"type":"string","description":"Cuándo avisa (instante ISO 8601)."},"assignees":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"description":"Para quién es: lo ven y reciben el aviso."},"notify_app":{"type":"boolean","description":"Avisa en Vialo y en el navegador."},"notify_email":{"type":"boolean","description":"Avisa también por mail."},"notify_before":{"type":"number","description":"Cuántos minutos antes de due_at avisa (0 = en el momento)."},"repeat":{"type":"string","enum":["none","daily","weekly","monthly"],"description":"none, daily, weekly o monthly. Uno que se repite, al marcarlo como hecho, pasa a la próxima fecha."},"repeat_until":{"description":"Hasta qué día se repite (AAAA-MM-DD); null = sin fin.","type":["string","null"]},"done_at":{"type":["string","null"]},"done_by_name":{"type":["string","null"]},"last_done_at":{"description":"La última vez que se hizo uno que se repite.","type":["string","null"]},"last_done_by_name":{"type":["string","null"]},"created_by":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"can_edit":{"type":"boolean","description":"Lo anotó la persona dueña del token: lo puede cambiar y borrar. Si no, solo marcarlo como hecho."},"overdue":{"type":"boolean","description":"Ya llegó el momento y sigue pendiente."},"version":{"type":"number"}},"required":["id","title","notes","due_date","due_time","due_at","assignees","notify_app","notify_email","notify_before","repeat","repeat_until","done_at","done_by_name","last_done_at","last_done_by_name","created_by","can_edit","overdue","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"delete":{"tags":["Recordatorios"],"summary":"Borrar un recordatorio","description":"Solo quien lo anotó. Se borra para todas las personas asignadas; para cerrarlo sin borrarlo, marcalo como hecho.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/locations/{id}/access":{"get":{"tags":["Biobanco"],"summary":"Quién ve y gestiona una ubicación","description":"Si la ubicación (sala, equipo, rack o caja) es restringida y quiénes la ven (o también la gestionan) además de la administración. Alcanza a todo lo que tiene adentro. Se elige desde Vialo (la administración), no con un token.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"restricted":{"type":"boolean","description":"Si es true, solo lo ven la administración (y, en equipos, su responsable) y las personas de «people»."},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: solo ve; manage: ve y gestiona (carga y cambia datos)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Quiénes lo ven además de la administración."},"sub_labs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: toda su gente ve; manage: ve y gestiona (si su rol en este laboratorio lo permite)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Sub-laboratorios a los que se abrió, con toda su gente."}},"required":["restricted","people","sub_labs"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/fields":{"get":{"tags":["Biobanco"],"summary":"Campos de la muestra","description":"Campos base y personalizados, con su tipo y opciones: dicen qué significa cada clave de custom_fields.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Clave estable: los campos personalizados aparecen así en custom_fields."},"label":{"type":"string"},"type":{"type":"string","enum":["text","long_text","number","date","boolean","select","multiselect","link","attachment"]},"custom":{"type":"boolean","description":"true si lo definió el laboratorio."},"required":{"type":"boolean"},"unit":{"type":["string","null"]},"help":{"type":["string","null"]},"options":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Opciones vigentes, para las listas."},"archived":{"type":"boolean"}},"required":["key","label","type","custom","required","unit","help","options","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/sample-types":{"get":{"tags":["Biobanco"],"summary":"Tipos de muestra","description":"","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"code_prefix":{"type":"string"},"default_unit":{"type":["string","null"]},"archived":{"type":"boolean"}},"required":["id","name","code_prefix","default_unit","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/projects":{"get":{"tags":["Biobanco"],"summary":"Proyectos","description":"Los proyectos del laboratorio, con los que se agrupan las muestras.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"code":{"type":"string"},"description":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","code","description","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples":{"get":{"tags":["Biobanco"],"summary":"Buscar muestras","description":"Las muestras vigentes que cumplen todos los filtros, paginadas. Es la misma búsqueda que el listado de la web.","parameters":[{"name":"q","in":"query","required":false,"description":"Texto libre: código, donante, notas y campos personalizados de texto.","schema":{"description":"Texto libre: código, donante, notas y campos personalizados de texto.","type":"string","maxLength":200}},{"name":"type","in":"query","required":false,"description":"Tipos de muestra, por id o por nombre, separados por coma (cualquiera de ellos).","schema":{"description":"Tipos de muestra, por id o por nombre, separados por coma (cualquiera de ellos).","type":"string"}},{"name":"status","in":"query","required":false,"description":"Estados separados por coma: available, in_use, depleted, discarded, transferred. Por defecto, todos.","schema":{"description":"Estados separados por coma: available, in_use, depleted, discarded, transferred. Por defecto, todos.","type":"string"}},{"name":"location","in":"query","required":false,"description":"Ubicaciones por id (sala, freezer, rack o caja): incluye lo que está adentro.","schema":{"description":"Ubicaciones por id (sala, freezer, rack o caja): incluye lo que está adentro.","type":"string"}},{"name":"donor","in":"query","required":false,"description":"Parte del código de paciente o donante.","schema":{"description":"Parte del código de paciente o donante.","type":"string","maxLength":200}},{"name":"collected_from","in":"query","required":false,"description":"Extraídas desde esta fecha (AAAA-MM-DD).","schema":{"description":"Extraídas desde esta fecha (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"collected_to","in":"query","required":false,"description":"Extraídas hasta esta fecha (AAAA-MM-DD).","schema":{"description":"Extraídas hasta esta fecha (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"created_from","in":"query","required":false,"description":"Cargadas desde esta fecha (AAAA-MM-DD).","schema":{"description":"Cargadas desde esta fecha (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"created_to","in":"query","required":false,"description":"Cargadas hasta esta fecha (AAAA-MM-DD).","schema":{"description":"Cargadas hasta esta fecha (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"created_by","in":"query","required":false,"description":"Quién las cargó, separado por coma: «me» (la persona de este acceso), id, nombre o email.","schema":{"description":"Quién las cargó, separado por coma: «me» (la persona de este acceso), id, nombre o email.","type":"string"}},{"name":"placement","in":"query","required":false,"description":"located = solo las ubicadas en una caja, unlocated = solo las que todavía no tienen lugar.","schema":{"description":"located = solo las ubicadas en una caja, unlocated = solo las que todavía no tienen lugar.","type":"string","enum":["located","unlocated"]}},{"name":"origin","in":"query","required":false,"description":"primary = solo muestras originales, aliquot = solo alícuotas y derivadas.","schema":{"description":"primary = solo muestras originales, aliquot = solo alícuotas y derivadas.","type":"string","enum":["primary","aliquot"]}},{"name":"sort","in":"query","required":false,"description":"Campo por el que ordenar; con «-» adelante, de mayor a menor. Ej.: «-collection_date», «code», «cf.lote». Por defecto, «-created_at».","schema":{"description":"Campo por el que ordenar; con «-» adelante, de mayor a menor. Ej.: «-collection_date», «code», «cf.lote». Por defecto, «-created_at».","type":"string","maxLength":80}},{"name":"page","in":"query","required":false,"description":"Página, desde 1.","schema":{"default":1,"description":"Página, desde 1.","type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"description":"Resultados por página (hasta 200).","schema":{"default":50,"description":"Resultados por página (hasta 200).","type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","page","limit","total"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Biobanco"],"summary":"Cargar muestras","description":"Hasta 100 muestras por pedido; se crean todas juntas o ninguna. El código lo asigna Vialo con el formato del laboratorio. Con una caja con grilla y sin posición, cada muestra va al primer lugar libre (con «position»: null queda en la caja sin posición); en una caja sin grilla, van sin posición. Conviene mandar «Idempotency-Key» para poder reintentar sin duplicar.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"samples":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"type":{"type":"string","minLength":1,"maxLength":80,"description":"Tipo de muestra, por id o por nombre (ver /biobank/sample-types)."},"status":{"default":"available","type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"project":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"null"}],"description":"Proyecto, por id o por nombre (ver /biobank/projects); null saca la muestra del proyecto."},"donor_code":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9._/-]{0,39}$"},{"type":"null"}],"description":"Código pseudonimizado del donante; null lo borra."},"collection_date":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha de extracción (AAAA-MM-DD)."},{"type":"null"}]},"quantity":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Cantidad (volumen, masa…); null la borra."},"unit":{"type":"string","maxLength":20,"description":"Unidad de la cantidad (mL, µL, mg…)."},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"box_id":{"description":"Caja donde se guarda (ver /biobank/locations); null = sin ubicar.","anyOf":[{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},{"type":"null"}]},"position":{"description":"Posición en la caja: «B4» (filas con letras) o «2-4». Si no se manda, va al primer lugar libre de la grilla; null = en la caja, sin posición. Una caja sin grilla siempre la guarda sin posición.","anyOf":[{"type":"string","maxLength":10},{"type":"null"}]}},"required":["type"]},"description":"Las muestras a cargar. Se crean todas juntas o ninguna."}},"required":["samples"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/{id}":{"get":{"tags":["Biobanco"],"summary":"Ver una muestra","description":"Por id o por código (por ejemplo PL-2026-00042), con su ubicación, la muestra de origen y sus alícuotas.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"aliquots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."}},"required":["id","code","status","quantity","unit","placement"],"additionalProperties":false}}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version","aliquots"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Biobanco"],"summary":"Editar una muestra","description":"Por id o por código. Solo cambian los campos que se mandan; en custom_fields, solo las claves que se mandan. Pide la «version» que devolvió la API: si alguien la cambió después, responde 409. Para moverla o cambiar su estado están /move y /status.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"type":{"type":"string","minLength":1,"maxLength":80,"description":"Tipo de muestra, por id o por nombre (ver /biobank/sample-types)."},"project":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"null"}],"description":"Proyecto, por id o por nombre (ver /biobank/projects); null saca la muestra del proyecto."},"donor_code":{"anyOf":[{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9._/-]{0,39}$"},{"type":"null"}],"description":"Código pseudonimizado del donante; null lo borra."},"collection_date":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha de extracción (AAAA-MM-DD)."},{"type":"null"}]},"quantity":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Cantidad (volumen, masa…); null la borra."},"unit":{"type":"string","maxLength":20,"description":"Unidad de la cantidad (mL, µL, mg…)."},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"delete":{"tags":["Biobanco"],"summary":"Borrar una muestra","description":"Borrado lógico, como en la web: deja de aparecer y la administración la puede restaurar desde «Borradas». No se ofrece por MCP.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","code","deleted"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/{id}/history":{"get":{"tags":["Biobanco"],"summary":"Historial de una muestra","description":"Quién hizo cada cambio, cuándo y por dónde, del más nuevo al más viejo.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/{id}/attachments":{"get":{"tags":["Biobanco"],"summary":"Adjuntos de una muestra","description":"Cada adjunto trae un enlace de descarga que vence a los 5 minutos.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"file_name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"uploaded_by":{"type":"string"},"download_url":{"description":"Enlace de descarga que vence a los 5 minutos.","type":["string","null"]}},"required":["id","file_name","mime_type","size_bytes","created_at","uploaded_by","download_url"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/locations":{"get":{"tags":["Biobanco"],"summary":"Ubicaciones","description":"Salas, equipos, racks y cajas con su ruta completa. En las cajas, si tienen grilla, su capacidad, cuántas muestras tienen y cuántas están ubicadas en la grilla.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"parent_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"kind":{"type":"string","enum":["room","freezer","fridge","ln2_tank","rack","box"],"description":"Sala, freezer, heladera, tanque de nitrógeno, rack o caja."},"name":{"type":"string"},"path":{"type":"string"},"temperature_c":{"type":["number","null"]},"box":{"anyOf":[{"type":"object","properties":{"grid":{"type":"boolean","description":"Si tiene grilla; sin grilla, las muestras van sin posición."},"rows":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"cols":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"capacity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Posiciones de la grilla (0 sin grilla)."},"used":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Muestras en la caja."},"placed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Muestras ubicadas en una posición de la grilla."}},"required":["grid","rows","cols","capacity","used","placed"],"additionalProperties":false},{"type":"null"}],"description":"Solo para cajas."}},"required":["id","parent_id","kind","name","path","temperature_c","box"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/boxes/{id}":{"get":{"tags":["Biobanco"],"summary":"Grilla de una caja","description":"Todas las posiciones de la caja, ocupadas o libres, en orden, y las muestras que están en la caja sin posición. Una caja sin grilla no tiene posiciones: todas sus muestras van en «unplaced».","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string"},"rows":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"null si no tiene grilla."},"cols":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"free":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"positions":{"type":"array","items":{"type":"object","properties":{"position":{"type":"string"},"row":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"col":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"sample":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"string"},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."}},"required":["id","code","type","status"],"additionalProperties":false},{"type":"null"}]}},"required":["position","row","col","sample"],"additionalProperties":false}},"unplaced":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"string"},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."}},"required":["id","code","type","status"],"additionalProperties":false},"description":"Muestras en la caja sin posición (todas, si la caja no tiene grilla)."}},"required":["id","name","path","rows","cols","free","positions","unplaced"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/{id}/move":{"post":{"tags":["Biobanco"],"summary":"Mover una muestra","description":"A otra caja o posición (sin «position», al primer lugar libre de la grilla; con «position»: null, a la caja sin posición), o sin ubicar con «box_id»: null. Vialo valida que el lugar esté libre y que la caja exista.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"box_id":{"anyOf":[{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},{"type":"null"}]},"position":{"description":"Posición en la caja: «B4» (filas con letras) o «2-4». Si no se manda, va al primer lugar libre de la grilla; null = en la caja, sin posición. Una caja sin grilla siempre la guarda sin posición.","anyOf":[{"type":"string","maxLength":10},{"type":"null"}]}},"required":["box_id"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/{id}/status":{"post":{"tags":["Biobanco"],"summary":"Cambiar el estado de una muestra","description":"Disponible, en uso, agotada, descartada o transferida. Agotada, descartada y transferida liberan su lugar en la caja.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."}},"required":["status"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/{id}/aliquots":{"post":{"tags":["Biobanco"],"summary":"Crear alícuotas","description":"Alícuotas de una muestra: mismo tipo, donante, fecha y campos personalizados, con código propio. Con una caja con grilla, van a sus primeras posiciones libres; sin grilla, quedan en la caja sin posición. Se crean todas juntas o ninguna.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"count":{"type":"integer","minimum":1,"maximum":50,"description":"Cuántas alícuotas crear."},"quantity":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Cantidad (volumen, masa…); null la borra."},"unit":{"type":"string","maxLength":20,"description":"Unidad de cada alícuota. Por defecto, la de la muestra de origen."},"box_id":{"description":"Caja donde van: si tiene grilla, en sus primeras posiciones libres; sin caja, quedan sin ubicar.","anyOf":[{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},{"type":"null"}]}},"required":["count"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"project":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proyecto de la muestra, si tiene (ver /biobank/projects)."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."},"donor_code":{"description":"Código pseudonimizado.","type":["string","null"]},"collection_date":{"description":"Fecha de extracción (AAAA-MM-DD).","type":["string","null"]},"quantity":{"type":["number","null"]},"unit":{"type":["string","null"]},"notes":{"type":["string","null"]},"placement":{"anyOf":[{"type":"object","properties":{"box_id":{"type":"string","description":"Identificador (UUID)."},"box":{"type":"string","description":"Nombre de la caja."},"path":{"type":"string","description":"Ruta completa, por ejemplo «Sala 2 › Freezer -80 °C › Rack 3 › Caja 12»."},"position":{"description":"Posición legible: «B4» (filas con letras) o «2-4»; null si está en la caja sin posición (la caja no tiene grilla o todavía no se la ubicó).","type":["string","null"]},"row":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"col":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]}},"required":["box_id","box","path","position","row","col"],"additionalProperties":false},{"type":"null"}],"description":"Dónde está guardada; null si no está ubicada en una caja."},"parent":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":["string","null"]}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"Muestra de origen, si es una alícuota o derivada."},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","type","project","status","donor_code","collection_date","quantity","unit","notes","placement","parent","custom_fields","created_at","updated_at","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/biobank/samples/status":{"post":{"tags":["Biobanco"],"summary":"Cambiar el estado de varias muestras","description":"Lo mismo que elegir varias muestras en el listado y «Cambiar estado»: hasta 200 por vez, por id o por código. Agotada, descartada y transferida liberan su lugar en la caja. Devuelve las que cambiaron y las que no se encontraron.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"samples":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1},"description":"Ids o códigos de las muestras."},"status":{"type":"string","enum":["available","in_use","depleted","discarded","transferred"],"description":"available = disponible, in_use = en uso, depleted = agotada, discarded = descartada, transferred = transferida."}},"required":["samples","status"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"updated":{"type":"number","description":"Cuántas cambiaron."},"codes":{"type":"array","items":{"type":"string"},"description":"Códigos de las que cambiaron."},"not_found":{"type":"array","items":{"type":"string"},"description":"Lo que se mandó y no corresponde a ninguna muestra vigente."}},"required":["updated","codes","not_found"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/fields":{"get":{"tags":["Equipos"],"summary":"Campos del equipo","description":"Campos base y personalizados, con su tipo y opciones: dicen qué significa cada clave de custom_fields.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Clave estable: los campos personalizados aparecen así en custom_fields."},"label":{"type":"string"},"type":{"type":"string","enum":["text","long_text","number","date","boolean","select","multiselect","link","attachment"]},"custom":{"type":"boolean","description":"true si lo definió el laboratorio."},"required":{"type":"boolean"},"unit":{"type":["string","null"]},"help":{"type":["string","null"]},"options":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Opciones vigentes, para las listas."},"archived":{"type":"boolean"}},"required":["key","label","type","custom","required","unit","help","options","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/types":{"get":{"tags":["Equipos"],"summary":"Tipos de equipo","description":"","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"description":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","description","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/providers":{"get":{"tags":["Equipos"],"summary":"Proveedores","description":"Servicio técnico y calibraciones, con sus datos de contacto.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"notes":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","contact_name","phone","email","notes","archived","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Equipos"],"summary":"Agregar un proveedor","description":"Un proveedor de servicio técnico y calibraciones, con sus datos de contacto. El nombre no se repite.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del proveedor. No se repite en el laboratorio."},"contact_name":{"type":"string","maxLength":120,"description":"Persona de contacto."},"phone":{"type":"string","maxLength":60,"description":"Teléfono."},"email":{"description":"Email. Vacío lo quita.","anyOf":[{"type":"string","const":""},{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}},"required":["name"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"notes":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","contact_name","phone","email","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items":{"get":{"tags":["Equipos"],"summary":"Buscar equipos","description":"Los equipos vigentes que cumplen todos los filtros, paginados. Es la misma búsqueda que el listado de la web.","parameters":[{"name":"q","in":"query","required":false,"description":"Texto libre: código, nombre, marca, modelo, n.º de serie o de inventario.","schema":{"description":"Texto libre: código, nombre, marca, modelo, n.º de serie o de inventario.","type":"string","maxLength":200}},{"name":"type","in":"query","required":false,"description":"Tipos de equipo, por id o por nombre, separados por coma (cualquiera de ellos).","schema":{"description":"Tipos de equipo, por id o por nombre, separados por coma (cualquiera de ellos).","type":"string"}},{"name":"status","in":"query","required":false,"description":"Estados separados por coma: in_service, out_of_service, retired. Por defecto, todos.","schema":{"description":"Estados separados por coma: in_service, out_of_service, retired. Por defecto, todos.","type":"string"}},{"name":"room","in":"query","required":false,"description":"Salas separadas por coma (sin importar mayúsculas).","schema":{"description":"Salas separadas por coma (sin importar mayúsculas).","type":"string"}},{"name":"responsible","in":"query","required":false,"description":"Responsables, separados por coma: «me» (la persona de este acceso), id, nombre o email.","schema":{"description":"Responsables, separados por coma: «me» (la persona de este acceso), id, nombre o email.","type":"string"}},{"name":"provider","in":"query","required":false,"description":"Servicios técnicos, por id o por nombre, separados por coma (cualquiera de ellos).","schema":{"description":"Servicios técnicos, por id o por nombre, separados por coma (cualquiera de ellos).","type":"string"}},{"name":"warranty","in":"query","required":false,"description":"active = solo los que están en garantía, expired = solo los de garantía vencida.","schema":{"description":"active = solo los que están en garantía, expired = solo los de garantía vencida.","type":"string","enum":["active","expired"]}},{"name":"biobank","in":"query","required":false,"description":"linked = solo los vinculados con un lugar del Biobanco, unlinked = solo los sin vincular. Pide el Biobanco habilitado.","schema":{"description":"linked = solo los vinculados con un lugar del Biobanco, unlinked = solo los sin vincular. Pide el Biobanco habilitado.","type":"string","enum":["linked","unlinked"]}},{"name":"attention","in":"query","required":false,"description":"due = con algo vencido o por vencer, overdue = con algo vencido, open_failure = con una falla abierta.","schema":{"description":"due = con algo vencido o por vencer, overdue = con algo vencido, open_failure = con una falla abierta.","type":"string","enum":["due","overdue","open_failure"]}},{"name":"sort","in":"query","required":false,"description":"Campo por el que ordenar; con «-» adelante, de mayor a menor. Ej.: «next_due», «-purchase_date», «name». Por defecto, «code».","schema":{"description":"Campo por el que ordenar; con «-» adelante, de mayor a menor. Ej.: «next_due», «-purchase_date», «name». Por defecto, «code».","type":"string","maxLength":80}},{"name":"page","in":"query","required":false,"description":"Página, desde 1.","schema":{"default":1,"description":"Página, desde 1.","type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"description":"Resultados por página (hasta 200).","schema":{"default":50,"description":"Resultados por página (hasta 200).","type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"status":{"type":"string","enum":["in_service","out_of_service","retired"],"description":"in_service = en servicio, out_of_service = fuera de servicio, retired = dado de baja."},"status_reason":{"type":"string","description":"Por qué está fuera de servicio o dado de baja."},"brand":{"type":"string"},"model":{"type":"string"},"serial_number":{"type":"string"},"asset_number":{"type":"string","description":"N.º de inventario o de patrimonio."},"room":{"type":"string"},"place":{"type":"string"},"responsible":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Servicio técnico habitual."},"purchase_date":{"type":["string","null"]},"warranty_until":{"type":["string","null"]},"next_due":{"anyOf":[{"type":"object","properties":{"due_on":{"type":["string","null"]},"status":{"type":"string","enum":["overdue","due_soon","ok","unscheduled"],"description":"overdue = vencida, due_soon = por vencer, ok = al día, unscheduled = sin fecha."}},"required":["due_on","status"],"additionalProperties":false},{"type":"null"}],"description":"La tarea del plan que vence primero y el peor estado del plan; null si no tiene plan."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","type","status","status_reason","brand","model","serial_number","asset_number","room","place","responsible","provider","purchase_date","warranty_until","next_due","notes","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","page","limit","total"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Equipos"],"summary":"Crear un equipo","description":"Da de alta un equipo con las mismas reglas que el formulario de la web. El código lo asigna el laboratorio (EQ-0001…). Tipo y servicio técnico van por id o por nombre.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del equipo."},"type":{"type":"string","minLength":1,"maxLength":120,"description":"Tipo de equipo, por id o por nombre (ver …/equipment/types)."},"status":{"description":"in_service = en servicio (por defecto), out_of_service = fuera de servicio, retired = dado de baja.","type":"string","enum":["in_service","out_of_service","retired"]},"status_reason":{"description":"Por qué está fuera de servicio o dado de baja: obligatorio en esos estados. En servicio no se guarda.","type":"string","maxLength":500},"brand":{"description":"Marca.","type":"string","maxLength":80},"model":{"description":"Modelo.","type":"string","maxLength":80},"serial_number":{"description":"N.º de serie.","type":"string","maxLength":80},"asset_number":{"description":"N.º de inventario o de patrimonio.","type":"string","maxLength":80},"room":{"description":"Sala.","type":"string","maxLength":80},"place":{"description":"Lugar dentro de la sala (mesada, estante…).","type":"string","maxLength":120},"responsible_id":{"anyOf":[{"type":"string","minLength":1,"maxLength":200,"description":"Miembro responsable: su id (el de responsible o person en las respuestas), su nombre o su email. null lo deja sin asignar."},{"type":"null"}]},"provider":{"description":"Servicio técnico habitual, por id o por nombre (ver …/equipment/providers). null lo quita.","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"purchase_date":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha de compra (AAAA-MM-DD)."},{"type":"null"}]},"warranty_until":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Garantía hasta (AAAA-MM-DD)."},{"type":"null"}]},"biobank_location_id":{"description":"Freezer, heladera o tanque del Biobanco que es este equipo. Si no mandás sala, toma la de esa ubicación.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"description":"Notas.","type":"string","maxLength":2000},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["name","type"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"status":{"type":"string","enum":["in_service","out_of_service","retired"],"description":"in_service = en servicio, out_of_service = fuera de servicio, retired = dado de baja."},"status_reason":{"type":"string","description":"Por qué está fuera de servicio o dado de baja."},"brand":{"type":"string"},"model":{"type":"string"},"serial_number":{"type":"string"},"asset_number":{"type":"string","description":"N.º de inventario o de patrimonio."},"room":{"type":"string"},"place":{"type":"string"},"responsible":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Servicio técnico habitual."},"purchase_date":{"type":["string","null"]},"warranty_until":{"type":["string","null"]},"next_due":{"anyOf":[{"type":"object","properties":{"due_on":{"type":["string","null"]},"status":{"type":"string","enum":["overdue","due_soon","ok","unscheduled"],"description":"overdue = vencida, due_soon = por vencer, ok = al día, unscheduled = sin fecha."}},"required":["due_on","status"],"additionalProperties":false},{"type":"null"}],"description":"La tarea del plan que vence primero y el peor estado del plan; null si no tiene plan."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","type","status","status_reason","brand","model","serial_number","asset_number","room","place","responsible","provider","purchase_date","warranty_until","next_due","notes","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}":{"get":{"tags":["Equipos"],"summary":"Ver un equipo","description":"Por id o por código (por ejemplo EQ-0004), con su plan de mantenimiento, sus fallas abiertas y quién lo está usando.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"status":{"type":"string","enum":["in_service","out_of_service","retired"],"description":"in_service = en servicio, out_of_service = fuera de servicio, retired = dado de baja."},"status_reason":{"type":"string","description":"Por qué está fuera de servicio o dado de baja."},"brand":{"type":"string"},"model":{"type":"string"},"serial_number":{"type":"string"},"asset_number":{"type":"string","description":"N.º de inventario o de patrimonio."},"room":{"type":"string"},"place":{"type":"string"},"responsible":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Servicio técnico habitual."},"purchase_date":{"type":["string","null"]},"warranty_until":{"type":["string","null"]},"next_due":{"anyOf":[{"type":"object","properties":{"due_on":{"type":["string","null"]},"status":{"type":"string","enum":["overdue","due_soon","ok","unscheduled"],"description":"overdue = vencida, due_soon = por vencer, ok = al día, unscheduled = sin fecha."}},"required":["due_on","status"],"additionalProperties":false},{"type":"null"}],"description":"La tarea del plan que vence primero y el peor estado del plan; null si no tiene plan."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"biobank_location_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"Freezer, heladera o tanque del Biobanco vinculado."},"tasks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other"],"description":"maintenance = mantenimiento, calibration = calibración, verification = verificación, cleaning = limpieza, other = otra."},"title":{"type":"string"},"every":{"type":"string","description":"Frecuencia legible: «Anual», «Cada 6 meses»."},"interval_value":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"interval_unit":{"type":"string","enum":["day","week","month","year"]},"performed_by":{"type":"string","enum":["internal","external"],"description":"internal = el laboratorio, external = el servicio técnico."},"last_done":{"type":["string","null"]},"due_on":{"type":["string","null"]},"due_status":{"type":"string","enum":["overdue","due_soon","ok","unscheduled"],"description":"overdue = vencida, due_soon = por vencer, ok = al día, unscheduled = sin fecha."}},"required":["id","kind","title","every","interval_value","interval_unit","performed_by","last_done","due_on","due_status"],"additionalProperties":false},"description":"Plan de mantenimiento vigente."},"open_failures":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other","failure","repair","note"],"description":"Qué se registró. Las fallas tienen severity y resolved_on."},"task_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"performed_on":{"type":"string","description":"Fecha (AAAA-MM-DD)."},"performed_by":{"description":"Quién lo hizo: un miembro, el servicio técnico o un técnico.","type":["string","null"]},"detail":{"type":"string"},"result":{"anyOf":[{"type":"string","enum":["pass","fail"]},{"type":"null"}],"description":"Calibraciones y verificaciones: pass = conforme, fail = no conforme."},"valid_until":{"type":["string","null"]},"severity":{"anyOf":[{"type":"string","enum":["high","low"]},{"type":"null"}],"description":"Fallas: high = impide usarlo, low = se puede seguir usando."},"resolved_on":{"type":["string","null"]},"resolution":{"type":["string","null"]},"cost":{"type":["number","null"]},"currency":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","kind","task_id","performed_on","performed_by","detail","result","valid_until","severity","resolved_on","resolution","cost","currency","created_at"],"additionalProperties":false}},"in_use_by":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Quién lo está usando ahora, si alguien."}},"required":["id","code","name","type","status","status_reason","brand","model","serial_number","asset_number","room","place","responsible","provider","purchase_date","warranty_until","next_due","notes","custom_fields","created_at","updated_at","version","biobank_location_id","tasks","open_failures","in_use_by"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Equipos"],"summary":"Modificar un equipo","description":"Por id o por código. Cambia solo los campos que mandás (en custom_fields, solo las claves que mandás); el resto queda como estaba. Pide la «version» que devolvió la API: si alguien lo cambió después, responde 409.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del equipo."},"type":{"type":"string","minLength":1,"maxLength":120,"description":"Tipo de equipo, por id o por nombre (ver …/equipment/types)."},"status":{"description":"in_service = en servicio (por defecto), out_of_service = fuera de servicio, retired = dado de baja.","type":"string","enum":["in_service","out_of_service","retired"]},"status_reason":{"description":"Por qué está fuera de servicio o dado de baja: obligatorio en esos estados. En servicio no se guarda.","type":"string","maxLength":500},"brand":{"description":"Marca.","type":"string","maxLength":80},"model":{"description":"Modelo.","type":"string","maxLength":80},"serial_number":{"description":"N.º de serie.","type":"string","maxLength":80},"asset_number":{"description":"N.º de inventario o de patrimonio.","type":"string","maxLength":80},"room":{"description":"Sala.","type":"string","maxLength":80},"place":{"description":"Lugar dentro de la sala (mesada, estante…).","type":"string","maxLength":120},"responsible_id":{"anyOf":[{"type":"string","minLength":1,"maxLength":200,"description":"Miembro responsable: su id (el de responsible o person en las respuestas), su nombre o su email. null lo deja sin asignar."},{"type":"null"}]},"provider":{"description":"Servicio técnico habitual, por id o por nombre (ver …/equipment/providers). null lo quita.","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"purchase_date":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha de compra (AAAA-MM-DD)."},{"type":"null"}]},"warranty_until":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Garantía hasta (AAAA-MM-DD)."},{"type":"null"}]},"biobank_location_id":{"description":"Freezer, heladera o tanque del Biobanco que es este equipo. Si no mandás sala, toma la de esa ubicación.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"description":"Notas.","type":"string","maxLength":2000},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"type":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"status":{"type":"string","enum":["in_service","out_of_service","retired"],"description":"in_service = en servicio, out_of_service = fuera de servicio, retired = dado de baja."},"status_reason":{"type":"string","description":"Por qué está fuera de servicio o dado de baja."},"brand":{"type":"string"},"model":{"type":"string"},"serial_number":{"type":"string"},"asset_number":{"type":"string","description":"N.º de inventario o de patrimonio."},"room":{"type":"string"},"place":{"type":"string"},"responsible":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Servicio técnico habitual."},"purchase_date":{"type":["string","null"]},"warranty_until":{"type":["string","null"]},"next_due":{"anyOf":[{"type":"object","properties":{"due_on":{"type":["string","null"]},"status":{"type":"string","enum":["overdue","due_soon","ok","unscheduled"],"description":"overdue = vencida, due_soon = por vencer, ok = al día, unscheduled = sin fecha."}},"required":["due_on","status"],"additionalProperties":false},{"type":"null"}],"description":"La tarea del plan que vence primero y el peor estado del plan; null si no tiene plan."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Valores de los campos personalizados por clave. Las listas devuelven el texto de la opción."},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","type","status","status_reason","brand","model","serial_number","asset_number","room","place","responsible","provider","purchase_date","warranty_until","next_due","notes","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/events":{"get":{"tags":["Equipos"],"summary":"Registro de un equipo","description":"Mantenimientos, calibraciones, verificaciones, limpiezas, fallas, reparaciones y notas, del más reciente al más viejo (hasta 500).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other","failure","repair","note"],"description":"Qué se registró. Las fallas tienen severity y resolved_on."},"task_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"performed_on":{"type":"string","description":"Fecha (AAAA-MM-DD)."},"performed_by":{"description":"Quién lo hizo: un miembro, el servicio técnico o un técnico.","type":["string","null"]},"detail":{"type":"string"},"result":{"anyOf":[{"type":"string","enum":["pass","fail"]},{"type":"null"}],"description":"Calibraciones y verificaciones: pass = conforme, fail = no conforme."},"valid_until":{"type":["string","null"]},"severity":{"anyOf":[{"type":"string","enum":["high","low"]},{"type":"null"}],"description":"Fallas: high = impide usarlo, low = se puede seguir usando."},"resolved_on":{"type":["string","null"]},"resolution":{"type":["string","null"]},"cost":{"type":["number","null"]},"currency":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","kind","task_id","performed_on","performed_by","detail","result","valid_until","severity","resolved_on","resolution","cost","currency","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Equipos"],"summary":"Registrar un mantenimiento","description":"Suma al registro del equipo un mantenimiento, calibración, verificación, limpieza, reparación, nota u otra tarea. Con task_id cuenta para el plan de mantenimiento: una calibración o verificación no conforme deja la tarea pendiente.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","repair","other","note"],"description":"maintenance = mantenimiento, calibration = calibración, verification = verificación, cleaning = limpieza, repair = reparación, other = otra tarea, note = nota. Las fallas van por …/failures."},"task_id":{"description":"Tarea del plan de mantenimiento que se cumplió (ver tasks en la ficha del equipo): así se recalcula su vencimiento.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"performed_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo se hizo (AAAA-MM-DD). Por defecto, hoy."},"performed_by_user_id":{"type":"string","minLength":1,"maxLength":200,"description":"Miembro que lo hizo: id, nombre o email. Por defecto, la persona del token, salvo que mandes provider o technician_name."},"provider":{"description":"Si lo hizo el servicio técnico: el proveedor, por id o por nombre (ver …/providers).","type":"string","maxLength":120},"technician_name":{"description":"Si lo hizo el servicio técnico: nombre del técnico.","type":"string","maxLength":120},"detail":{"description":"Qué se hizo, observaciones.","type":"string","maxLength":4000},"result":{"description":"Calibraciones y verificaciones (obligatorio): pass = conforme, fail = no conforme. No conforme deja la tarea pendiente.","type":"string","enum":["pass","fail"]},"valid_until":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Calibraciones y verificaciones: hasta cuándo vale (AAAA-MM-DD)."},"cost":{"description":"Costo, con hasta 2 decimales.","type":"number","minimum":0},"currency":{"description":"Moneda del costo (ARS, USD…). Por defecto, ARS.","type":"string","pattern":"^[A-Z]{3}$"},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["kind"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other","failure","repair","note"],"description":"Qué se registró. Las fallas tienen severity y resolved_on."},"task_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"performed_on":{"type":"string","description":"Fecha (AAAA-MM-DD)."},"performed_by":{"description":"Quién lo hizo: un miembro, el servicio técnico o un técnico.","type":["string","null"]},"detail":{"type":"string"},"result":{"anyOf":[{"type":"string","enum":["pass","fail"]},{"type":"null"}],"description":"Calibraciones y verificaciones: pass = conforme, fail = no conforme."},"valid_until":{"type":["string","null"]},"severity":{"anyOf":[{"type":"string","enum":["high","low"]},{"type":"null"}],"description":"Fallas: high = impide usarlo, low = se puede seguir usando."},"resolved_on":{"type":["string","null"]},"resolution":{"type":["string","null"]},"cost":{"type":["number","null"]},"currency":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","kind","task_id","performed_on","performed_by","detail","result","valid_until","severity","resolved_on","resolution","cost","currency","created_at"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/history":{"get":{"tags":["Equipos"],"summary":"Historial de un equipo","description":"Quién cambió los datos del equipo, cuándo y por dónde, del más nuevo al más viejo.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/access":{"get":{"tags":["Equipos"],"summary":"Quién ve y gestiona un equipo","description":"Si el equipo es restringido y quiénes lo ven (o también lo gestionan) además de la administración y el responsable. Se elige desde Vialo (la administración), no con un token.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"restricted":{"type":"boolean","description":"Si es true, solo lo ven la administración (y, en equipos, su responsable) y las personas de «people»."},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: solo ve; manage: ve y gestiona (carga y cambia datos)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Quiénes lo ven además de la administración."},"sub_labs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: toda su gente ve; manage: ve y gestiona (si su rol en este laboratorio lo permite)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Sub-laboratorios a los que se abrió, con toda su gente."}},"required":["restricted","people","sub_labs"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/attachments":{"get":{"tags":["Equipos"],"summary":"Documentos de un equipo","description":"Manuales, certificados y otros archivos del equipo. Cada uno trae un enlace de descarga que vence a los 5 minutos.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"file_name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"uploaded_by":{"type":"string"},"download_url":{"description":"Enlace de descarga que vence a los 5 minutos.","type":["string","null"]}},"required":["id","file_name","mime_type","size_bytes","created_at","uploaded_by","download_url"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/due":{"get":{"tags":["Equipos"],"summary":"Vencimientos","description":"Las tareas del plan de mantenimiento de todos los equipos, por fecha de vencimiento. Por defecto, solo lo vencido y lo que está por vencer.","parameters":[{"name":"status","in":"query","required":false,"description":"Estados del vencimiento separados por coma: overdue, due_soon, ok, unscheduled. Por defecto, overdue y due_soon.","schema":{"description":"Estados del vencimiento separados por coma: overdue, due_soon, ok, unscheduled. Por defecto, overdue y due_soon.","type":"string"}},{"name":"until","in":"query","required":false,"description":"Solo lo que vence hasta esta fecha (AAAA-MM-DD).","schema":{"description":"Solo lo que vence hasta esta fecha (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other"],"description":"maintenance = mantenimiento, calibration = calibración, verification = verificación, cleaning = limpieza, other = otra."},"title":{"type":"string"},"every":{"type":"string","description":"Frecuencia legible: «Anual», «Cada 6 meses»."},"interval_value":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"interval_unit":{"type":"string","enum":["day","week","month","year"]},"performed_by":{"type":"string","enum":["internal","external"],"description":"internal = el laboratorio, external = el servicio técnico."},"last_done":{"type":["string","null"]},"due_on":{"type":["string","null"]},"due_status":{"type":"string","enum":["overdue","due_soon","ok","unscheduled"],"description":"overdue = vencida, due_soon = por vencer, ok = al día, unscheduled = sin fecha."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false}},"required":["id","kind","title","every","interval_value","interval_unit","performed_by","last_done","due_on","due_status","equipment"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/todos":{"get":{"tags":["Equipos"],"summary":"Pendientes de un equipo","description":"Tareas abiertas del equipo (y las ya resueltas), con su fecha límite y el proveedor asociado. Los abiertos primero, por fecha límite.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"title":{"type":"string"},"detail":{"type":"string"},"due_on":{"description":"Fecha límite (AAAA-MM-DD), si tiene.","type":["string","null"]},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proveedor asociado, si tiene."},"done":{"type":"boolean","description":"true si ya se resolvió."},"done_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","title","detail","due_on","provider","done","done_at","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Equipos"],"summary":"Agregar un pendiente a un equipo","description":"Anota una tarea abierta del equipo, con fecha límite y proveedor (por id o por nombre) opcionales.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":160,"description":"Qué hay que hacer."},"detail":{"description":"Detalle (opcional).","type":"string","maxLength":2000},"due_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha límite (AAAA-MM-DD), opcional."},"provider":{"description":"Proveedor asociado, por id o por nombre (ver …/equipment/providers).","type":"string","maxLength":120}},"required":["title"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"title":{"type":"string"},"detail":{"type":"string"},"due_on":{"description":"Fecha límite (AAAA-MM-DD), si tiene.","type":["string","null"]},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proveedor asociado, si tiene."},"done":{"type":"boolean","description":"true si ya se resolvió."},"done_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","title","detail","due_on","provider","done","done_at","created_at"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/failures":{"get":{"tags":["Equipos"],"summary":"Fallas abiertas","description":"Las fallas sin cerrar de todos los equipos, de la más vieja a la más nueva.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other","failure","repair","note"],"description":"Qué se registró. Las fallas tienen severity y resolved_on."},"task_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"performed_on":{"type":"string","description":"Fecha (AAAA-MM-DD)."},"performed_by":{"description":"Quién lo hizo: un miembro, el servicio técnico o un técnico.","type":["string","null"]},"detail":{"type":"string"},"result":{"anyOf":[{"type":"string","enum":["pass","fail"]},{"type":"null"}],"description":"Calibraciones y verificaciones: pass = conforme, fail = no conforme."},"valid_until":{"type":["string","null"]},"severity":{"anyOf":[{"type":"string","enum":["high","low"]},{"type":"null"}],"description":"Fallas: high = impide usarlo, low = se puede seguir usando."},"resolved_on":{"type":["string","null"]},"resolution":{"type":["string","null"]},"cost":{"type":["number","null"]},"currency":{"type":["string","null"]},"created_at":{"type":"string"},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"reported_by":{"type":["string","null"]}},"required":["id","kind","task_id","performed_on","performed_by","detail","result","valid_until","severity","resolved_on","resolution","cost","currency","created_at","equipment","reported_by"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/bookings":{"get":{"tags":["Equipos"],"summary":"Reservas","description":"Reservas que tocan el rango pedido, en orden: por defecto, las pendientes y confirmadas; con «status», las de ese estado (también canceladas o rechazadas). «q» busca por motivo, equipo o persona. Las horas van en UTC; la zona del laboratorio está en /lab.","parameters":[{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD, en la hora del laboratorio). Por defecto, hoy.","schema":{"description":"Desde este día (AAAA-MM-DD, en la hora del laboratorio). Por defecto, hoy.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive. Por defecto, 7 días desde «from». Hasta 3 meses.","schema":{"description":"Hasta este día inclusive. Por defecto, 7 días desde «from». Hasta 3 meses.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"equipment","in":"query","required":false,"description":"Un equipo, por id o por código.","schema":{"description":"Un equipo, por id o por código.","type":"string","maxLength":80}},{"name":"q","in":"query","required":false,"description":"Texto a buscar en el motivo, en el nombre o código del equipo y en el nombre de la persona.","schema":{"description":"Texto a buscar en el motivo, en el nombre o código del equipo y en el nombre de la persona.","type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"description":"Solo las de este estado. Por defecto, pendientes y confirmadas (las que ocupan el equipo).","schema":{"description":"Solo las de este estado. Por defecto, pendientes y confirmadas (las que ocupan el equipo).","type":"string","enum":["pending","confirmed","rejected","cancelled"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"starts_at":{"type":"string","description":"Instante ISO 8601 (UTC)."},"ends_at":{"type":"string"},"purpose":{"type":"string"},"status":{"type":"string","enum":["pending","confirmed","rejected","cancelled"],"description":"pending = pendiente de aprobación, confirmed = confirmada, rejected = rechazada, cancelled = cancelada."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para cambiar el horario sin pisar otro cambio (PATCH)."}},"required":["id","equipment","person","starts_at","ends_at","purpose","status","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Equipos"],"summary":"Reservar un equipo","description":"Reserva un horario, o el mismo horario varios días con repeat. Si el equipo pide aprobación, queda pendiente (pero nadie más puede tomar ese horario). En una serie, los días que no se pueden (chocan con otra reserva, fuera de horario…) vuelven en rejected y los demás se reservan.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"equipment":{"type":"string","minLength":1,"maxLength":80,"description":"El equipo, por id o por código (EQ-0004)."},"starts_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Inicio: instante ISO 8601 con zona (2026-10-27T10:00:00-03:00 o …Z)."},"ends_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Fin, con el mismo formato."},"purpose":{"description":"Para qué se reserva.","type":"string","maxLength":300},"person_id":{"type":"string","minLength":1,"maxLength":200,"description":"Para reservar a nombre de otra persona (id, nombre o email; lo puede hacer quien es Colaborador o aprueba ese equipo). Por defecto, la persona del token."},"repeat":{"description":"Repetir el mismo horario (en la hora del laboratorio): weekly = cada semana, weekdays = de lunes a viernes, daily = todos los días. Hasta 60 reservas por serie.","type":"string","enum":["weekly","weekdays","daily"]},"repeat_until":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Con repeat: último día de la serie (AAAA-MM-DD), inclusive."}},"required":["equipment","starts_at","ends_at"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"created":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"starts_at":{"type":"string","description":"Instante ISO 8601 (UTC)."},"ends_at":{"type":"string"},"purpose":{"type":"string"},"status":{"type":"string","enum":["pending","confirmed","rejected","cancelled"],"description":"pending = pendiente de aprobación, confirmed = confirmada, rejected = rechazada, cancelled = cancelada."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para cambiar el horario sin pisar otro cambio (PATCH)."}},"required":["id","equipment","person","starts_at","ends_at","purpose","status","version"],"additionalProperties":false},"description":"Las reservas que se hicieron."},"rejected":{"type":"array","items":{"type":"object","properties":{"starts_at":{"type":"string"},"error":{"type":"string"}},"required":["starts_at","error"],"additionalProperties":false},"description":"Solo en las series: los días que no se pudieron reservar y por qué."}},"required":["created","rejected"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/usage":{"get":{"tags":["Equipos"],"summary":"Registro de uso","description":"Quién usó cada equipo, cuándo y cuánto tiempo, del más reciente al más viejo (hasta 1000).","parameters":[{"name":"from","in":"query","required":false,"description":"Usos que empezaron desde este día (AAAA-MM-DD). Por defecto, hace 30 días.","schema":{"description":"Usos que empezaron desde este día (AAAA-MM-DD). Por defecto, hace 30 días.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive. Por defecto, hoy. Hasta 3 meses.","schema":{"description":"Hasta este día inclusive. Por defecto, hoy. Hasta 3 meses.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"equipment","in":"query","required":false,"description":"Un equipo, por id o por código.","schema":{"description":"Un equipo, por id o por código.","type":"string","maxLength":80}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"started_at":{"type":"string"},"ended_at":{"description":"null mientras se está usando.","type":["string","null"]},"minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"purpose":{"type":"string"},"notes":{"type":"string"},"outcome":{"anyOf":[{"type":"string","enum":["ok","problem"]},{"type":"null"}],"description":"ok = sin problemas, problem = con un problema (abre una falla)."}},"required":["id","equipment","person","started_at","ended_at","minutes","purpose","notes","outcome"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/providers/{id}":{"patch":{"tags":["Equipos"],"summary":"Modificar un proveedor","description":"Cambia solo lo que se manda. Con «version», responde 409 si alguien lo cambió después de leerlo. Archivar o reactivar pide rol de administración, como en la web.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del proveedor. No se repite en el laboratorio."},"archived":{"description":"true lo archiva (no se ofrece al cargar equipos; los que lo tienen asignado no cambian); false lo reactiva. Pide rol de administración.","type":"boolean"},"contact_name":{"type":"string","maxLength":120,"description":"Persona de contacto."},"phone":{"type":"string","maxLength":60,"description":"Teléfono."},"email":{"description":"Email. Vacío lo quita.","anyOf":[{"type":"string","const":""},{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"notes":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","contact_name","phone","email","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/photo/suggestions":{"get":{"tags":["Equipos"],"summary":"Buscar fotos posibles de un equipo","description":"Imágenes de internet según los datos del registro, un texto o un enlace. Pertenecen a sus sitios de origen: son para usar dentro del laboratorio.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Otro texto para buscar, o el enlace de una página de producto o de una imagen. Sin esto, busca por los datos del registro.","schema":{"description":"Otro texto para buscar, o el enlace de una página de producto o de una imagen. Sin esto, busca por los datos del registro.","type":"string","maxLength":2000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"query":{"type":"string","description":"El texto o el enlace que dio estos resultados."},"data":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","description":"La imagen: es lo que se manda para elegirla."},"thumb_url":{"type":"string"},"title":{"type":"string"},"source":{"type":"string","description":"El sitio de donde sale."}},"required":["url","thumb_url","title","source"],"additionalProperties":false}}},"required":["query","data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/photo":{"post":{"tags":["Equipos"],"summary":"Elegir la foto de un equipo","description":"Vialo baja la imagen y la guarda en el laboratorio como un adjunto más, así no depende del sitio de origen.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri","description":"La imagen elegida (https)."},"thumb_url":{"description":"Su miniatura: se guarda si el sitio no deja bajar la imagen.","type":"string","maxLength":2000,"format":"uri"}},"required":["url"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"delete":{"tags":["Equipos"],"summary":"Quitar la foto de un equipo","description":"El archivo sigue entre sus adjuntos.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/todos/{id}/resolve":{"post":{"tags":["Equipos"],"summary":"Resolver un pendiente","description":"Marca un pendiente abierto como resuelto.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"title":{"type":"string"},"detail":{"type":"string"},"due_on":{"description":"Fecha límite (AAAA-MM-DD), si tiene.","type":["string","null"]},"provider":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proveedor asociado, si tiene."},"done":{"type":"boolean","description":"true si ya se resolvió."},"done_at":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","title","detail","due_on","provider","done","done_at","created_at"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/failures":{"post":{"tags":["Equipos"],"summary":"Reportar una falla","description":"Abre una falla del equipo. Con take_out_of_service queda fuera de servicio (no se puede usar ni reservar) hasta que se cierre.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"detail":{"type":"string","minLength":1,"maxLength":4000,"description":"Qué pasó con el equipo."},"severity":{"default":"high","description":"high = impide usarlo (por defecto), low = se puede seguir usando.","type":"string","enum":["high","low"]},"take_out_of_service":{"default":false,"description":"true deja el equipo fuera de servicio hasta que se cierre la falla.","type":"boolean"},"performed_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo pasó (AAAA-MM-DD). Por defecto, hoy."}},"required":["detail"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other","failure","repair","note"],"description":"Qué se registró. Las fallas tienen severity y resolved_on."},"task_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"performed_on":{"type":"string","description":"Fecha (AAAA-MM-DD)."},"performed_by":{"description":"Quién lo hizo: un miembro, el servicio técnico o un técnico.","type":["string","null"]},"detail":{"type":"string"},"result":{"anyOf":[{"type":"string","enum":["pass","fail"]},{"type":"null"}],"description":"Calibraciones y verificaciones: pass = conforme, fail = no conforme."},"valid_until":{"type":["string","null"]},"severity":{"anyOf":[{"type":"string","enum":["high","low"]},{"type":"null"}],"description":"Fallas: high = impide usarlo, low = se puede seguir usando."},"resolved_on":{"type":["string","null"]},"resolution":{"type":["string","null"]},"cost":{"type":["number","null"]},"currency":{"type":["string","null"]},"created_at":{"type":"string"}},"required":["id","kind","task_id","performed_on","performed_by","detail","result","valid_until","severity","resolved_on","resolution","cost","currency","created_at"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/failures/{id}/resolve":{"post":{"tags":["Equipos"],"summary":"Cerrar una falla","description":"Cierra una falla abierta (ver …/equipment/failures). Con back_in_service el equipo vuelve a estar en servicio, salvo que tenga otras fallas abiertas.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"resolution":{"type":"string","minLength":1,"maxLength":4000,"description":"Cómo se resolvió."},"resolved_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo se resolvió (AAAA-MM-DD). Por defecto, hoy."},"back_in_service":{"default":false,"description":"true vuelve a poner el equipo en servicio, si no le quedan otras fallas abiertas.","type":"boolean"}},"required":["resolution"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["maintenance","calibration","verification","cleaning","other","failure","repair","note"],"description":"Qué se registró. Las fallas tienen severity y resolved_on."},"task_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}]},"performed_on":{"type":"string","description":"Fecha (AAAA-MM-DD)."},"performed_by":{"description":"Quién lo hizo: un miembro, el servicio técnico o un técnico.","type":["string","null"]},"detail":{"type":"string"},"result":{"anyOf":[{"type":"string","enum":["pass","fail"]},{"type":"null"}],"description":"Calibraciones y verificaciones: pass = conforme, fail = no conforme."},"valid_until":{"type":["string","null"]},"severity":{"anyOf":[{"type":"string","enum":["high","low"]},{"type":"null"}],"description":"Fallas: high = impide usarlo, low = se puede seguir usando."},"resolved_on":{"type":["string","null"]},"resolution":{"type":["string","null"]},"cost":{"type":["number","null"]},"currency":{"type":["string","null"]},"created_at":{"type":"string"},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["in_service","out_of_service","retired"],"description":"in_service = en servicio, out_of_service = fuera de servicio, retired = dado de baja."}},"required":["id","code","name","status"],"additionalProperties":false},"other_open_failures":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Otras fallas abiertas del equipo: si hay, no vuelve a estar en servicio."}},"required":["id","kind","task_id","performed_on","performed_by","detail","result","valid_until","severity","resolved_on","resolution","cost","currency","created_at","equipment","other_open_failures"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/bookings/{id}":{"patch":{"tags":["Equipos"],"summary":"Cambiar el horario de una reserva","description":"Mueve una reserva pendiente o confirmada a otro horario del mismo equipo, o le cambia el motivo: la propia, o la de otra persona si el token es Colaborador o aprueba ese equipo. Valen las mismas reglas que al reservar (horario del equipo, anticipación, duración, choques). Si el equipo pide aprobación y el token no la aprueba, vuelve a quedar pendiente.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"starts_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Nuevo inicio: instante ISO 8601 con zona (2026-10-27T10:00:00-03:00 o …Z). Va junto con ends_at."},"ends_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Nuevo fin, con el mismo formato."},"purpose":{"description":"Nuevo motivo. Si no lo mandás, queda el que tenía.","type":"string","maxLength":300},"version":{"description":"La «version» que devolvió GET …/equipment/bookings. Si la mandás y alguien cambió la reserva después, la respuesta es 409 y no se pisa nada.","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"starts_at":{"type":"string","description":"Instante ISO 8601 (UTC)."},"ends_at":{"type":"string"},"purpose":{"type":"string"},"status":{"type":"string","enum":["pending","confirmed","rejected","cancelled"],"description":"pending = pendiente de aprobación, confirmed = confirmada, rejected = rechazada, cancelled = cancelada."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para cambiar el horario sin pisar otro cambio (PATCH)."}},"required":["id","equipment","person","starts_at","ends_at","purpose","status","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/bookings/{id}/cancel":{"post":{"tags":["Equipos"],"summary":"Cancelar una reserva","description":"Cancela una reserva pendiente o confirmada y libera el horario: la propia, o la de otra persona si el token es Colaborador o aprueba ese equipo. Con scope «following», también las siguientes de la misma serie.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"reason":{"description":"Por qué se cancela (opcional).","type":"string","maxLength":500},"scope":{"default":"one","description":"one = solo esta reserva (por defecto); following = esta y las siguientes de la misma serie.","type":"string","enum":["one","following"]}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"cancelled":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"starts_at":{"type":"string","description":"Instante ISO 8601 (UTC)."},"ends_at":{"type":"string"},"purpose":{"type":"string"},"status":{"type":"string","enum":["pending","confirmed","rejected","cancelled"],"description":"pending = pendiente de aprobación, confirmed = confirmada, rejected = rechazada, cancelled = cancelada."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para cambiar el horario sin pisar otro cambio (PATCH)."}},"required":["id","equipment","person","starts_at","ends_at","purpose","status","version"],"additionalProperties":false}}},"required":["cancelled"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/equipment/items/{id}/usage":{"post":{"tags":["Equipos"],"summary":"Registrar un uso","description":"Carga un uso que ya terminó, como «Registrar un uso» de la web. Si queda dentro de una reserva, se vincula solo. Con outcome «problem» también reporta la falla.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"started_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Cuándo empezó: instante ISO 8601 con zona (2026-10-24T09:00:00-03:00 o …Z)."},"ended_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","description":"Cuándo terminó, con el mismo formato."},"person_id":{"type":"string","minLength":1,"maxLength":200,"description":"Quién lo usó, si no es la persona del token: id, nombre o email (lo puede cargar quien es Colaborador)."},"purpose":{"description":"Para qué se usó.","type":"string","maxLength":300},"notes":{"description":"Observaciones del uso.","type":"string","maxLength":2000},"outcome":{"default":"ok","description":"ok = sin problemas (por defecto), problem = con un problema: abre una falla con failure_detail.","type":"string","enum":["ok","problem"]},"failure_detail":{"description":"Con outcome problem (obligatorio): qué pasó con el equipo.","type":"string","maxLength":4000},"severity":{"default":"high","description":"high = impide usarlo (por defecto), low = se puede seguir usando.","type":"string","enum":["high","low"]},"take_out_of_service":{"default":false,"description":"true deja el equipo fuera de servicio hasta que se cierre la falla.","type":"boolean"},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["started_at","ended_at"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"started_at":{"type":"string"},"ended_at":{"description":"null mientras se está usando.","type":["string","null"]},"minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"purpose":{"type":"string"},"notes":{"type":"string"},"outcome":{"anyOf":[{"type":"string","enum":["ok","problem"]},{"type":"null"}],"description":"ok = sin problemas, problem = con un problema (abre una falla)."},"failure_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"La falla que se abrió por el problema, si hubo uno."}},"required":["id","equipment","person","started_at","ended_at","minutes","purpose","notes","outcome","failure_id"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/fields":{"get":{"tags":["Insumos"],"summary":"Campos del artículo","description":"Campos base y personalizados de los artículos, con su tipo y opciones: dicen qué significa cada clave de custom_fields. En lot_custom_fields, los campos personalizados de los lotes.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Clave estable: los campos personalizados aparecen así en custom_fields."},"label":{"type":"string"},"type":{"type":"string","enum":["text","long_text","number","date","boolean","select","multiselect","link","attachment"]},"custom":{"type":"boolean","description":"true si lo definió el laboratorio."},"required":{"type":"boolean"},"unit":{"type":["string","null"]},"help":{"type":["string","null"]},"options":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Opciones vigentes, para las listas."},"archived":{"type":"boolean"}},"required":["key","label","type","custom","required","unit","help","options","archived"],"additionalProperties":false}},"lot_custom_fields":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Clave estable: los campos personalizados aparecen así en custom_fields."},"label":{"type":"string"},"type":{"type":"string","enum":["text","long_text","number","date","boolean","select","multiselect","link","attachment"]},"custom":{"type":"boolean","description":"true si lo definió el laboratorio."},"required":{"type":"boolean"},"unit":{"type":["string","null"]},"help":{"type":["string","null"]},"options":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Opciones vigentes, para las listas."},"archived":{"type":"boolean"}},"required":["key","label","type","custom","required","unit","help","options","archived"],"additionalProperties":false}}},"required":["data","lot_custom_fields"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/categories":{"get":{"tags":["Insumos"],"summary":"Categorías de insumos","description":"","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"description":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","description","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/places":{"get":{"tags":["Insumos"],"summary":"Lugares de guardado","description":"Dónde se guardan los insumos, como un árbol (sala › heladera › estante), con su conservación y el equipo vinculado.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string","description":"El camino desde la sala: «Laboratorio › Heladera › Estante 2»."},"parent_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"El lugar que lo contiene."},"kind":{"type":"string","description":"room = sala, cabinet = armario, fridge = heladera, freezer, shelf = estante, drawer = cajón, box = caja, other = otro."},"storage":{"type":"string","enum":["room_temp","fridge","freezer_20","freezer_80","ln2","other"],"description":"room_temp = temperatura ambiente, fridge = heladera (2 a 8 °C), freezer_20 = freezer −20 °C, freezer_80 = freezer −80 °C, ln2 = nitrógeno líquido, other = otra condición."},"grid":{"anyOf":[{"type":"object","properties":{"rows":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cols":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"row_labels":{"type":"string","enum":["letters","numbers"],"description":"letters = A1, A2… B1; numbers = 1-1, 1-2… 2-1."}},"required":["rows","cols","row_labels"],"additionalProperties":false},{"type":"null"}],"description":"La grilla del lugar (una caja, un cajón, una gradilla), si tiene: cada lote puede llevar su posición. null si no tiene."},"equipment_item_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"El equipo de Equipos que es este lugar (una heladera, un freezer)."},"notes":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","path","parent_id","kind","storage","grid","equipment_item_id","notes","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/places/{id}/access":{"get":{"tags":["Insumos"],"summary":"Quién ve y gestiona un lugar de guardado","description":"Si el lugar es restringido y quiénes lo ven (o también lo gestionan) además de la administración. Alcanza a los lugares de adentro y a los lotes guardados ahí. Se elige desde Vialo (la administración), no con un token.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"restricted":{"type":"boolean","description":"Si es true, solo lo ven la administración (y, en equipos, su responsable) y las personas de «people»."},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: solo ve; manage: ve y gestiona (carga y cambia datos)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Quiénes lo ven además de la administración."},"sub_labs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: toda su gente ve; manage: ve y gestiona (si su rol en este laboratorio lo permite)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Sub-laboratorios a los que se abrió, con toda su gente."}},"required":["restricted","people","sub_labs"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/places/{id}/grid":{"get":{"tags":["Insumos"],"summary":"Grilla de un lugar","description":"Las posiciones de un lugar con grilla (una caja, un cajón, una gradilla), ocupadas o libres, en orden, con el lote que hay en cada una. Los lotes agotados liberan su posición.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string"},"rows":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"cols":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"free":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"positions":{"type":"array","items":{"type":"object","properties":{"position":{"type":"string"},"row":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"col":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lot":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false}},"required":["id","code","item"],"additionalProperties":false},{"type":"null"}]}},"required":["position","row","col","lot"],"additionalProperties":false}}},"required":["id","name","path","rows","cols","free","positions"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/suppliers":{"get":{"tags":["Insumos"],"summary":"Proveedores de insumos","description":"Con sus datos de contacto y el n.º de cliente del laboratorio.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string"},"customer_number":{"type":"string","description":"El n.º de cliente del laboratorio en el proveedor."},"notes":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","contact_name","phone","email","website","customer_number","notes","archived","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Insumos"],"summary":"Agregar un proveedor de insumos","description":"Con sus datos de contacto y el n.º de cliente del laboratorio. El nombre no se repite.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del proveedor. No se repite en el laboratorio."},"contact_name":{"type":"string","maxLength":120,"description":"Persona de contacto."},"phone":{"type":"string","maxLength":60,"description":"Teléfono."},"email":{"description":"Email. Vacío lo quita.","anyOf":[{"type":"string","const":""},{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}]},"website":{"description":"Sitio o tienda en línea. Vacío lo quita.","anyOf":[{"type":"string","const":""},{"type":"string","format":"uri"}]},"customer_number":{"type":"string","maxLength":60,"description":"N.º de cliente del laboratorio en el proveedor."},"notes":{"type":"string","maxLength":1000,"description":"Días de entrega, pedido mínimo, condiciones…"}},"required":["name"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string"},"customer_number":{"type":"string","description":"El n.º de cliente del laboratorio en el proveedor."},"notes":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","contact_name","phone","email","website","customer_number","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items":{"get":{"tags":["Insumos"],"summary":"Buscar insumos","description":"Los artículos vigentes que cumplen todos los filtros, paginados, con su stock. Es la misma búsqueda que el inventario de la web.","parameters":[{"name":"q","in":"query","required":false,"description":"Texto libre: código, nombre, marca, n.º de catálogo, n.º CAS, o el código o n.º de un lote.","schema":{"description":"Texto libre: código, nombre, marca, n.º de catálogo, n.º CAS, o el código o n.º de un lote.","type":"string","maxLength":200}},{"name":"category","in":"query","required":false,"description":"Categorías, por id o por nombre, separadas por coma (cualquiera de ellas).","schema":{"description":"Categorías, por id o por nombre, separadas por coma (cualquiera de ellas).","type":"string"}},{"name":"place","in":"query","required":false,"description":"Lugares, por id, nombre o camino (Sala › Heladera), separados por coma: el lugar habitual o donde hay un lote con stock, incluido lo que tiene adentro.","schema":{"description":"Lugares, por id, nombre o camino (Sala › Heladera), separados por coma: el lugar habitual o donde hay un lote con stock, incluido lo que tiene adentro.","type":"string"}},{"name":"supplier","in":"query","required":false,"description":"Proveedores habituales, por id o por nombre, separados por coma.","schema":{"description":"Proveedores habituales, por id o por nombre, separados por coma.","type":"string"}},{"name":"storage","in":"query","required":false,"description":"Conservación, separadas por coma: room_temp, fridge, freezer_20, freezer_80, ln2, other.","schema":{"description":"Conservación, separadas por coma: room_temp, fridge, freezer_20, freezer_80, ln2, other.","type":"string"}},{"name":"hazards","in":"query","required":false,"description":"Pictogramas de peligro GHS, separados por coma (cualquiera de ellos): GHS01, GHS02, GHS03, GHS04, GHS05, GHS06, GHS07, GHS08, GHS09.","schema":{"description":"Pictogramas de peligro GHS, separados por coma (cualquiera de ellos): GHS01, GHS02, GHS03, GHS04, GHS05, GHS06, GHS07, GHS08, GHS09.","type":"string"}},{"name":"responsible","in":"query","required":false,"description":"Responsables, separados por coma: «me» (la persona de este acceso), id, nombre o email.","schema":{"description":"Responsables, separados por coma: «me» (la persona de este acceso), id, nombre o email.","type":"string"}},{"name":"attention","in":"query","required":false,"description":"any = vencido, por vencer o para pedir; reorder = en el punto de pedido; due = con lotes vencidos o por vencer; expired = con lotes vencidos; out = sin stock.","schema":{"description":"any = vencido, por vencer o para pedir; reorder = en el punto de pedido; due = con lotes vencidos o por vencer; expired = con lotes vencidos; out = sin stock.","type":"string","enum":["any","reorder","due","expired","out"]}},{"name":"controlled","in":"query","required":false,"description":"yes = solo las sustancias controladas, no = sin ellas.","schema":{"description":"yes = solo las sustancias controladas, no = sin ellas.","type":"string","enum":["yes","no"]}},{"name":"archived","in":"query","required":false,"description":"include = también los archivados, only = solo los archivados. Por defecto, sin archivados.","schema":{"description":"include = también los archivados, only = solo los archivados. Por defecto, sin archivados.","type":"string","enum":["include","only"]}},{"name":"sort","in":"query","required":false,"description":"Campo por el que ordenar; con «-» adelante, de mayor a menor. Ej.: «name», «stock», «next_expiry», «-created_at». Por defecto, «name».","schema":{"description":"Campo por el que ordenar; con «-» adelante, de mayor a menor. Ej.: «name», «stock», «next_expiry», «-created_at». Por defecto, «name».","type":"string","maxLength":80}},{"name":"page","in":"query","required":false,"description":"Página, desde 1.","schema":{"default":1,"description":"Página, desde 1.","type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"description":"Cuántos resultados (hasta 200).","schema":{"default":50,"description":"Cuántos resultados (hasta 200).","type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"category":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"presentation":{"type":"string"},"brand":{"type":"string"},"catalog_number":{"type":"string"},"cas_number":{"type":"string"},"unit":{"type":"string","description":"En qué se cuenta: frasco, caja, mL…"},"reorder_point":{"type":["number","null"]},"target_stock":{"type":["number","null"]},"storage":{"type":"string","enum":["room_temp","fridge","freezer_20","freezer_80","ln2","other"],"description":"room_temp = temperatura ambiente, fridge = heladera (2 a 8 °C), freezer_20 = freezer −20 °C, freezer_80 = freezer −80 °C, ln2 = nitrógeno líquido, other = otra condición."},"storage_notes":{"type":"string"},"default_place":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string"}},"required":["id","name","path"],"additionalProperties":false},{"type":"null"}],"description":"Lugar habitual."},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proveedor habitual."},"hazards":{"type":"array","items":{"type":"string"},"description":"Pictogramas del SGA (GHS01 a GHS09)."},"controlled":{"type":"boolean","description":"Sustancia controlada: cada movimiento pide un motivo."},"opened_shelf_life_days":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Vida útil una vez abierto, en días."},"warn_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Con cuántos días de anticipación avisa un vencimiento."},"responsible":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"notes":{"type":"string"},"stock":{"type":"object","properties":{"available":{"type":"number","description":"Lo que hay, sin contar los lotes vencidos."},"expired":{"type":"number","description":"Lo que hay en lotes vencidos."},"lots":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lotes con stock."},"next_expiry":{"description":"El vencimiento más cercano de un lote con stock.","type":["string","null"]},"expiry_status":{"anyOf":[{"type":"string","enum":["expired","due_soon","ok"]},{"type":"null"}],"description":"El peor estado de sus lotes con stock; null si no tiene."},"below_reorder":{"type":"boolean","description":"true si llegó al punto de pedido (aparece en «Para pedir»)."}},"required":["available","expired","lots","next_expiry","expiry_status","below_reorder"],"additionalProperties":false,"description":"Stock calculado de los lotes y sus movimientos, en la unidad del artículo."},"on_order":{"anyOf":[{"type":"object","properties":{"order_id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string","enum":["requested","ordered"]},"pending":{"type":"number","description":"Lo que falta llegar."}},"required":["order_id","status","pending"],"additionalProperties":false},{"type":"null"}],"description":"El pedido abierto del artículo; null si no hay."},"archived":{"type":"boolean"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","category","presentation","brand","catalog_number","cas_number","unit","reorder_point","target_stock","storage","storage_notes","default_place","supplier","hazards","controlled","opened_shelf_life_days","warn_days","responsible","notes","stock","on_order","archived","custom_fields","created_at","updated_at","version"],"additionalProperties":false}},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","page","limit","total"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Insumos"],"summary":"Cargar un insumo","description":"Da de alta un artículo del inventario. El código lo genera Vialo con el formato del laboratorio. El stock se carga después, con un ingreso (POST …/reagents/lots).\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del artículo."},"unit":{"type":"string","minLength":1,"maxLength":30,"description":"En qué se cuenta el stock: unidad, frasco, caja, kit, determinaciones, mL, g…"},"category":{"description":"Categoría, por id o por nombre (ver …/reagents/categories). null la quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"presentation":{"type":"string","maxLength":80,"description":"Presentación: «frasco de 1 L», «caja x 96»…"},"brand":{"type":"string","maxLength":80,"description":"Marca."},"catalog_number":{"type":"string","maxLength":80,"description":"N.º de catálogo del fabricante."},"cas_number":{"type":"string","maxLength":20,"description":"N.º CAS con guiones, como 64-17-5 (se verifica el dígito de control)."},"reorder_point":{"description":"Punto de pedido: con ese stock o menos, el artículo aparece en «Para pedir». null lo quita.","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"target_stock":{"description":"Stock objetivo: hasta cuánto conviene pedir. Igual o mayor que el punto de pedido.","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"storage":{"description":"Conservación: room_temp, fridge, freezer_20, freezer_80, ln2, other. Por defecto, room_temp.","type":"string","enum":["room_temp","fridge","freezer_20","freezer_80","ln2","other"]},"storage_notes":{"type":"string","maxLength":300,"description":"Indicaciones de conservación."},"default_place":{"description":"Lugar habitual, por id, nombre o camino (Sala › Heladera; ver …/reagents/places). null lo quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"supplier":{"description":"Proveedor habitual, por id o por nombre (ver …/reagents/suppliers). null lo quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"hazards":{"description":"Pictogramas del SGA: GHS01 a GHS09.","type":"array","items":{"type":"string","enum":["GHS01","GHS02","GHS03","GHS04","GHS05","GHS06","GHS07","GHS08","GHS09"]}},"controlled":{"description":"Sustancia controlada (precursor químico): cada movimiento va a pedir un motivo.","type":"boolean"},"opened_shelf_life_days":{"description":"Vida útil una vez abierto, en días (1 a 3650). null: no cambia al abrirlo.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"warn_days":{"description":"Con cuántos días de anticipación avisa un vencimiento (0 a 365). Por defecto, 30.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"responsible_id":{"description":"Quien se ocupa de pedirlo: el id de un miembro (ver /lab). null lo quita.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["name","unit"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/{id}":{"get":{"tags":["Insumos"],"summary":"Ver un insumo","description":"Por id o por código (por ejemplo RE-0004), con su stock, sus lotes y su pedido abierto.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"category":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"presentation":{"type":"string"},"brand":{"type":"string"},"catalog_number":{"type":"string"},"cas_number":{"type":"string"},"unit":{"type":"string","description":"En qué se cuenta: frasco, caja, mL…"},"reorder_point":{"type":["number","null"]},"target_stock":{"type":["number","null"]},"storage":{"type":"string","enum":["room_temp","fridge","freezer_20","freezer_80","ln2","other"],"description":"room_temp = temperatura ambiente, fridge = heladera (2 a 8 °C), freezer_20 = freezer −20 °C, freezer_80 = freezer −80 °C, ln2 = nitrógeno líquido, other = otra condición."},"storage_notes":{"type":"string"},"default_place":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string"}},"required":["id","name","path"],"additionalProperties":false},{"type":"null"}],"description":"Lugar habitual."},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proveedor habitual."},"hazards":{"type":"array","items":{"type":"string"},"description":"Pictogramas del SGA (GHS01 a GHS09)."},"controlled":{"type":"boolean","description":"Sustancia controlada: cada movimiento pide un motivo."},"opened_shelf_life_days":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Vida útil una vez abierto, en días."},"warn_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Con cuántos días de anticipación avisa un vencimiento."},"responsible":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"notes":{"type":"string"},"stock":{"type":"object","properties":{"available":{"type":"number","description":"Lo que hay, sin contar los lotes vencidos."},"expired":{"type":"number","description":"Lo que hay en lotes vencidos."},"lots":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Lotes con stock."},"next_expiry":{"description":"El vencimiento más cercano de un lote con stock.","type":["string","null"]},"expiry_status":{"anyOf":[{"type":"string","enum":["expired","due_soon","ok"]},{"type":"null"}],"description":"El peor estado de sus lotes con stock; null si no tiene."},"below_reorder":{"type":"boolean","description":"true si llegó al punto de pedido (aparece en «Para pedir»)."}},"required":["available","expired","lots","next_expiry","expiry_status","below_reorder"],"additionalProperties":false,"description":"Stock calculado de los lotes y sus movimientos, en la unidad del artículo."},"on_order":{"anyOf":[{"type":"object","properties":{"order_id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string","enum":["requested","ordered"]},"pending":{"type":"number","description":"Lo que falta llegar."}},"required":["order_id","status","pending"],"additionalProperties":false},{"type":"null"}],"description":"El pedido abierto del artículo; null si no hay."},"archived":{"type":"boolean"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"created_at":{"type":"string"},"updated_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"Código interno del lote (el de la etiqueta)."},"lot_number":{"type":"string","description":"N.º de lote del fabricante."},"quantity":{"type":"number","description":"Lo que queda."},"initial_quantity":{"type":"number"},"expires_on":{"description":"Vencimiento del fabricante.","type":["string","null"]},"effective_expiry":{"description":"El vencimiento que vale: el del fabricante o, si se abrió, el de su vida útil abierto.","type":["string","null"]},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."},"received_on":{"type":"string"},"opened_on":{"type":["string","null"]},"place":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string"}},"required":["id","name","path"],"additionalProperties":false},{"type":"null"}]},"position":{"description":"Posición en la grilla del lugar: «B4» (filas con letras) o «2-4»; null si el lugar no tiene grilla o no se indicó.","type":["string","null"]},"place_detail":{"type":"string"},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"unit_cost":{"type":["number","null"]},"currency":{"type":"string"},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","lot_number","quantity","initial_quantity","expires_on","effective_expiry","status","kept","received_on","opened_on","place","position","place_detail","supplier","unit_cost","currency","notes","custom_fields","created_at","version"],"additionalProperties":false},"description":"Primero los que tienen stock, el que vence primero arriba (el que conviene usar); al final los agotados."}},"required":["id","code","name","category","presentation","brand","catalog_number","cas_number","unit","reorder_point","target_stock","storage","storage_notes","default_place","supplier","hazards","controlled","opened_shelf_life_days","warn_days","responsible","notes","stock","on_order","archived","custom_fields","created_at","updated_at","version","lots"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Insumos"],"summary":"Modificar un insumo","description":"Cambia solo los campos que se mandan; el resto queda como estaba. Pide la «version» que devolvió la lectura: si alguien lo cambió después, responde 409.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del artículo."},"unit":{"type":"string","minLength":1,"maxLength":30,"description":"En qué se cuenta el stock: unidad, frasco, caja, kit, determinaciones, mL, g…"},"archived":{"description":"true lo archiva (sale del inventario y de «Para pedir», su historia se conserva); false lo vuelve al inventario.","type":"boolean"},"category":{"description":"Categoría, por id o por nombre (ver …/reagents/categories). null la quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"presentation":{"type":"string","maxLength":80,"description":"Presentación: «frasco de 1 L», «caja x 96»…"},"brand":{"type":"string","maxLength":80,"description":"Marca."},"catalog_number":{"type":"string","maxLength":80,"description":"N.º de catálogo del fabricante."},"cas_number":{"type":"string","maxLength":20,"description":"N.º CAS con guiones, como 64-17-5 (se verifica el dígito de control)."},"reorder_point":{"description":"Punto de pedido: con ese stock o menos, el artículo aparece en «Para pedir». null lo quita.","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"target_stock":{"description":"Stock objetivo: hasta cuánto conviene pedir. Igual o mayor que el punto de pedido.","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"storage":{"description":"Conservación: room_temp, fridge, freezer_20, freezer_80, ln2, other. Por defecto, room_temp.","type":"string","enum":["room_temp","fridge","freezer_20","freezer_80","ln2","other"]},"storage_notes":{"type":"string","maxLength":300,"description":"Indicaciones de conservación."},"default_place":{"description":"Lugar habitual, por id, nombre o camino (Sala › Heladera; ver …/reagents/places). null lo quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"supplier":{"description":"Proveedor habitual, por id o por nombre (ver …/reagents/suppliers). null lo quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"hazards":{"description":"Pictogramas del SGA: GHS01 a GHS09.","type":"array","items":{"type":"string","enum":["GHS01","GHS02","GHS03","GHS04","GHS05","GHS06","GHS07","GHS08","GHS09"]}},"controlled":{"description":"Sustancia controlada (precursor químico): cada movimiento va a pedir un motivo.","type":"boolean"},"opened_shelf_life_days":{"description":"Vida útil una vez abierto, en días (1 a 3650). null: no cambia al abrirlo.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"warn_days":{"description":"Con cuántos días de anticipación avisa un vencimiento (0 a 365). Por defecto, 30.","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"responsible_id":{"description":"Quien se ocupa de pedirlo: el id de un miembro (ver /lab). null lo quita.","anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/{id}/movements":{"get":{"tags":["Insumos"],"summary":"Movimientos de un insumo","description":"Ingresos, consumos, ajustes, descartes y traslados de todos sus lotes, del más reciente al más viejo. Los anulados vienen con voided = true y no cuentan para el stock.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Cuántos resultados (hasta 500).","schema":{"default":100,"description":"Cuántos resultados (hasta 500).","type":"integer","minimum":1,"maximum":500}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"kind":{"type":"string","enum":["receipt","consumption","adjustment","discard","transfer_out","transfer_in"],"description":"receipt = ingreso, consumption = consumo, adjustment = ajuste, discard = descarte, transfer_out / transfer_in = traslado (salida y entrada)."},"delta":{"type":"number","description":"Cuánto cambió el stock del lote: positivo si entró, negativo si salió."},"occurred_on":{"type":"string"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"purpose":{"type":"string","description":"Para qué se usó."},"reason":{"type":"string","description":"Motivo (descartes, ajustes y sustancias controladas)."},"used_expired":{"type":"boolean","description":"Se usó un lote vencido."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"void_reason":{"type":"string"},"created_at":{"type":"string"}},"required":["id","item","lot","kind","delta","occurred_on","person","purpose","reason","used_expired","voided","voided_at","void_reason","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/{id}/history":{"get":{"tags":["Insumos"],"summary":"Historial de un insumo","description":"Quién cambió los datos del artículo, cuándo y por dónde, del más nuevo al más viejo.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/{id}/attachments":{"get":{"tags":["Insumos"],"summary":"Documentos de un insumo","description":"Fichas de seguridad, certificados de análisis y otros archivos del artículo. Cada uno trae un enlace de descarga que vence a los 5 minutos.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"file_name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"uploaded_by":{"type":"string"},"download_url":{"description":"Enlace de descarga que vence a los 5 minutos.","type":["string","null"]}},"required":["id","file_name","mime_type","size_bytes","created_at","uploaded_by","download_url"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/lots":{"get":{"tags":["Insumos"],"summary":"Vencimientos","description":"Lotes con stock de los artículos vigentes, del que vence primero al último. Por defecto, solo los vencidos y los que están por vencer.","parameters":[{"name":"status","in":"query","required":false,"description":"Estados separados por coma: expired, due_soon, ok. Por defecto, expired y due_soon.","schema":{"description":"Estados separados por coma: expired, due_soon, ok. Por defecto, expired y due_soon.","type":"string"}},{"name":"q","in":"query","required":false,"description":"Código interno o n.º del lote, o el nombre, código o n.º de catálogo del artículo.","schema":{"description":"Código interno o n.º del lote, o el nombre, código o n.º de catálogo del artículo.","type":"string","maxLength":200}},{"name":"until","in":"query","required":false,"description":"Solo lo que vence hasta esta fecha (AAAA-MM-DD).","schema":{"description":"Solo lo que vence hasta esta fecha (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"item","in":"query","required":false,"description":"Un artículo, por id o por código.","schema":{"description":"Un artículo, por id o por código.","type":"string","maxLength":80}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"lot_number":{"type":"string"},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"},"controlled":{"type":"boolean"}},"required":["id","code","name","unit","controlled"],"additionalProperties":false},"quantity":{"type":"number"},"expires_on":{"description":"El vencimiento que vale.","type":["string","null"]},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."},"days_left":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Días hasta el vencimiento; negativo si ya venció."},"place":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"path":{"type":"string"}},"required":["id","name","path"],"additionalProperties":false},{"type":"null"}]},"position":{"description":"Posición en la grilla del lugar: «B4» (filas con letras) o «2-4»; null si el lugar no tiene grilla o no se indicó.","type":["string","null"]},"place_detail":{"type":"string"}},"required":["id","code","lot_number","item","quantity","expires_on","status","kept","days_left","place","position","place_detail"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Insumos"],"summary":"Ingresar stock","description":"Registra lo que llegó: un lote o, con containers, uno por envase (la cantidad se reparte en partes iguales). Vialo genera el código interno de cada lote y el movimiento de ingreso. Con order_id, cuenta para ese pedido.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"item":{"type":"string","minLength":1,"maxLength":80,"description":"El artículo que llegó, por id o por código (RE-0004)."},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Cuánto llegó en total, en la unidad del artículo. Con containers, se reparte en partes iguales."},"containers":{"description":"Un lote por envase, para seguir cada frasco por separado (se abren en fechas distintas): llegaron 3 frascos → 3. Por defecto, 1.","type":"integer","minimum":1,"maximum":50},"lot_number":{"type":"string","maxLength":80,"description":"N.º de lote del fabricante."},"expires_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Vencimiento (AAAA-MM-DD)."},{"type":"null"}]},"received_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo llegó (AAAA-MM-DD). Por defecto, hoy."},"place":{"description":"Dónde se guardó, por id, nombre o camino (Sala › Heladera). Por defecto, el lugar habitual del artículo; null lo deja sin lugar.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"place_detail":{"type":"string","maxLength":120,"description":"Detalle del lugar: estante, caja, posición…"},"position":{"description":"Posición en la grilla del lugar: «B4» o «2-4» (ver …/reagents/places/:id/grid). Opcional. Con varios envases, el primero va ahí y los demás a las siguientes libres.","type":"string","maxLength":10},"supplier":{"description":"Proveedor, por id o por nombre. Por defecto, el del pedido o el habitual del artículo; null lo deja sin proveedor.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"unit_cost":{"description":"Costo por unidad del artículo.","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"currency":{"description":"Moneda del costo (ISO 4217). Por defecto, ARS.","type":"string","pattern":"^[A-Z]{3}$"},"order_id":{"description":"El pedido abierto que se recibe (ver …/reagents/orders). Cuando llega todo, el pedido queda recibido.","type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"notes":{"type":"string","maxLength":1000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["item","quantity"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lots":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false}},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["item","lots","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/movements":{"get":{"tags":["Insumos"],"summary":"Libro de movimientos","description":"Todo lo que entró y salió en el laboratorio, del más reciente al más viejo (hasta 300 por página: con page se va más atrás). Con controlled = true es el libro de las sustancias controladas.","parameters":[{"name":"item","in":"query","required":false,"description":"Un artículo, por id o por código.","schema":{"description":"Un artículo, por id o por código.","type":"string","maxLength":80}},{"name":"kind","in":"query","required":false,"description":"Un tipo de movimiento: receipt, consumption, adjustment, discard, transfer_out, transfer_in.","schema":{"description":"Un tipo de movimiento: receipt, consumption, adjustment, discard, transfer_out, transfer_in.","type":"string","enum":["receipt","consumption","adjustment","discard","transfer_out","transfer_in"]}},{"name":"person","in":"query","required":false,"description":"Quién lo registró, por id.","schema":{"description":"Quién lo registró, por id.","type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"}},{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD).","schema":{"description":"Desde este día (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive (AAAA-MM-DD).","schema":{"description":"Hasta este día inclusive (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"controlled","in":"query","required":false,"description":"true = solo los de sustancias controladas (el libro de precursores).","schema":{"description":"true = solo los de sustancias controladas (el libro de precursores).","type":"string","enum":["true","false"]}},{"name":"limit","in":"query","required":false,"description":"Cuántos resultados (hasta 300).","schema":{"default":300,"description":"Cuántos resultados (hasta 300).","type":"integer","minimum":1,"maximum":300}},{"name":"page","in":"query","required":false,"description":"Página, desde 1.","schema":{"default":1,"description":"Página, desde 1.","type":"integer","minimum":1,"maximum":9007199254740991}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"kind":{"type":"string","enum":["receipt","consumption","adjustment","discard","transfer_out","transfer_in"],"description":"receipt = ingreso, consumption = consumo, adjustment = ajuste, discard = descarte, transfer_out / transfer_in = traslado (salida y entrada)."},"delta":{"type":"number","description":"Cuánto cambió el stock del lote: positivo si entró, negativo si salió."},"occurred_on":{"type":"string"},"person":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"purpose":{"type":"string","description":"Para qué se usó."},"reason":{"type":"string","description":"Motivo (descartes, ajustes y sustancias controladas)."},"used_expired":{"type":"boolean","description":"Se usó un lote vencido."},"voided":{"type":"boolean"},"voided_at":{"type":["string","null"]},"void_reason":{"type":"string"},"created_at":{"type":"string"}},"required":["id","item","lot","kind","delta","occurred_on","person","purpose","reason","used_expired","voided","voided_at","void_reason","created_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/orders":{"get":{"tags":["Insumos"],"summary":"Pedidos","description":"Los pedidos abiertos (por pedir y pedidos al proveedor, del más viejo al más nuevo) o los cerrados (del más reciente al más viejo, hasta 200), con lo que ya llegó de cada uno.","parameters":[{"name":"open","in":"query","required":false,"description":"true = los abiertos (por pedir y pedidos), false = los cerrados (recibidos y cancelados). Por defecto, true.","schema":{"default":"true","description":"true = los abiertos (por pedir y pedidos), false = los cerrados (recibidos y cancelados). Por defecto, true.","type":"string","enum":["true","false"]}},{"name":"item","in":"query","required":false,"description":"Un artículo, por id o por código.","schema":{"description":"Un artículo, por id o por código.","type":"string","maxLength":80}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"quantity":{"type":"number"},"received":{"type":"number","description":"Lo que ya se ingresó contra este pedido."},"pending":{"type":"number","description":"Lo que falta llegar."},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"status":{"type":"string","enum":["requested","ordered","received","cancelled"],"description":"requested = por pedir (alguien avisó que falta), ordered = pedido al proveedor, received = recibido, cancelled = cancelado."},"requested_by":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"requested_on":{"type":"string"},"ordered_on":{"type":["string","null"]},"expected_on":{"type":["string","null"]},"reference":{"type":"string","description":"N.º de pedido u orden de compra."},"notes":{"type":"string"},"closed_on":{"type":["string","null"]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","item","quantity","received","pending","supplier","status","requested_by","requested_on","ordered_on","expected_on","reference","notes","closed_on","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Insumos"],"summary":"Pedir un insumo","description":"Sin ordered, deja el artículo «por pedir» para quien hace las compras (si ya tiene un pedido abierto, devuelve ese con already_open = true). Con ordered = true, registra un pedido ya hecho al proveedor.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"item":{"type":"string","minLength":1,"maxLength":80,"description":"El artículo a pedir, por id o por código."},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Cuánto pedir, en la unidad del artículo (ver suggested_quantity en …/reagents/to-order)."},"notes":{"type":"string","maxLength":1000,"description":"Notas para quien hace las compras."},"ordered":{"default":false,"description":"true si ya se le pidió al proveedor. Si no, queda «por pedir» y, si el artículo ya tiene un pedido abierto, se devuelve ese en vez de duplicarlo.","type":"boolean"},"supplier":{"description":"Con ordered: el proveedor, por id o por nombre. Por defecto, el habitual del artículo.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reference":{"type":"string","maxLength":120,"description":"Con ordered: n.º de pedido u orden de compra."},"expected_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Con ordered: cuándo se espera que llegue (AAAA-MM-DD)."},{"type":"null"}]}},"required":["item","quantity"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"status":{"type":"string","enum":["requested","ordered","received","cancelled"],"description":"requested = por pedir (alguien avisó que falta), ordered = pedido al proveedor, received = recibido, cancelled = cancelado."},"quantity":{"type":"number"},"already_open":{"type":"boolean","description":"true si el artículo ya tenía un pedido abierto y se devolvió ese (no se duplica)."}},"required":["id","item","status","quantity","already_open"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/to-order":{"get":{"tags":["Insumos"],"summary":"Para pedir","description":"Los artículos vigentes que llegaron a su punto de pedido y no tienen un pedido abierto, por proveedor habitual, con la cantidad que conviene pedir.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"presentation":{"type":"string"},"catalog_number":{"type":"string"},"available":{"type":"number"},"reorder_point":{"type":"number"},"target_stock":{"type":["number","null"]},"suggested_quantity":{"type":"number","description":"Cuánto conviene pedir: hasta el stock objetivo o, sin objetivo, el doble del punto de pedido."},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Proveedor habitual."}},"required":["item","presentation","catalog_number","available","reorder_point","target_stock","suggested_quantity","supplier"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/{id}/photo/suggestions":{"get":{"tags":["Insumos"],"summary":"Buscar fotos posibles de un insumo","description":"Imágenes de internet según los datos del registro, un texto o un enlace. Pertenecen a sus sitios de origen: son para usar dentro del laboratorio.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"q","in":"query","required":false,"description":"Otro texto para buscar, o el enlace de una página de producto o de una imagen. Sin esto, busca por los datos del registro.","schema":{"description":"Otro texto para buscar, o el enlace de una página de producto o de una imagen. Sin esto, busca por los datos del registro.","type":"string","maxLength":2000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"query":{"type":"string","description":"El texto o el enlace que dio estos resultados."},"data":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","description":"La imagen: es lo que se manda para elegirla."},"thumb_url":{"type":"string"},"title":{"type":"string"},"source":{"type":"string","description":"El sitio de donde sale."}},"required":["url","thumb_url","title","source"],"additionalProperties":false}}},"required":["query","data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/{id}/photo":{"post":{"tags":["Insumos"],"summary":"Elegir la foto de un insumo","description":"Vialo baja la imagen y la guarda en el laboratorio como un adjunto más, así no depende del sitio de origen.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"url":{"type":"string","maxLength":2000,"format":"uri","description":"La imagen elegida (https)."},"thumb_url":{"description":"Su miniatura: se guarda si el sitio no deja bajar la imagen.","type":"string","maxLength":2000,"format":"uri"}},"required":["url"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"delete":{"tags":["Insumos"],"summary":"Quitar la foto de un insumo","description":"El archivo sigue entre sus adjuntos.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"ok":{"type":"boolean","const":true}},"required":["ok"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/suppliers/{id}":{"patch":{"tags":["Insumos"],"summary":"Modificar un proveedor de insumos","description":"Cambia solo lo que se manda. Con «version», responde 409 si alguien lo cambió después de leerlo. Archivar o reactivar pide rol de administración, como en la web.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del proveedor. No se repite en el laboratorio."},"archived":{"description":"true lo archiva (no se ofrece para cargas nuevas; lo ya cargado no cambia); false lo reactiva. Pide rol de administración.","type":"boolean"},"contact_name":{"type":"string","maxLength":120,"description":"Persona de contacto."},"phone":{"type":"string","maxLength":60,"description":"Teléfono."},"email":{"description":"Email. Vacío lo quita.","anyOf":[{"type":"string","const":""},{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}]},"website":{"description":"Sitio o tienda en línea. Vacío lo quita.","anyOf":[{"type":"string","const":""},{"type":"string","format":"uri"}]},"customer_number":{"type":"string","maxLength":60,"description":"N.º de cliente del laboratorio en el proveedor."},"notes":{"type":"string","maxLength":1000,"description":"Días de entrega, pedido mínimo, condiciones…"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string"},"website":{"type":"string"},"customer_number":{"type":"string","description":"El n.º de cliente del laboratorio en el proveedor."},"notes":{"type":"string"},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","contact_name","phone","email","website","customer_number","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/lots/{id}/consume":{"post":{"tags":["Insumos"],"summary":"Registrar un consumo","description":"Descuenta lo que se usó de un lote (por id o por código interno), a nombre de la persona del token. Conviene el lote que vence primero; un lote vencido pide confirm_expired. Las sustancias controladas piden reason.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"quantity":{"type":"number","exclusiveMinimum":0,"description":"Cuánto se usó, en la unidad del artículo."},"occurred_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo (AAAA-MM-DD). Por defecto, hoy."},"purpose":{"type":"string","maxLength":200,"description":"Para qué se usó (protocolo, proyecto, equipo…)."},"reason":{"type":"string","maxLength":500,"description":"Motivo. Obligatorio para las sustancias controladas."},"confirm_expired":{"default":false,"description":"true para registrar el uso de un lote vencido (queda marcado). Sin esto, un lote vencido no se puede usar.","type":"boolean"}},"required":["quantity"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"lot_number":{"type":"string"},"quantity":{"type":"number","description":"Lo que queda en el lote."},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."}},"required":["id","code","lot_number","quantity","status","kept"],"additionalProperties":false},"new_lot":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false},{"type":"null"}],"description":"Al trasladar una parte: el lote nuevo que quedó en el otro lugar."},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["item","lot","new_lot","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/lots/{id}/discard":{"post":{"tags":["Insumos"],"summary":"Descartar","description":"Retira un lote o una parte (vencido, roto, contaminado), con su motivo. Sin cantidad, el lote entero.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Por qué se descarta (vencido, roto, contaminado…)."},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Cuánto se descarta. Sin cantidad, el lote entero."},"occurred_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo (AAAA-MM-DD). Por defecto, hoy."}},"required":["reason"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"lot_number":{"type":"string"},"quantity":{"type":"number","description":"Lo que queda en el lote."},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."}},"required":["id","code","lot_number","quantity","status","kept"],"additionalProperties":false},"new_lot":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false},{"type":"null"}],"description":"Al trasladar una parte: el lote nuevo que quedó en el otro lugar."},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["item","lot","new_lot","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/lots/{id}/keep-expired":{"post":{"tags":["Insumos"],"summary":"Conservar un lote vencido","description":"Para los laboratorios que guardan lo vencido: el lote sigue vencido, con su stock (para usarlo hay que confirmarlo), pero deja de avisar en Inicio y en las notificaciones. Solo lotes vencidos con stock. Con keep = false vuelve a avisar. Si después cambia el vencimiento, vuelve a avisar solo.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"keep":{"default":true,"description":"true conserva el lote vencido sin aviso; false vuelve a avisar por él.","type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"lot_number":{"type":"string"},"quantity":{"type":"number","description":"Lo que queda en el lote."},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."}},"required":["id","code","lot_number","quantity","status","kept"],"additionalProperties":false},"new_lot":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false},{"type":"null"}],"description":"Al trasladar una parte: el lote nuevo que quedó en el otro lugar."},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["item","lot","new_lot","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/lots/{id}/adjust":{"post":{"tags":["Insumos"],"summary":"Ajustar al recuento","description":"Deja el lote con la cantidad contada (registra la diferencia como un ajuste), con su motivo.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"counted":{"type":"number","minimum":0,"description":"Lo que hay de verdad en el lote, contado (0 si no queda nada)."},"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Por qué se ajusta (recuento, error de carga…)."}},"required":["counted","reason"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"lot_number":{"type":"string"},"quantity":{"type":"number","description":"Lo que queda en el lote."},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."}},"required":["id","code","lot_number","quantity","status","kept"],"additionalProperties":false},"new_lot":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false},{"type":"null"}],"description":"Al trasladar una parte: el lote nuevo que quedó en el otro lugar."},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["item","lot","new_lot","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/lots/{id}/transfer":{"post":{"tags":["Insumos"],"summary":"Trasladar","description":"Mueve un lote a otro lugar (y, si el lugar tiene grilla, a una posición). Con una cantidad menor que la que tiene, esa parte queda como un lote nuevo en el otro lugar (new_lot).\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"place":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"A dónde va, por id, nombre o camino (Sala › Heladera; ver …/reagents/places). null lo deja sin lugar."},"place_detail":{"type":"string","maxLength":120,"description":"Detalle del lugar nuevo: estante, caja…"},"position":{"description":"Posición en la grilla del lugar: «B4» (filas con letras) o «2-4» (ver …/reagents/places/:id/grid). Opcional: sin posición, el lote queda en el lugar sin indicarla. Solo para lugares con grilla.","type":"string","maxLength":10},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Cuánto se traslada. Sin cantidad, el lote entero; una parte queda como un lote nuevo en el otro lugar."}},"required":["place"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"lot_number":{"type":"string"},"quantity":{"type":"number","description":"Lo que queda en el lote."},"status":{"type":"string","enum":["expired","due_soon","ok","depleted"],"description":"expired = vencido, due_soon = por vencer, ok = al día, depleted = agotado."},"kept":{"type":"boolean","description":"Vencido y el laboratorio decidió conservarlo: sigue vencido, pero no avisa (ver …/keep-expired)."}},"required":["id","code","lot_number","quantity","status","kept"],"additionalProperties":false},"new_lot":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false},{"type":"null"}],"description":"Al trasladar una parte: el lote nuevo que quedó en el otro lugar."},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["item","lot","new_lot","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/movements/{id}/void":{"post":{"tags":["Insumos"],"summary":"Anular un movimiento","description":"Anula un movimiento cargado por error, con su motivo: deja de contar para el stock pero queda en el libro, marcado como anulado.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":500,"description":"Por qué se anula (cargado por error, duplicado…)."}},"required":["reason"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"lot":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"quantity":{"type":"number"}},"required":["id","code","quantity"],"additionalProperties":false},"stock":{"type":"object","properties":{"available":{"type":"number"}},"required":["available"],"additionalProperties":false}},"required":["id","item","lot","stock"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/orders/{id}/ordered":{"post":{"tags":["Insumos"],"summary":"Marcar como pedido","description":"Registra que el pedido se le hizo al proveedor, con su n.º y la fecha estimada de llegada. Sirve también para corregir esos datos. Con «version», responde 409 si alguien lo cambió después de leerlo.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"ordered_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo se le pidió al proveedor (AAAA-MM-DD). Por defecto, hoy."},"expected_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo se espera que llegue (AAAA-MM-DD)."},{"type":"null"}]},"reference":{"type":"string","maxLength":120,"description":"N.º de pedido u orden de compra."},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Cuánto se pidió, si cambió. Por defecto, lo que estaba pedido."},"supplier":{"description":"A qué proveedor, por id o por nombre, si cambió. null lo quita.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"status":{"type":"string","enum":["requested","ordered","received","cancelled"],"description":"requested = por pedir (alguien avisó que falta), ordered = pedido al proveedor, received = recibido, cancelled = cancelado."},"quantity":{"type":"number"},"already_open":{"type":"boolean","description":"true si el artículo ya tenía un pedido abierto y se devolvió ese (no se duplica)."}},"required":["id","item","status","quantity","already_open"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/orders/{id}/close":{"post":{"tags":["Insumos"],"summary":"Cerrar un pedido","description":"Lo da por recibido (aunque haya llegado menos) o lo cancela. Lo que llega con un ingreso contra el pedido lo cierra solo.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"status":{"type":"string","enum":["received","cancelled"],"description":"received = recibido (aunque haya llegado menos de lo pedido), cancelled = cancelado. Un pedido cerrado solo lo reabre la administración."}},"required":["status"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"item":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","code","name","unit"],"additionalProperties":false},"status":{"type":"string","enum":["requested","ordered","received","cancelled"],"description":"requested = por pedir (alguien avisó que falta), ordered = pedido al proveedor, received = recibido, cancelled = cancelado."},"quantity":{"type":"number"},"already_open":{"type":"boolean","description":"true si el artículo ya tenía un pedido abierto y se devolvió ese (no se duplica)."}},"required":["id","item","status","quantity","already_open"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/items/archive":{"post":{"tags":["Insumos"],"summary":"Archivar varios insumos","description":"Lo mismo que elegir varios artículos en el inventario y «Archivar» (o, con archived: false, volverlos al inventario): hasta 200 por vez, por id o por código. Archivados salen del inventario y de «Para pedir»; su historia se conserva.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"items":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1},"description":"Ids o códigos de los artículos."},"archived":{"default":true,"description":"true archiva (lo de siempre); false los vuelve al inventario.","type":"boolean"}},"required":["items"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"updated":{"type":"number","description":"Cuántos cambiaron."},"codes":{"type":"array","items":{"type":"string"},"description":"Códigos de los que cambiaron."},"not_found":{"type":"array","items":{"type":"string"},"description":"Lo que se mandó y no corresponde a ningún artículo."}},"required":["updated","codes","not_found"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/gas-cylinders":{"get":{"tags":["Insumos"],"summary":"Tubos de gas","description":"Los tubos de gas vigentes del laboratorio, por gas y número: estado, proveedor, equipo al que alimentan, vencimiento y su pedido de carga en curso.","parameters":[{"name":"gas","in":"query","required":false,"description":"Solo los tubos de este gas.","schema":{"description":"Solo los tubos de este gas.","type":"string"}},{"name":"status","in":"query","required":false,"description":"Solo los tubos en este estado.","schema":{"description":"Solo los tubos en este estado.","type":"string","enum":["full","in_use","empty","at_supplier"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"gas":{"type":"string"},"number":{"type":"string","description":"N.º grabado en el tubo."},"capacity":{"type":"string"},"status":{"type":"string","enum":["full","in_use","empty","at_supplier"],"description":"full = lleno, in_use = en uso, empty = vacío, at_supplier = en carga."},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"equipment":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},{"type":"null"}],"description":"Equipo al que alimenta."},"record":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},{"type":"null"}],"description":"La ficha del propio tubo en Equipos (mantenimiento y cargas). null si no tiene."},"location":{"type":"string"},"filled_on":{"description":"Última carga.","type":["string","null"]},"expires_on":{"type":["string","null"]},"expiry":{"type":"string","enum":["ok","due_soon","expired","none"],"description":"Vencimiento: al día, por vencer (60 días), vencido o sin fecha."},"open_order":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string","enum":["requested","ordered","received","cancelled"]}},"required":["id","status"],"additionalProperties":false},{"type":"null"}],"description":"Su pedido de carga en curso, si tiene."},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","gas","number","capacity","status","supplier","equipment","record","location","filled_on","expires_on","expiry","open_order","notes","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Insumos"],"summary":"Agregar un tubo de gas","description":"Carga un tubo con su número, su proveedor y el equipo al que alimenta. El número no se repite entre los tubos vigentes. Con Equipos habilitado, crea también la ficha del tubo en Equipos (tipo «Tubo de gas») para registrar su mantenimiento y sus cargas.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"gas":{"type":"string","minLength":1,"maxLength":80,"description":"Gas: nitrógeno, CO2, argón…"},"number":{"type":"string","minLength":1,"maxLength":60,"description":"N.º grabado en el tubo."},"capacity":{"type":"string","maxLength":60,"description":"Capacidad: «6 m³», «40 L»…"},"status":{"description":"Por defecto, full (lleno).","type":"string","enum":["full","in_use","empty","at_supplier"]},"supplier":{"description":"Proveedor, por id o por nombre.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"equipment":{"description":"Equipo al que alimenta, por código (EQ-0004) o id.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"location":{"type":"string","maxLength":120,"description":"Dónde está."},"filled_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Última carga (AAAA-MM-DD)."},{"type":"null"}]},"expires_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Vencimiento (AAAA-MM-DD)."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}},"required":["gas","number"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","status","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/gas-orders":{"get":{"tags":["Insumos"],"summary":"Pedidos de carga de gases","description":"Los pedidos de carga abiertos (por pedir y pedidos, del más viejo al más nuevo) o los últimos cerrados.","parameters":[{"name":"open","in":"query","required":false,"description":"true = los abiertos (por pedir y pedidos), false = los cerrados. Por defecto, true.","schema":{"default":"true","description":"true = los abiertos (por pedir y pedidos), false = los cerrados. Por defecto, true.","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"gas":{"type":"string"},"quantity":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuántos tubos."},"cylinder":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"}},"required":["id","number"],"additionalProperties":false},{"type":"null"}],"description":"Si es la recarga de un tubo concreto."},"equipment":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},{"type":"null"}]},"supplier":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"status":{"type":"string","enum":["requested","ordered","received","cancelled"],"description":"requested = por pedir, ordered = pedido al proveedor, received = recibido, cancelled = cancelado."},"requested_by":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"Miembro del laboratorio."},"requested_on":{"type":"string"},"ordered_on":{"type":["string","null"]},"expected_on":{"type":["string","null"]},"reference":{"type":"string","description":"N.º de orden de compra o remito."},"notes":{"type":"string"},"closed_on":{"type":["string","null"]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","gas","quantity","cylinder","equipment","supplier","status","requested_by","requested_on","ordered_on","expected_on","reference","notes","closed_on","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Insumos"],"summary":"Pedir una carga de gas","description":"Con cylinder, pide la recarga de ese tubo (queda vacío hasta que llega; si ya tiene un pedido abierto, no se duplica). Sin cylinder, pide tubos de un gas (gas y quantity). Con ordered = true se registra ya pedido al proveedor.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"cylinder":{"description":"Tubo a recargar, por n.º o id. Sin tubo, va gas y quantity (tubos nuevos o a cambiar).","type":"string"},"gas":{"type":"string","maxLength":80,"description":"Gas (sin tubo)."},"quantity":{"description":"Cuántos tubos (sin tubo). Por defecto, 1.","type":"integer","minimum":1,"maximum":999},"equipment":{"description":"Equipo al que alimenta, por código (EQ-0004) o id.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"ordered":{"description":"true = ya se pidió al proveedor. Si no, queda «por pedir» (y el tubo, vacío).","type":"boolean"},"supplier":{"description":"Proveedor, por id o por nombre.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reference":{"type":"string","maxLength":120,"description":"N.º de orden de compra o remito."},"expected_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Para cuándo se necesita la carga o, si ya está pedida, cuándo llega (AAAA-MM-DD)."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}}}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","status","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/gas-cylinders/{id}":{"patch":{"tags":["Insumos"],"summary":"Modificar un tubo de gas","description":"Cambia solo lo que se manda (estado, equipo, proveedor, vencimiento…). Con «version», responde 409 si alguien lo cambió después de leerlo. El tubo se identifica por su id o su número.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"gas":{"type":"string","minLength":1,"maxLength":80,"description":"Gas: nitrógeno, CO2, argón…"},"number":{"type":"string","minLength":1,"maxLength":60,"description":"N.º grabado en el tubo."},"capacity":{"type":"string","maxLength":60,"description":"Capacidad: «6 m³», «40 L»…"},"status":{"description":"Por defecto, full (lleno).","type":"string","enum":["full","in_use","empty","at_supplier"]},"supplier":{"description":"Proveedor, por id o por nombre.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"equipment":{"description":"Equipo al que alimenta, por código (EQ-0004) o id.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"location":{"type":"string","maxLength":120,"description":"Dónde está."},"filled_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Última carga (AAAA-MM-DD)."},{"type":"null"}]},"expires_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Vencimiento (AAAA-MM-DD)."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","status","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/gas-orders/{id}/ordered":{"post":{"tags":["Insumos"],"summary":"Marcar una carga como pedida","description":"Registra que la carga ya se le pidió al proveedor, con su n.º y la fecha estimada. Si es la recarga de un tubo, el tubo pasa a «en carga». Sirve también para corregir esos datos. Con «version», responde 409 si alguien lo cambió.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"supplier":{"description":"A qué proveedor, por id o por nombre.","anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"reference":{"type":"string","maxLength":120,"description":"N.º de orden de compra o remito."},"expected_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo se espera (AAAA-MM-DD)."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","status","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/reagents/gas-orders/{id}/close":{"post":{"tags":["Insumos"],"summary":"Cerrar un pedido de carga","description":"received = llegó la carga (si era la recarga de un tubo, queda lleno con la fecha de hoy como última carga); cancelled = cancelado. Un pedido cerrado solo lo reabre la administración.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"status":{"type":"string","enum":["received","cancelled"],"description":"received = llegó (el tubo queda lleno, con la fecha de hoy), cancelled = cancelado."}},"required":["status"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"status":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","status","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/monitoring/sensors":{"get":{"tags":["Monitoreo"],"summary":"Sensores","description":"Los sensores de temperatura conectados, con su estado ahora, la última lectura y, si está fuera de rango, desde cuándo.","parameters":[{"name":"equipment","in":"query","required":false,"description":"Solo los sensores de un equipo, por id o por código.","schema":{"description":"Solo los sensores de un equipo, por id o por código.","type":"string"}},{"name":"archived","in":"query","required":false,"description":"include suma los desconectados; only, solo ellos.","schema":{"description":"include suma los desconectados; only, solo ellos.","type":"string","enum":["include","only"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false,"description":"El equipo donde está el sensor (módulo Equipos)."},"min_value":{"description":"Mínimo aceptable, en °C.","type":["number","null"]},"max_value":{"description":"Máximo aceptable, en °C.","type":["number","null"]},"range":{"type":"string","description":"El rango en palabras: «Entre 2 y 8 °C»."},"alarm_delay_minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutos fuera de rango antes de que cuente como alarma."},"alarm_repeat_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Cada cuántos minutos se repite el aviso mientras la alarma siga abierta. null: avisa una sola vez."},"offline_after_minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutos sin lecturas antes de avisar que no responde."},"state":{"type":"string","enum":["waiting","offline","alarm","out","ok"],"description":"waiting = nunca mandó una lectura, offline = dejó de mandar (sin datos), alarm = fuera de rango más tiempo que la demora, out = fuera de rango dentro de la demora, ok = en rango."},"latest":{"anyOf":[{"type":"object","properties":{"measured_at":{"type":"string","description":"Instante de la lectura (UTC)."},"value":{"type":"number","description":"Temperatura en °C."}},"required":["measured_at","value"],"additionalProperties":false},{"type":"null"}],"description":"La última lectura, o null si nunca mandó."},"open_excursion":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["high","low"],"description":"high = por encima del máximo, low = por debajo del mínimo."},"started_at":{"type":"string"},"ended_at":{"description":"Vacío mientras sigue fuera de rango.","type":["string","null"]},"peak_value":{"type":"number","description":"La temperatura más alta (high) o más baja (low) que llegó."},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuánto duró (o lleva), en minutos."},"acknowledged_at":{"description":"Cuándo se registró qué se hizo. Vacío: sin registrar.","type":["string","null"]},"acknowledged_by":{"type":["string","null"]},"note":{"type":"string","description":"La acción correctiva que se anotó."}},"required":["id","kind","started_at","ended_at","peak_value","minutes","acknowledged_at","acknowledged_by","note"],"additionalProperties":false},{"type":"null"}],"description":"Si ahora está fuera de rango, desde cuándo y hasta dónde llegó."},"key_prefix":{"description":"Los primeros caracteres de su clave vigente (vsn_…).","type":["string","null"]},"archived":{"type":"boolean","description":"true si está desconectado: su clave no funciona."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","equipment","min_value","max_value","range","alarm_delay_minutes","alarm_repeat_minutes","offline_after_minutes","state","latest","open_excursion","key_prefix","archived","created_at","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/monitoring/sensors/{id}":{"get":{"tags":["Monitoreo"],"summary":"Ver un sensor","description":"Por id, o por el código de su equipo si tiene un solo sensor. Con la lectura más baja y la más alta del período y sus alarmas.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"period","in":"query","required":false,"description":"Atajo: 12h, 24h, 7d o 30d (hasta ahora). Por defecto, 24h. Se ignora si van from o to.","schema":{"description":"Atajo: 12h, 24h, 7d o 30d (hasta ahora). Por defecto, 24h. Se ignora si van from o to.","type":"string","enum":["12h","24h","7d","30d"]}},{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD, en la hora del laboratorio). Hasta un año.","schema":{"description":"Desde este día (AAAA-MM-DD, en la hora del laboratorio). Hasta un año.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive. Por defecto, hoy.","schema":{"description":"Hasta este día inclusive. Por defecto, hoy.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false,"description":"El equipo donde está el sensor (módulo Equipos)."},"min_value":{"description":"Mínimo aceptable, en °C.","type":["number","null"]},"max_value":{"description":"Máximo aceptable, en °C.","type":["number","null"]},"range":{"type":"string","description":"El rango en palabras: «Entre 2 y 8 °C»."},"alarm_delay_minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutos fuera de rango antes de que cuente como alarma."},"alarm_repeat_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Cada cuántos minutos se repite el aviso mientras la alarma siga abierta. null: avisa una sola vez."},"offline_after_minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutos sin lecturas antes de avisar que no responde."},"state":{"type":"string","enum":["waiting","offline","alarm","out","ok"],"description":"waiting = nunca mandó una lectura, offline = dejó de mandar (sin datos), alarm = fuera de rango más tiempo que la demora, out = fuera de rango dentro de la demora, ok = en rango."},"latest":{"anyOf":[{"type":"object","properties":{"measured_at":{"type":"string","description":"Instante de la lectura (UTC)."},"value":{"type":"number","description":"Temperatura en °C."}},"required":["measured_at","value"],"additionalProperties":false},{"type":"null"}],"description":"La última lectura, o null si nunca mandó."},"open_excursion":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["high","low"],"description":"high = por encima del máximo, low = por debajo del mínimo."},"started_at":{"type":"string"},"ended_at":{"description":"Vacío mientras sigue fuera de rango.","type":["string","null"]},"peak_value":{"type":"number","description":"La temperatura más alta (high) o más baja (low) que llegó."},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuánto duró (o lleva), en minutos."},"acknowledged_at":{"description":"Cuándo se registró qué se hizo. Vacío: sin registrar.","type":["string","null"]},"acknowledged_by":{"type":["string","null"]},"note":{"type":"string","description":"La acción correctiva que se anotó."}},"required":["id","kind","started_at","ended_at","peak_value","minutes","acknowledged_at","acknowledged_by","note"],"additionalProperties":false},{"type":"null"}],"description":"Si ahora está fuera de rango, desde cuándo y hasta dónde llegó."},"key_prefix":{"description":"Los primeros caracteres de su clave vigente (vsn_…).","type":["string","null"]},"archived":{"type":"boolean","description":"true si está desconectado: su clave no funciona."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"period":{"type":"object","properties":{"from":{"type":"string","description":"Inicio del período (UTC)."},"to":{"type":"string","description":"Fin del período (UTC)."},"label":{"type":"string","description":"El período en palabras."}},"required":["from","to","label"],"additionalProperties":false},"lowest":{"anyOf":[{"type":"object","properties":{"measured_at":{"type":"string","description":"Instante de la lectura (UTC)."},"value":{"type":"number","description":"Temperatura en °C."}},"required":["measured_at","value"],"additionalProperties":false},{"type":"null"}],"description":"La lectura más baja del período."},"highest":{"anyOf":[{"type":"object","properties":{"measured_at":{"type":"string","description":"Instante de la lectura (UTC)."},"value":{"type":"number","description":"Temperatura en °C."}},"required":["measured_at","value"],"additionalProperties":false},{"type":"null"}],"description":"La lectura más alta del período."},"alarms":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["high","low"],"description":"high = por encima del máximo, low = por debajo del mínimo."},"started_at":{"type":"string"},"ended_at":{"description":"Vacío mientras sigue fuera de rango.","type":["string","null"]},"peak_value":{"type":"number","description":"La temperatura más alta (high) o más baja (low) que llegó."},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuánto duró (o lleva), en minutos."},"acknowledged_at":{"description":"Cuándo se registró qué se hizo. Vacío: sin registrar.","type":["string","null"]},"acknowledged_by":{"type":["string","null"]},"note":{"type":"string","description":"La acción correctiva que se anotó."}},"required":["id","kind","started_at","ended_at","peak_value","minutes","acknowledged_at","acknowledged_by","note"],"additionalProperties":false},"description":"Las alarmas del período, de la más nueva a la más vieja."}},"required":["id","name","equipment","min_value","max_value","range","alarm_delay_minutes","alarm_repeat_minutes","offline_after_minutes","state","latest","open_excursion","key_prefix","archived","created_at","version","period","lowest","highest","alarms"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Monitoreo"],"summary":"Modificar un sensor","description":"Cambia el nombre, el rango o las demoras de un sensor, o lo desconecta (archived). Cambia solo lo que mandás. Pide la «version» que devolvió la API: si alguien lo cambió después, responde 409.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"name":{"type":"string","minLength":1,"maxLength":80,"description":"Nombre del sensor dentro del equipo («Estante de arriba»)."},"min_value":{"description":"Mínimo aceptable. En °C. null lo quita.","anyOf":[{"type":"number","minimum":-273,"maximum":500},{"type":"null"}]},"max_value":{"description":"Máximo aceptable. En °C. null lo quita.","anyOf":[{"type":"number","minimum":-273,"maximum":500},{"type":"null"}]},"alarm_delay_minutes":{"description":"Minutos fuera de rango antes de que cuente como alarma.","type":"integer","minimum":0,"maximum":240},"alarm_repeat_minutes":{"description":"Cada cuántos minutos se repite el aviso mientras la alarma siga abierta. null: avisa una sola vez.","anyOf":[{"type":"integer","minimum":15,"maximum":1440},{"type":"null"}]},"offline_after_minutes":{"description":"Minutos sin lecturas antes de avisar que no responde.","type":"integer","minimum":5,"maximum":1440},"archived":{"description":"true lo desconecta (su clave deja de funcionar; las lecturas y alarmas quedan); false lo vuelve a conectar.","type":"boolean"}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false,"description":"El equipo donde está el sensor (módulo Equipos)."},"min_value":{"description":"Mínimo aceptable, en °C.","type":["number","null"]},"max_value":{"description":"Máximo aceptable, en °C.","type":["number","null"]},"range":{"type":"string","description":"El rango en palabras: «Entre 2 y 8 °C»."},"alarm_delay_minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutos fuera de rango antes de que cuente como alarma."},"alarm_repeat_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Cada cuántos minutos se repite el aviso mientras la alarma siga abierta. null: avisa una sola vez."},"offline_after_minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Minutos sin lecturas antes de avisar que no responde."},"state":{"type":"string","enum":["waiting","offline","alarm","out","ok"],"description":"waiting = nunca mandó una lectura, offline = dejó de mandar (sin datos), alarm = fuera de rango más tiempo que la demora, out = fuera de rango dentro de la demora, ok = en rango."},"latest":{"anyOf":[{"type":"object","properties":{"measured_at":{"type":"string","description":"Instante de la lectura (UTC)."},"value":{"type":"number","description":"Temperatura en °C."}},"required":["measured_at","value"],"additionalProperties":false},{"type":"null"}],"description":"La última lectura, o null si nunca mandó."},"open_excursion":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["high","low"],"description":"high = por encima del máximo, low = por debajo del mínimo."},"started_at":{"type":"string"},"ended_at":{"description":"Vacío mientras sigue fuera de rango.","type":["string","null"]},"peak_value":{"type":"number","description":"La temperatura más alta (high) o más baja (low) que llegó."},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuánto duró (o lleva), en minutos."},"acknowledged_at":{"description":"Cuándo se registró qué se hizo. Vacío: sin registrar.","type":["string","null"]},"acknowledged_by":{"type":["string","null"]},"note":{"type":"string","description":"La acción correctiva que se anotó."}},"required":["id","kind","started_at","ended_at","peak_value","minutes","acknowledged_at","acknowledged_by","note"],"additionalProperties":false},{"type":"null"}],"description":"Si ahora está fuera de rango, desde cuándo y hasta dónde llegó."},"key_prefix":{"description":"Los primeros caracteres de su clave vigente (vsn_…).","type":["string","null"]},"archived":{"type":"boolean","description":"true si está desconectado: su clave no funciona."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","equipment","min_value","max_value","range","alarm_delay_minutes","alarm_repeat_minutes","offline_after_minutes","state","latest","open_excursion","key_prefix","archived","created_at","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/monitoring/sensors/{id}/readings":{"get":{"tags":["Monitoreo"],"summary":"Lecturas de un sensor","description":"Las lecturas de un período, resumidas por tramos para graficar: de cada tramo, la más baja y la más alta. Las lecturas quedan tal cual 90 días; lo más viejo sale del resumen por hora (la más baja y la más alta de cada hora, con su momento).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"period","in":"query","required":false,"description":"Atajo: 12h, 24h, 7d o 30d (hasta ahora). Por defecto, 24h. Se ignora si van from o to.","schema":{"description":"Atajo: 12h, 24h, 7d o 30d (hasta ahora). Por defecto, 24h. Se ignora si van from o to.","type":"string","enum":["12h","24h","7d","30d"]}},{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD, en la hora del laboratorio). Hasta un año.","schema":{"description":"Desde este día (AAAA-MM-DD, en la hora del laboratorio). Hasta un año.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive. Por defecto, hoy.","schema":{"description":"Hasta este día inclusive. Por defecto, hoy.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"points","in":"query","required":false,"description":"En cuántos tramos se divide el período (de cada uno vienen la lectura más baja y la más alta). Por defecto, 360.","schema":{"default":360,"description":"En cuántos tramos se divide el período (de cada uno vienen la lectura más baja y la más alta). Por defecto, 360.","type":"integer","minimum":10,"maximum":1000}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string","description":"Inicio del período (UTC)."},"to":{"type":"string","description":"Fin del período (UTC)."},"label":{"type":"string","description":"El período en palabras."}},"required":["from","to","label"],"additionalProperties":false},"data":{"type":"array","items":{"type":"object","properties":{"measured_at":{"type":"string","description":"Instante de la lectura (UTC)."},"value":{"type":"number","description":"Temperatura en °C."}},"required":["measured_at","value"],"additionalProperties":false},"description":"De la más vieja a la más nueva. El período se divide en tramos y de cada uno vienen la lectura más baja y la más alta: un pico corto no se pierde."}},"required":["period","data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/monitoring/sensors/{id}/history":{"get":{"tags":["Monitoreo"],"summary":"Historial de un sensor","description":"Quién lo conectó, le cambió el rango o lo desconectó, cuándo y por dónde.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/monitoring/alarms":{"get":{"tags":["Monitoreo"],"summary":"Alarmas","description":"Cada vez que una temperatura estuvo fuera de rango más tiempo que la demora del sensor, con la acción correctiva registrada, de la más nueva a la más vieja (hasta 500).","parameters":[{"name":"pending","in":"query","required":false,"description":"true: solo las que todavía no tienen registrado qué se hizo.","schema":{"description":"true: solo las que todavía no tienen registrado qué se hizo.","type":"string","enum":["true","false"]}},{"name":"sensor","in":"query","required":false,"description":"Solo las de un sensor: su id, o el código del equipo si tiene uno solo.","schema":{"description":"Solo las de un sensor: su id, o el código del equipo si tiene uno solo.","type":"string"}},{"name":"from","in":"query","required":false,"description":"Las que se cruzan con el período, desde este día (AAAA-MM-DD). Sin from ni to, todas.","schema":{"description":"Las que se cruzan con el período, desde este día (AAAA-MM-DD). Sin from ni to, todas.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive.","schema":{"description":"Hasta este día inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["high","low"],"description":"high = por encima del máximo, low = por debajo del mínimo."},"started_at":{"type":"string"},"ended_at":{"description":"Vacío mientras sigue fuera de rango.","type":["string","null"]},"peak_value":{"type":"number","description":"La temperatura más alta (high) o más baja (low) que llegó."},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuánto duró (o lleva), en minutos."},"acknowledged_at":{"description":"Cuándo se registró qué se hizo. Vacío: sin registrar.","type":["string","null"]},"acknowledged_by":{"type":["string","null"]},"note":{"type":"string","description":"La acción correctiva que se anotó."},"sensor":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false,"description":"El equipo donde está el sensor (módulo Equipos)."}},"required":["id","kind","started_at","ended_at","peak_value","minutes","acknowledged_at","acknowledged_by","note","sensor","equipment"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/monitoring/alarms/{id}/acknowledge":{"post":{"tags":["Monitoreo"],"summary":"Registrar una alarma","description":"Registra una alarma a nombre de la persona del token, con qué se hizo (la acción correctiva) si lo cuenta; la nota es opcional. Cada alarma se registra una sola vez.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"note":{"type":"string","maxLength":1000,"description":"Qué se hizo: la acción correctiva («Se cerró la puerta y volvió a rango en 20 min»). Es opcional."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"kind":{"type":"string","enum":["high","low"],"description":"high = por encima del máximo, low = por debajo del mínimo."},"started_at":{"type":"string"},"ended_at":{"description":"Vacío mientras sigue fuera de rango.","type":["string","null"]},"peak_value":{"type":"number","description":"La temperatura más alta (high) o más baja (low) que llegó."},"minutes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Cuánto duró (o lleva), en minutos."},"acknowledged_at":{"description":"Cuándo se registró qué se hizo. Vacío: sin registrar.","type":["string","null"]},"acknowledged_by":{"type":["string","null"]},"note":{"type":"string","description":"La acción correctiva que se anotó."},"sensor":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"equipment":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false,"description":"El equipo donde está el sensor (módulo Equipos)."}},"required":["id","kind","started_at","ended_at","peak_value","minutes","acknowledged_at","acknowledged_by","note","sensor","equipment"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/catalog":{"get":{"tags":["Servicios"],"summary":"Catálogo de servicios","description":"Lo que ofrece el laboratorio, en qué se cuenta y (con «Ver montos») sus precios por lista con su historial. Sin los servicios restringidos que la persona no ve.","parameters":[{"name":"archived","in":"query","required":false,"description":"include suma los archivados; only, solo ellos.","schema":{"description":"include suma los archivados; only, solo ellos.","type":"string","enum":["include","only"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"Código propio u oficial (puede estar vacío)."},"name":{"type":"string"},"category":{"type":"string"},"unit":{"type":"string","description":"En qué se cuenta: reacción, muestra, hora…"},"description":{"type":"string"},"tax_pct":{"description":"Impuesto propio del servicio, en %; null = el habitual del laboratorio (si cobra impuestos).","type":["number","null"]},"archived":{"type":"boolean"},"prices":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"price_list":{"description":"Nombre de la lista de precios; null = la general.","type":["string","null"]},"unit_price":{"type":"number"},"currency":{"type":"string","description":"Moneda del arancel (ISO: ARS, USD…)."},"valid_from":{"type":"string","description":"Desde cuándo vale (AAAA-MM-DD)."},"min_quantity":{"type":"number","description":"Precio por volumen: desde cuántas unidades vale (0 = desde la primera)."},"minimum":{"description":"Lo mínimo que se cobra por ítem, en la moneda del precio.","type":["number","null"]},"notes":{"type":"string"}},"required":["id","price_list","unit_price","currency","valid_from","min_quantity","minimum","notes"],"additionalProperties":false}},{"type":"null"}],"description":"Precios vigentes y futuros por lista (null sin «Ver montos»). El vigente de cada lista es el de mayor valid_from que ya empezó; con precios por volumen, el de mayor min_quantity que alcanza la cantidad."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","category","unit","description","tax_pct","archived","prices","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Sumar un servicio al catálogo","description":"Pide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre del servicio."},"code":{"type":"string","maxLength":40,"description":"Código propio u oficial."},"category":{"type":"string","maxLength":80,"description":"Categoría."},"unit":{"type":"string","minLength":1,"maxLength":30,"description":"En qué se cuenta: reacción, muestra, hora…"},"description":{"type":"string","maxLength":2000,"description":"Descripción."},"tax_pct":{"description":"Impuesto propio del servicio en % (0 si está exento); null o sin esto, el habitual del laboratorio.","anyOf":[{"type":"number","minimum":0,"maximum":100},{"type":"null"}]}},"required":["name"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"Código propio u oficial (puede estar vacío)."},"name":{"type":"string"},"category":{"type":"string"},"unit":{"type":"string","description":"En qué se cuenta: reacción, muestra, hora…"},"description":{"type":"string"},"tax_pct":{"description":"Impuesto propio del servicio, en %; null = el habitual del laboratorio (si cobra impuestos).","type":["number","null"]},"archived":{"type":"boolean"},"prices":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"price_list":{"description":"Nombre de la lista de precios; null = la general.","type":["string","null"]},"unit_price":{"type":"number"},"currency":{"type":"string","description":"Moneda del arancel (ISO: ARS, USD…)."},"valid_from":{"type":"string","description":"Desde cuándo vale (AAAA-MM-DD)."},"min_quantity":{"type":"number","description":"Precio por volumen: desde cuántas unidades vale (0 = desde la primera)."},"minimum":{"description":"Lo mínimo que se cobra por ítem, en la moneda del precio.","type":["number","null"]},"notes":{"type":"string"}},"required":["id","price_list","unit_price","currency","valid_from","min_quantity","minimum","notes"],"additionalProperties":false}},{"type":"null"}],"description":"Precios vigentes y futuros por lista (null sin «Ver montos»). El vigente de cada lista es el de mayor valid_from que ya empezó; con precios por volumen, el de mayor min_quantity que alcanza la cantidad."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","category","unit","description","tax_pct","archived","prices","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/catalog/{id}/access":{"get":{"tags":["Servicios"],"summary":"Quién ve un servicio del catálogo","description":"Si el servicio es restringido y quiénes lo ven además de la administración y el responsable. Para el resto no existen ni el servicio ni los pedidos, cotizaciones, facturas y balance que lo incluyen. Se elige desde Vialo (la administración), no con un token.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"restricted":{"type":"boolean","description":"Si es true, solo lo ven la administración (y, en equipos, su responsable) y las personas de «people»."},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: solo ve; manage: ve y gestiona (carga y cambia datos)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Quiénes lo ven además de la administración."},"sub_labs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: toda su gente ve; manage: ve y gestiona (si su rol en este laboratorio lo permite)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Sub-laboratorios a los que se abrió, con toda su gente."}},"required":["restricted","people","sub_labs"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/clients":{"get":{"tags":["Servicios"],"summary":"Clientes","description":"Quienes contratan los servicios, con sus áreas y su lista de precios.","parameters":[{"name":"archived","in":"query","required":false,"description":"include suma los archivados; only, solo ellos.","schema":{"description":"include suma los archivados; only, solo ellos.","type":"string","enum":["include","only"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string","description":"Nombre o razón social."},"short_name":{"type":"string","description":"Cómo se lo nombra (la sigla)."},"tax_id":{"type":"string","description":"Identificación (CUIT o DNI, RUT, RFC, NIF, EIN…)."},"tax_exempt":{"type":"boolean","description":"Exento de impuestos."},"kind":{"type":"string","enum":["public_institution","company","individual","internal","other"]},"email":{"type":"string","description":"El mail de contacto principal."},"other_emails":{"type":"array","items":{"type":"string"},"description":"Los demás mails de contacto."},"phone":{"type":"string"},"address":{"type":"string"},"notes":{"type":"string"},"price_list":{"description":"Su lista de precios; null = la general.","type":["string","null"]},"areas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"email":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","contact_name","email","archived"],"additionalProperties":false}},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","short_name","tax_id","tax_exempt","kind","email","other_emails","phone","address","notes","price_list","areas","custom_fields","archived","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Cargar un cliente","description":"Pide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"Nombre o razón social."},"short_name":{"type":"string","maxLength":60,"description":"Cómo se lo nombra (la sigla)."},"tax_id":{"type":"string","maxLength":30,"description":"Identificación (CUIT o DNI, RUT, RFC, NIF, EIN…)."},"tax_exempt":{"description":"Exento de impuestos: sus ítems van sin impuesto.","type":"boolean"},"kind":{"type":"string","enum":["public_institution","company","individual","internal","other"]},"email":{"description":"El mail de contacto principal.","anyOf":[{"type":"string","const":""},{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}]},"other_emails":{"description":"Los demás mails de contacto. Si van, reemplazan a los que hay.","maxItems":10,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"phone":{"type":"string","maxLength":60,"description":"Teléfono."},"address":{"type":"string","maxLength":300,"description":"Dirección."},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"price_list":{"description":"Lista de precios por nombre; null = la general.","anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"areas":{"description":"Áreas que se suman (las que ya tiene quedan).","maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":80,"description":"Nombre del área."}},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["name"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string","description":"Nombre o razón social."},"short_name":{"type":"string","description":"Cómo se lo nombra (la sigla)."},"tax_id":{"type":"string","description":"Identificación (CUIT o DNI, RUT, RFC, NIF, EIN…)."},"tax_exempt":{"type":"boolean","description":"Exento de impuestos."},"kind":{"type":"string","enum":["public_institution","company","individual","internal","other"]},"email":{"type":"string","description":"El mail de contacto principal."},"other_emails":{"type":"array","items":{"type":"string"},"description":"Los demás mails de contacto."},"phone":{"type":"string"},"address":{"type":"string"},"notes":{"type":"string"},"price_list":{"description":"Su lista de precios; null = la general.","type":["string","null"]},"areas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"email":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","contact_name","email","archived"],"additionalProperties":false}},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","short_name","tax_id","tax_exempt","kind","email","other_emails","phone","address","notes","price_list","areas","custom_fields","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/clients/{id}":{"get":{"tags":["Servicios"],"summary":"Ver un cliente","description":"Por id, sigla, nombre o CUIT.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string","description":"Nombre o razón social."},"short_name":{"type":"string","description":"Cómo se lo nombra (la sigla)."},"tax_id":{"type":"string","description":"Identificación (CUIT o DNI, RUT, RFC, NIF, EIN…)."},"tax_exempt":{"type":"boolean","description":"Exento de impuestos."},"kind":{"type":"string","enum":["public_institution","company","individual","internal","other"]},"email":{"type":"string","description":"El mail de contacto principal."},"other_emails":{"type":"array","items":{"type":"string"},"description":"Los demás mails de contacto."},"phone":{"type":"string"},"address":{"type":"string"},"notes":{"type":"string"},"price_list":{"description":"Su lista de precios; null = la general.","type":["string","null"]},"areas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"email":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","contact_name","email","archived"],"additionalProperties":false}},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","short_name","tax_id","tax_exempt","kind","email","other_emails","phone","address","notes","price_list","areas","custom_fields","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Servicios"],"summary":"Modificar un cliente","description":"Cambia solo lo que mandás; «areas» suma áreas nuevas. «archived» lo archiva o reactiva.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"Nombre o razón social."},"short_name":{"type":"string","maxLength":60,"description":"Cómo se lo nombra (la sigla)."},"tax_id":{"type":"string","maxLength":30,"description":"Identificación (CUIT o DNI, RUT, RFC, NIF, EIN…)."},"tax_exempt":{"description":"Exento de impuestos: sus ítems van sin impuesto.","type":"boolean"},"kind":{"type":"string","enum":["public_institution","company","individual","internal","other"]},"email":{"description":"El mail de contacto principal.","anyOf":[{"type":"string","const":""},{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}]},"other_emails":{"description":"Los demás mails de contacto. Si van, reemplazan a los que hay.","maxItems":10,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"phone":{"type":"string","maxLength":60,"description":"Teléfono."},"address":{"type":"string","maxLength":300,"description":"Dirección."},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"price_list":{"description":"Lista de precios por nombre; null = la general.","anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"areas":{"description":"Áreas que se suman (las que ya tiene quedan).","maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":80,"description":"Nombre del área."}},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"archived":{"description":"true lo archiva; false lo reactiva.","type":"boolean"}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string","description":"Nombre o razón social."},"short_name":{"type":"string","description":"Cómo se lo nombra (la sigla)."},"tax_id":{"type":"string","description":"Identificación (CUIT o DNI, RUT, RFC, NIF, EIN…)."},"tax_exempt":{"type":"boolean","description":"Exento de impuestos."},"kind":{"type":"string","enum":["public_institution","company","individual","internal","other"]},"email":{"type":"string","description":"El mail de contacto principal."},"other_emails":{"type":"array","items":{"type":"string"},"description":"Los demás mails de contacto."},"phone":{"type":"string"},"address":{"type":"string"},"notes":{"type":"string"},"price_list":{"description":"Su lista de precios; null = la general.","type":["string","null"]},"areas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"contact_name":{"type":"string"},"email":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","contact_name","email","archived"],"additionalProperties":false}},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"archived":{"type":"boolean"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","name","short_name","tax_id","tax_exempt","kind","email","other_emails","phone","address","notes","price_list","areas","custom_fields","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/orders":{"get":{"tags":["Servicios"],"summary":"Pedidos","description":"Los pedidos de servicios, del más nuevo al más viejo, con filtros. Con «Ver montos», también el importe y el estado de facturación.","parameters":[{"name":"q","in":"query","required":false,"description":"Texto: código, cliente, área, referencia o servicio.","schema":{"description":"Texto: código, cliente, área, referencia o servicio.","type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"description":"received, in_progress, delivered o cancelled.","schema":{"description":"received, in_progress, delivered o cancelled.","type":"string","enum":["received","in_progress","delivered","cancelled"]}},{"name":"client","in":"query","required":false,"description":"Cliente por id, sigla, nombre o CUIT.","schema":{"description":"Cliente por id, sigla, nombre o CUIT.","type":"string"}},{"name":"billing","in":"query","required":false,"description":"Estado de facturación (pide «Ver montos»).","schema":{"description":"Estado de facturación (pide «Ver montos»).","type":"string","enum":["unpriced","to_invoice","unpaid","overdue","paid"]}},{"name":"from","in":"query","required":false,"description":"Recibidos desde este día.","schema":{"description":"Recibidos desde este día.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Recibidos hasta este día inclusive.","schema":{"description":"Recibidos hasta este día inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"SRV-2026-0001…"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"contact_name":{"type":"string"},"contact_emails":{"type":"array","items":{"type":"string"},"description":"A quién escribirle."},"reference":{"type":"string","description":"N.º de nota, orden o planilla del cliente."},"received_on":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"stage":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La etapa del laboratorio (si usa etapas); el estado sale de la etapa."},"delivered_on":{"type":["string","null"]},"delivered_by":{"description":"Quién entregó.","type":["string","null"]},"responsible":{"type":["string","null"]},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"amount":{"description":"Total con precio, con impuesto si lo hay (null sin «Ver montos»).","type":["number","null"]},"billing":{"anyOf":[{"type":"string","enum":["unpriced","to_invoice","unpaid","overdue","paid"],"description":"unpriced = algún ítem sin precio, to_invoice = pendiente de facturar, unpaid = facturado sin cobrar, overdue = factura vencida, paid = cobrado entero."},{"type":"null"}],"description":"Estado de facturación (null sin «Ver montos»)."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","client","area","contact_name","contact_emails","reference","received_on","status","stage","delivered_on","delivered_by","responsible","notes","custom_fields","amount","billing","created_at","version"],"additionalProperties":false}},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","page","limit","total"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Cargar un pedido","description":"Cliente, área y los servicios con su cantidad. Con «Facturar y cobrar», el precio sale del catálogo (o del que se mande) y, si está en otra moneda, con la cotización del día.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"client":{"type":"string","minLength":1,"maxLength":200,"description":"Cliente por id, sigla, nombre o CUIT."},"area":{"description":"Área del cliente por nombre o id.","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"received_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día en que llegó. Por defecto, hoy."},"reference":{"type":"string","maxLength":120,"description":"N.º de nota, orden o planilla del cliente."},"contact_name":{"type":"string","maxLength":120,"description":"Quién lo pidió."},"contact_emails":{"description":"A quién escribirle. Si no va al cargarlo, salen del área o del cliente.","maxItems":20,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"items":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"service":{"type":"string","minLength":1,"maxLength":120,"description":"Servicio del catálogo: id, código o nombre."},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":100000000},"notes":{"type":"string","maxLength":500,"description":"Nota del ítem (muestras, detalle)."},"unit_price":{"description":"Precio unitario (pide «Facturar y cobrar»). Si no va, sale del catálogo: la lista del cliente o la general. null lo deja sin precio.","anyOf":[{"type":"number","minimum":0,"maximum":10000000000},{"type":"null"}]},"currency":{"description":"Moneda del precio. Por defecto, la del catálogo o la del laboratorio.","type":"string","pattern":"^[A-Z]{3}$"},"adjustment_pct":{"description":"Descuento (negativo, -10 = 10 % menos) o recargo (positivo, 50 = 50 % más) sobre el ítem. Pide «Facturar y cobrar».","type":"number","minimum":-100,"maximum":1000}},"required":["service","quantity"]}},"exchange_rate":{"description":"Cotización para los precios en otra moneda. Si no va, se trae sola con la fuente que eligió el laboratorio (por defecto, dólar oficial vendedor del BNA para pesos y la referencia del BCE para otras monedas).","type":"number","exclusiveMinimum":0},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["client","items"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"SRV-2026-0001…"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"contact_name":{"type":"string"},"contact_emails":{"type":"array","items":{"type":"string"},"description":"A quién escribirle."},"reference":{"type":"string","description":"N.º de nota, orden o planilla del cliente."},"received_on":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"stage":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La etapa del laboratorio (si usa etapas); el estado sale de la etapa."},"delivered_on":{"type":["string","null"]},"delivered_by":{"description":"Quién entregó.","type":["string","null"]},"responsible":{"type":["string","null"]},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"amount":{"description":"Total con precio, con impuesto si lo hay (null sin «Ver montos»).","type":["number","null"]},"billing":{"anyOf":[{"type":"string","enum":["unpriced","to_invoice","unpaid","overdue","paid"],"description":"unpriced = algún ítem sin precio, to_invoice = pendiente de facturar, unpaid = facturado sin cobrar, overdue = factura vencida, paid = cobrado entero."},{"type":"null"}],"description":"Estado de facturación (null sin «Ver montos»)."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"service":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","name","unit"],"additionalProperties":false},"quantity":{"type":"number"},"notes":{"type":"string"},"charge":{"anyOf":[{"type":"object","properties":{"unit_price":{"type":"number","description":"En la moneda del arancel."},"currency":{"type":"string"},"exchange_rate":{"description":"Cotización usada si el arancel está en otra moneda.","type":["number","null"]},"rate_source":{"type":"string","description":"De dónde salió: argentinadatos:oficial o dolarapi:oficial (BNA), argentinadatos:bolsa (MEP), argentinadatos:mayorista, frankfurter:ecb (BCE), importado o manual."},"rate_date":{"type":["string","null"]},"minimum":{"description":"Mínimo por ítem, en la moneda del arancel.","type":["number","null"]},"adjustment_pct":{"type":"number","description":"Descuento (negativo) o recargo (positivo), en %."},"amount":{"type":"number","description":"Importe sin impuesto, en la moneda del laboratorio."},"tax_pct":{"type":"number","description":"Impuesto del ítem, en % (0 si no lleva)."},"tax_amount":{"type":"number"},"total":{"type":"number","description":"Lo que paga el cliente: importe + impuesto."},"amount_override_reason":{"type":"string","description":"Si el importe se cargó a mano, por qué."},"invoice":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"}},"required":["id","number"],"additionalProperties":false},{"type":"null"}],"description":"La factura que lo incluye; null = pendiente de facturar."}},"required":["unit_price","currency","exchange_rate","rate_source","rate_date","minimum","adjustment_pct","amount","tax_pct","tax_amount","total","amount_override_reason","invoice"],"additionalProperties":false},{"type":"null"}],"description":"El monto del ítem (null sin precio o sin «Ver montos»)."}},"required":["id","service","quantity","notes","charge"],"additionalProperties":false}}},"required":["id","code","client","area","contact_name","contact_emails","reference","received_on","status","stage","delivered_on","delivered_by","responsible","notes","custom_fields","amount","billing","created_at","version","items"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/orders/{id}":{"get":{"tags":["Servicios"],"summary":"Ver un pedido","description":"Por id o código (SRV-2026-0001), con sus ítems y, con «Ver montos», sus precios y facturas.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"SRV-2026-0001…"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"contact_name":{"type":"string"},"contact_emails":{"type":"array","items":{"type":"string"},"description":"A quién escribirle."},"reference":{"type":"string","description":"N.º de nota, orden o planilla del cliente."},"received_on":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"stage":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La etapa del laboratorio (si usa etapas); el estado sale de la etapa."},"delivered_on":{"type":["string","null"]},"delivered_by":{"description":"Quién entregó.","type":["string","null"]},"responsible":{"type":["string","null"]},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"amount":{"description":"Total con precio, con impuesto si lo hay (null sin «Ver montos»).","type":["number","null"]},"billing":{"anyOf":[{"type":"string","enum":["unpriced","to_invoice","unpaid","overdue","paid"],"description":"unpriced = algún ítem sin precio, to_invoice = pendiente de facturar, unpaid = facturado sin cobrar, overdue = factura vencida, paid = cobrado entero."},{"type":"null"}],"description":"Estado de facturación (null sin «Ver montos»)."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"service":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","name","unit"],"additionalProperties":false},"quantity":{"type":"number"},"notes":{"type":"string"},"charge":{"anyOf":[{"type":"object","properties":{"unit_price":{"type":"number","description":"En la moneda del arancel."},"currency":{"type":"string"},"exchange_rate":{"description":"Cotización usada si el arancel está en otra moneda.","type":["number","null"]},"rate_source":{"type":"string","description":"De dónde salió: argentinadatos:oficial o dolarapi:oficial (BNA), argentinadatos:bolsa (MEP), argentinadatos:mayorista, frankfurter:ecb (BCE), importado o manual."},"rate_date":{"type":["string","null"]},"minimum":{"description":"Mínimo por ítem, en la moneda del arancel.","type":["number","null"]},"adjustment_pct":{"type":"number","description":"Descuento (negativo) o recargo (positivo), en %."},"amount":{"type":"number","description":"Importe sin impuesto, en la moneda del laboratorio."},"tax_pct":{"type":"number","description":"Impuesto del ítem, en % (0 si no lleva)."},"tax_amount":{"type":"number"},"total":{"type":"number","description":"Lo que paga el cliente: importe + impuesto."},"amount_override_reason":{"type":"string","description":"Si el importe se cargó a mano, por qué."},"invoice":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"}},"required":["id","number"],"additionalProperties":false},{"type":"null"}],"description":"La factura que lo incluye; null = pendiente de facturar."}},"required":["unit_price","currency","exchange_rate","rate_source","rate_date","minimum","adjustment_pct","amount","tax_pct","tax_amount","total","amount_override_reason","invoice"],"additionalProperties":false},{"type":"null"}],"description":"El monto del ítem (null sin precio o sin «Ver montos»)."}},"required":["id","service","quantity","notes","charge"],"additionalProperties":false}}},"required":["id","code","client","area","contact_name","contact_emails","reference","received_on","status","stage","delivered_on","delivered_by","responsible","notes","custom_fields","amount","billing","created_at","version","items"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Servicios"],"summary":"Modificar un pedido","description":"Cambia solo lo que mandás. «status»: delivered registra la entrega (hoy, si no va delivered_on). Si van «items», reemplazan los del pedido (los facturados no se tocan). Pide la «version».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"client":{"type":"string","minLength":1,"maxLength":200,"description":"Cliente por id, sigla, nombre o CUIT."},"area":{"description":"Área del cliente por nombre o id.","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"received_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día en que llegó. Por defecto, hoy."},"reference":{"type":"string","maxLength":120,"description":"N.º de nota, orden o planilla del cliente."},"contact_name":{"type":"string","maxLength":120,"description":"Quién lo pidió."},"contact_emails":{"description":"A quién escribirle. Si no va al cargarlo, salen del área o del cliente.","maxItems":20,"type":"array","items":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"items":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"service":{"type":"string","minLength":1,"maxLength":120,"description":"Servicio del catálogo: id, código o nombre."},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":100000000},"notes":{"type":"string","maxLength":500,"description":"Nota del ítem (muestras, detalle)."},"unit_price":{"description":"Precio unitario (pide «Facturar y cobrar»). Si no va, sale del catálogo: la lista del cliente o la general. null lo deja sin precio.","anyOf":[{"type":"number","minimum":0,"maximum":10000000000},{"type":"null"}]},"currency":{"description":"Moneda del precio. Por defecto, la del catálogo o la del laboratorio.","type":"string","pattern":"^[A-Z]{3}$"},"adjustment_pct":{"description":"Descuento (negativo, -10 = 10 % menos) o recargo (positivo, 50 = 50 % más) sobre el ítem. Pide «Facturar y cobrar».","type":"number","minimum":-100,"maximum":1000}},"required":["service","quantity"]}},"exchange_rate":{"description":"Cotización para los precios en otra moneda. Si no va, se trae sola con la fuente que eligió el laboratorio (por defecto, dólar oficial vendedor del BNA para pesos y la referencia del BCE para otras monedas).","type":"number","exclusiveMinimum":0},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"status":{"description":"received, in_progress, delivered (con delivered_on) o cancelled.","type":"string","enum":["received","in_progress","delivered","cancelled"]},"delivered_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día de la entrega. Por defecto, hoy al entregar."},"delivered_by_name":{"type":"string","maxLength":80,"description":"Quién entregó, si no usa Vialo."},"stage":{"description":"Etapa del laboratorio por nombre o id (si usa etapas): el estado sale de la etapa.","type":"string","minLength":1,"maxLength":60}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"SRV-2026-0001…"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"contact_name":{"type":"string"},"contact_emails":{"type":"array","items":{"type":"string"},"description":"A quién escribirle."},"reference":{"type":"string","description":"N.º de nota, orden o planilla del cliente."},"received_on":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"stage":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La etapa del laboratorio (si usa etapas); el estado sale de la etapa."},"delivered_on":{"type":["string","null"]},"delivered_by":{"description":"Quién entregó.","type":["string","null"]},"responsible":{"type":["string","null"]},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"amount":{"description":"Total con precio, con impuesto si lo hay (null sin «Ver montos»).","type":["number","null"]},"billing":{"anyOf":[{"type":"string","enum":["unpriced","to_invoice","unpaid","overdue","paid"],"description":"unpriced = algún ítem sin precio, to_invoice = pendiente de facturar, unpaid = facturado sin cobrar, overdue = factura vencida, paid = cobrado entero."},{"type":"null"}],"description":"Estado de facturación (null sin «Ver montos»)."},"created_at":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"service":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"unit":{"type":"string"}},"required":["id","name","unit"],"additionalProperties":false},"quantity":{"type":"number"},"notes":{"type":"string"},"charge":{"anyOf":[{"type":"object","properties":{"unit_price":{"type":"number","description":"En la moneda del arancel."},"currency":{"type":"string"},"exchange_rate":{"description":"Cotización usada si el arancel está en otra moneda.","type":["number","null"]},"rate_source":{"type":"string","description":"De dónde salió: argentinadatos:oficial o dolarapi:oficial (BNA), argentinadatos:bolsa (MEP), argentinadatos:mayorista, frankfurter:ecb (BCE), importado o manual."},"rate_date":{"type":["string","null"]},"minimum":{"description":"Mínimo por ítem, en la moneda del arancel.","type":["number","null"]},"adjustment_pct":{"type":"number","description":"Descuento (negativo) o recargo (positivo), en %."},"amount":{"type":"number","description":"Importe sin impuesto, en la moneda del laboratorio."},"tax_pct":{"type":"number","description":"Impuesto del ítem, en % (0 si no lleva)."},"tax_amount":{"type":"number"},"total":{"type":"number","description":"Lo que paga el cliente: importe + impuesto."},"amount_override_reason":{"type":"string","description":"Si el importe se cargó a mano, por qué."},"invoice":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"}},"required":["id","number"],"additionalProperties":false},{"type":"null"}],"description":"La factura que lo incluye; null = pendiente de facturar."}},"required":["unit_price","currency","exchange_rate","rate_source","rate_date","minimum","adjustment_pct","amount","tax_pct","tax_amount","total","amount_override_reason","invoice"],"additionalProperties":false},{"type":"null"}],"description":"El monto del ítem (null sin precio o sin «Ver montos»)."}},"required":["id","service","quantity","notes","charge"],"additionalProperties":false}}},"required":["id","code","client","area","contact_name","contact_emails","reference","received_on","status","stage","delivered_on","delivered_by","responsible","notes","custom_fields","amount","billing","created_at","version","items"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/orders/{id}/history":{"get":{"tags":["Servicios"],"summary":"Historial de un pedido","description":"","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/to-invoice":{"get":{"tags":["Servicios"],"summary":"Para facturar","description":"Los ítems con precio que todavía no están en una factura, por cliente (pide «Ver montos»). Los pedidos cancelados no aparecen.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"total":{"type":"number","description":"Con el impuesto, si lo hay."},"lines":{"type":"array","items":{"type":"object","properties":{"charge_id":{"type":"string","description":"Identificador (UUID)."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"area":{"type":["string","null"]},"service":{"type":"string"},"quantity":{"type":"number"},"amount":{"type":"number","description":"Sin impuesto."},"total":{"type":"number","description":"Con el impuesto."},"delivered":{"type":"boolean"},"delivered_on":{"type":["string","null"]}},"required":["charge_id","order","area","service","quantity","amount","total","delivered","delivered_on"],"additionalProperties":false}}},"required":["client","total","lines"],"additionalProperties":false}},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/invoices":{"get":{"tags":["Servicios"],"summary":"Facturas","description":"Las facturas con su total, lo cobrado y el estado (pide «Ver montos»).","parameters":[{"name":"status","in":"query","required":false,"description":"open (por defecto) = sin cobrar entera (issued, partial u overdue).","schema":{"default":"open","description":"open (por defecto) = sin cobrar entera (issued, partial u overdue).","type":"string","enum":["open","issued","partial","paid","overdue","cancelled","all"]}},{"name":"client","in":"query","required":false,"description":"Cliente por id, sigla, nombre o CUIT.","schema":{"description":"Cliente por id, sigla, nombre o CUIT.","type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"issued_on":{"type":"string"},"due_on":{"type":["string","null"]},"total":{"type":"number"},"paid":{"type":"number"},"status":{"type":"string","enum":["issued","partial","paid","overdue","cancelled"],"description":"issued = sin cobrar, partial = cobrada en parte, paid = cobrada, overdue = vencida sin cobrar entera, cancelled = anulada."},"notes":{"type":"string"},"cancel_reason":{"type":"string"},"budget_account_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"Cuenta del presupuesto donde entran sus cobros (módulo Presupuesto); null: no entran."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","number","client","issued_on","due_on","total","paid","status","notes","cancel_reason","budget_account_id","version"],"additionalProperties":false}},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Crear una factura","description":"Con los ítems con precio y sin facturar de los pedidos que mandás (de un mismo cliente). La factura se emite afuera; acá se anota el número. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"orders":{"minItems":1,"maxItems":200,"type":"array","items":{"type":"string","minLength":1,"maxLength":60},"description":"Pedidos a facturar por código o id: entran sus ítems con precio que no están facturados. Todos del mismo cliente."},"number":{"type":"string","maxLength":60,"description":"N.º de la factura emitida."},"issued_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha de la factura. Por defecto, hoy."},"due_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Vencimiento. Por defecto, 30 días después."},"notes":{"type":"string","maxLength":1000,"description":"Notas."},"budget_account":{"description":"Cuenta del presupuesto (nombre, código o id) donde entran sus cobros. Por defecto, la de sus servicios si todos van a la misma, si no la que recibe los cobros de Servicios; null: ninguna.","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]}},"required":["orders"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"issued_on":{"type":"string"},"due_on":{"type":["string","null"]},"total":{"type":"number"},"paid":{"type":"number"},"status":{"type":"string","enum":["issued","partial","paid","overdue","cancelled"],"description":"issued = sin cobrar, partial = cobrada en parte, paid = cobrada, overdue = vencida sin cobrar entera, cancelled = anulada."},"notes":{"type":"string"},"cancel_reason":{"type":"string"},"budget_account_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"Cuenta del presupuesto donde entran sus cobros (módulo Presupuesto); null: no entran."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"array","items":{"type":"object","properties":{"charge_id":{"type":"string","description":"Identificador (UUID)."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"area":{"type":["string","null"]},"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"exchange_rate":{"type":["number","null"]},"amount":{"type":"number","description":"Sin impuesto."},"tax_amount":{"type":"number"},"total":{"type":"number"}},"required":["charge_id","order","area","service","quantity","unit_price","currency","exchange_rate","amount","tax_amount","total"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"received_on":{"type":"string"},"amount":{"type":"number"},"method":{"type":"string"},"reference":{"type":"string"},"notes":{"type":"string"}},"required":["id","received_on","amount","method","reference","notes"],"additionalProperties":false}},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto de sus cobros, con su nombre."},"summary":{"type":"string","description":"El texto para pegar en el sistema donde se emite la factura, con el formato que eligió el laboratorio (por defecto «Genotipificación x16 $290.880 · … · USD BNA $1.515»)."},"summary_ok":{"type":"boolean","description":"false si algún importe no cierra con su fórmula (cantidad × precio, el mínimo, el ajuste y la cotización)."}},"required":["id","number","client","issued_on","due_on","total","paid","status","notes","cancel_reason","budget_account_id","version","lines","payments","budget_account","summary","summary_ok"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/invoices/{id}":{"get":{"tags":["Servicios"],"summary":"Ver una factura","description":"Por id o número, con sus ítems, sus cobros y el resumen para pegar en el sistema donde se emite (pide «Ver montos»).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"issued_on":{"type":"string"},"due_on":{"type":["string","null"]},"total":{"type":"number"},"paid":{"type":"number"},"status":{"type":"string","enum":["issued","partial","paid","overdue","cancelled"],"description":"issued = sin cobrar, partial = cobrada en parte, paid = cobrada, overdue = vencida sin cobrar entera, cancelled = anulada."},"notes":{"type":"string"},"cancel_reason":{"type":"string"},"budget_account_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"Cuenta del presupuesto donde entran sus cobros (módulo Presupuesto); null: no entran."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"array","items":{"type":"object","properties":{"charge_id":{"type":"string","description":"Identificador (UUID)."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"area":{"type":["string","null"]},"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"exchange_rate":{"type":["number","null"]},"amount":{"type":"number","description":"Sin impuesto."},"tax_amount":{"type":"number"},"total":{"type":"number"}},"required":["charge_id","order","area","service","quantity","unit_price","currency","exchange_rate","amount","tax_amount","total"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"received_on":{"type":"string"},"amount":{"type":"number"},"method":{"type":"string"},"reference":{"type":"string"},"notes":{"type":"string"}},"required":["id","received_on","amount","method","reference","notes"],"additionalProperties":false}},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto de sus cobros, con su nombre."},"summary":{"type":"string","description":"El texto para pegar en el sistema donde se emite la factura, con el formato que eligió el laboratorio (por defecto «Genotipificación x16 $290.880 · … · USD BNA $1.515»)."},"summary_ok":{"type":"boolean","description":"false si algún importe no cierra con su fórmula (cantidad × precio, el mínimo, el ajuste y la cotización)."}},"required":["id","number","client","issued_on","due_on","total","paid","status","notes","cancel_reason","budget_account_id","version","lines","payments","budget_account","summary","summary_ok"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Servicios"],"summary":"Modificar o anular una factura","description":"Número, fechas o notas; «cancel» la anula (sin cobros). Pide «Facturar y cobrar» y la «version».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"number":{"type":"string","maxLength":60,"description":"N.º de factura."},"issued_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha."},"due_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Vencimiento."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."},"budget_account":{"description":"Cuenta del presupuesto (nombre, código o id); null: ninguna. Solo sin cobros.","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"cancel":{"description":"true la anula (sin cobros): sus ítems vuelven a «Para facturar».","type":"boolean"},"cancel_reason":{"type":"string","maxLength":300,"description":"Por qué se anula."}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"issued_on":{"type":"string"},"due_on":{"type":["string","null"]},"total":{"type":"number"},"paid":{"type":"number"},"status":{"type":"string","enum":["issued","partial","paid","overdue","cancelled"],"description":"issued = sin cobrar, partial = cobrada en parte, paid = cobrada, overdue = vencida sin cobrar entera, cancelled = anulada."},"notes":{"type":"string"},"cancel_reason":{"type":"string"},"budget_account_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"Cuenta del presupuesto donde entran sus cobros (módulo Presupuesto); null: no entran."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"array","items":{"type":"object","properties":{"charge_id":{"type":"string","description":"Identificador (UUID)."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"area":{"type":["string","null"]},"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"exchange_rate":{"type":["number","null"]},"amount":{"type":"number","description":"Sin impuesto."},"tax_amount":{"type":"number"},"total":{"type":"number"}},"required":["charge_id","order","area","service","quantity","unit_price","currency","exchange_rate","amount","tax_amount","total"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"received_on":{"type":"string"},"amount":{"type":"number"},"method":{"type":"string"},"reference":{"type":"string"},"notes":{"type":"string"}},"required":["id","received_on","amount","method","reference","notes"],"additionalProperties":false}},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto de sus cobros, con su nombre."},"summary":{"type":"string","description":"El texto para pegar en el sistema donde se emite la factura, con el formato que eligió el laboratorio (por defecto «Genotipificación x16 $290.880 · … · USD BNA $1.515»)."},"summary_ok":{"type":"boolean","description":"false si algún importe no cierra con su fórmula (cantidad × precio, el mínimo, el ajuste y la cotización)."}},"required":["id","number","client","issued_on","due_on","total","paid","status","notes","cancel_reason","budget_account_id","version","lines","payments","budget_account","summary","summary_ok"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/catalog/{id}/prices":{"post":{"tags":["Servicios"],"summary":"Cargar un precio","description":"Un precio nuevo desde una fecha (el historial queda). Pide «Facturar y cobrar». Los pedidos ya cargados conservan el suyo.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"unit_price":{"type":"number","minimum":0,"maximum":10000000000,"description":"Precio por unidad del servicio."},"currency":{"type":"string","pattern":"^[A-Z]{3}$","description":"Moneda ISO (ARS, USD…)."},"valid_from":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde cuándo vale. Por defecto, hoy."},"price_list":{"description":"Lista por nombre; null = la general.","anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"min_quantity":{"description":"Precio por volumen: desde cuántas unidades vale. Para varios tramos, un precio por tramo con la misma fecha (0, 10, 100…).","type":"number","minimum":0,"maximum":1000000000},"minimum":{"description":"Lo mínimo que se cobra por ítem, en la moneda del precio.","anyOf":[{"type":"number","minimum":0,"maximum":10000000000},{"type":"null"}]},"notes":{"type":"string","maxLength":300,"description":"Nota."}},"required":["unit_price","currency"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string","description":"Código propio u oficial (puede estar vacío)."},"name":{"type":"string"},"category":{"type":"string"},"unit":{"type":"string","description":"En qué se cuenta: reacción, muestra, hora…"},"description":{"type":"string"},"tax_pct":{"description":"Impuesto propio del servicio, en %; null = el habitual del laboratorio (si cobra impuestos).","type":["number","null"]},"archived":{"type":"boolean"},"prices":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"price_list":{"description":"Nombre de la lista de precios; null = la general.","type":["string","null"]},"unit_price":{"type":"number"},"currency":{"type":"string","description":"Moneda del arancel (ISO: ARS, USD…)."},"valid_from":{"type":"string","description":"Desde cuándo vale (AAAA-MM-DD)."},"min_quantity":{"type":"number","description":"Precio por volumen: desde cuántas unidades vale (0 = desde la primera)."},"minimum":{"description":"Lo mínimo que se cobra por ítem, en la moneda del precio.","type":["number","null"]},"notes":{"type":"string"}},"required":["id","price_list","unit_price","currency","valid_from","min_quantity","minimum","notes"],"additionalProperties":false}},{"type":"null"}],"description":"Precios vigentes y futuros por lista (null sin «Ver montos»). El vigente de cada lista es el de mayor valid_from que ya empezó; con precios por volumen, el de mayor min_quantity que alcanza la cantidad."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","category","unit","description","tax_pct","archived","prices","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/invoices/{id}/payments":{"post":{"tags":["Servicios"],"summary":"Registrar un cobro","description":"Un cobro de la factura (puede ser parcial; no se pasa del total). Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"amount":{"type":"number","exclusiveMinimum":0,"maximum":1000000000000},"received_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día del cobro. Por defecto, hoy."},"method":{"type":"string","maxLength":60,"description":"Medio: transferencia, cheque…"},"reference":{"type":"string","maxLength":120,"description":"N.º de transferencia u otra referencia."},"notes":{"type":"string","maxLength":500,"description":"Notas."}},"required":["amount"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"number":{"type":"string"},"client":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"issued_on":{"type":"string"},"due_on":{"type":["string","null"]},"total":{"type":"number"},"paid":{"type":"number"},"status":{"type":"string","enum":["issued","partial","paid","overdue","cancelled"],"description":"issued = sin cobrar, partial = cobrada en parte, paid = cobrada, overdue = vencida sin cobrar entera, cancelled = anulada."},"notes":{"type":"string"},"cancel_reason":{"type":"string"},"budget_account_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"Cuenta del presupuesto donde entran sus cobros (módulo Presupuesto); null: no entran."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"lines":{"type":"array","items":{"type":"object","properties":{"charge_id":{"type":"string","description":"Identificador (UUID)."},"order":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},"area":{"type":["string","null"]},"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"exchange_rate":{"type":["number","null"]},"amount":{"type":"number","description":"Sin impuesto."},"tax_amount":{"type":"number"},"total":{"type":"number"}},"required":["charge_id","order","area","service","quantity","unit_price","currency","exchange_rate","amount","tax_amount","total"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"received_on":{"type":"string"},"amount":{"type":"number"},"method":{"type":"string"},"reference":{"type":"string"},"notes":{"type":"string"}},"required":["id","received_on","amount","method","reference","notes"],"additionalProperties":false}},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto de sus cobros, con su nombre."},"summary":{"type":"string","description":"El texto para pegar en el sistema donde se emite la factura, con el formato que eligió el laboratorio (por defecto «Genotipificación x16 $290.880 · … · USD BNA $1.515»)."},"summary_ok":{"type":"boolean","description":"false si algún importe no cierra con su fórmula (cantidad × precio, el mínimo, el ajuste y la cotización)."}},"required":["id","number","client","issued_on","due_on","total","paid","status","notes","cancel_reason","budget_account_id","version","lines","payments","budget_account","summary","summary_ok"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/balance":{"get":{"tags":["Servicios"],"summary":"Balance","description":"Lo facturado, lo cobrado, lo pendiente de cobro, cada deducción del reparto y el neto del período, por servicio, cliente, tipo de cliente o mes, con filtros de mes, servicio, cliente y tipo de cliente; por servicio o por mes, también los egresos imputados de Presupuesto y el saldo (pide «Ver montos»).","parameters":[{"name":"year","in":"query","required":false,"description":"Año (AAAA). Por defecto, el actual.","schema":{"description":"Año (AAAA). Por defecto, el actual.","type":"string","pattern":"^\\d{4}$"}},{"name":"from","in":"query","required":false,"description":"Desde (fecha de cobro). Si va, manda sobre «year».","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde (fecha de cobro). Si va, manda sobre «year»."}},{"name":"to","in":"query","required":false,"description":"Hasta (fecha de cobro). Por defecto, hoy.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta (fecha de cobro). Por defecto, hoy."}},{"name":"month","in":"query","required":false,"description":"Un mes (AAAA-MM) dentro del período: achica las cifras a ese mes.","schema":{"description":"Un mes (AAAA-MM) dentro del período: achica las cifras a ese mes.","type":"string","pattern":"^\\d{4}-\\d{2}$"}},{"name":"service","in":"query","required":false,"description":"Solo este servicio (id, código o nombre).","schema":{"description":"Solo este servicio (id, código o nombre).","type":"string","maxLength":120}},{"name":"client","in":"query","required":false,"description":"Solo este cliente (id o nombre). Sin egresos.","schema":{"description":"Solo este cliente (id o nombre). Sin egresos.","type":"string","maxLength":200}},{"name":"client_kind","in":"query","required":false,"description":"Solo este tipo de cliente (public_institution, company, individual, internal, other). Sin egresos.","schema":{"description":"Solo este tipo de cliente (public_institution, company, individual, internal, other). Sin egresos.","type":"string","enum":["public_institution","company","individual","internal","other"]}},{"name":"group_by","in":"query","required":false,"description":"service (por defecto), client, client_kind o month.","schema":{"default":"service","description":"service (por defecto), client, client_kind o month.","type":"string","enum":["service","client","client_kind","month"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Id del servicio o del cliente, el tipo de cliente, o el mes (AAAA-MM)."},"label":{"type":"string"},"units":{"type":"number","description":"Unidades facturadas (reacciones, muestras…)."},"invoiced":{"type":"number","description":"Lo facturado (sin impuesto, sin anuladas)."},"collected":{"type":"number","description":"Lo cobrado."},"pending":{"type":"number","description":"Lo que falta cobrar de lo facturado en el período."},"deductions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"amount":{"type":"number"}},"required":["name","amount"],"additionalProperties":false},"description":"Cada deducción del reparto, en el orden de la cadena."},"net":{"type":"number","description":"Lo cobrado menos las deducciones."},"expenses":{"description":"Egresos de Presupuesto imputados (solo por servicio o por mes, con Presupuesto y sin filtro de cliente).","type":["number","null"]},"balance":{"description":"Neto menos egresos.","type":["number","null"]}},"required":["key","label","units","invoiced","collected","pending","deductions","net","expenses","balance"],"additionalProperties":false}},"total":{"type":"object","properties":{"key":{"type":"string","description":"Id del servicio o del cliente, el tipo de cliente, o el mes (AAAA-MM)."},"label":{"type":"string"},"units":{"type":"number","description":"Unidades facturadas (reacciones, muestras…)."},"invoiced":{"type":"number","description":"Lo facturado (sin impuesto, sin anuladas)."},"collected":{"type":"number","description":"Lo cobrado."},"pending":{"type":"number","description":"Lo que falta cobrar de lo facturado en el período."},"deductions":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"amount":{"type":"number"}},"required":["name","amount"],"additionalProperties":false},"description":"Cada deducción del reparto, en el orden de la cadena."},"net":{"type":"number","description":"Lo cobrado menos las deducciones."},"expenses":{"description":"Egresos de Presupuesto imputados (solo por servicio o por mes, con Presupuesto y sin filtro de cliente).","type":["number","null"]},"balance":{"description":"Neto menos egresos.","type":["number","null"]}},"required":["key","label","units","invoiced","collected","pending","deductions","net","expenses","balance"],"additionalProperties":false},"from":{"type":"string"},"to":{"type":"string"},"currency":{"type":"string"}},"required":["data","total","from","to","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/productivity":{"get":{"tags":["Servicios"],"summary":"Productividad","description":"La productividad cobrada en el período por persona y servicio, con cada cobro. Sin «Ver montos», solo la de la persona del token, si tiene el permiso «Ver su productividad».","parameters":[{"name":"year","in":"query","required":false,"description":"Año (AAAA). Por defecto, el actual.","schema":{"description":"Año (AAAA). Por defecto, el actual.","type":"string","pattern":"^\\d{4}$"}},{"name":"from","in":"query","required":false,"description":"Desde (fecha de cobro). Si va, manda sobre «year».","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde (fecha de cobro). Si va, manda sobre «year»."}},{"name":"to","in":"query","required":false,"description":"Hasta (fecha de cobro). Por defecto, hoy.","schema":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta (fecha de cobro). Por defecto, hoy."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"total":{"type":"number"},"services":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string"},"amount":{"type":"number"}},"required":["service","amount"],"additionalProperties":false}},"payments":{"type":"array","items":{"type":"object","properties":{"received_on":{"type":"string"},"invoice_number":{"type":"string"},"issued_on":{"type":"string"},"service":{"type":"string"},"pct":{"type":"number"},"amount":{"type":"number"}},"required":["received_on","invoice_number","issued_on","service","pct","amount"],"additionalProperties":false}}},"required":["person","total","services","payments"],"additionalProperties":false}},"from":{"type":"string"},"to":{"type":"string"},"currency":{"type":"string"}},"required":["data","from","to","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/invoices/{id}/productivity":{"get":{"tags":["Servicios"],"summary":"Productividad de una factura","description":"Por id o número: lo que le tocó a cada participante de lo cobrado de la factura hasta hoy, por servicio y porcentaje (pide «Ver montos»).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number","description":"Porcentaje del participante (10 = 10 %)."},"amount":{"type":"number"}},"required":["person","service","pct","amount"],"additionalProperties":false}},"total":{"type":"number","description":"La productividad de todos los participantes."},"paid":{"type":"number","description":"Lo cobrado (con impuesto) sobre lo que se calcula."},"invoiced":{"type":"number","description":"Lo facturado (con impuesto, sin anuladas)."},"currency":{"type":"string"}},"required":["data","total","paid","invoiced","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/orders/{id}/productivity":{"get":{"tags":["Servicios"],"summary":"Productividad de un pedido","description":"Por id o código: la parte del pedido en la productividad de cada cobro de sus facturas, en proporción a lo que suma en cada servicio (pide «Ver montos»).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number","description":"Porcentaje del participante (10 = 10 %)."},"amount":{"type":"number"}},"required":["person","service","pct","amount"],"additionalProperties":false}},"total":{"type":"number","description":"La productividad de todos los participantes."},"paid":{"type":"number","description":"Lo cobrado (con impuesto) sobre lo que se calcula."},"invoiced":{"type":"number","description":"Lo facturado (con impuesto, sin anuladas)."},"currency":{"type":"string"}},"required":["data","total","paid","invoiced","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/split":{"get":{"tags":["Servicios"],"summary":"Reparto","description":"La cadena de deducciones (comisión, productividad, amortización…) con todos sus tramos, y los participantes de la productividad de cada servicio (pide «Ver montos»).","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"deductions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"]},"service":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"null: todos los servicios."},"pct":{"description":"Porcentaje (10 = 10 %). null en la productividad y en el recupero de fondos.","type":["number","null"]},"amount":{"description":"Monto fijo por factura y servicio, en la moneda del laboratorio. Solo el recupero de fondos.","type":["number","null"]},"base":{"type":"string","enum":["gross","remaining"],"description":"gross: sobre lo cobrado; remaining: sobre lo que queda (sin efecto en el recupero de fondos)."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_kinds":{"anyOf":[{"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}],"description":"Tipos de cliente a los que se aplica (public_institution, company, individual, internal, other); null: a todos."},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto a la que va lo deducido (entra como ingreso aparte); null: sale del laboratorio y se descuenta del ingreso del cobro."},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","name","kind","service","pct","amount","base","position","client_kinds","budget_account","valid_from","valid_to","notes"],"additionalProperties":false}},"participants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number"},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","service","person","pct","valid_from","valid_to","notes"],"additionalProperties":false}}},"required":["deductions","participants"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/split/deductions":{"post":{"tags":["Servicios"],"summary":"Agregar una deducción al reparto","description":"Un tramo nuevo de una deducción. Dos tramos de la misma deducción no se superponen. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"Nombre (Comisión institucional, Amortización…)."},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"],"description":"fee, productivity, amortization, recovery (recupero de fondos: monto fijo que se descuenta antes de la productividad, solo a servicios que tienen productividad) u other."},"service":{"description":"Servicio (id, código o nombre); sin él, todos.","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"pct":{"description":"Porcentaje; no va en la productividad (es la suma de sus participantes) ni en el recupero de fondos (lleva «amount»).","type":"number","exclusiveMinimum":0,"maximum":100},"amount":{"description":"Monto fijo por factura y servicio; solo en el recupero de fondos (kind recovery).","type":"number","exclusiveMinimum":0,"maximum":1000000000},"base":{"default":"gross","type":"string","enum":["gross","remaining"]},"position":{"type":"integer","minimum":0,"maximum":99,"description":"Paso en la cadena."},"client_kinds":{"description":"Solo para estos tipos de cliente (por ejemplo, sin «internal» para que los internos no paguen comisión). Sin esto, para todos.","anyOf":[{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}]},"budget_account":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Cuenta del presupuesto (id, nombre o código) a la que va lo deducido; null o sin ella, sale del laboratorio."},"valid_from":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde (fecha de factura o de cobro, según la configuración del laboratorio)."},"valid_to":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta."},{"type":"null"}]},"notes":{"type":"string","maxLength":300,"description":"Notas."}},"required":["name","kind","position","valid_from"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"deductions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"]},"service":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"null: todos los servicios."},"pct":{"description":"Porcentaje (10 = 10 %). null en la productividad y en el recupero de fondos.","type":["number","null"]},"amount":{"description":"Monto fijo por factura y servicio, en la moneda del laboratorio. Solo el recupero de fondos.","type":["number","null"]},"base":{"type":"string","enum":["gross","remaining"],"description":"gross: sobre lo cobrado; remaining: sobre lo que queda (sin efecto en el recupero de fondos)."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_kinds":{"anyOf":[{"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}],"description":"Tipos de cliente a los que se aplica (public_institution, company, individual, internal, other); null: a todos."},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto a la que va lo deducido (entra como ingreso aparte); null: sale del laboratorio y se descuenta del ingreso del cobro."},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","name","kind","service","pct","amount","base","position","client_kinds","budget_account","valid_from","valid_to","notes"],"additionalProperties":false}},"participants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number"},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","service","person","pct","valid_from","valid_to","notes"],"additionalProperties":false}}},"required":["deductions","participants"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/split/deductions/{id}/account":{"patch":{"tags":["Servicios"],"summary":"Elegir adónde va una deducción","description":"La cuenta del presupuesto a la que va lo deducido: entra como ingreso aparte en esa cuenta en vez de salir del laboratorio (por ejemplo, la amortización en una subcuenta). No cambia el reparto, así que vale también para tramos ya aplicados: los ingresos se recalculan. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"budget_account":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Cuenta del presupuesto (id, nombre o código) a la que va lo deducido; null o sin ella, sale del laboratorio."}},"required":["budget_account"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"deductions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"]},"service":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"null: todos los servicios."},"pct":{"description":"Porcentaje (10 = 10 %). null en la productividad y en el recupero de fondos.","type":["number","null"]},"amount":{"description":"Monto fijo por factura y servicio, en la moneda del laboratorio. Solo el recupero de fondos.","type":["number","null"]},"base":{"type":"string","enum":["gross","remaining"],"description":"gross: sobre lo cobrado; remaining: sobre lo que queda (sin efecto en el recupero de fondos)."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_kinds":{"anyOf":[{"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}],"description":"Tipos de cliente a los que se aplica (public_institution, company, individual, internal, other); null: a todos."},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto a la que va lo deducido (entra como ingreso aparte); null: sale del laboratorio y se descuenta del ingreso del cobro."},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","name","kind","service","pct","amount","base","position","client_kinds","budget_account","valid_from","valid_to","notes"],"additionalProperties":false}},"participants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number"},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","service","person","pct","valid_from","valid_to","notes"],"additionalProperties":false}}},"required":["deductions","participants"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/split/participants":{"post":{"tags":["Servicios"],"summary":"Agregar un participante de la productividad","description":"Quién cobra productividad de un servicio, con su porcentaje y desde cuándo. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"service":{"type":"string","minLength":1,"maxLength":120,"description":"Servicio (id, código o nombre)."},"person":{"description":"Persona del laboratorio (id, email o nombre).","type":"string","maxLength":200},"external_name":{"type":"string","maxLength":120,"description":"Nombre de alguien que no usa Vialo."},"pct":{"type":"number","exclusiveMinimum":0,"maximum":100},"valid_from":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde (fecha de factura)."},"valid_to":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Hasta."},{"type":"null"}]},"notes":{"type":"string","maxLength":300,"description":"Notas."}},"required":["service","pct","valid_from"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"deductions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"]},"service":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"null: todos los servicios."},"pct":{"description":"Porcentaje (10 = 10 %). null en la productividad y en el recupero de fondos.","type":["number","null"]},"amount":{"description":"Monto fijo por factura y servicio, en la moneda del laboratorio. Solo el recupero de fondos.","type":["number","null"]},"base":{"type":"string","enum":["gross","remaining"],"description":"gross: sobre lo cobrado; remaining: sobre lo que queda (sin efecto en el recupero de fondos)."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_kinds":{"anyOf":[{"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}],"description":"Tipos de cliente a los que se aplica (public_institution, company, individual, internal, other); null: a todos."},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto a la que va lo deducido (entra como ingreso aparte); null: sale del laboratorio y se descuenta del ingreso del cobro."},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","name","kind","service","pct","amount","base","position","client_kinds","budget_account","valid_from","valid_to","notes"],"additionalProperties":false}},"participants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number"},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","service","person","pct","valid_from","valid_to","notes"],"additionalProperties":false}}},"required":["deductions","participants"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/split/deductions/{id}/change":{"post":{"tags":["Servicios"],"summary":"Cambiar una deducción desde una fecha","description":"Cambio de régimen: el tramo vigente termina el día anterior a «from» y empieza otro con el porcentaje nuevo. Lo ya cobrado no cambia. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"from":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde cuándo vale el nuevo tramo (fecha de factura)."},"pct":{"description":"Porcentaje nuevo (no va en la productividad ni en el recupero de fondos).","type":"number","exclusiveMinimum":0,"maximum":100},"amount":{"description":"Monto nuevo (solo el recupero de fondos).","type":"number","exclusiveMinimum":0,"maximum":1000000000}},"required":["from"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"deductions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"]},"service":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"null: todos los servicios."},"pct":{"description":"Porcentaje (10 = 10 %). null en la productividad y en el recupero de fondos.","type":["number","null"]},"amount":{"description":"Monto fijo por factura y servicio, en la moneda del laboratorio. Solo el recupero de fondos.","type":["number","null"]},"base":{"type":"string","enum":["gross","remaining"],"description":"gross: sobre lo cobrado; remaining: sobre lo que queda (sin efecto en el recupero de fondos)."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_kinds":{"anyOf":[{"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}],"description":"Tipos de cliente a los que se aplica (public_institution, company, individual, internal, other); null: a todos."},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto a la que va lo deducido (entra como ingreso aparte); null: sale del laboratorio y se descuenta del ingreso del cobro."},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","name","kind","service","pct","amount","base","position","client_kinds","budget_account","valid_from","valid_to","notes"],"additionalProperties":false}},"participants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number"},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","service","person","pct","valid_from","valid_to","notes"],"additionalProperties":false}}},"required":["deductions","participants"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/split/participants/{id}/change":{"post":{"tags":["Servicios"],"summary":"Cambiar el porcentaje de un participante desde una fecha","description":"Cambio de régimen: el tramo vigente termina el día anterior a «from» y empieza otro con el porcentaje nuevo. Lo ya cobrado no cambia. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"from":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Desde cuándo vale el nuevo tramo (fecha de factura)."},"pct":{"description":"Porcentaje nuevo (no va en la productividad ni en el recupero de fondos).","type":"number","exclusiveMinimum":0,"maximum":100},"amount":{"description":"Monto nuevo (solo el recupero de fondos).","type":"number","exclusiveMinimum":0,"maximum":1000000000}},"required":["from"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"deductions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["fee","productivity","amortization","recovery","other"]},"service":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"null: todos los servicios."},"pct":{"description":"Porcentaje (10 = 10 %). null en la productividad y en el recupero de fondos.","type":["number","null"]},"amount":{"description":"Monto fijo por factura y servicio, en la moneda del laboratorio. Solo el recupero de fondos.","type":["number","null"]},"base":{"type":"string","enum":["gross","remaining"],"description":"gross: sobre lo cobrado; remaining: sobre lo que queda (sin efecto en el recupero de fondos)."},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"client_kinds":{"anyOf":[{"type":"array","items":{"type":"string","enum":["public_institution","company","individual","internal","other"]}},{"type":"null"}],"description":"Tipos de cliente a los que se aplica (public_institution, company, individual, internal, other); null: a todos."},"budget_account":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}],"description":"La cuenta del presupuesto a la que va lo deducido (entra como ingreso aparte); null: sale del laboratorio y se descuenta del ingreso del cobro."},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","name","kind","service","pct","amount","base","position","client_kinds","budget_account","valid_from","valid_to","notes"],"additionalProperties":false}},"participants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"service":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"person":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"pct":{"type":"number"},"valid_from":{"type":"string"},"valid_to":{"type":["string","null"]},"notes":{"type":"string"}},"required":["id","service","person","pct","valid_from","valid_to","notes"],"additionalProperties":false}}},"required":["deductions","participants"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/quotes":{"get":{"tags":["Servicios"],"summary":"Cotizaciones","description":"Las cotizaciones a clientes con su total y su estado (pide «Ver montos»).","parameters":[{"name":"status","in":"query","required":false,"description":"open (por defecto: borrador, enviada o vencida), un estado o all.","schema":{"default":"open","description":"open (por defecto: borrador, enviada o vencida), un estado o all.","type":"string","enum":["open","draft","sent","expired","accepted","rejected","all"]}},{"name":"client","in":"query","required":false,"description":"Cliente: sigla, nombre o CUIT.","schema":{"description":"Cliente: sigla, nombre o CUIT.","type":"string","maxLength":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"COT-2026-0001."},"client":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"type":["string","null"]},"contact_name":{"type":"string"},"issued_on":{"type":"string"},"valid_until":{"type":["string","null"]},"status":{"type":"string","enum":["draft","sent","expired","accepted","rejected"],"description":"draft (borrador), sent (enviada), expired (vencida sin respuesta), accepted o rejected."},"total":{"type":"number","description":"Con el impuesto, si lo hay, en la moneda del laboratorio."},"order":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"El pedido que se creó al aceptarla."},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","client","area","contact_name","issued_on","valid_until","status","total","order","notes","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Crear una cotización","description":"Para un cliente, con sus servicios: si no mandás el precio, sale del catálogo (de la lista del cliente si tiene). Queda en borrador. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"client":{"type":"string","minLength":1,"maxLength":200,"description":"Cliente: id, sigla, nombre o CUIT."},"area":{"description":"Área del cliente.","anyOf":[{"type":"string","maxLength":120},{"type":"null"}]},"contact_name":{"type":"string","maxLength":120,"description":"Contacto."},"issued_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha. Por defecto, hoy."},"valid_until":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Vale hasta. Por defecto, 30 días después."},{"type":"null"}]},"items":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"service":{"type":"string","minLength":1,"maxLength":120,"description":"Servicio del catálogo: id, código o nombre."},"quantity":{"type":"number","exclusiveMinimum":0,"maximum":100000000},"notes":{"type":"string","maxLength":500,"description":"Nota del ítem (muestras, detalle)."},"unit_price":{"description":"Precio unitario (pide «Facturar y cobrar»). Si no va, sale del catálogo: la lista del cliente o la general. null lo deja sin precio.","anyOf":[{"type":"number","minimum":0,"maximum":10000000000},{"type":"null"}]},"currency":{"description":"Moneda del precio. Por defecto, la del catálogo o la del laboratorio.","type":"string","pattern":"^[A-Z]{3}$"},"adjustment_pct":{"description":"Descuento (negativo, -10 = 10 % menos) o recargo (positivo, 50 = 50 % más) sobre el ítem. Pide «Facturar y cobrar».","type":"number","minimum":-100,"maximum":1000}},"required":["service","quantity"]}},"exchange_rate":{"description":"Cotización a la moneda del laboratorio, si algún precio está en otra. Sin ella, se trae la del día.","type":"number","exclusiveMinimum":0},"notes":{"type":"string","maxLength":2000,"description":"Condiciones y observaciones (van impresas)."}},"required":["client","items"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"COT-2026-0001."},"client":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"type":["string","null"]},"contact_name":{"type":"string"},"issued_on":{"type":"string"},"valid_until":{"type":["string","null"]},"status":{"type":"string","enum":["draft","sent","expired","accepted","rejected"],"description":"draft (borrador), sent (enviada), expired (vencida sin respuesta), accepted o rejected."},"total":{"type":"number","description":"Con el impuesto, si lo hay, en la moneda del laboratorio."},"order":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"El pedido que se creó al aceptarla."},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"items":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"minimum":{"description":"Mínimo por ítem, en la moneda del precio.","type":["number","null"]},"adjustment_pct":{"type":"number","description":"Descuento (negativo) o recargo (positivo), en %."},"amount":{"type":"number","description":"Sin impuesto."},"tax_pct":{"type":"number"},"tax_amount":{"type":"number"},"notes":{"type":"string"}},"required":["service","quantity","unit_price","currency","minimum","adjustment_pct","amount","tax_pct","tax_amount","notes"],"additionalProperties":false}},"exchange_rate":{"type":["number","null"]},"rate_source":{"type":"string"},"rate_date":{"type":["string","null"]}},"required":["id","code","client","area","contact_name","issued_on","valid_until","status","total","order","notes","version","items","exchange_rate","rate_source","rate_date"],"additionalProperties":false},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/quotes/{id}":{"get":{"tags":["Servicios"],"summary":"Ver una cotización","description":"Por id o código (COT-2026-0001), con sus ítems y la cotización del dólar usada (pide «Ver montos»).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"COT-2026-0001."},"client":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"type":["string","null"]},"contact_name":{"type":"string"},"issued_on":{"type":"string"},"valid_until":{"type":["string","null"]},"status":{"type":"string","enum":["draft","sent","expired","accepted","rejected"],"description":"draft (borrador), sent (enviada), expired (vencida sin respuesta), accepted o rejected."},"total":{"type":"number","description":"Con el impuesto, si lo hay, en la moneda del laboratorio."},"order":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"El pedido que se creó al aceptarla."},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"items":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"minimum":{"description":"Mínimo por ítem, en la moneda del precio.","type":["number","null"]},"adjustment_pct":{"type":"number","description":"Descuento (negativo) o recargo (positivo), en %."},"amount":{"type":"number","description":"Sin impuesto."},"tax_pct":{"type":"number"},"tax_amount":{"type":"number"},"notes":{"type":"string"}},"required":["service","quantity","unit_price","currency","minimum","adjustment_pct","amount","tax_pct","tax_amount","notes"],"additionalProperties":false}},"exchange_rate":{"type":["number","null"]},"rate_source":{"type":"string"},"rate_date":{"type":["string","null"]}},"required":["id","code","client","area","contact_name","issued_on","valid_until","status","total","order","notes","version","items","exchange_rate","rate_source","rate_date"],"additionalProperties":false},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/quotes/{id}/accept":{"post":{"tags":["Servicios"],"summary":"Aceptar una cotización","description":"El cliente la aceptó: se crea el pedido con sus servicios y precios (recibido hoy) y la cotización ya no cambia. Devuelve la cotización con su pedido. Pide «Facturar y cobrar».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"COT-2026-0001."},"client":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"area":{"type":["string","null"]},"contact_name":{"type":"string"},"issued_on":{"type":"string"},"valid_until":{"type":["string","null"]},"status":{"type":"string","enum":["draft","sent","expired","accepted","rejected"],"description":"draft (borrador), sent (enviada), expired (vencida sin respuesta), accepted o rejected."},"total":{"type":"number","description":"Con el impuesto, si lo hay, en la moneda del laboratorio."},"order":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"}},"required":["id","code"],"additionalProperties":false},{"type":"null"}],"description":"El pedido que se creó al aceptarla."},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"items":{"type":"array","items":{"type":"object","properties":{"service":{"type":"string"},"quantity":{"type":"number"},"unit_price":{"type":"number"},"currency":{"type":"string"},"minimum":{"description":"Mínimo por ítem, en la moneda del precio.","type":["number","null"]},"adjustment_pct":{"type":"number","description":"Descuento (negativo) o recargo (positivo), en %."},"amount":{"type":"number","description":"Sin impuesto."},"tax_pct":{"type":"number"},"tax_amount":{"type":"number"},"notes":{"type":"string"}},"required":["service","quantity","unit_price","currency","minimum","adjustment_pct","amount","tax_pct","tax_amount","notes"],"additionalProperties":false}},"exchange_rate":{"type":["number","null"]},"rate_source":{"type":"string"},"rate_date":{"type":["string","null"]}},"required":["id","code","client","area","contact_name","issued_on","valid_until","status","total","order","notes","version","items","exchange_rate","rate_source","rate_date"],"additionalProperties":false},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/settings":{"get":{"tags":["Servicios"],"summary":"Configuración de Servicios","description":"Lo que el laboratorio ajusta: fuente de la cotización, formato del resumen para facturar, impuestos, avisos, condiciones de las cotizaciones, criterio del reparto y si registra muestras.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"rate_source":{"type":"string","enum":["oficial","bolsa","mayorista","ecb","manual"],"description":"De dónde se trae la cotización: oficial (BNA), bolsa (MEP), mayorista (BCRA), ecb (Banco Central Europeo) o manual."},"summary":{"type":"object","properties":{"group":{"type":"string","enum":["area","service"],"description":"Una línea por área del cliente (o servicio) o por servicio."},"line":{"type":"string","description":"Plantilla de cada línea: {label}, {qty}, {unit}, {amount}, {unit_price}."},"separator":{"type":"string"},"rate":{"type":"boolean","description":"Si termina con la cotización usada."}},"required":["group","line","separator","rate"],"additionalProperties":false},"alerts":{"type":"object","properties":{"unbilled_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"quote_expiring_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tier_ending_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["unbilled_days","quote_expiring_days","tier_ending_days"],"additionalProperties":false},"quotes":{"type":"object","properties":{"validity_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"terms":{"type":"string","description":"Condiciones que se proponen en cada cotización."}},"required":["validity_days","terms"],"additionalProperties":false},"taxes":{"type":"object","properties":{"enabled":{"type":"boolean"},"label":{"type":"string","description":"IVA, VAT, GST…"},"default_pct":{"type":"number"}},"required":["enabled","label","default_pct"],"additionalProperties":false},"split_date":{"type":"string","enum":["invoice","payment"],"description":"Qué fecha elige el tramo del reparto: la de la factura o la del cobro."},"samples":{"type":"boolean","description":"Si cada pedido lleva la lista de sus muestras."}},"required":["rate_source","summary","alerts","quotes","taxes","split_date","samples"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Servicios"],"summary":"Cambiar la configuración de Servicios","description":"Cambia solo lo que mandás (las partes anidadas también: summary, alerts, quotes, taxes). Solo la administración.\n\nPide un token con rol Coordinación.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"rate_source":{"type":"string","enum":["oficial","bolsa","mayorista","ecb","manual"]},"summary":{"type":"object","properties":{"group":{"type":"string","enum":["area","service"]},"line":{"type":"string","minLength":1,"maxLength":120},"separator":{"type":"string","maxLength":10},"rate":{"type":"boolean"}}},"alerts":{"type":"object","properties":{"unbilled_days":{"type":"integer","minimum":1,"maximum":365},"quote_expiring_days":{"type":"integer","minimum":1,"maximum":90},"tier_ending_days":{"type":"integer","minimum":1,"maximum":180}}},"quotes":{"type":"object","properties":{"validity_days":{"type":"integer","minimum":1,"maximum":365},"terms":{"type":"string","maxLength":2000}}},"taxes":{"type":"object","properties":{"enabled":{"type":"boolean"},"label":{"type":"string","minLength":1,"maxLength":20},"default_pct":{"type":"number","minimum":0,"maximum":100}}},"split_date":{"type":"string","enum":["invoice","payment"]},"samples":{"type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"rate_source":{"type":"string","enum":["oficial","bolsa","mayorista","ecb","manual"],"description":"De dónde se trae la cotización: oficial (BNA), bolsa (MEP), mayorista (BCRA), ecb (Banco Central Europeo) o manual."},"summary":{"type":"object","properties":{"group":{"type":"string","enum":["area","service"],"description":"Una línea por área del cliente (o servicio) o por servicio."},"line":{"type":"string","description":"Plantilla de cada línea: {label}, {qty}, {unit}, {amount}, {unit_price}."},"separator":{"type":"string"},"rate":{"type":"boolean","description":"Si termina con la cotización usada."}},"required":["group","line","separator","rate"],"additionalProperties":false},"alerts":{"type":"object","properties":{"unbilled_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"quote_expiring_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"tier_ending_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["unbilled_days","quote_expiring_days","tier_ending_days"],"additionalProperties":false},"quotes":{"type":"object","properties":{"validity_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"terms":{"type":"string","description":"Condiciones que se proponen en cada cotización."}},"required":["validity_days","terms"],"additionalProperties":false},"taxes":{"type":"object","properties":{"enabled":{"type":"boolean"},"label":{"type":"string","description":"IVA, VAT, GST…"},"default_pct":{"type":"number"}},"required":["enabled","label","default_pct"],"additionalProperties":false},"split_date":{"type":"string","enum":["invoice","payment"],"description":"Qué fecha elige el tramo del reparto: la de la factura o la del cobro."},"samples":{"type":"boolean","description":"Si cada pedido lleva la lista de sus muestras."}},"required":["rate_source","summary","alerts","quotes","taxes","split_date","samples"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/stages":{"get":{"tags":["Servicios"],"summary":"Etapas del pedido","description":"Las etapas propias del laboratorio, cada una sobre un estado del pedido (vacío: el laboratorio no usa etapas).","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"archived":{"type":"boolean"}},"required":["id","name","status","position","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Agregar una etapa del pedido","description":"Pide un token con rol Coordinación.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60,"description":"Nombre de la etapa (Muestra recibida, En análisis…)."},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"],"description":"El estado del pedido en esa etapa: received, in_progress, delivered o cancelled."}},"required":["name","status"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"archived":{"type":"boolean"}},"required":["id","name","status","position","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/stages/{id}":{"patch":{"tags":["Servicios"],"summary":"Modificar una etapa del pedido","description":"Renombrar, reordenar, archivar o cambiar su estado (una etapa con pedidos no cambia de estado).\n\nPide un token con rol Coordinación.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":60,"description":"Nombre de la etapa (Muestra recibida, En análisis…)."},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"],"description":"El estado del pedido en esa etapa: received, in_progress, delivered o cancelled."},"position":{"type":"integer","minimum":0,"maximum":999},"archived":{"description":"true la archiva; false la reactiva.","type":"boolean"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["received","in_progress","delivered","cancelled"]},"position":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"archived":{"type":"boolean"}},"required":["id","name","status","position","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/orders/{id}/samples":{"get":{"tags":["Servicios"],"summary":"Muestras de un pedido","description":"","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string","enum":["pending","received","processing","done","rejected"]},"received_on":{"type":["string","null"]},"item_id":{"description":"El ítem (servicio) del pedido, si tiene varios.","type":["string","null"]},"result":{"type":"string"},"notes":{"type":"string"}},"required":["id","code","kind","status","received_on","item_id","result","notes"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Servicios"],"summary":"Sumar muestras a un pedido","description":"Varias de una vez, con el mismo tipo, estado e ítem. Un código no se repite dentro del pedido.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"codes":{"minItems":1,"maxItems":500,"type":"array","items":{"type":"string","minLength":1,"maxLength":80,"description":"Código de la muestra."},"description":"Los códigos de las muestras que llegaron."},"kind":{"type":"string","maxLength":60,"description":"Tipo (sangre, ADN, tejido…)."},"status":{"description":"pending (por llegar), received, processing, done o rejected. Por defecto, received.","type":"string","enum":["pending","received","processing","done","rejected"]},"item":{"description":"El ítem del pedido (id) o el nombre de su servicio, si el pedido tiene varios.","type":"string"}},"required":["codes"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string","enum":["pending","received","processing","done","rejected"]},"received_on":{"type":["string","null"]},"item_id":{"description":"El ítem (servicio) del pedido, si tiene varios.","type":["string","null"]},"result":{"type":"string"},"notes":{"type":"string"}},"required":["id","code","kind","status","received_on","item_id","result","notes"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/services/samples/{id}":{"patch":{"tags":["Servicios"],"summary":"Modificar una muestra","description":"Su estado, su resultado, su código o su tipo. Cambia solo lo que mandás.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"code":{"type":"string","minLength":1,"maxLength":80,"description":"Código."},"kind":{"type":"string","maxLength":60,"description":"Tipo."},"status":{"type":"string","enum":["pending","received","processing","done","rejected"]},"received_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día en que llegó."},{"type":"null"}]},"result":{"type":"string","maxLength":2000,"description":"Resultado."},"notes":{"type":"string","maxLength":500,"description":"Notas."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string","enum":["pending","received","processing","done","rejected"]},"received_on":{"type":["string","null"]},"item_id":{"description":"El ítem (servicio) del pedido, si tiene varios.","type":["string","null"]},"result":{"type":"string"},"notes":{"type":"string"}},"required":["id","code","kind","status","received_on","item_id","result","notes"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/accounts":{"get":{"tags":["Presupuesto"],"summary":"Cuentas","description":"Las cuentas o fuentes de fondos que la persona del token ve, con su saldo. Las restringidas que no puede ver no aparecen.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["institutional","services","project","external","other"],"description":"institutional, services, project (subsidio o proyecto), external u other."},"responsible":{"type":["string","null"]},"starts_on":{"type":["string","null"]},"ends_on":{"type":["string","null"]},"restricted":{"type":"boolean","description":"Solo la ven la administración, su responsable y las personas elegidas."},"archived":{"type":"boolean"},"parent_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"La cuenta principal, si es una subcuenta (un nivel, misma moneda). El saldo de cada cuenta es solo el suyo."},"services_default":{"type":"boolean","description":"Recibe los cobros de Servicios cuando la factura no dice otra cuenta."},"currency":{"type":"string","description":"Moneda de la cuenta (ISO 4217): sus montos están en esta."},"funder":{"type":"string","description":"Quién la financia (texto libre)."},"requires_submission":{"type":"boolean","description":"Sus gastos se rinden. Si no, solo se registran."},"approver":{"type":"string","enum":["admin","responsible"],"description":"Quién aprueba sus rendiciones: admin (la administración) o responsible (su responsable)."},"categories":{"type":"array","items":{"type":"string"},"description":"Rubros que acepta (vacío: todos)."},"balance":{"type":"number","description":"Saldo: ingresos y transferencias recibidas, menos gastos pagados y transferencias hechas."},"committed":{"type":"number","description":"Gastos comprometidos (sin pagar): no bajan el saldo."},"available":{"type":"number","description":"Disponible: el saldo menos lo comprometido."},"income":{"type":"number"},"expense":{"type":"number"},"pending":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Gastos pendientes de rendir."},"missing_amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Movimientos sin monto."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","kind","responsible","starts_on","ends_on","restricted","archived","parent_id","services_default","currency","funder","requires_submission","approver","categories","balance","committed","available","income","expense","pending","missing_amount","version"],"additionalProperties":false}},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/accounts/{id}":{"get":{"tags":["Presupuesto"],"summary":"Ver una cuenta","description":"Por id o nombre, con su saldo.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"code":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["institutional","services","project","external","other"],"description":"institutional, services, project (subsidio o proyecto), external u other."},"responsible":{"type":["string","null"]},"starts_on":{"type":["string","null"]},"ends_on":{"type":["string","null"]},"restricted":{"type":"boolean","description":"Solo la ven la administración, su responsable y las personas elegidas."},"archived":{"type":"boolean"},"parent_id":{"anyOf":[{"type":"string","description":"Identificador (UUID)."},{"type":"null"}],"description":"La cuenta principal, si es una subcuenta (un nivel, misma moneda). El saldo de cada cuenta es solo el suyo."},"services_default":{"type":"boolean","description":"Recibe los cobros de Servicios cuando la factura no dice otra cuenta."},"currency":{"type":"string","description":"Moneda de la cuenta (ISO 4217): sus montos están en esta."},"funder":{"type":"string","description":"Quién la financia (texto libre)."},"requires_submission":{"type":"boolean","description":"Sus gastos se rinden. Si no, solo se registran."},"approver":{"type":"string","enum":["admin","responsible"],"description":"Quién aprueba sus rendiciones: admin (la administración) o responsible (su responsable)."},"categories":{"type":"array","items":{"type":"string"},"description":"Rubros que acepta (vacío: todos)."},"balance":{"type":"number","description":"Saldo: ingresos y transferencias recibidas, menos gastos pagados y transferencias hechas."},"committed":{"type":"number","description":"Gastos comprometidos (sin pagar): no bajan el saldo."},"available":{"type":"number","description":"Disponible: el saldo menos lo comprometido."},"income":{"type":"number"},"expense":{"type":"number"},"pending":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Gastos pendientes de rendir."},"missing_amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Movimientos sin monto."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","code","name","kind","responsible","starts_on","ends_on","restricted","archived","parent_id","services_default","currency","funder","requires_submission","approver","categories","balance","committed","available","income","expense","pending","missing_amount","version"],"additionalProperties":false},"currency":{"type":"string"}},"required":["data","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/accounts/{id}/balance":{"get":{"tags":["Presupuesto"],"summary":"Balance de una cuenta","description":"El año contable de una cuenta: lo ingresado, gastado y comprometido mes a mes con el saldo al cierre de cada uno, y lo gastado por rubro (contra lo asignado), proveedor, servicio y estado de rendición, más los gastos más grandes. Filtra por mes, rubro, proveedor, servicio y rendición.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"year","in":"query","required":false,"description":"Año contable: el año en que empieza (con inicio en julio, 2026 va de julio de 2026 a junio de 2027). Por defecto, el actual.","schema":{"description":"Año contable: el año en que empieza (con inicio en julio, 2026 va de julio de 2026 a junio de 2027). Por defecto, el actual.","type":"integer","minimum":2000,"maximum":2100}},{"name":"month","in":"query","required":false,"description":"Un mes (AAAA-MM) del año contable: achica las cifras a ese mes.","schema":{"description":"Un mes (AAAA-MM) del año contable: achica las cifras a ese mes.","type":"string","pattern":"^\\d{4}-\\d{2}$"}},{"name":"category","in":"query","required":false,"description":"Solo gastos de este rubro (id o nombre); «none»: sin rubro.","schema":{"description":"Solo gastos de este rubro (id o nombre); «none»: sin rubro.","type":"string","maxLength":120}},{"name":"supplier","in":"query","required":false,"description":"Solo gastos de este proveedor (nombre exacto); «none»: sin proveedor.","schema":{"description":"Solo gastos de este proveedor (nombre exacto); «none»: sin proveedor.","type":"string","maxLength":200}},{"name":"service","in":"query","required":false,"description":"Solo gastos imputados a este servicio (id o nombre); «none»: sin servicio.","schema":{"description":"Solo gastos imputados a este servicio (id o nombre); «none»: sin servicio.","type":"string","maxLength":120}},{"name":"status","in":"query","required":false,"description":"Solo gastos con esta rendición; «none»: los que no se rinden.","schema":{"description":"Solo gastos con esta rendición; «none»: los que no se rinden.","type":"string","enum":["pending","submitted","approved","rejected","none"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"currency":{"type":"string"}},"required":["id","name","currency"],"additionalProperties":false},"year":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"year_label":{"type":"string"},"month":{"type":["string","null"]},"opening_balance":{"type":"number","description":"El saldo con que empezó el año."},"closing_balance":{"type":"number","description":"El saldo al cierre del año (sin filtros)."},"totals":{"type":"object","properties":{"income":{"type":"number"},"expense":{"type":"number"},"committed":{"type":"number"},"transfers_in":{"type":"number"},"transfers_out":{"type":"number"},"movements":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"missing_amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"monthly_average":{"type":"number"},"peak_month":{"type":["string","null"]},"peak_amount":{"type":"number"}},"required":["income","expense","committed","transfers_in","transfers_out","movements","missing_amount","monthly_average","peak_month","peak_amount"],"additionalProperties":false},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"string","description":"AAAA-MM."},"income":{"type":"number"},"expense":{"type":"number"},"committed":{"type":"number"},"transfers_in":{"type":"number"},"transfers_out":{"type":"number"},"net":{"type":"number","description":"Lo que movió el saldo en el mes."},"closing_balance":{"type":["number","null"]},"movements":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"missing_amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["month","income","expense","committed","transfers_in","transfers_out","net","closing_balance","movements","missing_amount"],"additionalProperties":false}},"by_category":{"type":"array","items":{"type":"object","properties":{"category":{"type":["string","null"]},"expense":{"type":"number"},"committed":{"type":"number"},"allocated":{"type":["number","null"]},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["category","expense","committed","allocated","count"],"additionalProperties":false}},"by_supplier":{"type":"array","items":{"type":"object","properties":{"supplier":{"type":["string","null"]},"expense":{"type":"number"},"committed":{"type":"number"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["supplier","expense","committed","count"],"additionalProperties":false}},"by_service":{"type":"array","items":{"type":"object","properties":{"service":{"type":["string","null"]},"expense":{"type":"number"},"committed":{"type":"number"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["service","expense","committed","count"],"additionalProperties":false}},"by_status":{"type":"array","items":{"type":"object","properties":{"status":{"type":["string","null"]},"expense":{"type":"number"},"committed":{"type":"number"},"count":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["status","expense","committed","count"],"additionalProperties":false}},"biggest_expenses":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"date":{"type":"string"},"concept":{"type":"string"},"supplier":{"type":"string"},"amount":{"type":"number"}},"required":["id","date","concept","supplier","amount"],"additionalProperties":false}}},"required":["account","year","year_label","month","opening_balance","closing_balance","totals","months","by_category","by_supplier","by_service","by_status","biggest_expenses"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/movements":{"get":{"tags":["Presupuesto"],"summary":"Movimientos","description":"Ingresos, gastos (con su rendición) y transferencias, del más nuevo al más viejo.","parameters":[{"name":"q","in":"query","required":false,"description":"Concepto, proveedor, factura o cuenta.","schema":{"description":"Concepto, proveedor, factura o cuenta.","type":"string","maxLength":200}},{"name":"account","in":"query","required":false,"description":"Cuenta por id o nombre.","schema":{"description":"Cuenta por id o nombre.","type":"string"}},{"name":"kind","in":"query","required":false,"schema":{"type":"string","enum":["income","expense","transfer_out","transfer_in"]}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","submitted","approved","rejected"]}},{"name":"missing_amount","in":"query","required":false,"description":"true: solo los que no tienen monto.","schema":{"description":"true: solo los que no tienen monto.","type":"string","enum":["true"]}},{"name":"committed","in":"query","required":false,"description":"true: solo los comprometidos (sin pagar); false: los pagados.","schema":{"description":"true: solo los comprometidos (sin pagar); false: los pagados.","type":"string","enum":["true","false"]}},{"name":"from","in":"query","required":false,"description":"Desde este día.","schema":{"description":"Desde este día.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive.","schema":{"description":"Hasta este día inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"limit","in":"query","required":false,"schema":{"default":50,"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"kind":{"type":"string","enum":["income","expense","transfer_out","transfer_in"]},"date":{"type":"string"},"concept":{"type":"string"},"amount":{"description":"En la moneda de la cuenta. null: falta completar el monto.","type":["number","null"]},"currency":{"type":"string","description":"Moneda de la cuenta."},"committed":{"type":"boolean","description":"Solo egresos: comprometido (la orden está hecha, sin pagar)."},"category":{"type":["string","null"]},"supplier_name":{"type":"string"},"supplier_tax_id":{"type":"string"},"invoice_number":{"type":"string"},"service":{"description":"Servicio al que se imputa (módulo Servicios).","type":["string","null"]},"submission_status":{"anyOf":[{"type":"string","enum":["pending","submitted","approved","rejected"]},{"type":"null"}],"description":"Solo egresos: pending (sin rendir), submitted (rendida), approved, rejected."},"submitted_on":{"type":["string","null"]},"approved_on":{"type":["string","null"]},"transfer_id":{"type":["string","null"]},"source":{"type":"string","description":"manual, services_payment (el neto de un cobro de Servicios), services_deduction (lo que una deducción del reparto manda a la cuenta), equipment_event, reagents_lot o import."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","account","kind","date","concept","amount","currency","committed","category","supplier_name","supplier_tax_id","invoice_number","service","submission_status","submitted_on","approved_on","transfer_id","source","notes","custom_fields","version"],"additionalProperties":false}},"page":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"limit":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","page","limit","total"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Presupuesto"],"summary":"Cargar un gasto o un ingreso","description":"Un gasto queda «pendiente de rendir». Sin monto se guarda igual y queda marcado para completar.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"account":{"type":"string","minLength":1,"maxLength":120,"description":"Cuenta por id o nombre."},"kind":{"default":"expense","type":"string","enum":["income","expense"]},"date":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha (AAAA-MM-DD). Por defecto, hoy."},"concept":{"type":"string","minLength":1,"maxLength":200,"description":"Qué se pagó o qué entró."},"amount":{"description":"Monto en la moneda de la cuenta. null o sin mandar: queda «Completar monto».","anyOf":[{"type":"number","minimum":0,"maximum":1000000000000},{"type":"null"}]},"category":{"description":"Rubro por nombre o id.","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"supplier_name":{"type":"string","maxLength":200,"description":"Proveedor."},"supplier_tax_id":{"type":"string","maxLength":30,"description":"Identificación fiscal del proveedor (CUIT, RUT, RFC, EIN…, según el país del laboratorio)."},"invoice_number":{"type":"string","maxLength":60,"description":"N.º de factura."},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"committed":{"description":"Solo gastos: comprometido (la orden de compra está hecha y todavía no se pagó). No baja el saldo hasta que se pague.","type":"boolean"},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["account","concept"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"kind":{"type":"string","enum":["income","expense","transfer_out","transfer_in"]},"date":{"type":"string"},"concept":{"type":"string"},"amount":{"description":"En la moneda de la cuenta. null: falta completar el monto.","type":["number","null"]},"currency":{"type":"string","description":"Moneda de la cuenta."},"committed":{"type":"boolean","description":"Solo egresos: comprometido (la orden está hecha, sin pagar)."},"category":{"type":["string","null"]},"supplier_name":{"type":"string"},"supplier_tax_id":{"type":"string"},"invoice_number":{"type":"string"},"service":{"description":"Servicio al que se imputa (módulo Servicios).","type":["string","null"]},"submission_status":{"anyOf":[{"type":"string","enum":["pending","submitted","approved","rejected"]},{"type":"null"}],"description":"Solo egresos: pending (sin rendir), submitted (rendida), approved, rejected."},"submitted_on":{"type":["string","null"]},"approved_on":{"type":["string","null"]},"transfer_id":{"type":["string","null"]},"source":{"type":"string","description":"manual, services_payment (el neto de un cobro de Servicios), services_deduction (lo que una deducción del reparto manda a la cuenta), equipment_event, reagents_lot o import."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","account","kind","date","concept","amount","currency","committed","category","supplier_name","supplier_tax_id","invoice_number","service","submission_status","submitted_on","approved_on","transfer_id","source","notes","custom_fields","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/movements/{id}":{"get":{"tags":["Presupuesto"],"summary":"Ver un movimiento","description":"","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"kind":{"type":"string","enum":["income","expense","transfer_out","transfer_in"]},"date":{"type":"string"},"concept":{"type":"string"},"amount":{"description":"En la moneda de la cuenta. null: falta completar el monto.","type":["number","null"]},"currency":{"type":"string","description":"Moneda de la cuenta."},"committed":{"type":"boolean","description":"Solo egresos: comprometido (la orden está hecha, sin pagar)."},"category":{"type":["string","null"]},"supplier_name":{"type":"string"},"supplier_tax_id":{"type":"string"},"invoice_number":{"type":"string"},"service":{"description":"Servicio al que se imputa (módulo Servicios).","type":["string","null"]},"submission_status":{"anyOf":[{"type":"string","enum":["pending","submitted","approved","rejected"]},{"type":"null"}],"description":"Solo egresos: pending (sin rendir), submitted (rendida), approved, rejected."},"submitted_on":{"type":["string","null"]},"approved_on":{"type":["string","null"]},"transfer_id":{"type":["string","null"]},"source":{"type":"string","description":"manual, services_payment (el neto de un cobro de Servicios), services_deduction (lo que una deducción del reparto manda a la cuenta), equipment_event, reagents_lot o import."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","account","kind","date","concept","amount","currency","committed","category","supplier_name","supplier_tax_id","invoice_number","service","submission_status","submitted_on","approved_on","transfer_id","source","notes","custom_fields","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Presupuesto"],"summary":"Modificar o rendir un movimiento","description":"Cambia solo lo que mandás (por ejemplo, completar el monto) o el estado de la rendición. Pide la «version».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"account":{"type":"string","minLength":1,"maxLength":120,"description":"Cuenta por id o nombre."},"date":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha (AAAA-MM-DD). Por defecto, hoy."},"concept":{"type":"string","minLength":1,"maxLength":200,"description":"Qué se pagó o qué entró."},"amount":{"description":"Monto en la moneda de la cuenta. null o sin mandar: queda «Completar monto».","anyOf":[{"type":"number","minimum":0,"maximum":1000000000000},{"type":"null"}]},"category":{"description":"Rubro por nombre o id.","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"supplier_name":{"type":"string","maxLength":200,"description":"Proveedor."},"supplier_tax_id":{"type":"string","maxLength":30,"description":"Identificación fiscal del proveedor (CUIT, RUT, RFC, EIN…, según el país del laboratorio)."},"invoice_number":{"type":"string","maxLength":60,"description":"N.º de factura."},"notes":{"type":"string","maxLength":2000,"description":"Notas."},"committed":{"description":"Solo gastos: comprometido (la orden de compra está hecha y todavía no se pagó). No baja el saldo hasta que se pague.","type":"boolean"},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"submission_status":{"description":"submitted = rendida (editores); approved o rejected, quien aprueba las de la cuenta (la administración o su responsable).","type":"string","enum":["pending","submitted","approved","rejected"]}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"kind":{"type":"string","enum":["income","expense","transfer_out","transfer_in"]},"date":{"type":"string"},"concept":{"type":"string"},"amount":{"description":"En la moneda de la cuenta. null: falta completar el monto.","type":["number","null"]},"currency":{"type":"string","description":"Moneda de la cuenta."},"committed":{"type":"boolean","description":"Solo egresos: comprometido (la orden está hecha, sin pagar)."},"category":{"type":["string","null"]},"supplier_name":{"type":"string"},"supplier_tax_id":{"type":"string"},"invoice_number":{"type":"string"},"service":{"description":"Servicio al que se imputa (módulo Servicios).","type":["string","null"]},"submission_status":{"anyOf":[{"type":"string","enum":["pending","submitted","approved","rejected"]},{"type":"null"}],"description":"Solo egresos: pending (sin rendir), submitted (rendida), approved, rejected."},"submitted_on":{"type":["string","null"]},"approved_on":{"type":["string","null"]},"transfer_id":{"type":["string","null"]},"source":{"type":"string","description":"manual, services_payment (el neto de un cobro de Servicios), services_deduction (lo que una deducción del reparto manda a la cuenta), equipment_event, reagents_lot o import."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","account","kind","date","concept","amount","currency","committed","category","supplier_name","supplier_tax_id","invoice_number","service","submission_status","submitted_on","approved_on","transfer_id","source","notes","custom_fields","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"delete":{"tags":["Presupuesto"],"summary":"Borrar un movimiento","description":"Solo la administración. Borrado lógico, como en la web: deja de contar en el saldo y queda en el historial. Si es una pata de una transferencia, se borran las dos.\n\nPide un token con rol Coordinación.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/movements/{id}/history":{"get":{"tags":["Presupuesto"],"summary":"Historial de un movimiento","description":"","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/summary":{"get":{"tags":["Presupuesto"],"summary":"Resumen del año","description":"Por cuenta y por mes del año contable: lo gastado, lo comprometido, lo ingresado y las transferencias, cada cuenta en su moneda. Solo las cuentas que la persona ve.","parameters":[{"name":"year","in":"query","required":false,"description":"Año contable: el año en que empieza (con inicio en julio, 2026 va de julio de 2026 a junio de 2027). Por defecto, el actual.","schema":{"description":"Año contable: el año en que empieza (con inicio en julio, 2026 va de julio de 2026 a junio de 2027). Por defecto, el actual.","type":"integer","minimum":2000,"maximum":2100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"year":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"year_label":{"type":"string","description":"«2026», o «2026–27» si no empieza en enero."},"fiscal_start_month":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"currency":{"type":"string","description":"Moneda del laboratorio."},"data":{"type":"array","items":{"type":"object","properties":{"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"currency":{"type":"string"}},"required":["id","name","currency"],"additionalProperties":false},"months":{"type":"array","items":{"type":"object","properties":{"month":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"year":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"income":{"type":"number"},"expense":{"type":"number"},"committed":{"type":"number"},"transfers_in":{"type":"number"},"transfers_out":{"type":"number"},"missing_amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["month","year","income","expense","committed","transfers_in","transfers_out","missing_amount"],"additionalProperties":false}},"expense":{"type":"number"},"committed":{"type":"number"},"income":{"type":"number"}},"required":["account","months","expense","committed","income"],"additionalProperties":false}}},"required":["year","year_label","fiscal_start_month","currency","data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/settings":{"get":{"tags":["Presupuesto"],"summary":"Configuración del presupuesto","description":"Cómo maneja la plata el laboratorio: cuándo empieza el año contable, si los gastos se rinden y quién aprueba (lo que se propone para las cuentas nuevas), si se cargan comprometidos, los días de los avisos, el país y la moneda.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"fiscal_start_month":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"requires_submission":{"type":"boolean"},"approver":{"type":"string","enum":["admin","responsible"]},"commitments":{"type":"boolean"},"pending_after_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"ending_within_days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"profile":{"anyOf":[{"type":"string","enum":["public","university","private","custom"]},{"type":"null"}]},"country":{"type":"string"},"currency":{"type":"string"}},"required":["fiscal_start_month","requires_submission","approver","commitments","pending_after_days","ending_within_days","profile","country","currency"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Presupuesto"],"summary":"Cambiar la configuración del presupuesto","description":"Solo la administración. Cambia solo lo que mandás. Rendir y quién aprueba es lo que se propone para las cuentas nuevas.\n\nPide un token con rol Colaborador.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"fiscal_start_month":{"description":"Mes en que empieza el año contable (1 = enero).","type":"integer","minimum":1,"maximum":12},"requires_submission":{"description":"Las cuentas nuevas rinden sus gastos.","type":"boolean"},"approver":{"description":"Quién aprueba las rendiciones en las cuentas nuevas.","type":"string","enum":["admin","responsible"]},"commitments":{"description":"Se cargan gastos comprometidos (órdenes de compra sin pagar).","type":"boolean"},"pending_after_days":{"description":"Días sin rendir a partir de los cuales un gasto pide atención.","type":"integer","minimum":1,"maximum":365},"ending_within_days":{"description":"Días antes del fin de una cuenta en que se avisa.","type":"integer","minimum":1,"maximum":365}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/category-templates":{"get":{"tags":["Presupuesto"],"summary":"Rubros sugeridos por financiador","description":"Las listas de rubros que se pueden cargar de una vez (generales, Agencia I+D+i, CONICET, subsidio federal de EE. UU., Horizonte Europa, Brasil, empresa).","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"name":{"type":"string"},"categories":{"type":"array","items":{"type":"string"}}},"required":["key","name","categories"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/categories":{"get":{"tags":["Presupuesto"],"summary":"Rubros","description":"","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"},"archived":{"type":"boolean"}},"required":["id","name","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/transfers":{"post":{"tags":["Presupuesto"],"summary":"Transferir entre cuentas","description":"Dos movimientos (sale y entra) que no suman como gasto ni como ingreso del laboratorio: solo mueven saldo.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"from":{"type":"string","minLength":1,"maxLength":120,"description":"Cuenta de la que sale (id o nombre)."},"to":{"type":"string","minLength":1,"maxLength":120,"description":"Cuenta a la que entra (id o nombre)."},"amount":{"type":"number","exclusiveMinimum":0,"maximum":1000000000000,"description":"Lo que sale, en la moneda de la cuenta de origen."},"to_amount":{"description":"Solo entre cuentas de distinta moneda: lo que entra, en la moneda de la cuenta de destino.","type":"number","exclusiveMinimum":0,"maximum":1000000000000},"date":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha. Por defecto, hoy."},"concept":{"type":"string","minLength":1,"maxLength":200,"description":"Concepto."},"notes":{"type":"string","maxLength":2000,"description":"Notas."}},"required":["from","to","amount","concept"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"account":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"kind":{"type":"string","enum":["income","expense","transfer_out","transfer_in"]},"date":{"type":"string"},"concept":{"type":"string"},"amount":{"description":"En la moneda de la cuenta. null: falta completar el monto.","type":["number","null"]},"currency":{"type":"string","description":"Moneda de la cuenta."},"committed":{"type":"boolean","description":"Solo egresos: comprometido (la orden está hecha, sin pagar)."},"category":{"type":["string","null"]},"supplier_name":{"type":"string"},"supplier_tax_id":{"type":"string"},"invoice_number":{"type":"string"},"service":{"description":"Servicio al que se imputa (módulo Servicios).","type":["string","null"]},"submission_status":{"anyOf":[{"type":"string","enum":["pending","submitted","approved","rejected"]},{"type":"null"}],"description":"Solo egresos: pending (sin rendir), submitted (rendida), approved, rejected."},"submitted_on":{"type":["string","null"]},"approved_on":{"type":["string","null"]},"transfer_id":{"type":["string","null"]},"source":{"type":"string","description":"manual, services_payment (el neto de un cobro de Servicios), services_deduction (lo que una deducción del reparto manda a la cuenta), equipment_event, reagents_lot o import."},"notes":{"type":"string"},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","account","kind","date","concept","amount","currency","committed","category","supplier_name","supplier_tax_id","invoice_number","service","submission_status","submitted_on","approved_on","transfer_id","source","notes","custom_fields","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/allocations":{"get":{"tags":["Presupuesto"],"summary":"Asignado contra gastado","description":"Lo asignado a cada cuenta en el año contable o para toda su vigencia (en total o por rubro), contra lo gastado y lo comprometido (las cuentas que ve la persona). Cada cuenta en su moneda.","parameters":[{"name":"year","in":"query","required":false,"description":"Año contable (el año en que empieza). Por defecto, el actual.","schema":{"description":"Año contable (el año en que empieza). Por defecto, el actual.","type":"integer","minimum":2000,"maximum":2100}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"account":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"currency":{"type":"string"}},"required":["id","name","currency"],"additionalProperties":false},"period":{"type":"string","description":"El año contable, o «vigencia» si es para toda la vigencia de la cuenta."},"category":{"description":"null: el total de la cuenta.","type":["string","null"]},"allocated":{"type":"number"},"spent":{"type":"number"},"committed":{"type":"number","description":"Comprometido, sin pagar."},"remaining":{"type":"number","description":"Lo asignado menos lo gastado y lo comprometido."}},"required":["account","period","category","allocated","spent","committed","remaining"],"additionalProperties":false}},"year":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"year_label":{"type":"string"},"currency":{"type":"string","description":"Moneda del laboratorio."}},"required":["data","year","year_label","currency"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/suggestions":{"get":{"tags":["Presupuesto"],"summary":"Para imputar","description":"Registros de Equipos y lotes de Insumos con costo que todavía no son un egreso del presupuesto.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string","enum":["equipment_event","reagents_lot"],"description":"equipment_event (registro de Equipos) o reagents_lot (lote de Insumos)."},"source_id":{"type":"string"},"date":{"type":"string"},"concept":{"type":"string"},"amount":{"type":"number","description":"Costo, en su moneda."},"currency":{"type":"string"},"supplier":{"type":"string"},"detail":{"type":"string"}},"required":["source","source_id","date","concept","amount","currency","supplier","detail"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/budget/suggestions/impute":{"post":{"tags":["Presupuesto"],"summary":"Imputar un gasto sugerido","description":"Convierte un registro de Equipos o un lote de Insumos con costo en un egreso de una cuenta (pendiente de rendir, si la cuenta se rinde).\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"source":{"type":"string","enum":["equipment_event","reagents_lot"]},"source_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"account":{"type":"string","minLength":1,"maxLength":120,"description":"Cuenta (nombre, código o id)."},"category":{"description":"Rubro (nombre o id).","type":"string","maxLength":120},"amount":{"description":"Monto en la moneda de la cuenta. Por defecto, el costo si está en esa moneda; si no, queda sin monto.","anyOf":[{"type":"number","minimum":0},{"type":"null"}]},"date":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha. Por defecto, la del registro o el lote."},"concept":{"type":"string","maxLength":200,"description":"Concepto. Por defecto, el sugerido."}},"required":["source","source_id","account"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents":{"get":{"tags":["Protocolos"],"summary":"Documentos","description":"Los protocolos y procedimientos del laboratorio, con su versión vigente, quién la aprobó y cuándo toca revisarla. Quien solo consulta ve los publicados.","parameters":[{"name":"q","in":"query","required":false,"description":"Busca en el título, el código y la categoría.","schema":{"description":"Busca en el título, el código y la categoría.","type":"string","maxLength":100}},{"name":"category","in":"query","required":false,"description":"Solo esa categoría.","schema":{"description":"Solo esa categoría.","type":"string","maxLength":60}},{"name":"state","in":"query","required":false,"description":"effective: con versión vigente; draft: con un borrador abierto (quien edita); archived: retirados; review: con la revisión vencida o por llegar. Sin esto, los no retirados.","schema":{"description":"effective: con versión vigente; draft: con un borrador abierto (quien edita); archived: retirados; review: con la revisión vencida o por llegar. Sin esto, los no retirados.","type":"string","enum":["effective","draft","archived","review"]}},{"name":"linked_type","in":"query","required":false,"description":"Junto con «linked»: solo los vinculados a un registro de este tipo (equipment.item, equipment.type, services.catalog, reagents.item, biobank.location).","schema":{"description":"Junto con «linked»: solo los vinculados a un registro de este tipo (equipment.item, equipment.type, services.catalog, reagents.item, biobank.location).","type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"]}},{"name":"linked","in":"query","required":false,"description":"Código, nombre o id del registro. Para un equipo, también trae los vinculados a su tipo.","schema":{"description":"Código, nombre o id del registro. Para un equipo, también trae los vinculados a su tipo.","type":"string","maxLength":160}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Protocolos"],"summary":"Crear un documento","description":"Crea el documento con su primer borrador. Queda sin publicar: lo aprueba y lo publica, desde Vialo, quien tenga el permiso «Aprobar documentos». El código se genera solo si no lo mandás.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":160,"description":"Título del documento."},"code":{"type":"string","maxLength":60,"description":"Código propio. Si no lo mandás se genera con el formato del laboratorio (PRO-001) y no cambia nunca."},"category":{"type":"string","maxLength":60,"description":"Categoría («Procedimientos», «Bioseguridad»…)."},"responsible":{"type":"string","minLength":1,"maxLength":200,"description":"Persona responsable del documento: id, nombre o email («me» es la persona del token)."},"review_interval_months":{"description":"Cada cuántos meses se revisa. Sin esto, no hay revisión programada.","anyOf":[{"type":"integer","minimum":1,"maximum":120},{"type":"null"}]},"body":{"description":"Texto del primer borrador. Markdown con tablas: títulos con ## y ###, listas con - o 1., listas de verificación con - [ ] y - [x], **negrita**, _cursiva_, ~~tachado~~, ==resaltado==, links, líneas divisorias (---) y tablas con |. Avisos de colores: un bloque que empieza con > [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING] o > [!CAUTION] (lo que sigue en esa línea es el título) y sigue con renglones que empiezan con >.","type":"string","maxLength":100000}},"required":["title"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}":{"get":{"tags":["Protocolos"],"summary":"Ver un documento","description":"Por código (PRO-001) o id. Trae el texto de la versión vigente (o de la que pidas con «number»), todas las versiones y tu lectura pendiente, si la tenés.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"Número de versión a leer. Por defecto, la vigente.","schema":{"description":"Número de versión a leer. Por defecto, la vigente.","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."},"shown":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."},"body":{"type":"string","description":"Texto en Markdown. Vacío si el contenido es un archivo adjunto."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version","body"],"additionalProperties":false},{"type":"null"}],"description":"La versión pedida (por defecto, la vigente) con su texto."},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},"description":"Todas, de la más nueva a la más vieja."},"my_reading":{"anyOf":[{"type":"object","properties":{"assignment_id":{"type":"string"},"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Versión que hay que leer."},"due_on":{"type":["string","null"]},"late":{"type":"boolean","description":"Pasó el plazo y falta confirmar."},"confirmed_at":{"type":["string","null"]}},"required":["assignment_id","document","number","due_on","late","confirmed_at"],"additionalProperties":false},{"type":"null"}],"description":"Tu lectura de la versión vigente."},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Id del vínculo (para quitarlo)."},"type":{"type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"],"description":"equipment.item: un equipo; equipment.type: todos los equipos de un tipo; services.catalog: un servicio del catálogo; reagents.item: un insumo; biobank.location: una ubicación del Biobanco."},"target_id":{"type":"string"},"label":{"type":"string","description":"Código y nombre del registro vinculado."}},"required":["id","type","target_id","label"],"additionalProperties":false},"description":"Equipos, servicios, insumos y ubicaciones a los que se aplica el documento."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version","shown","versions","my_reading","links"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Protocolos"],"summary":"Modificar un documento","description":"Cambia el título, la categoría, el responsable o cada cuánto se revisa. El código no se cambia. Cambia solo lo que mandás y pide la «version» que devolvió la API (409 si alguien lo cambió).\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"title":{"type":"string","minLength":1,"maxLength":160,"description":"Título."},"category":{"type":"string","maxLength":60,"description":"Categoría."},"responsible":{"anyOf":[{"type":"string","minLength":1,"maxLength":200,"description":"Persona responsable (id, nombre o email)."},{"type":"null"}]},"review_interval_months":{"description":"Cada cuántos meses se revisa. null lo quita.","anyOf":[{"type":"integer","minimum":1,"maximum":120},{"type":"null"}]}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/history":{"get":{"tags":["Protocolos"],"summary":"Historial de un documento","description":"Quién creó el documento y le cambió el título, la categoría o el responsable, cuándo y por dónde. Las versiones y las lecturas tienen su propio historial inmutable en Vialo.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"at":{"type":"string"},"action":{"type":"string","enum":["insert","update","soft_delete","restore","delete","move","status_change"]},"actor":{"type":"string"},"via":{"description":"«vía API · <token>» si no se hizo desde la web.","type":["string","null"]},"changed_fields":{"type":"array","items":{"type":"string"}},"old":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]},"new":{"anyOf":[{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}},{"type":"null"}]}},"required":["at","action","actor","via","changed_fields","old","new"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/access":{"get":{"tags":["Protocolos"],"summary":"Quién ve y gestiona un documento","description":"Si el documento es restringido y quiénes lo ven (o también lo gestionan) además de la administración y su responsable. Se elige desde Vialo (la administración), no con un token.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"restricted":{"type":"boolean","description":"Si es true, solo lo ven la administración (y, en equipos, su responsable) y las personas de «people»."},"people":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: solo ve; manage: ve y gestiona (carga y cambia datos)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Quiénes lo ven además de la administración."},"sub_labs":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"level":{"type":"string","enum":["view","manage"],"description":"view: toda su gente ve; manage: ve y gestiona (si su rol en este laboratorio lo permite)."}},"required":["id","name","level"],"additionalProperties":false},"description":"Sub-laboratorios a los que se abrió, con toda su gente."}},"required":["restricted","people","sub_labs"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/attachments":{"get":{"tags":["Protocolos"],"summary":"Archivos de una versión","description":"El archivo adjunto de la versión vigente (o de la que pidas con «number»), con un enlace de descarga que vence a los 5 minutos.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"number","in":"query","required":false,"description":"Número de versión a leer. Por defecto, la vigente.","schema":{"description":"Número de versión a leer. Por defecto, la vigente.","type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID)."},"file_name":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"created_at":{"type":"string"},"uploaded_by":{"type":"string"},"download_url":{"description":"Enlace de descarga que vence a los 5 minutos.","type":["string","null"]}},"required":["id","file_name","mime_type","size_bytes","created_at","uploaded_by","download_url"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/reading":{"get":{"tags":["Protocolos"],"summary":"Mis lecturas","description":"Los documentos que te asignaron para leer y todavía no confirmaste, primero los de plazo más cercano. La confirmación «Leí y entendí» solo se hace desde Vialo, por la propia persona.","parameters":[{"name":"confirmed","in":"query","required":false,"description":"true: también las que ya confirmaste.","schema":{"description":"true: también las que ya confirmaste.","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"assignment_id":{"type":"string"},"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Versión que hay que leer."},"due_on":{"type":["string","null"]},"late":{"type":"boolean","description":"Pasó el plazo y falta confirmar."},"confirmed_at":{"type":["string","null"]}},"required":["assignment_id","document","number","due_on","late","confirmed_at"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/compliance":{"get":{"tags":["Protocolos"],"summary":"Cumplimiento de la lectura","description":"Por cada documento vigente, quiénes confirmaron la lectura y quiénes faltan. Pide el permiso «Aprobar documentos» (la coordinación lo tiene siempre).","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"assigned":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"confirmed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"missing":{"type":"array","items":{"type":"object","properties":{"assignment_id":{"type":"string"},"person":{"type":"string"},"due_on":{"type":["string","null"]},"late":{"type":"boolean"}},"required":["assignment_id","person","due_on","late"],"additionalProperties":false}},"done":{"type":"array","items":{"type":"object","properties":{"person":{"type":"string"},"confirmed_at":{"type":"string"}},"required":["person","confirmed_at"],"additionalProperties":false}}},"required":["document","number","assigned","confirmed","missing","done"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/trainings":{"get":{"tags":["Protocolos"],"summary":"Capacitaciones","description":"El registro de capacitaciones, de la más nueva a la más vieja (hasta 500). Quien solo consulta ve las suyas.","parameters":[{"name":"document","in":"query","required":false,"description":"Solo las de un documento: su código (PRO-001) o su id.","schema":{"description":"Solo las de un documento: su código (PRO-001) o su id.","type":"string"}},{"name":"person","in":"query","required":false,"description":"Solo las de una persona del laboratorio: su id, su nombre o su email.","schema":{"description":"Solo las de una persona del laboratorio: su id, su nombre o su email.","type":"string"}},{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD).","schema":{"description":"Desde este día (AAAA-MM-DD).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive.","schema":{"description":"Hasta este día inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"person":{"type":"string"},"user_id":{"description":"null si la persona no usa Vialo.","type":["string","null"]},"topic":{"type":"string"},"document":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},{"type":"null"}]},"number":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Versión vigente cuando se registró."},"trained_on":{"type":"string"},"trainer":{"type":"string"},"hours":{"type":["number","null"]},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","person","user_id","topic","document","number","trained_on","trainer","hours","notes","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Protocolos"],"summary":"Registrar una capacitación","description":"Anota una capacitación para una o más personas (del laboratorio o solo por su nombre). Si va sobre un documento, queda anotada su versión vigente.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"topic":{"type":"string","minLength":1,"maxLength":160,"description":"Tema de la capacitación."},"document":{"description":"Documento sobre el que fue: su código (PRO-001) o su id.","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"trained_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día de la capacitación (AAAA-MM-DD). No puede ser futuro."},"people":{"description":"Personas del laboratorio que se capacitaron.","maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":200,"description":"Id, nombre o email de una persona del laboratorio."}},"other_people":{"description":"Nombres de quienes no usan Vialo (una pasante, un visitante).","maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":160,"description":"Nombre."}},"trainer":{"type":"string","maxLength":120,"description":"Quién la dio."},"hours":{"anyOf":[{"type":"number","exclusiveMinimum":0,"maximum":999},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}},"required":["topic","trained_on"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"person":{"type":"string"},"user_id":{"description":"null si la persona no usa Vialo.","type":["string","null"]},"topic":{"type":"string"},"document":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},{"type":"null"}]},"number":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Versión vigente cuando se registró."},"trained_on":{"type":"string"},"trainer":{"type":"string"},"hours":{"type":["number","null"]},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","person","user_id","topic","document","number","trained_on","trainer","hours","notes","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/links":{"post":{"tags":["Protocolos"],"summary":"Vincular un documento","description":"Vincula el documento con un equipo (o todos los de un tipo), un servicio del catálogo, un insumo o una ubicación del Biobanco: aparece en su ficha. Devuelve el documento con todos sus vínculos.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"type":{"type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"],"description":"equipment.item: un equipo; equipment.type: todos los equipos de un tipo; services.catalog: un servicio del catálogo; reagents.item: un insumo; biobank.location: una ubicación del Biobanco (freezer, heladera, tanque, sala)."},"target":{"type":"string","minLength":1,"maxLength":160,"description":"Código, nombre o id del registro a vincular."}},"required":["type","target"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."},"shown":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."},"body":{"type":"string","description":"Texto en Markdown. Vacío si el contenido es un archivo adjunto."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version","body"],"additionalProperties":false},{"type":"null"}],"description":"La versión pedida (por defecto, la vigente) con su texto."},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},"description":"Todas, de la más nueva a la más vieja."},"my_reading":{"anyOf":[{"type":"object","properties":{"assignment_id":{"type":"string"},"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Versión que hay que leer."},"due_on":{"type":["string","null"]},"late":{"type":"boolean","description":"Pasó el plazo y falta confirmar."},"confirmed_at":{"type":["string","null"]}},"required":["assignment_id","document","number","due_on","late","confirmed_at"],"additionalProperties":false},{"type":"null"}],"description":"Tu lectura de la versión vigente."},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Id del vínculo (para quitarlo)."},"type":{"type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"],"description":"equipment.item: un equipo; equipment.type: todos los equipos de un tipo; services.catalog: un servicio del catálogo; reagents.item: un insumo; biobank.location: una ubicación del Biobanco."},"target_id":{"type":"string"},"label":{"type":"string","description":"Código y nombre del registro vinculado."}},"required":["id","type","target_id","label"],"additionalProperties":false},"description":"Equipos, servicios, insumos y ubicaciones a los que se aplica el documento."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version","shown","versions","my_reading","links"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/links/{link_id}":{"delete":{"tags":["Protocolos"],"summary":"Quitar un vínculo","description":"El documento deja de aparecer en la ficha de ese registro. El id del vínculo está en «links» del documento.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"link_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."},"shown":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."},"body":{"type":"string","description":"Texto en Markdown. Vacío si el contenido es un archivo adjunto."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version","body"],"additionalProperties":false},{"type":"null"}],"description":"La versión pedida (por defecto, la vigente) con su texto."},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},"description":"Todas, de la más nueva a la más vieja."},"my_reading":{"anyOf":[{"type":"object","properties":{"assignment_id":{"type":"string"},"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Versión que hay que leer."},"due_on":{"type":["string","null"]},"late":{"type":"boolean","description":"Pasó el plazo y falta confirmar."},"confirmed_at":{"type":["string","null"]}},"required":["assignment_id","document","number","due_on","late","confirmed_at"],"additionalProperties":false},{"type":"null"}],"description":"Tu lectura de la versión vigente."},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Id del vínculo (para quitarlo)."},"type":{"type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"],"description":"equipment.item: un equipo; equipment.type: todos los equipos de un tipo; services.catalog: un servicio del catálogo; reagents.item: un insumo; biobank.location: una ubicación del Biobanco."},"target_id":{"type":"string"},"label":{"type":"string","description":"Código y nombre del registro vinculado."}},"required":["id","type","target_id","label"],"additionalProperties":false},"description":"Equipos, servicios, insumos y ubicaciones a los que se aplica el documento."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version","shown","versions","my_reading","links"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/versions":{"post":{"tags":["Protocolos"],"summary":"Crear una versión nueva","description":"Abre un borrador nuevo a partir de la versión vigente. No se edita nunca la vigente: la nueva la reemplaza cuando se aprueba. Hay a lo sumo un borrador abierto por documento.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."},"shown":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."},"body":{"type":"string","description":"Texto en Markdown. Vacío si el contenido es un archivo adjunto."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version","body"],"additionalProperties":false},{"type":"null"}],"description":"La versión pedida (por defecto, la vigente) con su texto."},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},"description":"Todas, de la más nueva a la más vieja."},"my_reading":{"anyOf":[{"type":"object","properties":{"assignment_id":{"type":"string"},"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Versión que hay que leer."},"due_on":{"type":["string","null"]},"late":{"type":"boolean","description":"Pasó el plazo y falta confirmar."},"confirmed_at":{"type":["string","null"]}},"required":["assignment_id","document","number","due_on","late","confirmed_at"],"additionalProperties":false},{"type":"null"}],"description":"Tu lectura de la versión vigente."},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Id del vínculo (para quitarlo)."},"type":{"type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"],"description":"equipment.item: un equipo; equipment.type: todos los equipos de un tipo; services.catalog: un servicio del catálogo; reagents.item: un insumo; biobank.location: una ubicación del Biobanco."},"target_id":{"type":"string"},"label":{"type":"string","description":"Código y nombre del registro vinculado."}},"required":["id","type","target_id","label"],"additionalProperties":false},"description":"Equipos, servicios, insumos y ubicaciones a los que se aplica el documento."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version","shown","versions","my_reading","links"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/documents/{id}/draft":{"patch":{"tags":["Protocolos"],"summary":"Escribir el borrador","description":"Cambia el texto (Markdown) o el resumen de cambios del borrador abierto. Una versión publicada no se modifica. Pide la «version» del borrador (campo «version» de «draft»).\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"body":{"description":"Texto completo del borrador. Markdown con tablas: títulos con ## y ###, listas con - o 1., listas de verificación con - [ ] y - [x], **negrita**, _cursiva_, ~~tachado~~, ==resaltado==, links, líneas divisorias (---) y tablas con |. Avisos de colores: un bloque que empieza con > [!NOTE], > [!TIP], > [!IMPORTANT], > [!WARNING] o > [!CAUTION] (lo que sigue en esa línea es el título) y sigue con renglones que empiezan con >.","type":"string","maxLength":100000},"change_summary":{"type":"string","maxLength":1000,"description":"Qué cambió respecto de la versión vigente. Hace falta para publicar desde la segunda versión."}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string","description":"PRO-001: no cambia nunca."},"title":{"type":"string"},"category":{"type":"string"},"responsible":{"description":"Nombre de la persona responsable.","type":["string","null"]},"review_interval_months":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"state":{"type":"string","enum":["effective","draft","archived"],"description":"effective: tiene una versión vigente; draft: todavía no se publicó ninguna; archived: retirado."},"review":{"type":"object","properties":{"state":{"type":"string","enum":["none","ok","due_soon","overdue"]},"days":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Días hasta la próxima revisión (negativo si ya pasó)."}},"required":["state","days"],"additionalProperties":false,"description":"Cómo está la revisión de la versión vigente."},"current":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"La versión vigente."},"draft":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},{"type":"null"}],"description":"El borrador abierto (solo lo ve quien edita)."},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar el documento: se manda de vuelta."},"shown":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."},"body":{"type":"string","description":"Texto en Markdown. Vacío si el contenido es un archivo adjunto."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version","body"],"additionalProperties":false},{"type":"null"}],"description":"La versión pedida (por defecto, la vigente) con su texto."},"versions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identificador (UUID) de la versión."},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Número de versión: 1, 2, 3…"},"status":{"type":"string","enum":["draft","effective","superseded","archived"],"description":"draft: borrador; effective: la vigente; superseded: reemplazada por una más nueva; archived: el documento se retiró."},"change_summary":{"type":"string","description":"Qué cambió respecto de la anterior."},"effective_from":{"description":"Día desde el que rige (AAAA-MM-DD).","type":["string","null"]},"review_on":{"description":"Día de la próxima revisión (AAAA-MM-DD).","type":["string","null"]},"approved_at":{"anyOf":[{"type":"string","description":"Cuándo se aprobó."},{"type":"null"}]},"approved_by":{"description":"Nombre de quien la aprobó.","type":["string","null"]},"reviewed_at":{"anyOf":[{"type":"string","description":"Última revisión sin cambios."},{"type":"null"}]},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Para modificar un borrador: se manda de vuelta como «version»."}},"required":["id","number","status","change_summary","effective_from","review_on","approved_at","approved_by","reviewed_at","version"],"additionalProperties":false},"description":"Todas, de la más nueva a la más vieja."},"my_reading":{"anyOf":[{"type":"object","properties":{"assignment_id":{"type":"string"},"document":{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},"number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Versión que hay que leer."},"due_on":{"type":["string","null"]},"late":{"type":"boolean","description":"Pasó el plazo y falta confirmar."},"confirmed_at":{"type":["string","null"]}},"required":["assignment_id","document","number","due_on","late","confirmed_at"],"additionalProperties":false},{"type":"null"}],"description":"Tu lectura de la versión vigente."},"links":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Id del vínculo (para quitarlo)."},"type":{"type":"string","enum":["equipment.item","equipment.type","services.catalog","reagents.item","biobank.location"],"description":"equipment.item: un equipo; equipment.type: todos los equipos de un tipo; services.catalog: un servicio del catálogo; reagents.item: un insumo; biobank.location: una ubicación del Biobanco."},"target_id":{"type":"string"},"label":{"type":"string","description":"Código y nombre del registro vinculado."}},"required":["id","type","target_id","label"],"additionalProperties":false},"description":"Equipos, servicios, insumos y ubicaciones a los que se aplica el documento."}},"required":["id","code","title","category","responsible","review_interval_months","state","review","current","draft","version","shown","versions","my_reading","links"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/protocols/trainings/{id}":{"patch":{"tags":["Protocolos"],"summary":"Modificar una capacitación","description":"Cambia el tema, el documento, el día, quién la dio, las horas o las notas. Cambia solo lo que mandás y pide la «version» (409 si alguien la cambió).\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"topic":{"type":"string","minLength":1,"maxLength":160,"description":"Tema."},"document":{"description":"Código o id del documento. null lo quita.","anyOf":[{"type":"string","maxLength":80},{"type":"null"}]},"trained_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día (AAAA-MM-DD)."},"trainer":{"type":"string","maxLength":120,"description":"Quién la dio."},"hours":{"anyOf":[{"type":"number","exclusiveMinimum":0,"maximum":999},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"person":{"type":"string"},"user_id":{"description":"null si la persona no usa Vialo.","type":["string","null"]},"topic":{"type":"string"},"document":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"code":{"type":"string"},"title":{"type":"string"}},"required":["id","code","title"],"additionalProperties":false},{"type":"null"}]},"number":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Versión vigente cuando se registró."},"trained_on":{"type":"string"},"trainer":{"type":"string"},"hours":{"type":["number","null"]},"notes":{"type":"string"},"version":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["id","person","user_id","topic","document","number","trained_on","trainer","hours","notes","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"delete":{"tags":["Protocolos"],"summary":"Borrar una capacitación","description":"Borrado lógico, para una cargada por error: queda en el historial de cambios. No se ofrece por MCP.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","const":true}},"required":["id","deleted"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/elements":{"get":{"tags":["Seguridad e Higiene"],"summary":"Elementos de seguridad","description":"Matafuegos, duchas, lavaojos, botiquines y demás, con sus controles periódicos: cuándo se hizo el último, cómo dio y cuándo vence el próximo.","parameters":[{"name":"kind","in":"query","required":false,"description":"Solo un tipo (extinguisher, shower, eyewash…).","schema":{"description":"Solo un tipo (extinguisher, shower, eyewash…).","type":"string","enum":["extinguisher","shower","eyewash","first_aid","spill_kit","fume_hood","fire_blanket","emergency_light","smoke_detector","hydrant","alarm_button","emergency_exit","electrical_panel","gas_shutoff","assembly_point","other"]}},{"name":"archived","in":"query","required":false,"description":"include suma los dados de baja.","schema":{"description":"include suma los dados de baja.","type":"string","enum":["include"]}},{"name":"due","in":"query","required":false,"description":"true: solo los que tienen un control vencido o por vencer, o con falla.","schema":{"description":"true: solo los que tienen un control vencido o por vencer, o con falla.","type":"string","enum":["true"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["extinguisher","shower","eyewash","first_aid","spill_kit","fume_hood","fire_blanket","emergency_light","smoke_detector","hydrant","alarm_button","emergency_exit","electrical_panel","gas_shutoff","assembly_point","other"]},"kind_label":{"type":"string"},"name":{"type":"string"},"identifier":{"type":"string"},"place":{"type":["string","null"]},"location_detail":{"type":"string"},"agent":{"type":"string"},"capacity":{"type":"string"},"charge_level":{"anyOf":[{"type":"string","enum":["full","low","empty"]},{"type":"null"}],"description":"Solo matafuegos: cómo está la carga según el manómetro."},"charge_label":{"type":["string","null"]},"responsible":{"type":["string","null"]},"archived":{"type":"boolean"},"checks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"every":{"type":"number"},"unit":{"type":"string","enum":["week","month","year"]},"provider":{"type":"string"},"responsible":{"description":"La persona del laboratorio que lo hace, si hay una asignada.","type":["string","null"]},"last_done_on":{"type":["string","null"]},"last_result":{"anyOf":[{"type":"string","enum":["ok","observed","failed"]},{"type":"null"}]},"next_due_on":{"type":["string","null"]},"state":{"type":"string","enum":["none","ok","due_soon","overdue"]}},"required":["id","name","every","unit","provider","responsible","last_done_on","last_result","next_due_on","state"],"additionalProperties":false}}},"required":["id","kind","kind_label","name","identifier","place","location_detail","agent","capacity","charge_level","charge_label","responsible","archived","checks"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/elements/{id}":{"get":{"tags":["Seguridad e Higiene"],"summary":"Ver un elemento de seguridad","description":"Por id, nombre o identificación. Con sus controles y los últimos 50 registrados.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","enum":["extinguisher","shower","eyewash","first_aid","spill_kit","fume_hood","fire_blanket","emergency_light","smoke_detector","hydrant","alarm_button","emergency_exit","electrical_panel","gas_shutoff","assembly_point","other"]},"kind_label":{"type":"string"},"name":{"type":"string"},"identifier":{"type":"string"},"place":{"type":["string","null"]},"location_detail":{"type":"string"},"agent":{"type":"string"},"capacity":{"type":"string"},"charge_level":{"anyOf":[{"type":"string","enum":["full","low","empty"]},{"type":"null"}],"description":"Solo matafuegos: cómo está la carga según el manómetro."},"charge_label":{"type":["string","null"]},"responsible":{"type":["string","null"]},"archived":{"type":"boolean"},"checks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"every":{"type":"number"},"unit":{"type":"string","enum":["week","month","year"]},"provider":{"type":"string"},"responsible":{"description":"La persona del laboratorio que lo hace, si hay una asignada.","type":["string","null"]},"last_done_on":{"type":["string","null"]},"last_result":{"anyOf":[{"type":"string","enum":["ok","observed","failed"]},{"type":"null"}]},"next_due_on":{"type":["string","null"]},"state":{"type":"string","enum":["none","ok","due_soon","overdue"]}},"required":["id","name","every","unit","provider","responsible","last_done_on","last_result","next_due_on","state"],"additionalProperties":false}},"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"check":{"type":"string"},"done_on":{"type":"string"},"next_due_on":{"type":["string","null"]},"result":{"type":"string","enum":["ok","observed","failed"]},"result_label":{"type":"string"},"performer":{"type":"string"},"notes":{"type":"string"}},"required":["id","check","done_on","next_due_on","result","result_label","performer","notes"],"additionalProperties":false}}},"required":["id","kind","kind_label","name","identifier","place","location_detail","agent","capacity","charge_level","charge_label","responsible","archived","checks","records"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/checks/{id}/records":{"post":{"tags":["Seguridad e Higiene"],"summary":"Registrar un control","description":"Registra que se hizo un control (el id sale de los controles de un elemento). Mueve el próximo vencimiento: el de next_due_on o, sin él, la fecha más la frecuencia. Con resultado failed, el elemento queda marcado con falla hasta otro control bien.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"done_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Cuándo se hizo (AAAA-MM-DD). Por defecto, hoy."},"next_due_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Próximo vencimiento, el que figura en la tarjeta o el certificado (AAAA-MM-DD, posterior a done_on). Por defecto, se calcula con la frecuencia del control."},"result":{"default":"ok","description":"ok, observed (con observaciones) o failed (con falla).","type":"string","enum":["ok","observed","failed"]},"performer_name":{"type":"string","maxLength":120,"description":"Quién lo hizo, si no es la persona del token (el técnico del proveedor)."},"notes":{"type":"string","maxLength":1000,"description":"Notas del control."}}}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"next_due_on":{"type":["string","null"]}},"required":["id","next_due_on"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/hazards":{"get":{"tags":["Seguridad e Higiene"],"summary":"Peligros por lugar","description":"Sale de Insumos: los artículos con pictogramas de peligro (GHS01–GHS09) que tienen stock, agrupados por mueble (armario, heladera…; si están sueltos, la sala), con las incompatibilidades orientativas por pictograma y los artículos sin hoja de seguridad adjunta.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"place":{"type":"string"},"room":{"type":"string"},"hazards":{"type":"array","items":{"type":"string"}},"conflicts":{"type":"array","items":{"type":"object","properties":{"level":{"type":"string","enum":["apart","separate"]},"why":{"type":"string"},"pictograms":{"type":"array","items":{"type":"string"}},"items":{"type":"array","items":{"type":"string"}}},"required":["level","why","pictograms","items"],"additionalProperties":false}},"items":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"hazards":{"type":"array","items":{"type":"string"}},"quantity":{"type":"number"},"unit":{"type":"string"},"place_path":{"type":"string"},"has_sds":{"type":"boolean"}},"required":["code","name","hazards","quantity","unit","place_path","has_sds"],"additionalProperties":false}}},"required":["place","room","hazards","conflicts","items"],"additionalProperties":false}},"missing_sds":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}},"required":["code","name"],"additionalProperties":false}}},"required":["data","missing_sds"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/waste":{"get":{"tags":["Seguridad e Higiene"],"summary":"Residuos","description":"Las corrientes de residuos con lo que hay en acopio y desde cuándo, y los registros (generado y retiros) del período, del más nuevo al más viejo.","parameters":[{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD). Por defecto, el trimestre en curso (residuos) o el último período cerrado (controladas).","schema":{"description":"Desde este día (AAAA-MM-DD). Por defecto, el trimestre en curso (residuos) o el último período cerrado (controladas).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive.","schema":{"description":"Hasta este día inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"additionalProperties":false},"streams":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"code":{"type":"string"},"category":{"type":"string"},"unit":{"type":"string"},"stored":{"type":"number"},"days_in_storage":{"type":["number","null"]},"max_storage_days":{"type":["number","null"]},"over_max":{"type":"boolean"},"last_pickup":{"type":["string","null"]}},"required":["id","name","code","category","unit","stored","days_in_storage","max_storage_days","over_max","last_pickup"],"additionalProperties":false}},"records":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"stream":{"type":"string"},"kind":{"type":"string","enum":["generated","pickup"]},"occurred_on":{"type":"string"},"quantity":{"type":"number"},"manifest_number":{"type":"string"},"transporter":{"type":"string"},"operator":{"type":"string"},"notes":{"type":"string"}},"required":["id","stream","kind","occurred_on","quantity","manifest_number","transporter","operator","notes"],"additionalProperties":false}}},"required":["period","streams","records"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Seguridad e Higiene"],"summary":"Registrar residuos","description":"Registra residuo generado o un retiro (con manifiesto, transportista y operador).\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"stream":{"type":"string","minLength":1,"description":"La corriente: su id, nombre o código (Y41)."},"kind":{"type":"string","enum":["generated","pickup"],"description":"generated: residuo generado; pickup: un retiro."},"occurred_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Fecha (AAAA-MM-DD). Por defecto, hoy."},"quantity":{"type":"number","exclusiveMinimum":0},"manifest_number":{"type":"string","maxLength":60,"description":"Solo retiros: n.º de manifiesto."},"transporter":{"type":"string","maxLength":120,"description":"Solo retiros: transportista."},"operator":{"type":"string","maxLength":120,"description":"Solo retiros: operador o planta de tratamiento."},"notes":{"type":"string","maxLength":1000,"description":"Notas."}},"required":["stream","kind","quantity"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/controlled":{"get":{"tags":["Seguridad e Higiene"],"summary":"Informe de sustancias controladas","description":"Por cada sustancia controlada de Insumos, en el período: existencia inicial, ingresos, consumos, descartes, ajustes y existencia final, en la unidad del informe. Sin fechas, el último período cerrado. También dice si ese período ya se presentó y cuándo vence, y cuál es la próxima presentación (el período en curso) y su vencimiento.","parameters":[{"name":"from","in":"query","required":false,"description":"Desde este día (AAAA-MM-DD). Por defecto, el trimestre en curso (residuos) o el último período cerrado (controladas).","schema":{"description":"Desde este día (AAAA-MM-DD). Por defecto, el trimestre en curso (residuos) o el último período cerrado (controladas).","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},{"name":"to","in":"query","required":false,"description":"Hasta este día inclusive.","schema":{"description":"Hasta este día inclusive.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"registry":{"type":"string"},"registration":{"type":"string"},"period":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"additionalProperties":false},"last_closed":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"due_on":{"type":"string"},"submitted_on":{"type":["string","null"]}},"required":["from","to","due_on","submitted_on"],"additionalProperties":false},"next":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"due_on":{"type":"string"}},"required":["from","to","due_on"],"additionalProperties":false},"data":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"official_name":{"type":"string"},"registry_code":{"type":"string"},"cas_number":{"type":"string"},"list":{"type":"string"},"unit":{"type":"string"},"stock_start":{"type":"number"},"receipts":{"type":"number"},"consumption":{"type":"number"},"discards":{"type":"number"},"adjustments":{"type":"number"},"stock_end":{"type":"number"}},"required":["code","name","official_name","registry_code","cas_number","list","unit","stock_start","receipts","consumption","discards","adjustments","stock_end"],"additionalProperties":false}}},"required":["registry","registration","period","last_closed","next","data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/incidents":{"get":{"tags":["Seguridad e Higiene"],"summary":"Incidentes","description":"Accidentes, casi accidentes, derrames y exposiciones, con su acción correctiva y si están cerrados, del más nuevo al más viejo (hasta 500).","parameters":[{"name":"open","in":"query","required":false,"description":"true: solo los abiertos (por defecto, todos).","schema":{"description":"true: solo los abiertos (por defecto, todos).","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"occurred_at":{"type":"string"},"kind":{"type":"string","enum":["injury","near_miss","spill","fire","exposure","other"]},"kind_label":{"type":"string"},"severity":{"type":"string","enum":["minor","moderate","serious"]},"severity_label":{"type":"string"},"title":{"type":"string"},"place":{"type":["string","null"]},"location_detail":{"type":"string"},"description":{"type":"string"},"people_involved":{"type":"string"},"immediate_action":{"type":"string"},"root_cause":{"type":"string"},"corrective_action":{"type":"string"},"corrective_due_on":{"type":["string","null"]},"responsible":{"type":["string","null"]},"closed_at":{"type":["string","null"]},"closing_note":{"type":"string"},"version":{"type":"number"}},"required":["id","occurred_at","kind","kind_label","severity","severity_label","title","place","location_detail","description","people_involved","immediate_action","root_cause","corrective_action","corrective_due_on","responsible","closed_at","closing_note","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Seguridad e Higiene"],"summary":"Registrar un incidente","description":"Registra un incidente. El lugar y el responsable se eligen desde la web.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":160,"description":"Título corto («Derrame de fenol en la campana»)."},"occurred_at":{"description":"Cuándo pasó, en la hora del laboratorio (AAAA-MM-DDTHH:MM). Por defecto, ahora.","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}$"},"kind":{"type":"string","enum":["injury","near_miss","spill","fire","exposure","other"],"description":"injury, near_miss, spill, fire, exposure u other."},"severity":{"default":"minor","description":"minor, moderate o serious.","type":"string","enum":["minor","moderate","serious"]},"location_detail":{"type":"string","maxLength":160,"description":"Dónde pasó."},"description":{"type":"string","maxLength":4000,"description":"Qué pasó."},"people_involved":{"type":"string","maxLength":1000,"description":"Personas involucradas."},"immediate_action":{"type":"string","maxLength":2000,"description":"Qué se hizo en el momento."},"root_cause":{"type":"string","maxLength":2000,"description":"Causa."},"corrective_action":{"type":"string","maxLength":2000,"description":"Acción correctiva."},"corrective_due_on":{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Plazo de la acción correctiva (AAAA-MM-DD)."}},"required":["title","kind"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"occurred_at":{"type":"string"},"kind":{"type":"string","enum":["injury","near_miss","spill","fire","exposure","other"]},"kind_label":{"type":"string"},"severity":{"type":"string","enum":["minor","moderate","serious"]},"severity_label":{"type":"string"},"title":{"type":"string"},"place":{"type":["string","null"]},"location_detail":{"type":"string"},"description":{"type":"string"},"people_involved":{"type":"string"},"immediate_action":{"type":"string"},"root_cause":{"type":"string"},"corrective_action":{"type":"string"},"corrective_due_on":{"type":["string","null"]},"responsible":{"type":["string","null"]},"closed_at":{"type":["string","null"]},"closing_note":{"type":"string"},"version":{"type":"number"}},"required":["id","occurred_at","kind","kind_label","severity","severity_label","title","place","location_detail","description","people_involved","immediate_action","root_cause","corrective_action","corrective_due_on","responsible","closed_at","closing_note","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/incidents/{id}/close":{"post":{"tags":["Seguridad e Higiene"],"summary":"Cerrar un incidente","description":"Cierra un incidente cuando la acción correctiva está hecha, con una nota opcional.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"note":{"type":"string","maxLength":1000,"description":"Qué se hizo para cerrarlo."}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"closed_at":{"type":"string"}},"required":["id","closed_at"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/people/fields":{"get":{"tags":["Seguridad e Higiene"],"summary":"Campos del personal","description":"Campos base y propios del laboratorio (carnet de vacunación, EPP entregados, aptos…), con su tipo y opciones: dicen qué significa cada clave de custom_fields.","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"Clave estable: los campos personalizados aparecen así en custom_fields."},"label":{"type":"string"},"type":{"type":"string","enum":["text","long_text","number","date","boolean","select","multiselect","link","attachment"]},"custom":{"type":"boolean","description":"true si lo definió el laboratorio."},"required":{"type":"boolean"},"unit":{"type":["string","null"]},"help":{"type":["string","null"]},"options":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Opciones vigentes, para las listas."},"archived":{"type":"boolean"}},"required":["key","label","type","custom","required","unit","help","options","archived"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/people":{"get":{"tags":["Seguridad e Higiene"],"summary":"Personal","description":"Quién trabaja en el laboratorio, con los campos propios del laboratorio.","parameters":[{"name":"archived","in":"query","required":false,"description":"include suma a quienes ya no trabajan en el laboratorio.","schema":{"description":"include suma a quienes ya no trabajan en el laboratorio.","type":"string","enum":["exclude","include"]}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"string"},"document_id":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"started_on":{"type":["string","null"]},"account":{"description":"Nombre de su cuenta en Vialo, si tiene.","type":["string","null"]},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Campos propios del laboratorio por clave (ver safety/people/fields)."},"notes":{"type":"string"},"archived":{"type":"boolean","description":"Ya no trabaja en el laboratorio."},"version":{"type":"number"}},"required":["id","name","position","document_id","email","phone","started_on","account","custom_fields","notes","archived","version"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"post":{"tags":["Seguridad e Higiene"],"summary":"Sumar una persona al personal","description":"Suma a alguien que trabaja en el laboratorio. La cuenta en Vialo y los campos de tipo archivo se cargan desde la web.\n\nPide un token con rol Colaborador.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Clave única de la operación (por ejemplo un UUID). Si el pedido se repite con la misma clave en 24 horas, no se vuelve a ejecutar y se recibe la primera respuesta.","schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre y apellido."},"position":{"type":"string","maxLength":80,"description":"Cargo o función (becaria, técnico…)."},"document_id":{"type":"string","maxLength":40,"description":"DNI, pasaporte o legajo."},"email":{"type":"string","maxLength":200,"description":"Mail."},"phone":{"type":"string","maxLength":40,"description":"Teléfono."},"started_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día de ingreso al laboratorio."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["name"]}}}},"responses":{"201":{"description":"Creado","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"string"},"document_id":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"started_on":{"type":["string","null"]},"account":{"description":"Nombre de su cuenta en Vialo, si tiene.","type":["string","null"]},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Campos propios del laboratorio por clave (ver safety/people/fields)."},"notes":{"type":"string"},"archived":{"type":"boolean","description":"Ya no trabaja en el laboratorio."},"version":{"type":"number"}},"required":["id","name","position","document_id","email","phone","started_on","account","custom_fields","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/safety/people/{id}":{"get":{"tags":["Seguridad e Higiene"],"summary":"Ver una persona del personal","description":"Por id o por nombre.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"string"},"document_id":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"started_on":{"type":["string","null"]},"account":{"description":"Nombre de su cuenta en Vialo, si tiene.","type":["string","null"]},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Campos propios del laboratorio por clave (ver safety/people/fields)."},"notes":{"type":"string"},"archived":{"type":"boolean","description":"Ya no trabaja en el laboratorio."},"version":{"type":"number"}},"required":["id","name","position","document_id","email","phone","started_on","account","custom_fields","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}},"patch":{"tags":["Seguridad e Higiene"],"summary":"Modificar una persona del personal","description":"Cambia solo lo que mandás (datos, campos propios, o si ya no trabaja en el laboratorio). Pide la «version».\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"La «version» que devolvió la API al leer el registro. Si alguien lo cambió después, la respuesta es 409 y no se pisa nada."},"name":{"type":"string","minLength":1,"maxLength":120,"description":"Nombre y apellido."},"archived":{"description":"true: ya no trabaja en el laboratorio; false: volvió.","type":"boolean"},"position":{"type":"string","maxLength":80,"description":"Cargo o función (becaria, técnico…)."},"document_id":{"type":"string","maxLength":40,"description":"DNI, pasaporte o legajo."},"email":{"type":"string","maxLength":200,"description":"Mail."},"phone":{"type":"string","maxLength":40,"description":"Teléfono."},"started_on":{"anyOf":[{"type":"string","format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","description":"Día de ingreso al laboratorio."},{"type":"null"}]},"notes":{"type":"string","maxLength":1000,"description":"Notas."},"custom_fields":{"description":"Campos personalizados por clave (ver …/fields). Las listas aceptan el texto de la opción. Los de tipo attachment se adjuntan desde la web: acá solo se pueden vaciar. null borra el valor; las claves que no se mandan quedan como estaban.","type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["version"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"position":{"type":"string"},"document_id":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"started_on":{"type":["string","null"]},"account":{"description":"Nombre de su cuenta en Vialo, si tiene.","type":["string","null"]},"custom_fields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"Campos propios del laboratorio por clave (ver safety/people/fields)."},"notes":{"type":"string"},"archived":{"type":"boolean","description":"Ya no trabaja en el laboratorio."},"version":{"type":"number"}},"required":["id","name","position","document_id","email","phone","started_on","account","custom_fields","notes","archived","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/floorplan/plans":{"get":{"tags":["Lugares · Plano"],"summary":"Planos y qué hay en cada sala","description":"Los planos del laboratorio (uno por planta o sector), con sus salas dibujadas: a qué sala de Lugares corresponde cada una y lo que tiene adentro (freezers y demás lugares con sus tubos, equipos y elementos de seguridad, según los módulos que se usan).","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"building":{"type":"string"},"label":{"type":"string"},"has_image":{"type":"boolean"},"areas":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"group":{"type":"string"},"color":{"type":"string"},"room":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},{"type":"null"}]},"tubes":{"type":"number"},"places":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["equipment","safety","place"]},"id":{"type":"string"},"name":{"type":"string"},"detail":{"type":"string"},"reference":{"type":"string"},"tubes":{"type":"number"},"pinned":{"type":"boolean"}},"required":["kind","id","name","detail","reference","tubes","pinned"],"additionalProperties":false}},"equipment":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["equipment","safety","place"]},"id":{"type":"string"},"name":{"type":"string"},"detail":{"type":"string"},"reference":{"type":"string"},"tubes":{"type":"number"},"pinned":{"type":"boolean"}},"required":["kind","id","name","detail","reference","tubes","pinned"],"additionalProperties":false}},"safety":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["equipment","safety","place"]},"id":{"type":"string"},"name":{"type":"string"},"detail":{"type":"string"},"reference":{"type":"string"},"tubes":{"type":"number"},"pinned":{"type":"boolean"}},"required":["kind","id","name","detail","reference","tubes","pinned"],"additionalProperties":false}}},"required":["id","name","group","color","room","tubes","places","equipment","safety"],"additionalProperties":false}}},"required":["id","name","building","label","has_image","areas"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/floorplan/locate":{"get":{"tags":["Lugares · Plano"],"summary":"Dónde está algo en el plano","description":"Busca por nombre o código equipos, lugares, elementos de seguridad y salas, y tubos por el comienzo de su código, y dice en qué plano y sala está cada uno (y adentro de qué, si es una caja o un rack). Hasta 20.","parameters":[{"name":"q","in":"query","required":true,"description":"Nombre o código de un equipo, lugar, elemento de seguridad o sala, o código de un tubo (empieza así).","schema":{"type":"string","minLength":2,"maxLength":80,"description":"Nombre o código de un equipo, lugar, elemento de seguridad o sala, o código de un tubo (empieza así)."}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["equipment","safety","place","sample"]},"id":{"type":"string"},"name":{"type":"string"},"plan":{"type":["string","null"]},"area":{"type":["string","null"]},"inside":{"type":"array","items":{"type":"string"}},"pinned":{"type":"boolean"}},"required":["kind","id","name","plan","area","inside","pinned"],"additionalProperties":false}}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}},"/floorplan/areas/{id}":{"patch":{"tags":["Lugares · Plano"],"summary":"Enlazar una sala del plano","description":"Dice a qué sala de Lugares corresponde una sala dibujada en el plano (por id o por nombre exacto), o la desenlaza con null. Dibujar salas y poner marcas se hace desde la web.\n\nPide un token con rol Colaborador.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"room":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"description":"La sala de Lugares (id o nombre exacto) que es esta sala del plano; null la desenlaza."},"version":{"description":"Para no pisar un cambio ajeno.","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["room"]}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"room":{"type":["string","null"]},"version":{"type":"number"}},"required":["id","room","version"],"additionalProperties":false}},"required":["data"],"additionalProperties":false}}}},"default":{"description":"Error: 400, 401, 403, 404, 405, 409, 413, 429, 500 o 503, con un código estable y un mensaje en español.","content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}}}}}}