Saltar al contenido
FreshApp Demo

DOCUMENTACIÓN PARA DESARROLLADORES

Documentación de la API de generación

Con la API de generación, crea generaciones con los modelos del sitio desde tu propio código. Una solicitud indica un modelo y su entrada; la respuesta es una generación que sigues hasta que termina, y sus archivos se descargan de este sitio. Los modelos, precios, límites y códigos de error de esta página son los que están en vigor.

Crear generaciones por la API requiere un paquete de créditos de pago o una suscripción de pago activa, y solo gasta créditos de pago. Consultar, listar y descargar funcionan con cualquier clave de la cuenta.

Inicio rápido

Crea una clave en la página de claves de API, guárdala en tu servidor y asígnala a API_KEY. Los ejemplos crean una generación con seed-audio-1.0, la consultan hasta que termina y descargan su primer archivo.

Envía una Idempotency-Key nueva con cada solicitud nueva. Cuando una solicitud no recibe respuesta, vuelve a enviarla con la misma clave y el mismo cuerpo: recibes la generación que creó la primera solicitud y se cobra una sola vez.

cURL

export API_ORIGIN='https://demo.freshapp.ai'
export API_KEY='sk_YOUR_API_KEY'

curl --fail-with-body "$API_ORIGIN/api/v1/generations" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1001' \
  -d '{"model":"seed-audio-1.0","input":{"prompt":"Un faro sobre un acantilado al amanecer, mar en calma, luz suave."}}'

# Read it every 5 to 10 seconds until its status ends.
curl --fail-with-body "$API_ORIGIN/api/v1/generations/GENERATION_ID" \
  -H "Authorization: Bearer $API_KEY"

# A delivered output's url is a signed link: no key needed.
curl --fail-with-body -o result "OUTPUT_URL"

Cliente TypeScript

import { createClient } from './open-api-client';

const client = createClient({
  baseUrl: "https://demo.freshapp.ai",
  apiKey: process.env.API_KEY, // on your server only
});
const generation = await client.create(
  {
    "model": "seed-audio-1.0",
    "input": {
      "prompt": "Un faro sobre un acantilado al amanecer, mar en calma, luz suave."
    }
  },
  { idempotencyKey: "order-1001" }
);
const done = await client.wait(generation.id);
for (const output of done.outputs)
  if (output.status === 'delivered') {
    const file = await client.download(output);
    // file.body is the output, as output.content_type says
  }

Hook de React

import { createClient } from './open-api-client';
import { useGeneration } from './open-api-react';

// In a browser on this site: no key, the visitor's own session.
const client = createClient();

export function Progress({ id }: { id: string }) {
  const { generation, error, done } = useGeneration(client, id);
  if (error) return <p>{String(error)}</p>;
  return <p>{generation?.status ?? '…'}{done ? ' ✓' : ''}</p>;
}

Claves y permisos

Cada solicitud lleva Authorization: Bearer con una clave de la página de claves de API. Una clave es sk_ seguido de 43 letras, dígitos, guiones o guiones bajos, y se muestra una sola vez, al crearla o rotarla. Una solicitud con Authorization se juzga solo por su clave, nunca por una sesión iniciada a su lado.

Una clave solo lee (lista, consulta y descarga) o también puede generar (crea y cancela). Una clave de solo lectura recibe 403 insufficient_scope cuando intenta crear o cancelar, y no se escribe nada.

Una clave puede tener una lista de IP permitidas con direcciones y redes: desde cualquier otra dirección recibe 403 ip_not_allowed. Dar más permisos a una clave, subir un límite o ampliar la lista requiere un inicio de sesión reciente; restringirlos, nunca.

Rotar una clave le da un valor nuevo al instante y el anterior deja de funcionar. Revocarla la detiene para siempre: sus generaciones aún no enviadas a un modelo se cancelan y sus créditos vuelven, y las que ya están en curso terminan.

Solo las cuentas con acceso de pago crean generaciones por la API (si no, 403 not_eligible), y la API solo gasta créditos de pago (402 insufficient_credits). Los créditos de regalo y de registro diario quedan para el sitio web.

Endpoints de la API de generación

Todas las rutas están en este sitio. Los cuerpos de solicitud y respuesta son JSON, salvo los archivos de resultado.

https://demo.freshapp.ai

MétodoRutaPermisoQué hace
POST/api/v1/generationsgenerations:writeCrea una generación. Necesita una Idempotency-Key; responde 202 con la generación.
GET/api/v1/generationsgenerations:readLas generaciones de la cuenta, de la más reciente a la más antigua, página a página (limit, cursor, module). Las generaciones de texto solo se consultan por id.
GET/api/v1/generations/{id}generations:readUna generación de la cuenta, con sus salidas, sus créditos y por qué terminó.
POST/api/v1/generations/{id}/cancelgenerations:writeCancela una generación aún no enviada a su modelo y devuelve sus créditos.
GET, HEAD/api/media/{id}generations:read (o un enlace firmado)El archivo de una salida, con un rango de bytes como máximo. Un enlace firmado no necesita clave y funciona desde cualquier dirección.

Modelos y precios

Los modelos activados en este sitio, como los acepta la API: usa el id como model y los campos como input. Una solicitud reserva su resultado más caro al crearse; cuando termina, pagas lo que se entregó.

Id del modeloNombreTipoPrecioMáximo por solicitudCampos de entrada
seed-audio-1.0Seed Audio 1.0Audio75 créditos por minuto; al menos 10 por un resultado entregado150 créditosprompt (obligatorio), voice, audio_references, image_url, output_format, sample_rate, speed, volume, pitch, multilingual

Idempotencia

Crear una generación requiere una cabecera Idempotency-Key de 1 a 128 letras, dígitos, puntos, dos puntos, guiones bajos o guiones. Usa un id de tu propio sistema, como un número de pedido, para que el mismo trabajo siempre tenga la misma clave.

La misma clave con la misma solicitud devuelve la misma generación, por muchas veces que se envíe, y se cobra una sola vez. La misma clave con otra solicitud da 409 idempotency_conflict y no se crea nada.

Un tiempo de espera agotado o una conexión cortada no significan que la solicitud falló. Vuelve a enviarla con la misma clave y el mismo cuerpo, y guarda ambos hasta tener respuesta. Un 5xx, un 429 o un 408 se tratan igual: espera lo que diga Retry-After y vuelve a enviar la solicitud sin cambios.

Estados y consultas

Consulta una generación con GET /api/v1/generations/{id} cada 5 segundos al principio y luego hasta cada 10 segundos, hasta que su estado sea final. Un 429 indica en Retry-After cuándo volver a consultar.

EstadoSignificado
queuedAceptada y a la espera de enviarse a su modelo. Todavía se puede cancelar.
processingEnviada a su modelo, o se están guardando y liquidando sus archivos.
succeededTodas las salidas se entregaron y los créditos están liquidados.
partially_succeededAlgunas salidas se entregaron y se cobraron; los créditos de las demás volvieron.
failedNo se entregó nada; error dice por qué, y los créditos reservados volvieron.
canceledCancelada antes de enviarse, por ti o porque se revocó su clave; los créditos volvieron.

billing.reserved_credits es lo que reservó la creación. Una vez liquidada, charged_credits es lo que pagaste y refunded_credits lo que volvió; hasta entonces ambos son null y held_credits muestra lo reservado.

Una generación que espera una revisión manual muestra review con la hora en que empezó la revisión, y conserva sus créditos hasta que termina; después continúa o sus créditos vuelven.

Archivos de resultado

Cada salida entregada tiene una url en este sitio. Para una clave, es un enlace firmado que funciona durante una hora sin la clave y desde cualquier dirección, así que puedes dárselo a una herramienta de descarga. Pasada la hora, vuelve a consultar la generación para obtener un enlace nuevo.

Con la propia clave, GET /api/media/{id} también devuelve el archivo, dentro de la lista de IP de la clave. Ambos aceptan HEAD y un rango de bytes (Range: bytes=0-1023), y nunca redirigen a otro sitio.

Un archivo citado en una entrada, como una muestra de audio o una imagen, debe haberlo subido esta cuenta al sitio web, ser una de las muestras del sitio o un enlace a una fuente que el sitio permite; cualquier otra cosa se rechaza antes de reservar créditos.

Límites

Cada límite de abajo es el que este sitio aplica ahora, y cada rechazo indica cuál se alcanzó.

  • Una solicitud reserva como máximo 150 créditos, la solicitud más cara de los modelos activados. Una clave puede tener un límite menor, y el max_credits de una solicitud lo baja para esa solicitud; por encima, la respuesta es 400 request_limit_exceeded.
  • Cada clave gasta como máximo 5000 créditos por día UTC salvo que le fijes su propio límite, hasta 1.000.000; al superarlo, la clave recibe 429 key_daily_limit_exceeded hasta el siguiente día UTC.
  • Todas las claves de una cuenta, con sus clientes de IA, gastan como máximo 10.000 créditos por día UTC salvo que fijes el límite propio de la cuenta; al superarlo, la respuesta es 429 account_daily_limit_exceeded.
  • Cada clave y cada cuenta envía como máximo 20 creaciones y cancelaciones y 240 consultas y descargas por minuto; al superarlo, 429 rate_limited con Retry-After.
  • Como máximo 2 generaciones de una cuenta se ejecutan a la vez; otra espera con 429 too_many_active.
  • El cuerpo de una solicitud tiene como máximo 32 KiB de JSON; uno mayor da 413 request_too_large.

Códigos de error

Un error tiene la forma {"error": {"code": …, "message": …}}. El código siempre es uno de estos, y el mensaje está en inglés, para desarrolladores. Un 429 o un 503 indica en Retry-After cuántos segundos esperar. Una generación fallida o cancelada lleva en su campo error uno de los códigos marcados como de una generación.

HTTPCódigoSignificadoQué hacer
401invalid_credentialLa clave de API falta, está mal formada, es desconocida, se revocó o se reemplazó.Revisa la clave de API, su permiso y su lista de IP permitidas.
401credential_revokedLa clave se revocó o rotó durante la solicitud; una generación en cola de una clave revocada se cancela y sus créditos vuelven.Revisa la clave de API, su permiso y su lista de IP permitidas.
403insufficient_scopeLa clave no puede hacer esto: el error indica el permiso necesario en required_scope.Revisa la clave de API, su permiso y su lista de IP permitidas.
403ip_not_allowedLa clave no se puede usar desde esta dirección: está fuera de su lista de IP permitidas.Revisa la clave de API, su permiso y su lista de IP permitidas.
401unauthorizedLa sesión del sitio terminó: vuelve a iniciar sesión.Cambia la solicitud antes de volver a enviarla.
403invalid_originUna solicitud del sitio web debe venir del propio sitio.Cambia la solicitud antes de volver a enviarla.
403forbiddenLa solicitud llegó sin una dirección de cliente de confianza.Contacta con el soporte del sitio.
400invalid_requestLa solicitud está mal formada: su JSON, sus cabeceras (Idempotency-Key, Content-Type) o su consulta.Cambia la solicitud antes de volver a enviarla.
400invalid_inputLa entrada no encaja con los campos del modelo, o el modelo no pudo usarla.Cambia la solicitud antes de volver a enviarla.
413request_too_largeEl cuerpo de la solicitud es demasiado grande.Cambia la solicitud antes de volver a enviarla.
409idempotency_conflictEsta Idempotency-Key ya se usó con otra solicitud distinta.Cambia la solicitud antes de volver a enviarla.
404model_unavailableEl modelo es desconocido o no está disponible ahora.Cambia la solicitud antes de volver a enviarla.
404not_foundNo existe esa ruta, generación o archivo para esta cuenta.Cambia la solicitud antes de volver a enviarla.
405method_not_allowedLa ruta no acepta este método; Allow indica los que acepta.Cambia la solicitud antes de volver a enviarla.
409not_cancelableLa generación ya se envió a su modelo o ya terminó.Cambia la solicitud antes de volver a enviarla.
409not_readyEl archivo aún no está listo.Espera lo que diga Retry-After y vuelve a enviarla.
410expiredEl archivo superó el periodo de conservación y se eliminó.Cambia la solicitud antes de volver a enviarla.
400request_limit_exceededLa solicitud costaría más que su max_credits, o que el límite por solicitud de la clave o del sitio.Cambia la solicitud antes de volver a enviarla.
403not_eligibleGenerar por la API requiere una cuenta de pago.Compra un paquete de créditos o un plan: la API solo gasta créditos de pago.
403email_unverifiedVerifica el correo de la cuenta para generar.Cambia la solicitud antes de volver a enviarla.
402insufficient_creditsNo hay créditos suficientes: la API solo gasta créditos de pago.Compra un paquete de créditos o un plan: la API solo gasta créditos de pago.
403generation_restrictedLa generación está en pausa para esta cuenta tras rechazos de contenido repetidos; ends_at dice hasta cuándo.Contacta con el soporte del sitio.
403trial_pausedLas pruebas del sitio están en pausa para esta cuenta después de que varias salidas de prueba superaran los límites de la prueba; ends_at dice hasta cuándo. Las solicitudes sin prueba siguen como siempre.Cambia la solicitud antes de volver a enviarla.
429key_daily_limit_exceededSe alcanzó el límite de gasto diario de la clave.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: hasta el siguiente día UTC.
429account_daily_limit_exceededSe alcanzó el límite de gasto diario de la cuenta para la API.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: hasta el siguiente día UTC.
429rate_limitedDemasiadas solicitudes en poco tiempo.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: la ventana del límite.
429too_many_activeHay demasiadas generaciones de la cuenta en curso.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 30 s.
429too_many_under_reviewAlgunas generaciones de la cuenta esperan una revisión manual.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 3600 s.
503busyHay demasiadas generaciones en curso en el sitio ahora mismo.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 30 s.
503pausedLa generación está en pausa por ahora.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 60 s.
503temporarily_unavailableLa solicitud no pudo completarse en este momento.Vuelve a enviar la misma solicitud con la misma Idempotency-Key. Retry-After: 60 s.
503api_unavailableLa generación aún no está disponible en este sitio.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 60 s.
503retryAlgo cambió durante la solicitud, como los ajustes de la clave.Vuelve a enviar la misma solicitud con la misma Idempotency-Key. Retry-After: 60 s.
503unavailableLos archivos no están disponibles temporalmente.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 60 s.
500internal_errorAlgo falló en el sitio.Vuelve a enviar la misma solicitud con la misma Idempotency-Key.
400request_failedLa solicitud se rechazó por un motivo sin código propio.Contacta con el soporte del sitio.
400captcha_requiredCompleta la verificación de seguridad del sitio.Cambia la solicitud antes de volver a enviarla.
403captcha_failedLa verificación de seguridad del sitio no se superó.Cambia la solicitud antes de volver a enviarla.
503captcha_unavailableLa verificación de seguridad del sitio no está disponible.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 60 s.
400reference_unavailableUn archivo subido y citado ya no existe o no es de esta cuenta.Cambia la solicitud antes de volver a enviarla.
413reference_too_largeLos archivos citados pueden sumar como máximo 10 MB.Cambia la solicitud antes de volver a enviarla.
503reference_storage_unavailableEl almacenamiento de archivos citados no está disponible.Espera lo que diga Retry-After y vuelve a enviarla. Retry-After: 60 s.
409storage_quota_exceededEl almacenamiento de la cuenta está lleno.Contacta con el soporte del sitio.
En una generacióncanceledLa generación se canceló antes de enviarse; sus créditos volvieron.Cambia la solicitud antes de volver a enviarla.
En una generaciónsubmission_expiredLa generación no pudo enviarse a tiempo; sus créditos volvieron.Vuelve a enviar la misma solicitud con la misma Idempotency-Key.
En una generaciónmodel_busyEl modelo estaba ocupado; los créditos volvieron.Espera lo que diga Retry-After y vuelve a enviarla.
En una generacióncontent_rejectedLos controles de seguridad del contenido rechazaron la entrada o la salida.Cambia la solicitud antes de volver a enviarla.
En una generaciónresult_expiredEl resultado no pudo guardarse a tiempo.Contacta con el soporte del sitio.
En una generacióngeneration_failedLa generación falló.Contacta con el soporte del sitio.
En una generacióndelivery_failedEl resultado no pudo entregarse; sus créditos volvieron.Contacta con el soporte del sitio.
En una generacióntrial_limit_exceededLa salida de la prueba del sitio superó los límites de la prueba y no se entregó; sus créditos volvieron.Cambia la solicitud antes de volver a enviarla.

Cliente TypeScript y hook de React

El cliente TypeScript, open-api-client.ts, no necesita ningún otro paquete y funciona en servidores, workers y navegadores. En un servidor, pásale baseUrl y apiKey; en un navegador de este sitio, no le pases ninguno, y las solicitudes usan la sesión del propio visitante.

create envía una Idempotency-Key, la tuya o un valor aleatorio nuevo, y vuelve a enviar la misma solicitud tras una conexión cortada, un 5xx, un 429 o un 408, esperando lo que diga Retry-After. Cuando se rinde, su error lleva la clave, para que reenvíes la solicitud más tarde. Con un store como localStorage, una solicitud conserva su primera clave al recargar la página.

wait consulta una generación hasta que termina, cada 5 segundos al principio y luego hasta 10, y se detiene cuando lo cancelas. download obtiene el archivo de una salida y solo envía la clave a los enlaces sin firmar de este sitio.

El hook de React, open-api-react.ts, sigue una generación con el wait del cliente y se detiene cuando el componente se desmonta. Descarga ambos archivos, ponlos juntos y cámbiales la extensión a .ts.

Descargas