En treinta segundos
Saca una clave en tu cuenta, mándala en la
cabecera X-Distria-Key y pide un trabajo. Contesta con un id,
no con la imagen: al otro lado hay la tarjeta gráfica de otra persona.
curl -X POST https://distria.example/v1/jobs \
-H "X-Distria-Key: dsk_..." \
-H "Content-Type: application/json" \
-d '{"model": "sdxl-turbo", "prompt": "un faro en la niebla"}'
{"id": "6f1c…", "status": "queued", "price_credits": 1, "queue_position": 0}
Y luego se pregunta por él hasta que esté:
curl https://distria.example/v1/jobs/6f1c… \
-H "X-Distria-Key: dsk_..."
La clave
Se hace en tu cuenta y ahí es la
única vez que se ve entera. No es que esté escondida en
algún menú: el gateway guarda su sha256 y no la puede volver a
decir ni queriendo, que es lo que hace que perder nuestra base de datos no
sea perder tu dinero.
Haz una por cada sitio desde el que llames, y no una para todo. El día que
se te escape una en un repositorio, apagas esa y lo demás sigue andando.
Empiezan por dsk_ a propósito, para que los buscadores de
secretos de GitHub y de los pre-commit las reconozcan y te avisen
antes de que el commit salga.
Crear y revocar claves no se puede hacer con una clave: hace falta la sesión del navegador. Si una clave pudiera hacerse otra, robar una sería robar la cuenta para siempre, porque el ladrón se haría otra y revocar la que se filtró no serviría de nada.
Qué se puede pedir, y a cómo
Esta tabla la trae /v1/models ahora mismo, no está escrita aquí: si un modelo entra o cambia de precio, cambia sola. Míralo desde tu programa también, en vez de llevar los ids y los precios a mano.
| id | Qué hace | Créditos | Parámetros que lee |
|---|
Ahora mismo no se ha podido traer el catálogo. Está en /v1/models.
Cada ficha del catálogo trae además sus limits: entre qué
valores admite cada parámetro y con qué salto. Un cliente que los lee de
ahí no se come un 422 por pedir un ancho que ese modelo no hace.
Cómo se cobra
En créditos, y al encargar, no al terminar. Al revés no se puede: si se cobrara al final, con saldo para un trabajo se podrían pedir cien a la vez, y quien pone la GPU ya habría gastado la luz cuando se descubriera.
- Si el trabajo falla, se devuelve entero. Una avería de la red no la paga el que pidió.
- Si sale, no se devuelve, aunque el resultado no guste. La tarjeta de esa persona ha estado ocupada igual.
- Sin saldo es un 402, y el mensaje dice cuánto falta.
El apunte de cada cobro y de cada devolución está en
GET /v1/consumo, con el prompt al lado, para que puedas cuadrar
tu factura sin creerte la nuestra.
Los topes, y el 429
Cada clave puede llevar dos topes, y los pones tú en tu cuenta. No los ponemos nosotros: son para que un bucle tuyo que se ha vuelto loco no se lleve por delante el saldo del mes.
| Tope | Qué protege | Cuándo se reinicia |
|---|---|---|
| Peticiones por minuto | al gateway | cada minuto |
| Créditos al día | a tu cartera | a medianoche UTC |
Pasarse de cualquiera de los dos es un 429 con la cabecera
Retry-After puesta, en segundos. Espera eso y
reintenta; reintentar en bucle solo hace que el minuto no acabe
nunca, porque cada intento cuenta también.
Un 429 no es un 402 y no se arreglan igual: en el 429 tienes saldo de sobra y lo que falta es turno. Si tu cliente los trata igual, el día que uno de los dos salte vas a estar mirando donde no es.
Esperar el resultado
POST /v1/jobs contesta 202 y un id. Hay dos formas
de enterarse de cómo va, y conviene la segunda:
-
Preguntar por
GET /v1/jobs/{id}cada pocos segundos. Sencillo, y suficiente si generas de uno en uno. Cada consulta cuenta para tu tope de peticiones por minuto, así que preguntar diez veces por segundo es la forma más rápida de darte un 429 a ti mismo. -
El WebSocket
/v1/jobs/{id}/stream, que empuja cada cambio de estado sin que preguntes y, en los modelos de texto, va mandando el texto según se escribe. No sale en /docs porque OpenAPI no sabe describir WebSockets, no porque sea de segunda: es lo que usa nuestra propia web.
Los estados son queued, running,
done, failed y canceled. Los tres
últimos son finales: no hay que seguir preguntando.
Cuando termina, result_url viene firmada y caduca.
Es para bajarte el fichero, no para enlazarlo desde tu web: si lo enlazas,
el día que caduque tu página se queda con un hueco. Bájalo y guárdalo donde
sea tuyo.
Cuando dice que no
| Código | Qué ha pasado | Qué hacer |
|---|---|---|
| 401 | no hay clave válida ni sesión | mirar la cabecera; si la clave está revocada, hacer otra |
| 402 | no queda saldo | recargar |
| 403 | el filtro ha parado el prompt | cambiarlo. No se dice qué palabra saltó, porque decirlo sería enseñar a rodearlo |
| 404 | ese modelo no existe, o no lo tiene encendido nadie | mirar el catálogo |
| 422 | un parámetro fuera de lo que admite ese modelo | el detalle dice cuál y entre qué valores |
| 429 | tope de la clave | esperar el Retry-After |
| 503 | la red no acepta ese modelo a este precio | es temporal; reintentar más tarde |
El motivo va siempre en detail, escrito para leerlo. Si alguna
vez te sale uno que no entiendes, es un fallo nuestro y no tuyo.
Lo que no está documentado, y por qué
En /docs no salen las rutas del worker, las del panel del proveedor, las de administración ni el webhook de pagos. No están escondidas —el código está abierto y ahí se ven todas—: es que son el protocolo interno entre las piezas de Distria y no prometen seguir igual mañana. Lo que sí sale ahí, sí lo promete.
Si construyes encima de una ruta que no aparece en /docs, un
día se te va a romper sin aviso y vas a tener razón en enfadarte, pero no
motivo.
Antes de mandar nada
Lo mismo que le decimos a quien usa la web, y aquí más todavía porque un programa manda mucho más volumen: tu prompt se procesa en el ordenador de otra persona. No mandes por esta API nada que no quieras que exista en una máquina ajena —datos de tus clientes, nada confidencial—. El recorrido entero está contado en Dónde va tu prompt.