spicyapiDocumentación
Cuenta y facturación
Contenido principal

Facturación

Consulta cómo se factura el uso de SpicyAPI en USD: cotizaciones, retenciones, cargos finales, fondos, límites de gasto y facturas.

Dinero, no créditos

Los precios se expresan en dólares estadounidenses: «$0.008 por imagen», «$0.042 por segundo de salida». Los fondos prepagados, las aportaciones promocionales y las líneas de crédito se denominan en dólares, pero un límite de crédito no es un saldo en efectivo.

Evitar un sistema de créditos es una decisión deliberada. Ese sistema añade una conversión entre «recarga X y recibe Y de bono» y «cuánto vale un crédito», lo que dificulta calcular el costo real por unidad. El precio que ves es el que pagas.

Cómo funciona el pago

  1. Primero añade fondos. Una cuenta nueva empieza con un saldo de $0 y no hay un nivel gratuito. Una tarea enviada antes de añadir fondos se rechaza con 40201 y no tiene costo.
  2. Al aceptar una tarea, se reserva su precio estimado. Esto se llama retención. El dinero sigue siendo tuyo, pero no puede pagar otra tarea al mismo tiempo.
  3. Si la tarea termina correctamente, pagas lo que realmente se utilizó, sin superar la retención. El importe restante vuelve a tu saldo.
  4. Las tareas fallidas o vencidas normalmente liberan toda la retención. Algunos rechazos de contenido se cobran al precio aceptado únicamente si la página del modelo informa expresamente de esa excepción. Consulta settled y cost para conocer el cargo final.
  5. Los límites de gasto de cada clave de API impiden que un script fuera de control vacíe tu saldo.

El resto de esta página explica cada paso en detalle.

Añadir fondos

Añade fondos en Facturación, dentro de la consola, con tarjeta, criptomonedas o transferencia manual cuando aparezca esa opción. También puedes activar la recarga automática para que los trabajos largos no se detengan cuando el saldo baje. El saldo pagado no vence; el crédito promocional vence en la fecha que aparece en Facturación.

Para ver los pasos, las opciones de pago, cuándo llegan los fondos y cómo funciona la recarga automática, consulta Configuración de la cuenta. Las recargas generalmente no se reembolsan en efectivo; la política de reembolsos detalla las excepciones, como un cargo duplicado.

Tres fases

Todas las tareas pasan por las mismas tres fases de facturación. No tienes que hacer nada en ellas; las describimos para que puedas interpretar tu historial de saldo con confianza.

hold
settlerelease
El importe se retiene al aceptar la tarea y se resuelve una sola vez: se liquida según el uso real o se devuelve completo.

Retención

Al crear una tarea retenemos fondos para el uso estimado. El importe es exactamente el estimatedCost devuelto por createTask.

Una retención reserva las fuentes de financiación utilizadas por esa tarea; no es un cargo final. Los fondos prepagados reservados, las aportaciones disponibles o el crédito aprobado no pueden financiar otra tarea al mismo tiempo. Aparece como held en GET /api/v1/chat/credit y como «Retenido» en la consola.

La retención y el registro de la tarea se guardan en una sola transacción de base de datos. No existe un estado intermedio en el que haya una tarea sin retención, o al revés.

Liquidación o liberación

  • succeeded → se liquida según el uso real, con el límite de la retención aceptada. Los fondos no utilizados se liberan a sus fuentes originales; no se cobra después ningún importe que supere esa retención.
  • failed / expired → normalmente se libera el importe completo. La página de un modelo puede indicar expresamente que ciertos fallos content_rejected se cobran al precio aceptado. Los registros históricos canceled también liberan el importe completo, pero actualmente no se pueden cancelar las tareas aceptadas.

Cuando termina la liquidación, recordInfo informa settled: true y cost es definitivo. Mientras settled sea false, cost todavía puede cambiar.

Proceso de recuperación

Si nuestro proceso se interrumpe durante la ejecución, un proceso de recuperación encuentra las retenciones asociadas a tareas que ya alcanzaron un estado final y completa su liquidación o liberación según el resultado registrado.

La liquidación y la liberación comparten una clave de deduplicación, por lo que el ciclo de facturación de cada tarea termina exactamente una vez: los reintentos no pueden contabilizarlo dos veces.

Consulta la liquidación, además del estado de la tarea

Las tareas fallidas o vencidas normalmente liberan toda la retención. Algunos rechazos de contenido se cobran al precio aceptado únicamente si la página del modelo informa expresamente de esa excepción. Consulta settled y cost para conocer el cargo final. Un rechazo cobrado mantiene state: "failed" con errorCode: "content_rejected"; una vez liquidado, settled es true y cost es positivo. Los demás fallos y las tareas vencidas liberan automáticamente toda la retención.

Consultar tu saldo

La forma más rápida es la página Facturación de la consola: muestra tu saldo disponible, el importe retenido y todos los movimientos. Desde tu código, llama a:

GET /api/v1/chat/credit
curl
curl https://api.spicyapi.ai/api/v1/chat/credit \
  -H "Authorization: Bearer $SPICY_API_KEY"
JavaScript
const res = await fetch('https://api.spicyapi.ai/api/v1/chat/credit', {
  headers: { Authorization: `Bearer ${process.env.SPICY_API_KEY}` },
});
const body = await res.json();
if (body.code !== 200) throw new Error(`${body.code} ${body.msg}`);

const balance = body.data;
console.log(balance.funding ?? balance);
Python
import os, requests

res = requests.get(
    "https://api.spicyapi.ai/api/v1/chat/credit",
    headers={"Authorization": f"Bearer {os.environ['SPICY_API_KEY']}"},
)
body = res.json()
if body["code"] != 200:
    raise RuntimeError(f'{body["code"]} {body["msg"]}')

balance = body["data"]
print(balance.get("funding", balance))
{
  "code": 200,
  "msg": "success",
  "data": {
    "available": "128.42",
    "held": "0.36",
    "total": "128.78"
  }
}
CampoSignificado
availableImporte neto de la cuenta; puede ser negativo tras utilizar crédito aprobado y no basta por sí solo para comprobar si una tarea será aceptada
heldImporte reservado para tareas en ejecución
totalSuma de los dos anteriores

Si los fondos disponibles para el modelo y el momento seleccionados no cubren la estimación, createTask devuelve 40201. El vencimiento del crédito, los límites agotados y un déficit por recuperación de pagos también pueden afectar la aceptación. No sustituyas las comprobaciones del servidor por una prueba en el cliente que solo compruebe el signo de available.

No necesitas consultar el saldo antes de cada generación: la aceptación de la tarea ya comprueba el saldo disponible y los límites de gasto.

En la API, los importes son cadenas sin el símbolo del dólar

«$0.008» es la forma en que esta página muestra los precios a los lectores. La API devuelve una cadena decimal sin símbolo de moneda: estimatedCost, cost y los tres campos del saldo tienen el formato "0.008": sin $, sin separadores y siempre en USD.

// Keep the exact decimal string for display
const usd = task.cost;

Se utilizan cadenas en lugar de números JSON de forma deliberada: en la mayoría de los lenguajes, un número JSON se convierte en un float64, y 0.008 no tiene una representación binaria exacta. Si vas a registrar el importe en tu contabilidad, interprétalo como un decimal:

from decimal import Decimal
usd = Decimal(task["cost"])   # not float()

Límites de gasto

Un límite de gasto establece cuánto dinero se puede gastar. Una tarea puede estar sujeta a hasta seis límites; el primero que se alcance rechaza la tarea con 40202, antes de crearla o retener fondos:

LímiteQuién lo definemsg al alcanzarlo
Límite total de la claveTú, en la página de claves de API. Es el máximo para toda la vida de esa claveThis key has reached its total spend cap
Límite mensual de la claveTú, en la página de claves de API. Es el presupuesto de este mes calendarioThis key has reached its monthly budget
Límite diario de la claveTú, en la página de claves de API. Las claves nuevas no tienen límite salvo que lo establezcasThis key has reached its daily spend cap
Límite diario del equipoPropietarios, administradores y responsables de presupuesto, en la página del equipo. Solo se aplica a claves que pertenecen a un equipoWorkspace daily budget has been reached
Límite mensual del equipoIgual que el anteriorWorkspace monthly budget has been reached
Límite diario de la plataformaNosotros. Es nuestra protección general; tú no puedes aumentarloPlatform quota for today is exhausted, please try again later

Los límites diarios se reinician a las 00:00 UTC; los mensuales siguen el mes calendario en UTC y se reinician el día 1. El límite total nunca se reinicia. Si se alcanza el límite de la plataforma, reintenta después de las 00:00 UTC o contacta con soporte si sigue ocurriendo.

Una retención pendiente cuenta para todos los límites, totales, mensuales y diarios, hasta que se liquide la tarea, sin importar el día o el mes: el dinero todavía no se ha gastado, pero tampoco puede gastarse dos veces. Los límites de equipo se describen en Consola y equipos.

Un campo de límite vacío no significa lo mismo en todos los casos

  • Al crear o editar una clave: dejar el límite vacío significa sin límite, igual que 0. Las claves nuevas no tienen límite salvo que lo establezcas. Vaciar un límite de una clave existente lo elimina; para conservarlo, deja un número en el campo.
  • Límites de gasto del equipo: un campo vacío conserva el valor actual; 0 significa sin límite.

Los límites existen para protegerte. Un bucle fuera de control que consume un importe elevado en unas horas es un incidente habitual en este sector y casi siempre ocurre en una cuenta sin límite configurado.

Registro de movimientos

La página Facturación de la consola muestra todos los movimientos del saldo con etiquetas claras, como Recarga, Retenido, Cobrado y Devuelto. Al descargar la lista mediante Exportar CSV, la columna kind contiene uno de estos códigos estables:

TipoSignificado
topupDinero que pagaste, añadido a tu saldo
bonusImporte adicional de una oferta de recarga, contabilizado por separado de lo que pagaste
trialCrédito de una campaña de prueba, separado de recargas y bonos
holdImporte estimado reservado al aceptar una tarea; no es un cargo
settleCargo final de la tarea, incluido un rechazo de contenido cobrado según las condiciones del modelo; la parte no utilizada de la retención se devuelve
refundDevolución de toda la retención porque la tarea falló o agotó el tiempo de espera
adjustCorrección manual de nuestro equipo; siempre incluye la identidad del operador y un motivo
chargebackSaldo retirado tras una disputa de pago
forfeitSaldo restante al que renunciaste al cerrar tu cuenta
grant_expireFondos promocionales no utilizados retirados después de vencer
grant_revokeFondos promocionales no utilizados revocados

El registro solo permite añadir entradas. Una entrada existente nunca se reescribe: la devolución de una retención crea una entrada nueva, no borra la original. Así se puede recalcular cualquier saldo desde el principio y demostrar por qué los números coinciden o no.

El crédito de bono se contabiliza por separado de lo que pagaste porque un reembolso del pago, es decir, dinero devuelto a tu tarjeta, solo cubre el importe pagado; un bono no tiene valor en efectivo. Esto no está relacionado con las entradas refund anteriores, que devuelven a tu saldo la retención de una tarea fallida.

Estos movimientos se conservan durante 10 años, separados del contenido de las tareas, para que sigan disponibles para conciliaciones y disputas mucho después de que se eliminen los prompts y resultados. Consulta Retención de datos.

Facturas e informes de uso

Puedes emitir dos documentos desde Facturación → Facturas en la consola, ambos descargables en PDF:

DocumentoQué cubre¿Es un documento de pago?
Factura de pagoUna recarga que ya pagaste, por el importe cobradoSí. Es la que debes presentar para solicitar un reembolso de gastos
Informe de usoLo que realmente gastaste en un mes ya cerradoNo. Ese dinero se pagó al recargar; presentar ambos equivaldría a reclamar el mismo dinero dos veces

Introduce tus datos una vez en la parte superior de Facturación → Facturas. Son obligatorios el nombre de tu empresa o el tuyo, la primera línea de la dirección, la ciudad y el país; el número fiscal, como VAT o GST, es opcional. Los datos se imprimen tal como los introduces: tú los proporcionas y nosotros no verificamos ninguno, incluido el número fiscal. Solo se pueden imprimir caracteres latinos, griegos y cirílicos, por lo que debes escribir el nombre de una empresa japonesa o coreana en su forma romanizada registrada. Un documento ya emitido conserva los datos del momento de emisión; las modificaciones posteriores solo afectan a documentos nuevos.

  • Cada recarga pagada y cada mes cerrado se puede documentar una vez. Si el documento ya existe, descárgalo en lugar de emitir otro.
  • Para corregir datos incorrectos, selecciona Volver a emitir: el documento anterior se marca como anulado y se genera otro con un número nuevo para el mismo concepto. Usa Anular sin sustituir únicamente cuando el documento corresponda a una recarga o mes incorrectos.
  • Los estados de cuenta, más abajo en la misma página, son distintos: una instantánea mensual fija de todos los movimientos del saldo para tu contabilidad. No son recibos ni documentos fiscales.

El impuesto figura como cero: somos un proveedor estadounidense y no recaudamos ni remitimos VAT, GST o impuestos sobre ventas en tu nombre. Todos los documentos incluyen un aviso de inversión del sujeto pasivo, de modo que debes gestionar cualquier impuesto que corresponda donde estés. Una factura emitida nunca se edita: se anula y se vuelve a emitir, dejando registrados el motivo y el documento sustituto.

Unidades de facturación

Cada modelo tiene exactamente una unidad de facturación.

UnidadSignificadoQué campo de input aporta la cantidad
per_imagePor imagen generadaEl campo que declare el modelo; el valor predeterminado es 1
per_secondPor segundo de salida. Algunos endpoints redondean la duración hacia arriba a un bloque fijo; consulta Duración facturada en bloques completosConsulta el quantityField y el esquema actuales; el campo estándar de duración es duration_seconds. No supongas que omitir la duración selecciona el nivel más corto.
per_requestPor llamada, sin importar los parámetros—
per_1k_tokensPor token. La unidad de la API es per_1k_tokens; el sitio web y price.perMillionTokens del catálogo muestran los mismos precios por millón de tokens. La entrada, la entrada en caché, las escrituras en caché y la salida pueden tener precios distintos—

No tienes que adivinar el nombre: quantityField del endpoint del catálogo lo indica para cada modelo; una cadena vacía significa una unidad por llamada.

Un modelo puede tener precios diferentes según el nivel. La resolución, la duración, las opciones de audio y los medios de referencia pueden afectar la cotización, según su esquema. pricing[].variant identifica un nivel de la tabla de precios; no hay un campo variant en el cuerpo de la solicitud. No supongas que esa etiqueta siempre se puede enviar como resolution, ni calcules todos los modelos como precio inicial × duración. Envía la entrada completa a jobs/quote para obtener la estimación exacta y el límite del cargo.

Consulta siempre la cantidad y el precio en el catálogo actualizado

No fijes en el código un campo de cantidad para toda una categoría de modelos. Un quantityField vacío significa una unidad de facturación por llamada; si no está vacío, consulta la estimación a partir del campo de entrada indicado. Los niveles, valores predeterminados y reglas de facturación pueden cambiar con el catálogo. El cargo tiene como límite el importe retenido al aceptar la tarea: los fondos no utilizados se liberan y no se cobra después nada por encima de esa retención.

Duración facturada en bloques completos

La mayoría de los modelos per_second factura la duración exacta que produce. Algunos facturan en bloques fijos: la duración medida se redondea hacia arriba al siguiente bloque completo antes de calcular el precio. Si el bloque es de 8 segundos, un clip de 6 y uno de 8 segundos cuestan lo mismo, mientras que uno de 9 segundos cuesta dos bloques. No todos los modelos por segundo funcionan así: solo se aplica a los endpoints que lo declaran y cada uno lo indica en su página.

También tienen algo en común que explica el redondeo de la cotización: obtienen la duración de un video que tú proporcionas, en lugar de un valor duration_seconds elegido por ti. Por eso no se conoce la duración del resultado hasta leer el clip. Su quantityField está vacío y el importe cotizado antes del envío corresponde al peor caso: el clip más largo que acepta el endpoint:

{
  "estimatedCost": "0.96",
  "maxCharge": "0.96",
  "quantity": "32",
  "unit": "per_second"
}

Los importes son ilustrativos; aquí quantity es un máximo en segundos, no una medición. El importe cotizado es el importe retenido; el cargo final se calcula según la duración redondeada y nunca supera la retención. El resto se libera al liquidar la tarea, igual que en las tres fases anteriores.

La retención será mayor que el cargo final

Es el comportamiento esperado de estos endpoints, no un cobro excesivo. Entre la aceptación y la liquidación, tu saldo muestra el máximo retenido porque, hasta leer el clip, no se conoce la duración del resultado. Cuando se liquida la tarea se cobra la duración real redondeada al bloque y la diferencia vuelve automáticamente a tu saldo. El registro conserva ambos movimientos, por lo que siempre se pueden comparar hold y settle.

De aquí se derivan dos cosas que conviene prever:

  • Calcula tu presupuesto con la cotización, no con tu clip. Hasta liquidar la tarea, el importe reservado es el máximo y cuenta para tus límites de gasto como cualquier otra retención.
  • Un clip corto también cuesta un bloque completo. Recortar de 9 a 8 segundos puede reducir a la mitad el precio de un endpoint con bloques de 8 segundos; recortar de 8 a 5 no cambia nada.

Las unidades y los precios exactos aparecen en la página de precios y en la página de cada modelo.

Descuentos y promociones para clientes

Las ofertas pueden aplicarse a todos o a una cuenta concreta, en todos los modelos o solo en algunos. Las ofertas continuas permanecen activas hasta deshabilitarse; las temporales solo se aplican entre su inicio y fin reales. Los precios particulares se aplican cuando esa cuenta inicia sesión o solicita una cotización con su clave de API, y nunca se publican como precios de otro cliente.

Las ofertas no se acumulan. Se aplica automáticamente el menor precio al que tengas derecho. Para un cargo estándar de $10, una oferta pública del 10% y un descuento de cuenta del 20% dan un precio de $8, no un descuento compuesto de $7.20. Cuando una oferta termina o se deshabilita, las nuevas cotizaciones utilizan la mejor oferta restante que te corresponda, o el precio estándar si no queda ninguna.

Las ofertas de la página de inicio, el catálogo y las páginas de modelos te ayudan a comparar opciones. Obtén la estimación real de jobs/quote con tu identidad, modelo y entradas completas. Una cuenta regresiva no reserva un precio: actualiza la cotización cuando cambie una oferta, una entrada o un precio. Las tareas aceptadas conservan su precio fijado aunque la oferta termine durante la ejecución, y el cargo final no puede superar lo retenido al aceptarlas.

Las ofertas se aplican automáticamente a los cargos de uso de la API, no al importe que recargas, y no ofrecen devolución de dinero por recarga. Los ejemplos de presupuesto diario o mensual extrapolan el precio actual; una oferta temporal puede terminar antes que ese periodo de presupuesto, por lo que también debes comprobar su fecha de fin.

Fondos promocionales y líneas de crédito

GET /api/v1/chat/credit conserva available, held y total, y puede incluir un desglose funding. Las respuestas antiguas pueden omitir funding; que falte un dato no significa cero. Usa client.getBalance() en el SDK o spicyapi balance --json en la CLI.

  • funding.prepaidAvailableUsd contiene los fondos disponibles prepagados o heredados sin restricciones; grantAvailableUsd suma las aportaciones activas. Cada entrada de grants indica importes otorgados, disponibles, retenidos y gastados, estado, inicio, vencimiento y modelSlugs. Una lista de modelos vacía significa todos los modelos; de lo contrario, la aportación solo paga los modelos enumerados. La lista contiene hasta 100 aportaciones, prioriza las que tienen saldo restante o retenido y después las ordena de más reciente a más antigua. grantsHasMore indica que hay más registros. No sustituyas el total de la cuenta por el subtotal de la lista visible.
  • funding.credit describe una línea aprobada de pago diferido. limitUsd es su máximo, availableUsd es el crédito disponible que cumple las condiciones, usedUsd es el principal ya contabilizado y pendiente de pago, heldUsd es lo reservado para tareas aceptadas y expiresAt es su vencimiento. El límite de crédito no es una recarga, una aportación ni un saldo en efectivo. Vencer, deshabilitarse o superar el límite restringe las nuevas solicitudes; la deuda existente sigue siendo pagadera.
  • Los fondos promocionales no se pueden retirar. Los descuentos fijan el precio de la solicitud; las aportaciones y el crédito determinan cómo se financia ese precio. Una aportación no reduce el precio de la tabla del modelo. Se aplican su alcance de modelos y su vigencia, y los importes no utilizados pueden vencer o revocarse. Las tareas fallidas y las reservas no utilizadas liberan los fondos a su fuente original; eso no reactiva una aportación vencida o revocada.
  • Un funding.cashShortfallUsd positivo indica un déficit por recuperación externa de pagos. Las aportaciones y el crédito no pueden cubrirlo; las llamadas nuevas permanecen bloqueadas hasta cubrirlo. En cambio, un available negativo puede reflejar el uso de crédito aprobado. No deduzcas un rechazo a partir de su signo ni lo sumes directamente al límite de crédito. El servidor comprueba las fuentes de fondos, la disponibilidad para el modelo, la vigencia y los límites de gasto.

Los importes siguen siendo cadenas decimales exactas en USD y las fechas usan RFC3339. Indica la zona horaria al mostrar fechas. La página de facturación de la consola muestra detalles de fondos y aportaciones; los cambios solo entran en vigor tras la aprobación manual de un administrador. Para preguntar por aportaciones o líneas de crédito, abre una conversación en Soporte dentro de la consola o escribe a support@spicyapi.ai. La API pública no ofrece operaciones de escritura para aumentar tu propia capacidad ni emitir aportaciones.

Uso de la clave de API actual

Para ver un gráfico del gasto por día y por modelo de toda tu cuenta o de un equipo, usa Facturación → Uso en la consola. El siguiente endpoint de la API informa únicamente sobre la clave que lo llama:

curl 'https://api.spicyapi.ai/api/v1/usage?from=2026-09-01&to=2026-09-06' \
  -H "Authorization: Bearer $SPICY_API_KEY"

Las fechas usan UTC [from,to), por lo que este ejemplo incluye del 1 al 5 de septiembre. Omite las fechas para consultar los últimos siete días, incluido hoy; el intervalo máximo es de 92 días. Los resultados pertenecen únicamente a la clave de API actual. No hay un parámetro para consultar otra clave ni un informe de toda la cuenta; usa chat/credit para el saldo de la cuenta.

data.totalCalls cuenta todas las tareas; data.totalSpend solo incluye cargos liquidados. days y models agrupan las mismas tareas por fecha de creación y modelo, con cadenas decimales exactas en USD. Se excluyen las retenciones pendientes y una liquidación tardía puede actualizar fechas anteriores. El historial de tareas oculto sigue incluido; se omiten los días sin llamadas. No sumes las dos agrupaciones.

Usa client.getUsage({ from, to }) en el SDK o spicyapi usage --from 2026-09-01 --to 2026-09-06 en la CLI. Este endpoint tiene su propio límite de solicitudes, más estricto; consulta Límites de solicitudes.

En esta página