{"name":"ai-api","description":"Proxy y balanceador de IA. Un único endpoint POST /chat con respuesta en streaming, que reparte las peticiones entre varios proveedores (round-robin) con fallback automático.","howItWorks":["Cada petición se asigna a un proveedor rotando por turnos (round-robin).","Si el proveedor del turno falla al iniciar la respuesta, se prueba el siguiente automáticamente.","La respuesta es un stream de texto plano (los trozos del modelo tal cual)."],"authentication":{"scheme":"Bearer","header":"Authorization: Bearer <AUTH_TOKEN>","appliesTo":["POST /chat"],"note":"El <AUTH_TOKEN> lo facilita el administrador de la API por un canal privado. Este endpoint de documentación NUNCA expone su valor, ni las claves de los proveedores."},"endpoints":[{"method":"GET","path":"/","auth":false,"description":"Esta documentación (HTML para navegador, JSON para agentes)."},{"method":"GET","path":"/docs","auth":false,"description":"Alias de /, siempre disponible."},{"method":"GET","path":"/health","auth":false,"description":"Estado del servicio y proveedores disponibles."},{"method":"POST","path":"/chat","auth":true,"description":"Envía una conversación y recibe la respuesta del modelo en streaming.","requestBody":{"messages":"Array no vacío de { role: \"user\" | \"assistant\" | \"system\", content: string }"},"responses":{"200":"Stream de texto plano con la respuesta del modelo.","400":"JSON inválido o \"messages\" mal formado.","401":"Falta o no coincide el token de autorización.","502":"Todos los proveedores de IA fallaron."}}],"streaming":{"contentType":"text/event-stream","note":"El cuerpo es texto plano SIN el prefijo \"data:\" del estándar SSE. NO uses EventSource ni el SDK de OpenAI: lee el ReadableStream directamente."},"examples":{"curl":"curl -N -X POST http://ai-api.aterrasap.es/chat \\\n  -H \"Authorization: Bearer <AUTH_TOKEN>\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"messages\": [ { \"role\": \"user\", \"content\": \"Hola\" } ] }'","typescript":"const res = await fetch(\"http://ai-api.aterrasap.es/chat\", {\n  method: \"POST\",\n  headers: {\n    \"Authorization\": `Bearer ${process.env.AI_API_TOKEN}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ messages: [{ role: \"user\", content: \"Hola\" }] }),\n});\nconst reader = res.body.getReader();\nconst decoder = new TextDecoder();\nwhile (true) {\n  const { done, value } = await reader.read();\n  if (done) break;\n  process.stdout.write(decoder.decode(value, { stream: true }));\n}"},"security":["Guarda tu <AUTH_TOKEN> en una variable de entorno, nunca en el código.","En un frontend público no pongas el token en el navegador: llama a esta API desde tu backend.","Esta API no almacena ni registra el contenido de tus mensajes más allá de reenviarlos al proveedor."]}