spicyapiDocumentación
Desarrollar con la API
Contenido principal

Cotizaciones y compatibilidad de protocolos

Conoce el precio exacto de una solicitud antes de pagar, envíala a ese precio, recupérate de una respuesta perdida y entiende cómo se cobran las API compatibles de texto y de video.

Cotiza una solicitud exacta

Una cotización te dice el precio de una solicitud concreta antes de pagar. Es gratuita, no crea ninguna tarea ni retiene fondos. Después envías esa misma solicitud con la cotización adjunta, de modo que solo se acepta al precio que se te mostró.

Los comandos siguientes son para una terminal de macOS o Linux, con SPICY_API_KEY definida como en el Inicio rápido. MODEL_ID_FROM_CATALOG es un marcador: usa un valor de model de tu catálogo en vivo (GET /api/v1/models) y toma cada campo de input del esquema de ese modelo.

Guarda la solicitud que vas a enviar

Crea un archivo llamado request.json con exactamente el model, el input y, si lo usas, el callBackUrl que vas a enviar:

request.json
{
  "model": "MODEL_ID_FROM_CATALOG",
  "input": { "prompt": "A cinematic night portrait" }
}

Pide el precio

curl https://api.spicyapi.ai/api/v1/jobs/quote \
  -H "Authorization: Bearer $SPICY_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @request.json
{
  "code": 200,
  "msg": "success",
  "data": {
    "quoteId": "QUOTE_ID_FROM_RESPONSE",
    "model": "MODEL_ID_FROM_CATALOG",
    "estimatedCost": "0.008",
    "maxCharge": "0.008",
    "currency": "USD",
    "quantity": "1",
    "unit": "per_image",
    "expiresAt": "2026-09-17T10:05:00Z"
  },
  "request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}

Los importes son cadenas decimales en dólares estadounidenses. maxCharge es lo máximo que puede costar esta solicitud; hoy es siempre igual a estimatedCost. quantity y unit indican qué se está contando, por ejemplo segundos de video. Muestra el importe y expiresAt a quien tenga que aprobar el gasto.

Una cotización pasa las mismas comprobaciones que un envío real, así que ya puede fallar en este punto: 400 (la entrada no coincide con el esquema del modelo), 40201 (saldo insuficiente), 40202 (un límite de gasto de la clave o la cuota de la plataforma) o 403 (esta clave no puede usar el modelo).

Envía la misma solicitud con la cotización adjunta

Antes de que pasen cinco minutos, envía la solicitud sin cambios a createTask con dos campos más: quoteId, tomado de la cotización, y expectedCost, con el valor de estimatedCost que se cotizó. Este paso cuesta dinero.

submit.json
{
  "model": "MODEL_ID_FROM_CATALOG",
  "input": { "prompt": "A cinematic night portrait" },
  "quoteId": "QUOTE_ID_FROM_RESPONSE",
  "expectedCost": "0.008"
}
SPICY_IDEMPOTENCY_KEY="$(uuidgen)"   # una por cada tarea nueva; reutilízala solo para reenviar esta misma solicitud

curl https://api.spicyapi.ai/api/v1/jobs/createTask \
  -H "Authorization: Bearer $SPICY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
  --data-binary @submit.json

La respuesta es la respuesta normal de tarea 202 Accepted que se describe en el Inicio rápido. La cotización no sustituye al Idempotency-Key: envía las dos cosas.

La cotización está ligada aDeja de valer cuando
Tu cuenta y la clave de API con la que se pidióEnvías la solicitud con otra clave
El model, el input y el callBackUrl exactosCambia cualquiera de ellos, aunque sea un solo carácter del prompt. El orden de los campos y los espacios no importan
El precio de ese momentoPasan cinco minutos o cambia el precio

40901 significa que la cotización ya no describe la solicitud

Una entrada modificada, otra clave de API, una cotización caducada, un precio que ha cambiado o un expectedCost distinto del cotizado se manifiestan todos igual: la aceptación falla con 40901 y no se cobra nada. Vuelve a cotizar y a confirmar; no quites quoteId y expectedCost para forzar el envío sin precio confirmado.

POST /api/v1/jobs/stream, el stream nativo de texto, acepta una cotización de la misma manera; consulta Texto y streaming.

Recuperarse de una respuesta perdida

Si un envío agotó el tiempo de espera o se cortó la conexión, no sabes si se aceptó. Para createTask, retry y POST /v1/videos:

  1. Reenvía la solicitud original con su Idempotency-Key original y con la misma clave de API. Recibes la tarea original, en su estado actual, y no se te cobra dos veces.
  2. No crees otra tarea con una clave de idempotencia nueva. Una clave nueva significa una generación nueva y un cobro nuevo.
  3. Reenviar una solicitud ya aceptada sigue siendo válido aunque la cotización haya caducado. La caducidad solo condiciona la aceptación, no la tarea que esa aceptación creó.
  4. Un 409 no significa «no se creó». O bien la solicitud cambió (es un trabajo nuevo que necesita una clave nueva), o bien se envió con otra clave de API de la misma cuenta (reenvíala con la clave original). Consulta Idempotencia.
  5. Lee cost y settled en recordInfo para conocer el cobro final.

Las solicitudes de texto y streaming no se pueden recuperar así

La respuesta a una solicitud de texto (/api/v1/jobs/stream y los endpoints de texto bajo /v1 y /v1beta) se te envía a medida que se genera y no se almacena. Reenviar una clave ya aceptada devuelve un error en lugar de la respuesta: 400 si el cuerpo es el mismo y 409 si es distinto. No se cobra nada más, pero la respuesta perdida no se puede recuperar. Para volver a obtener una respuesta, envía la solicitud con una clave nueva y págala. Consulta en Idempotencia qué endpoints leen la cabecera.

Una estimación no es una liquidación

estimatedCost es lo que esperamos cobrar. La marca de fin de texto en un stream solo dice que dejaron de llegar bytes. Ninguna de las dos demuestra que el cobro sea definitivo. En las tareas, lo demuestra settled: true junto con cost en recordInfo. Las llamadas de texto no devuelven ID de tarea: encuentra su cobro enumerando las tareas con la misma clave de API (GET /api/v1/jobs) o en Consola → Registros, y considera cost definitivo cuando settled sea true.

Las cotizaciones en las herramientas oficiales

La CLI y el servidor MCP piden una cotización y preguntan a una persona antes de cada llamada de pago, así que no tienes que construir este paso tú:

  • CLI: spicyapi tasks quote calcula el precio de una solicitud; spicyapi tasks create vuelve a cotizar, muestra el importe y pregunta antes de crear la tarea. Consulta Costos, confirmación y seguridad.
  • MCP: el asistente puede pedir cotizaciones libremente, pero crear una tarea te pregunta a ti a través de tu cliente de IA, mostrando el precio. Consulta Costos, confirmación y seguridad.
  • SDK: quoteTask devuelve la cotización; pasa su quoteId y su estimatedCost a createTask o a run.

Un agente no debe confirmar en nombre del usuario

La confirmación existe para que decida una persona. Un agente que la responde por su cuenta, o un cliente configurado para aprobar automáticamente, ha eliminado el único límite de gasto que había en esa vía.

Compatibilidad de texto y video

SpicyAPI también habla los formatos de OpenAI, Anthropic y Google Gemini para los modelos de texto, y el formato OpenAI Videos para el video. La lista completa de endpoints está en la referencia de la API; las solicitudes, los streams y los errores de cada protocolo están en Texto y streaming.

URL base. El formato OpenAI usa https://api.spicyapi.ai/v1. Los SDK de Anthropic y de Google GenAI añaden ellos mismos /v1 o /v1beta, así que configura su URL base como https://api.spicyapi.ai.

Credencial. Una sola clave de API para todos, en la cabecera Authorization: Bearer. También se aceptan la cabecera x-api-key que usa el SDK de Anthropic y la cabecera x-goog-api-key que usa el SDK de Google GenAI. Un ?key= en la URL no se acepta nunca.

Modelo. Elige un modelo exacto del catálogo en vivo. Que funcionen las herramientas, los mensajes con imágenes y las opciones de generación depende del esquema de ese modelo, no del protocolo que hayas elegido.

Forma de la respuesta. Cada protocolo devuelve su propia envoltura, no la envoltura {code, msg, data, request_id} de la plataforma.

Campos de razonamiento

Los modelos de chat que exponen el texto de su razonamiento pueden devolver una cadena opcional en message.reasoning_content, o en delta.reasoning_content durante el streaming. Al continuar después de una llamada a una herramienta, puedes conservarla en el mensaje del asistente correspondiente si el esquema del modelo en vivo lo admite.

usage.completion_tokens_details.reasoning_tokens describe la parte de razonamiento ya incluida en completion_tokens; no la sumes otra vez. No todos los modelos devuelven texto de razonamiento ni este desglose de tokens.

Dos formatos que conviene conocer antes de empezar

  • Responses exige la conversación completa en input. previous_response_id no se admite.
  • Videos acepta JSON con model, prompt, input_reference, seconds y size, que se traducen a los campos propios del modelo. El id de video que devuelve es también un ID de tarea que acepta recordInfo. Su endpoint de contenido redirige con HTTP 302 a una URL firmada de corta duración.

Las API compatibles cobran el precio del momento de aceptación

quoteId y expectedCost solo se aplican a jobs/createTask y jobs/stream. /v1 y /v1beta usan el precio vigente cuando se acepta la solicitud y rechazan esos dos campos, así que por esa vía no hay confirmación de precio por llamada. Cuando un flujo tenga que confirmar un límite de cobro, usa la API de tareas nativa; para acotar todo lo que puede gastar una clave, fija sus límites diario, mensual y acumulado, como se explica en Autenticación.

Para ver un ejemplo de chat en streaming con los clientes oficiales de OpenAI, Anthropic y Google, consulta Usa un SDK oficial. La CLI y el servidor MCP envían y siguen tareas nativas; no transmiten en streaming los tokens de chat.

En esta página