Tu app de personajes adultos promete una imagen nueva. El cliente pulsa Generar, la animación de espera dura un rato y después la página indica que la conexión agotó su tiempo. Pulsa otra vez. Un minuto después aparecen dos imágenes y el saldo baja dos veces.
La segunda puede ser preciosa. Sigue siendo una forma cara de descubrir que un timeout de conexión no es una generación fallida.
En una API de imágenes NSFW se llaman reintento tres acciones distintas: comprobar una tarea existente, repetir su envío original y pagar otro intento creativo. Sepáralas. Si tienes un ID de tarea, consulta esa tarea. Si desapareció la respuesta de creación, repite la solicitud sin cambios con su clave original de idempotencia. Si la tarea terminó pero la imagen no cumple el encargo, otra generación es una compra nueva.
Esta última distinción importa especialmente en imágenes de personajes adultos. Un modelo puede terminar correctamente y suavizar la escena, cambiar la ropa o producir otro rostro. El éxito de tarea dice que se entregó un resultado; no promete que quieras utilizarlo.
¿Qué ocurrió y qué botón debes ofrecer?
| Qué ve el cliente | Qué sabes realmente | Siguiente acción |
|---|---|---|
| La solicitud agotó el tiempo antes de devolver un ID | No se sabe si fue aceptada | Repite la misma creación con la misma clave |
Tienes ID y la tarea está queued o running | Ya existe una generación | Consulta el estado; no crees otra tarea |
Está failed o expired | El intento llegó a un resultado terminal | Lee el motivo y el cargo liquidado antes de otro intento |
| El modelo rechazó la solicitud NSFW | Se rechazó esta solicitud concreta | Revisa comportamiento de contenido y nota de cobro del modelo/tarea exactos |
| Llegó una imagen, pero personaje o escena son incorrectos | La generación funcionó; no cumplió la intención | Decide si merece otro cargo editar o crear una variación |
| No se descarga la imagen | Falló la entrega o caducó el enlace | Recupera el recurso existente mientras siga disponible |

Esperar, recuperar un envío y crear otra variación son acciones diferentes.
Una interfaz útil para creadores adultos podría llamarlas Consultar imagen existente, Recuperar envío, Generar otra variación e Intentar descargar de nuevo. Una sola etiqueta Reintentar oculta la diferencia entre consultar gratis el estado y autorizar más gasto en generación.
Si tienes un ID, conserva la tarea original
El flujo asíncrono de imágenes de SpicyAPI acepta una solicitud, devuelve un ID y permite acceder a la imagen después. Una respuesta de creación aceptada no es la imagen terminada. La tarea pasa por estados como queued, running y succeeded; failed, canceled y expired también son terminales.
Guarda el ID en cuanto el servidor lo reciba, antes de actualizar el navegador. Si un cliente recarga, vuelve a iniciar sesión o abre su proyecto en otro dispositivo, la app debe recuperar esa tarea guardada y no volver a enviar el prompt.
Por ejemplo, un creador solicita un retrato de noche de su personaje adulto ficticio. El servidor recibe un ID, pero el navegador pierde conexión antes de mostrar la tarjeta de espera. Al volver, la tarjeta debe reconectarse a esa tarea. Recargar la página no significa pedir otro retrato.
Usa GET /api/v1/jobs/recordInfo con el ID para recuperar el estado. La documentación de tareas describe solicitud y respuesta. Puedes usar un webhook para recibir la finalización, pero un webhook retrasado no convierte la tarea existente en fallo. Consultar el estado sigue siendo una vía de recuperación.
No conviertas un límite local de espera en una decisión de cobro. El navegador puede dejar de esperar a los 30 segundos, la solicitud HTTP del servidor a los 60 y la tarea remota seguir ejecutándose. El registro incluye un plazo de ejecución, deadlineAt, que describe la ejecución remota, no cuánto mantiene abierta la conexión la página. La caducidad del enlace de descarga es otro reloj distinto.
En la pantalla de espera, usa un mensaje como «Tu imagen sigue procesándose. Puedes salir y volver a la misma tarea». No prometas una duración exacta sin mediciones de ese modelo y carga. La latencia medida por un competidor para imágenes normales de producto no garantiza tiempos para tus prompts NSFW.
Si perdiste la respuesta de creación, repite el mismo envío
El caso difícil es una conexión que cae después de enviar la solicitud pero antes de recibir confirmación. Ese error no permite saber si la plataforma aceptó la tarea.
SpicyAPI ofrece una protección real de servidor: la cabecera opcional Idempotency-Key. Para la misma cuenta y API key, repetir una clave con el mismo modelo normalizado, entrada y URL de callback durante 24 horas devuelve la tarea original sin volver a reservar fondos. Una solicitud cambiada entra en conflicto con esa clave. Otra API key de la misma cuenta tampoco puede recuperar ese mapeo: recibe un conflicto sin revelar el ID original.
Crea una clave estable para la imagen solicitada, no para cada intento HTTP. Un valor generado por la app como project-8-image-12-v1 ilustra la idea. No incluyas datos personales ni el prompt sin procesar. Genera y guarda la clave antes de la primera creación. Otro intento de red la reutiliza; una imagen realmente nueva recibe otra versión o ID de operación.
Una secuencia mínima de recuperación es:
- Guarda en la app la operación de imagen prevista, el cuerpo original y su clave.
- Envía la solicitud con
Idempotency-Key. - Si se pierde la confirmación, marca la operación local como pendiente de confirmar.
- Repite cuerpo y clave sin cambios con la misma credencial API.
- Guarda el ID devuelto y pasa a consultar su estado.
Mantén estable la solicitud exacta mientras la recuperas. No dejes que la interfaz la reconstruya desde controles que el cliente haya cambiado. Si pasa de retrato cercano a composición amplia, aumenta resolución, modifica el prompt o el callback, ya no es el envío original.
La protección tiene un límite: 24 horas no son almacenamiento indefinido para evitar duplicados en la app. Tras ese plazo, no supongas que reutilizar la clave recuperará una tarea antigua. Tu mapeo duradero de operación a tarea debe resolver regresos posteriores. Si no sabes si se aceptó y no puedes identificarla, concilia los registros de tareas de la cuenta o consulta soporte antes de crear automáticamente una sustituta.
Desactivar Generar ayuda, pero no basta
Desactivar el botón durante la carga evita un doble toque habitual. No evita envíos duplicados desde dos pestañas, un móvil reconectado, un worker en segundo plano o un reinicio del servidor.
La app debe vincular todos esos eventos a una operación lógica de imagen. Una regla de unicidad en tu base impide que dos workers reclamen la misma operación de forma independiente. La clave de plataforma protege después la frontera de creación remota. Son protecciones distintas; necesitas ambas si la app tiene varias vías de envío.
Piensa en un producto de compañía que genera opcionalmente un retrato tras conversar. El usuario pulsa además el botón manual antes de confirmarse la solicitud automática. Si ambas acciones cumplen la misma solicitud de retrato, relaciónalas con una operación. Si el botón pide explícitamente una segunda variación, muestra que es otra generación pagada. No fusiones silenciosamente dos compras deliberadas ni cobres dos veces una sola promesa.
La clave no decide esa semántica de producto. La app decide qué cuenta como la misma solicitud. Tampoco ayuda una fila local sin duplicados si cada recuperación del cliente saliente usa otra clave remota. El valor debe sobrevivir a todo el recorrido.
Rechazo, fallo técnico e imagen no deseada tienen facturas distintas
Una solicitud adulta puede terminar de varias maneras. Evita prometer que las generaciones NSFW fallidas siempre son gratis y afirmar lo contrario, que se cobra todo error.

Estado de tarea y satisfacción creativa difieren. Comprueba el registro liquidado y las excepciones de cobro del modelo.
SpicyAPI reserva un importe estimado al aceptar la tarea. Mientras settled es falso, cost representa esa retención. Liquidada la tarea, representa el cargo final. Una tarea exitosa se cobra hasta el importe retenido; los fondos no usados se liberan.
Una tarea fallida o caducada normalmente libera la retención. Hay excepciones en la política de reembolsos, incluidos modelos cuyas páginas indican cobro por solicitudes rechazadas o fallidas y uso entregado antes de una interrupción. Si el modelo rechaza una tarea de imagen, revisa su nota de cobro y el registro liquidado final. No expliques el saldo únicamente mediante el error HTTP.
Una imagen correcta pero suavizada es distinta. Imagina que pediste un personaje adulto ficticio seguro en una escena editorial adulta concreta y recibes un retrato convencional. Si terminó y entregó resultado, no estar satisfecho con la escena no lo convierte en fallo técnico reembolsable. Lo mismo ocurre con un peinado incorrecto, un accesorio no deseado o una expresión que no te gusta.
Por eso una política útil de reintentos necesita un límite de gasto creativo, no solo un número de reintentos de red. Un worker que repite todas las imágenes que la app desaprueba puede seguir comprando salidas exitosas mucho después de resolver los fallos técnicos.
Lee la página del modelo exacto para tu tarea. Que una ruta de texto a imagen sea permisiva no demuestra que la edición se comporte igual, y la familia no basta para predecir todas las solicitudes NSFW. Usa solo personajes adultos y material que tengas derecho a enviar; repetir no hace aceptables solicitudes prohibidas.
Reintentar un fallo terminal crea trabajo nuevo
La API tiene también POST /api/v1/jobs/retry, que toma el ID de una tarea fuente y crea otra desde un fallo terminal elegible. No devuelve la tarea antigua a ejecución. Se reevalúan entradas actuales del modelo, permisos, disponibilidad, saldo y precio. La fuente debe conservar entrada y tener la conciliación de cobro terminada; una tarea activa o exitosa no es elegible.
Usa la misma API key que creó la fuente. Si aplicas idempotencia a la acción de reintento, la clave protege ese nuevo intento particular y está delimitada a la tarea fuente. Repetir esa acción recupera su tarea nueva; difiere de repetir la primera creación para recuperar la original.
En una app creadora, muéstralo como un nuevo intento con precio. Si debe cambiar el prompt, crea una solicitud con la entrada revisada en vez de esperar que el reintento de fuente la edite. Una solicitud fallida por referencia caducada también necesita una referencia utilizable para volver a funcionar. La liberación del cargo original y la nueva retención son entradas separadas.
Qué cuestan realmente los intentos repetidos
Estas son configuraciones iniciales actuales de tres endpoints de imágenes. Los precios describen generación, no garantizan que cada imagen cumpla un encargo NSFW.

Ejemplo hipotético de planificación: los duplicados accidentales añaden $2.40 a $7.20 de intentos creativos intencionados.
| Endpoint y configuración explícita | Precio por imagen | Tres intentos cobrados | Diez intentos cobrados |
|---|---|---|---|
| Texto a imagen Z-Image Turbo, expansión desactivada | $0.010 | $0.030 | $0.100 |
| Texto a imagen Qwen Image 2.1, 1K | $0.024 | $0.072 | $0.240 |
| Texto a imagen Seedream 5.0 Pro, 1K seleccionado | $0.036 | $0.108 | $0.360 |
Importan los detalles. Z-Image Turbo con expansión activada cuesta $0.016 por imagen en vez de $0.010. Seedream 5.0 Pro usa 2K por defecto, a $0.072, en vez de 1K a $0.036. Seleccionar expresamente el nivel hace que el cálculo coincida con la tarea.
Supón que planeas 100 retratos finales Qwen Image 2.1 a 1K. Si cada final necesita de media tres intentos creativos cobrados, gastas $7.20: 100 × 3 × $0.024. Si un fallo de confirmación duplica además un envío por cada final, añade 100 × $0.024 = $2.40, para un total de $9.60. Son ejemplos de planificación, no una tasa medida de éxito.
Cambiar el timeout HTTP no reduce a uno un proceso creativo de tres intentos. Sí puedes eliminar el cuarto intento accidental. Cuenta por separado variaciones intencionadas y duplicados para ver qué problema estás pagando.
En un flujo pequeño, decide antes el límite: quizá una imagen inicial y dos intentos revisados para esa pieza. Es una sugerencia de presupuesto de app, no un límite de plataforma. Si los tres fallan el mismo requisito, deja de comprar solicitudes casi idénticas y cambia de enfoque.
Si la imagen NSFW terminada no cumple el encargo, cambia algo relevante
Si el rostro está bien pero la habitación o la ropa no, editar de forma específica puede ser mejor compra que regenerar desde texto. Conserva el resultado útil, describe el cambio y elige un modelo con la tarea adecuada. La edición cuesta dinero; no es una corrección gratuita incluida en la generación.
Si la misma solicitud devuelve repetidamente escenas suavizadas, identifica antes si es rechazo de contenido, interpretación conservadora de una solicitud permitida o prompt sobrecargado. Reenviarlo idéntico no explica qué pasó. Mira la imagen entregada y el código estable de error, si existe, en vez de tratar NSFW como un interruptor universal.
Como ejemplo no gráfico, un retrato podría necesitar un personaje adulto ficticio, chaqueta oscura de satén, postura sentada, luz cálida lateral y habitación despejada. Si todos incluyen una habitación recargada, quita detalles secundarios manteniendo personaje y luz. Si aparece otra cara, pasa a un flujo adecuado con referencias en vez de añadir adjetivos a un prompt solo textual.
Cuando haga falta otra variación real, usa operación y clave nuevas. Repetir la primera solicitud aceptada con su clave recupera la primera tarea; no pide imaginar una segunda mejor. Si cambias una semilla para una variación, registra otro intento creativo. La semilla identifica la solicitud, pero no garantiza el personaje entre modelos distintos.
Después de los primeros intentos, compara el costo final de imagen útil, no solo el precio inicial anunciado. Una generación de $0.010 usada cuatro veces cuesta $0.040. Una de $0.024 usada una vez cuesta $0.024. No prueba que el segundo modelo sea más fiable; dice qué medir en tu propio planteamiento.
Cuando una imagen existente no se descarga
No regeneres una imagen exitosa porque falló la descarga. El archivo puede seguir existiendo aunque su enlace temporal haya caducado, o la app puede haber fallado al copiarlo.
Conserva la tarea completada y la identidad del recurso de salida. Recupera una ruta de descarga autorizada actual mientras se retenga y vuelve a transferir ese recurso. No añadas la API key a una URL multimedia firmada independiente. Confirma que el destino tiene realmente los bytes antes de mostrar Guardado en la biblioteca del cliente.
La guía de entrega multimedia explica copiar resultados a tu almacenamiento. Para un creador adulto también es una frontera de privacidad: copiar con éxito no convierte una imagen o referencia en recurso de galería pública. La recuperación debe conservar el acceso privado previsto.
Si los bytes originales ya se eliminaron según la retención efectiva, un ID no los restaura. Sustituirlos sería generar otra imagen que podría ser distinta. Explica la distinción al cliente en lugar de reemplazar silenciosamente el retrato por otro cobrado.
Haz que la siguiente acción del cliente corresponda al cargo
Muestra juntos estado y cargo liquidado de la tarea existente. Si sigue sin resolverse, conserva su lugar sin presentar otro reintento pagado como única salida. Si falló, muestra motivo y si se liberó la retención. Si funcionó, separa Descargar otra vez de Generar otra variación.
Para soporte, sirven ID de tarea, ID de solicitud si existe, fecha y hora, importe y descripción breve. Dos ID distintos no son lo mismo que una tarea cobrada dos veces. La política pide informar de cargos duplicados, superiores a la retención, salidas exitosas no entregadas o retenciones de tareas fallidas no devueltas en 24 horas. No incluyas API keys, enlaces firmados ni prompts sensibles en registros corrientes o capturas de soporte.
El creador debe entender el historial como «un retrato solicitado, un envío recuperado, un resultado entregado», no como una lista de intentos HTTP invisibles. Ese es el objetivo: recuperar la red conserva la compra original; otro intento creativo es una decisión deliberada con precio visible.








