POST /v1/systemone
Evalúa un estado con preguntas tipadas y recibe una respuesta por pregunta. Es el endpoint compatible con Jev: la misma solicitud y las mismas respuestas que la API System One de TypeSafe.
POSThttps://api.sonoeai.com/v1/systemone
POST /v1/systemone HTTP/1.1
Host: api.sonoeai.com
Authorization: Bearer sk_sonoe_...
Content-Type: application/jsonCuerpo de la solicitud
statestring | object | arrayrequeridoAquello sobre lo que se decide. Mira Estado.
modelstringrequeridosonoe-latest,sonoe-previewosonoe-1.1.0. Los nombres de Jev (jev-latest,jev-preview,jev-1.x.y) se aceptan como alias. Mira GET /v1/models.questionsmap<string, Question>requeridoHasta 64 preguntas. Tú eliges cada clave y las respuestas vuelven bajo las mismas claves. Cada pregunta es un Noul, un Choice o un Score:
type"noul" | "choice" | "score"requeridoinstructionsstring | object | arrayopcional- La pregunta. Los objetos y las listas se leen como texto, igual que el estado.
criteriaobject | map | arrayopcional- Noul: descripciones de
true/false. Choice: opción → descripción onull(2–255). Score: niveles en orden (2–10).
Los campos desconocidos del nivel superior se ignoran.
Ejemplo
{
"model": "sonoe-latest",
"state": "My card was charged twice for order 4417 and I need the money back today.",
"questions": {
"wants_refund": { "type": "noul", "instructions": "Does the customer want their money back?" },
"team": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "Payments, charges, refunds",
"shipping": "Deliveries and tracking",
"technical": "Bugs, the app or the website"
}
},
"urgency": {
"type": "score",
"instructions": "How urgent is this?",
"criteria": ["Can wait", "Soon", "Today"]
}
}
}Respuesta
modelstringrequerido- El modelo con versión que respondió, p. ej.
sonoe-1.1.0. answersmap<string, Answer>requeridoUna respuesta por pregunta, bajo las mismas claves. Cada respuesta tiene un
type:noulobjectopcional{ type, noul }choiceobjectopcional{ type, choice, probabilities, confidence }scoreobjectopcional{ type, score, legend, probabilities, confidence }
usageobjectrequeridoinput_tokensintegerrequerido- Tokens que Sonoe leyó en esta solicitud. Es lo que se cobra.
output_tokensintegerrequerido- Siempre
0: Sonoe no genera texto.
{
"model": "sonoe-1.1.0",
"answers": {
"wants_refund": { "type": "noul", "noul": 0.8695 },
"team": {
"type": "choice",
"choice": "billing",
"probabilities": { "billing": 0.9913, "shipping": 0.0031, "technical": 0.0056 },
"confidence": 0.9493
},
"urgency": {
"type": "score",
"score": 1.15,
"legend": { "0": "Can wait", "1": "Soon", "2": "Today" },
"probabilities": { "0": 0.2452, "1": 0.3596, "2": 0.3952 },
"confidence": 0.0175
}
},
"usage": { "input_tokens": 372, "output_tokens": 0 }
}Encabezados de la respuesta
| Encabezado | |
|---|---|
x-typesafe-request-id | Un id único de la solicitud, como req_7bd253c46fc2c54145dbe9e9. Los SDK de TypeSafe lo exponen como request_id / requestId. |
x-request-id | El mismo id. |
Retry-After | En un 429: segundos que esperar antes de reintentar. |
Compresión
El cuerpo puede ir comprimido con Content-Encoding: zstd, gzip o x-gzip. Los SDK de TypeSafe comprimen con zstd desde 1 KiB. El límite de tamaño (64 KiB) aplica después de descomprimir. Cualquier otra codificación devuelve 415; un cuerpo que no se puede descomprimir devuelve 400.
Límites
| Cuerpo | 64 KiB, después de descomprimir |
| Preguntas por solicitud | 64 |
| Opciones de Choice | De 2 a 255 |
| Niveles de Score | De 2 a 10 |
| Instrucciones | 8,000 caracteres (Sonoe lee como mucho 256 tokens por opción) |
Imágenes, assets, preguntas Box, cuerpos multipart | No se aceptan (422) |
Errores
Los errores son JSON con error y detail, así que cualquier cliente encuentra un mensaje:
{
"detail": [
{ "loc": ["body", "questions", "tone", "criteria"], "msg": "A Choice needs between 2 and 255 options.", "type": "value_error" }
],
"error": { "type": "invalid_request_error", "message": "questions.tone.criteria: A Choice needs between 2 and 255 options." }
}| Estado | Cuándo |
|---|---|
400 | El cuerpo no es JSON UTF-8 válido, o un cuerpo comprimido no se puede descomprimir. |
401 | Key ausente, inválida o revocada. |
404 | model desconocido. |
413 | El cuerpo pasa de 64 KiB. |
415 | Content-Encoding no admitido. |
422 | Un campo ausente o inválido (detail[].loc dice cuál), o imágenes / Box. |
429 | Pasaste un límite: por minuto, por día, la cuota mensual o el límite de la key. Mira Errores y límites. |
503 | El modelo no está disponible en el servidor ahora mismo. Reintenta en unos segundos. |
Ejemplos
curl https://api.sonoeai.com/v1/systemone \
-H "Authorization: Bearer $SONOE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"sonoe-latest","state":"¡Ayuda! Mis pagos llevan 3 días fallando.","questions":{"urgente":{"type":"noul","instructions":"¿Es urgente?"}}}'from typesafe_sdk import Noul, TypeSafeClient
# TYPESAFE_BASE_URL=https://api.sonoeai.com y TYPESAFE_API_KEY=sk_sonoe_… en el entorno
client = TypeSafeClient()
result = client.system_one(
"¡Ayuda! Mis pagos llevan 3 días fallando.",
{"urgente": Noul(instructions="¿Es urgente?")},
)
print(result.nouls["urgente"].noul, result.request_id)import { noul, TypeSafeClient } from "@typesafe-ai/sdk";
// TYPESAFE_BASE_URL=https://api.sonoeai.com y TYPESAFE_API_KEY=sk_sonoe_… en el entorno
const client = new TypeSafeClient();
const { data, requestId } = await client
.systemOne({
state: "¡Ayuda! Mis pagos llevan 3 días fallando.",
questions: { urgente: noul("¿Es urgente?") },
})
.withResponse();
console.log(data.answers.urgente.noul, requestId);