Contrato de solicitud: una lista de etiquetas
Envía POST /api/v1/decisions con Authorization: Bearer YOUR_API_KEY, Content-Type: application/json e Idempotency-Key de 8 a 100 caracteres. El cuerpo incluye text (3–6.000 caracteres), instructions (3–1.500), labels (2–12 opciones únicas de hasta 60 caracteres en una línea) y threshold (0,5–1, valor inicial 0,85).
La clave pertenece a una cuenta con un periodo de acceso activo; créala en el panel del espacio de trabajo. Cada solicitud completada consume un crédito. Las pruebas anónimas tienen un límite separado y nunca exponen tus credenciales.
Un cuerpo es de una forma o de la otra. Envía instructions con labels para una decisión de una etiqueta, o questions para una tipada, nunca ambas; y reutiliza la misma Idempotency-Key solo para la misma solicitud lógica.
Prueba la misma solicitud en el área de pruebas · Crea y revoca una clave API · Tutorial de Jev en OpenRouter
Contrato de solicitud: preguntas tipadas
Envía questions en lugar de instructions y labels para plantear hasta cuatro preguntas tipadas sobre el mismo texto. Cada pregunta tiene un id (1–32 caracteres: minúsculas, números o guiones bajos, empezando por letra y único en la solicitud), un tipo, instructions (3–1.500 caracteres) y sus criterios: de 2 a 12 etiquetas para choice, exactamente true y false para noul, y de 2 a 7 niveles ordenados de hasta 80 caracteres para score. La línea de guía de un criterio puede estar vacía, pero no superar 300 caracteres ni ocupar dos líneas.
Un cuerpo que lleve questions junto con instructions o labels se rechaza con 400 ambiguous_input, igual que una solicitud con más de cuatro preguntas o un id repetido. Una solicitud cuesta un crédito en ambos casos: preguntar más cambia cuánto se responde, no el precio.
{
"text": "La página de pago se queda en blanco al pulsar Pagar. Probé dos navegadores.",
"questions": [
{"id": "team", "type": "choice", "instructions": "¿Qué equipo debería atender este ticket?", "criteria": {"facturacion": "Cobros o reembolsos.", "tecnico": "Errores o fallos.", "cuenta": "Acceso, permisos o perfil."}},
{"id": "is_bug", "type": "noul", "instructions": "¿Quien escribe informa de un defecto?", "criteria": {"true": "Describe un comportamiento roto.", "false": "Hace una pregunta o pide una función."}},
{"id": "urgency", "type": "score", "instructions": "¿Con qué urgencia necesita respuesta?", "criteria": ["Puede esperar", "Esta semana", "Bloquea su trabajo"]}
],
"threshold": 0.85
}El LLM como juez: reglas tipadas auditables · Clasificación por lotes y exportación
Contrato de respuesta
Una decisión nueva responde 201 con choice, confidence, probabilities, needsReview, model, id y latencyMs. model indica el modelo Jev que respondió; esta implementación solicita typesafe/jev-1.13. Una solicitud de cuenta devuelve además los créditos restantes, y una repetición idempotente añade replayed: true.
Una solicitud tipada añade answers: una entrada por id de pregunta, con el tipo que pediste. Un choice incluye su etiqueta, confianza y probabilidades; un noul incluye una probabilidad entre 0 y 1 y ninguna confianza, porque el proveedor no la envía; un score incluye su posición en tus niveles con confianza, probabilidades y una leyenda cuando el proveedor la aporta. Los campos choice, confidence y probabilities de nivel superior reflejan la primera pregunta —un noul como true o false con confianza null y mapa vacío— y needsReview es true cuando alguna respuesta requiere revisión.
needsReview es la lectura de este servicio según tu umbral. Un choice o un score quedan por debajo si falta la confianza o si es menor que el umbral; un noul se mide directamente por su probabilidad, así que 0,80 requiere revisión con umbral 0,85. Las probabilidades solo se validan por dominio y límites: no deben sumar uno, la mayor no tiene que coincidir con la respuesta y una tabla ausente llega como {}. Un fallo del modelo es una respuesta de error, nunca una etiqueta por defecto.
{
"answers": {
"team": { "type": "choice", "choice": "tecnico", "confidence": 0.88, "probabilities": { "facturacion": 0.03, "tecnico": 0.88, "cuenta": 0.09 }, "needsReview": false },
"is_bug": { "type": "noul", "noul": 0.93, "needsReview": false },
"urgency": { "type": "score", "score": 2, "confidence": 0.80, "probabilities": { "0": 0.03, "1": 0.17, "2": 0.80 }, "needsReview": true }
},
"choice": "tecnico",
"confidence": 0.88,
"probabilities": { "facturacion": 0.03, "tecnico": 0.88, "cuenta": 0.09 },
"needsReview": true,
"model": "typesafe/jev-1.13",
"id": "6f2c1a4e-9d7b-4c11-8f3a-2b5e9c0d1a77",
"latencyMs": 1180,
"credits": 19
}Reintentos seguros
Usa una clave por solicitud lógica y conserva el contenido exacto si desconoces el resultado, incluido un error genérico de pasarela. Repetir una solicitud completada devuelve el resultado sin otro cargo, con replayed: true. Un 409 idempotency_conflict indica contenido distinto; un 409 request_running exige conservar la clave y esperar. Solo cuando la API confirme request_failed, resuelve la causa y crea una nueva clave para otro intento. Limita los reintentos y guarda el identificador para soporte.
