{"openapi":"3.1.0","info":{"title":"Corag Ayuda directa API","version":"1.6.0","description":"API pública e idempotente para consultar el panorama, buscar ayudas, leer cobertura y trazabilidad, y enviar solicitudes u ofrecimientos a revisión en Corag. La identidad documental del solicitante no forma parte del contrato público. Corag publica además sus centros de acopio en el Protocolo Cabuya 0.1 (manifiesto en /.well-known/cabuya.json, feed en /api/cabuya/places); ese feed no transporta datos de personas."},"servers":[{"url":"https://ayuda.corag.org"}],"tags":[{"name":"Consulta","description":"Panorama, búsqueda, cobertura y línea de tiempo públicas."},{"name":"Publicación","description":"Envío idempotente de solicitudes y ofrecimientos a la bandeja de revisión."},{"name":"Logística","description":"Traslados disponibles con origen, destino y trazabilidad."},{"name":"MCP","description":"Servidor remoto para asistentes y agentes."}],"paths":{"/api/public/v1/inventario":{"get":{"tags":["Consulta"],"summary":"Qué tiene y qué le falta a cada centro de acopio","description":"Cantidades declaradas por cada centro, con unidad y antigüedad. Con categoria responde «quién tiene ya esto en la ciudad», que es lo que convierte una necesidad en un traslado en vez de una compra. Cada línea trae hoursSinceUpdate y stale: pasadas 24 horas la cantidad puede ya no estar.","parameters":[{"name":"emergencia","in":"query","schema":{"type":"string","example":"eje-cafetero"}},{"name":"categoria","in":"query","description":"Filtra por categoría y añade el listado plano de existencias en «stock».","schema":{"type":"string","enum":["alimentos","agua","medicamentos","higiene","panales","mascotas","ropa","salud","refugio","transporte","herramientas","voluntariado","acopio","rescate","otro"]}}],"responses":{"200":{"description":"Inventario agrupado por centro","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Inventario"}}}},"500":{"description":"No fue posible consultar el inventario"}}}},"/api/public/v1/help":{"get":{"tags":["Consulta"],"summary":"Descubrir la API, consultar panorama, buscar o ver una ayuda","description":"Sin view devuelve descubrimiento. Usa view=panorama, view=list o view=detail. La lectura nunca devuelve documentos privados.","parameters":[{"name":"view","in":"query","schema":{"type":"string","enum":["discovery","panorama","list","detail"],"default":"discovery"}},{"name":"id","in":"query","description":"Obligatorio para view=detail.","schema":{"type":"string"}},{"name":"emergencySlug","in":"query","schema":{"type":"string","example":"eje-cafetero"}},{"name":"type","in":"query","schema":{"type":"string","enum":["all","request","offer"],"default":"all"}},{"name":"status","in":"query","schema":{"type":"string","enum":["all","active","in_process","completed"],"default":"active"}},{"name":"category","in":"query","schema":{"type":"string","enum":["alimentos","agua","medicamentos","higiene","panales","mascotas","ropa","salud","refugio","transporte","herramientas","voluntariado","acopio","rescate","otro"]}},{"name":"priority","in":"query","schema":{"type":"string","enum":["all","urgent","deficit","near_covered"],"default":"all"}},{"name":"q","in":"query","description":"Busca título, descripción, ubicación, categoría o nombre público.","schema":{"type":"string","maxLength":120}},{"name":"latitude","in":"query","schema":{"type":"number","minimum":-4.3,"maximum":13.6}},{"name":"longitude","in":"query","schema":{"type":"number","minimum":-79.1,"maximum":-66.8}},{"name":"radiusKm","in":"query","schema":{"type":"number","minimum":0.1,"maximum":500,"default":25}},{"name":"logistics","in":"query","description":"Con true devuelve solicitudes activas compatibles con operación logística.","schema":{"type":"boolean","default":false}},{"name":"capacity","in":"query","description":"Máxima cantidad pendiente que puede transportar la oferta.","schema":{"type":"number","minimum":0}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Consulta pública","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Discovery"},{"$ref":"#/components/schemas/Panorama"},{"$ref":"#/components/schemas/HelpList"},{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"item":{"$ref":"#/components/schemas/PublicHelp"}}}]}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"404":{"description":"Ayuda no encontrada"}}},"post":{"tags":["Publicación"],"summary":"Enviar una solicitud o un ofrecimiento a revisión","description":"No requiere autenticación. Lo recibido entra a la bandeja de la emergencia y un líder decide si se publica: no aparece en el mapa por enviarlo. source + externalId hacen la operación idempotente. El contacto se publica si se aprueba, y requiere consentimiento explícito.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Opcional; la idempotencia principal usa source + externalId."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/HelpRequest"},{"$ref":"#/components/schemas/HelpOffer"}]}}}},"responses":{"202":{"description":"Recibido y en espera de revisión","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishResult"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"413":{"description":"Solicitud demasiado grande"},"415":{"description":"Se requiere application/json"},"429":{"description":"Límite temporal alcanzado"}}},"options":{"summary":"CORS preflight","responses":{"204":{"description":"CORS habilitado"}}}},"/api/logistics-operations":{"get":{"tags":["Logística"],"summary":"Listar operaciones logísticas disponibles","description":"Devuelve rutas con recogida y destino confirmados. No expone el contacto privado del voluntario.","parameters":[{"name":"emergencia","in":"query","required":true,"schema":{"type":"string","example":"eje-cafetero"}}],"responses":{"200":{"description":"Rutas disponibles","content":{"application/json":{"schema":{"type":"object","properties":{"operations":{"type":"array","items":{"$ref":"#/components/schemas/LogisticsOperation"}},"canManage":{"type":"boolean","const":false}}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"}}}},"/mcp":{"get":{"tags":["MCP"],"summary":"Abrir transporte MCP Streamable HTTP","responses":{"200":{"description":"Flujo MCP"}}},"post":{"tags":["MCP"],"summary":"Enviar mensajes MCP","description":"Herramientas: listar_emergencias, consultar_panorama, buscar_ayudas, ver_ayuda, buscar_operaciones_logisticas, publicar_solicitud y publicar_ofrecimiento (ambas envían a revisión, no publican).","responses":{"200":{"description":"Respuesta MCP"}}},"delete":{"tags":["MCP"],"summary":"Cerrar una sesión MCP","responses":{"200":{"description":"Sesión cerrada"}}}}},"components":{"responses":{"InvalidRequest":{"description":"Datos o filtros inválidos","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Common":{"type":"object","required":["source","externalId","title","category","contactName","contactWhatsapp","publishContact"],"properties":{"source":{"type":"string","example":"mi-app","description":"Nombre estable de la integración."},"externalId":{"type":"string","example":"caso-1842","description":"Identificador estable en la aplicación de origen."},"emergencySlug":{"type":"string","example":"eje-cafetero","description":"Obligatorio cuando hay varias emergencias activas."},"title":{"type":"string","minLength":4,"maxLength":100},"description":{"type":"string","maxLength":600},"category":{"type":"string","enum":["alimentos","agua","medicamentos","higiene","panales","mascotas","ropa","salud","refugio","transporte","herramientas","voluntariado","acopio","rescate","otro"]},"contactName":{"type":"string","minLength":2,"maxLength":100},"contactWhatsapp":{"type":"string","example":"+573001234567"},"publishContact":{"type":"boolean","const":true,"description":"Confirma que nombre y WhatsApp pueden mostrarse públicamente."}}},"HelpRequest":{"allOf":[{"$ref":"#/components/schemas/Common"},{"type":"object","required":["type","address","latitude","longitude"],"properties":{"type":{"type":"string","const":"request"},"address":{"type":"string","minLength":4,"maxLength":180},"neighborhood":{"type":"string","maxLength":80},"latitude":{"type":"number","minimum":-4.3,"maximum":13.6},"longitude":{"type":"number","minimum":-79.1,"maximum":-66.8},"urgency":{"type":"string","enum":["urgent","needed","stable"],"default":"needed"},"neededPeople":{"type":"integer","minimum":0,"maximum":10000,"default":1,"deprecated":true,"description":"Alias compatible. Para recursos usa quantityRequired y unit."},"resourceLabel":{"type":"string","maxLength":160,"example":"Mercados familiares"},"quantityRequired":{"type":"number","exclusiveMinimum":0,"maximum":1000000,"example":12},"unit":{"type":"string","minLength":1,"maxLength":40,"example":"mercados"}}}]},"HelpOffer":{"allOf":[{"$ref":"#/components/schemas/Common"},{"type":"object","required":["type"],"properties":{"type":{"type":"string","const":"offer"},"address":{"type":"string","maxLength":180},"latitude":{"type":"number","minimum":-4.3,"maximum":13.6},"longitude":{"type":"number","minimum":-79.1,"maximum":-66.8},"collectionCenterStatus":{"type":"string","enum":["full","needs_volunteers","needs_resources"]},"vehicle":{"type":"string","maxLength":80,"example":"Camioneta"},"capacityKg":{"type":"number","minimum":0,"maximum":100000},"capacityBoxes":{"type":"integer","minimum":0,"maximum":100000},"passengerCapacity":{"type":"integer","minimum":0,"maximum":10000},"zones":{"type":"string","maxLength":180,"example":"Pereira, Dosquebradas y Santa Rosa"},"availableUntil":{"type":"string","format":"date","example":"2026-08-20"},"needsTransport":{"type":"boolean","description":"Indica que la ayuda ofrecida necesita recogida y coordinación logística."}}}]},"PublicHelp":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["request","offer"]},"emergency":{"type":"object"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"urgency":{"type":"string"},"status":{"type":"string"},"operationalStatus":{"type":"string"},"priorityScore":{"type":"number"},"location":{"type":"object"},"contact":{"type":"object"},"quantities":{"type":["object","null"]},"resources":{"type":"array","items":{"type":"object"}},"verification":{"type":"object"},"logistics":{"type":["object","null"]},"collectionCenter":{"type":["object","null"]},"timeline":{"type":"array","items":{"type":"object"}},"publicUrl":{"type":"string","format":"uri"}}},"LogisticsOperation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"emergency_slug":{"type":"string"},"destination_help_point_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"supply_description":{"type":"string"},"quantity_label":{"type":["string","null"]},"pickup_address":{"type":"string"},"pickup_latitude":{"type":"number"},"pickup_longitude":{"type":"number"},"destination_address":{"type":"string"},"destination_latitude":{"type":"number"},"destination_longitude":{"type":"number"},"distance_km":{"type":"number"},"route_conditions":{"type":["string","null"]},"status":{"type":"string","const":"available"},"created_at":{"type":"string","format":"date-time"}}},"HelpList":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"total":{"type":"integer"},"returned":{"type":"integer"},"filters":{"type":"object"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PublicHelp"}}}},"Panorama":{"type":"object","properties":{"generatedAt":{"type":"string","format":"date-time"},"emergencies":{"type":"array","items":{"type":"object"}},"counts":{"type":"object"},"quantities":{"type":"object"},"routes":{"type":"object"}}},"LineaInventario":{"type":"object","properties":{"id":{"type":"string"},"collectionCenterId":{"type":"string"},"kind":{"type":"string","enum":["have","need"]},"category":{"type":"string"},"categoryLabel":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string"},"note":{"type":"string"},"updatedAt":{"type":"string","format":"date-time"},"hoursSinceUpdate":{"type":"number"},"stale":{"type":"boolean","description":"Cierto pasadas 24 horas sin tocarse: la cantidad puede ya no estar."}}},"Inventario":{"type":"object","properties":{"emergencySlug":{"type":"string"},"category":{"type":"string","nullable":true},"stock":{"type":"array","items":{"$ref":"#/components/schemas/LineaInventario"}},"centers":{"type":"array","items":{"type":"object","properties":{"collectionCenterId":{"type":"string"},"title":{"type":"string"},"location":{"type":"string","nullable":true},"status":{"type":"string","nullable":true},"have":{"type":"array","items":{"$ref":"#/components/schemas/LineaInventario"}},"need":{"type":"array","items":{"$ref":"#/components/schemas/LineaInventario"}}}}}}},"Discovery":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"public":{"type":"boolean"},"documentation":{"type":"string"},"openapi":{"type":"string"},"mcp":{"type":"string"},"views":{"type":"object"},"capabilities":{"type":"array","items":{"type":"string"}},"emergencies":{"type":"array","items":{"type":"object"}}}},"PublishResult":{"type":"object","properties":{"ok":{"type":"boolean"},"queued":{"type":"boolean"},"id":{"type":"string"},"type":{"type":"string"},"emergencySlug":{"type":"string"},"reviewStatus":{"type":"string"},"message":{"type":"string"}}},"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{}}}}}}