# Staglight API > API REST y servidor MCP con créditos prepago para anuncios de tiendas online (imágenes, video, voz, música, subtítulos) en español, inglés, alemán y portugués. Sin suscripción. URL base https://staglight.ai/api/v1. Autenticación: `Authorization: Bearer ` (las claves empiezan por sl_live_). Los POST de pago aceptan el encabezado `Idempotency-Key` y `max_credits`. Los trabajos responden 202 con un id: consulta GET /api/v1/jobs/?wait=30. Sin créditos es 402 con needed y balance; los trabajos fallidos se reembolsan. Servidor MCP: https://staglight.ai/mcp. versión en inglés: https://staglight.ai/llms-full.txt ## Crear con la API y el MCP Crea imágenes de producto, video, locuciones, música y anuncios terminados desde tu propio código o desde un agente de IA. Un solo saldo paga el estudio, la API REST y el servidor MCP. ### Introducción Todo lo que haces en el estudio lo puedes hacer desde código: imágenes de producto, clips de video, locuciones, música y anuncios completos con pasos de revisión. Antes de cada trabajo puedes consultar el precio gratis, y si falla, te devolvemos los créditos automáticamente. Las solicitudes y respuestas son JSON, salvo las subidas, que van como multipart form data. Todas las rutas empiezan con `/api/v1`, la versión actual. - URL base: `https://staglight.ai/api/v1` - Autenticación: `Bearer ` - Formato: `JSON` - OpenAPI: `/api/v1/openapi.json` **Clave de API en menos de un minuto** Regístrate, confirma tu email y abre Claves de API en el estudio para crear una. Se muestra una sola vez, así que cópiala enseguida. Puedes ponerle un límite diario de créditos. [Obtener clave de API](https://staglight.ai/es/registro?next=/app/api) ### Autenticación Crea una clave en [el estudio](https://staglight.ai/app/api) y ponle un límite diario de créditos. La clave se muestra una sola vez. Empieza por `sl_live_`. Envíala en cada solicitud como `Authorization: Bearer `. También vale `X-API-Key: `. Los ejemplos la leen de `STAGLIGHT_API_KEY`. Terminal: ```bash export STAGLIGHT_API_KEY="sl_live_..." ``` > Nunca pongas una clave en código del navegador, en un repositorio ni en un chat. Si se filtra, revócala en el estudio. ### ¿Perdiste tu clave de API? Las claves se guardan solo como hash, así que nadie puede volver a mostrarte una clave existente, ni siquiera nuestro soporte. Cámbiala tú: inicia sesión, abre [Claves de API](https://staglight.ai/app/api), crea una clave nueva y revoca la antigua. Puedes tener hasta 20 claves activas a la vez, así que cambias sin cortes: crea la clave nueva, ponla en tu app y luego revoca la antigua. Una clave revocada deja de funcionar al instante. ### Créditos 1 crédito = US$0,01. Cada trabajo tiene su precio antes de empezar, y ese precio se cobra al crearlo. - Si un trabajo falla, se reembolsa entero y de forma automática. - Si cancelas un trabajo antes de que empiece, se reembolsa. - Los créditos comprados no caducan. - Sin suscripción y sin recargo por usar la API: la API y el MCP tienen los mismos precios que el estudio. - Al llegar a su límite diario, una clave se detiene con `402 daily_limit_reached`. Consulta el saldo con `GET /api/v1/me` o, junto con su historial, en `GET /api/v1/credits`. Compra créditos en [el estudio](https://staglight.ai/app/creditos). ### Límites de uso Los límites se cuentan por clave de API en una ventana deslizante de un minuto (por cuenta en las sesiones iniciadas en el navegador). Las llamadas de una misma fila comparten el mismo contador. | Límite | Se cuenta por | Se aplica a | |---|---|---| | 30 por minuto | Clave de API | Llamadas que crean: `POST /api/v1/characters`, `DELETE /api/v1/characters/{character_id}`, `PATCH /api/v1/characters/{character_id}`, `POST /api/v1/characters/{character_id}/sheet`, `POST /api/v1/formats/{format_id}/series`, `DELETE /api/v1/formats/{format_id}/series/{series_id}`, `PATCH /api/v1/formats/{format_id}/series/{series_id}`, `POST /api/v1/generate/image`, `POST /api/v1/generate/video`, `POST /api/v1/jobs`, `POST /api/v1/products`, `POST /api/v1/runs`, `POST /api/v1/runs/from-analysis`, `POST /api/v1/runs/propose`, `POST /api/v1/runs/{run_id}/approve`, `POST /api/v1/runs/{run_id}/redo`, `POST /api/v1/runs/{run_id}/scenes`, `POST /api/v1/scripts`, `POST /api/v1/scripts/{job_id}/make`, `PUT /api/v1/studio/library`, `POST /api/v1/studio/{studio_id}/helpers/{name}`, `POST /api/v1/studio/{studio_id}/helpers/{name}/cancel`, `POST /api/v1/studio/{studio_id}/runs`, `POST /api/v1/studio/{studio_id}/series`, `DELETE /api/v1/studio/{studio_id}/series/{series_id}`, `PATCH /api/v1/studio/{studio_id}/series/{series_id}`, `DELETE /api/v1/studio/{studio_id}/user-cards/{card_id}`, `POST /api/v1/uploads`, `POST /api/v1/uploads/from-library`, `POST /api/v1/uploads/from-url` | | 120 por minuto | Clave de API | Cualquier otra llamada con clave (41 endpoints) | | 60 por minuto | Dirección IP | Llamadas sin una clave válida | - Si pasas el límite, recibes `429 rate_limited` con `retry_after` y un encabezado `Retry-After`. - Las consultas largas (`wait`) mantienen la solicitud abierta hasta 50 s. - Subidas: imágenes de hasta 20 MB, video y audio de hasta 1024 MB. El servidor MCP cuenta igual: herramientas de pago 30 por minuto, herramientas gratis 120 por minuto. ### Convenciones Estas reglas se aplican a todos los endpoints. #### Errores Todos los errores tienen la misma forma. `code` es estable; `message` es para personas. JSON: ```json { "error": { "code": "insufficient_credits", "message": "This needs 63 credits and the balance is 10. Buy credits to continue.", "needed": 63, "balance": 10 } } ``` | Estado | Código | Qué hacer | |---|---|---| | 400 | invalid_idempotency_key | Usa de 1 a 255 caracteres ASCII visibles, por ejemplo un UUID. | | 401 | unauthorized | Falta la clave, es incorrecta o está revocada. | | 402 | insufficient_credits | Incluye `needed` y `balance`. No se cobró nada. Compra créditos y reintenta. | | 402 | daily_limit_reached | Esta clave llegó a su límite diario. Súbelo en el estudio o espera. | | 403 | csrf_failed | Solo en sesiones del navegador. Las claves de API nunca lo ven. | | 404 | not_found | El id no existe o es de otra cuenta. | | 409 | price_above_max | El precio supera tu `max_credits`. No se cobró nada. | | 409 | idempotency_mismatch | Esta clave se usó con otro cuerpo. Usa una clave nueva. | | 409 | idempotency_in_progress | La primera solicitud con esta clave sigue en curso. Reintenta en un segundo. | | 413 | file_too_large | Imágenes de hasta 20 MB, video y audio de hasta 1024 MB. | | 415 | unsupported_media | Usa JPG, PNG, WEBP, GIF, MP4, MOV, WEBM, MP3, WAV o M4A. | | 422 | invalid_request | Revisa `field` y `message`. | | 422 | content_not_allowed | La solicitud pide contenido que no generamos. Consulta los términos. | | 429 | rate_limited | Espera `retry_after` segundos (también en `Retry-After`). | | 503 | service_unavailable | La generación está en pausa unos minutos. No se cobró nada. | #### Reintentos e idempotencia Envía un encabezado `Idempotency-Key` (un UUID) en cada POST que gaste créditos. - Misma clave y mismo cuerpo dentro de 24 h: recibes otra vez la primera respuesta, sin cobro nuevo y con el encabezado `Idempotent-Replayed: true`. - Misma clave con otro cuerpo: `409 idempotency_mismatch`. - La primera solicitud sigue en curso: `409 idempotency_in_progress`. Reintenta en un segundo. - Una solicitud que terminó en error se olvida, así que puedes reintentarla con la misma clave. Si se agota el tiempo de espera, no reenvíes a ciegas. Busca antes el trabajo: `GET /api/v1/jobs?idempotency_key=`. Pon un tope de precio con `max_credits` en el cuerpo. Junto con la clave, un reintento nunca cobra dos veces ni más de lo que permitiste. #### Paginación Las listas aceptan `limit` (por defecto 20, máximo 100) y responden con `next`. Pásalo como `before` para pedir la página siguiente. En la última página `next` es `null`. Listas que se paginan así: `GET /api/v1/characters`, `GET /api/v1/credits`, `GET /api/v1/jobs`, `GET /api/v1/media`, `GET /api/v1/products`, `GET /api/v1/runs`, `GET /api/v1/studio/{studio_id}/runs`. ### Tu primer trabajo La generación es asíncrona. Estos ejemplos usan curl y leen tu clave de `STAGLIGHT_API_KEY`. #### Subir una foto del producto Terminal: ```bash curl -s -X POST https://staglight.ai/api/v1/uploads \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -F "file=@product.jpg" ``` La respuesta es un objeto de archivo. Usa su `id` (`med_...`) en los parámetros del trabajo. Las imágenes se recodifican, lo que elimina los datos EXIF y GPS. Para subir desde un enlace público, usa `POST /api/v1/uploads/from-url`. #### Consultar el precio (gratis) Terminal: ```bash curl -s -X POST https://staglight.ai/api/v1/estimate \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"op": "image.nano-banana-pro", "params": {"prompt": "La zapatilla roja sobre fondo de papel blanco, luz suave de mañana", "reference_images": ["med_19a2b3c4d5e6f7a8b9c0d1"], "aspect_ratio": "4:5"}}' ``` Usa los mismos `op` y `params` que en el trabajo. Recibes `credits`, `usd`, `eta_seconds`, tu saldo en `balance` y `enough_credits`. No se cobra nada. `GET /api/v1/models` lista cada op con sus campos. #### Crear el trabajo Terminal: ```bash curl -s -X POST https://staglight.ai/api/v1/jobs \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"op": "image.nano-banana-pro", "params": {"prompt": "La zapatilla roja sobre fondo de papel blanco, luz suave de mañana", "reference_images": ["med_19a2b3c4d5e6f7a8b9c0d1"], "aspect_ratio": "4:5"}, "max_credits": 40}' ``` La respuesta es `202` con el trabajo y un encabezado `Location`. Los créditos se cobran en ese momento. Si el precio supera `max_credits`, recibes `409 price_above_max` y no se cobra nada. #### Consultar hasta que termine Terminal: ```bash curl -s "https://staglight.ai/api/v1/jobs/job_19a2b3c4d5e6f7a8b9c0d1?wait=30" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` `wait=30` mantiene la solicitud abierta hasta que el trabajo termina (hasta 50 s). Estados: `queued`, `running`, `succeeded`, `failed` (reembolsado) y `canceled` (reembolsado). JSON: ```json { "id": "job_19a2b3c4d5e6f7a8b9c0d1", "op": "image.nano-banana-pro", "status": "succeeded", "credits": 23, "outputs": [ { "id": "med_19a2b3c4d5e6f7a8b9c0d2", "kind": "image", "mime": "image/png", "width": 1664, "height": 2080, "url": "https://staglight.ai/media/med_19a2b3c4d5e6f7a8b9c0d2/image.png?exp=...&sig=...", "download_url": "https://staglight.ai/media/med_19a2b3c4d5e6f7a8b9c0d2/image.png?exp=...&sig=...&dl=1" } ], "error": null } ``` #### Descargar el resultado Terminal: ```bash curl -L -o product-ad.png "" ``` Los enlaces van firmados, duran unas 24 h y no necesitan encabezado de autenticación. Vuelve a consultar el trabajo para obtener enlaces nuevos. Los archivos se guardan 30 días. ### Anuncios completos (formatos) Un formato genera un anuncio terminado por pasos: guion, fotogramas clave, clips, voz, música y montaje final. Se detiene en los pasos de revisión para que apruebes una toma o la repitas. `GET /api/v1/formats` los lista con el precio de cada nivel de calidad. Terminal: ```bash curl -s -X POST https://staglight.ai/api/v1/runs \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"format": "product_hero", "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1", "options": {"tier": "draft", "aspect": "9:16", "lang": "es"}}' ``` Consulta `GET /api/v1/runs/?wait=30`. Cuando `status` sea `awaiting_approval`, aprueba con `POST /api/v1/runs//approve` o pide otra toma con `/redo`. Al empezar solo se cobra el paso de planificación; cada aprobación cobra los pasos que pone en marcha. ### Webhooks Aún no hay webhooks. Consulta con `wait=30`: responde en cuanto el trabajo termina. ### Siguientes pasos - [Referencia de la API](https://staglight.ai/es/docs/api): cada endpoint con un ejemplo de curl. - [Configurar el MCP](https://staglight.ai/es/docs/mcp): Claude Code, Codex y Cursor. - [Kit para agentes](https://staglight.ai/es/docs/agente): prompt, skill y recetas de FFmpeg. - [Documento OpenAPI](https://staglight.ai/api/v1/openapi.json) para generadores de código. - [llms.txt](https://staglight.ai/es/llms.txt) y [llms-full.txt](https://staglight.ai/es/llms-full.txt) para modelos de lenguaje. ## Referencia de la API Se genera a partir del [documento OpenAPI](https://staglight.ai/api/v1/openapi.json) actual, así que siempre coincide con el servidor. - URL base: `https://staglight.ai/api/v1` - Autenticación: `Bearer ` - Formato: `JSON` - OpenAPI: `/api/v1/openapi.json` ¿Primera vez aquí? Empieza por la [guía rápida](https://staglight.ai/es/docs): claves, créditos, idempotencia y errores. > Las descripciones de los endpoints están en inglés, como en el documento OpenAPI. ### Cuenta y créditos #### GET /api/v1/me Who am I and my balance ```bash curl -s "https://staglight.ai/api/v1/me" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` The account behind this key or session - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### GET /api/v1/credits Balance and credit history | Name | In | Required | Description | |---|---|---|---| | limit | query | no | | | before | query | no | Ledger id from `next` | ```bash curl -s "https://staglight.ai/api/v1/credits" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Newest movements first - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) ### Modelos y precios #### GET /api/v1/models Models and tools you can run, with fields and prices | Name | In | Required | Description | |---|---|---|---| | kind | query | no | image \| video \| audio \| text \| edit \| analysis | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/models" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Public operations - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### GET /api/v1/presets Presets: ready-made recipes with their price Each preset names its op, the settings it fixes, the inputs it asks for, the prompt with its {detail} blank and its price at the default settings. Send it as a normal job: POST /jobs with the op and the filled params. | Name | In | Required | Description | |---|---|---|---| | page | query | no | video \| image | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/presets" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### POST /api/v1/estimate Price of a job before you run it (free) Takes the same `op` and `params` as POST /jobs. Nothing is charged. | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```json { "op": "video.kling-3", "params": { "duration": 10, "mode": "pro", "prompt": "Slow push-in" } } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/estimate" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"op": "video.kling-3", "params": {"duration": 10, "mode": "pro", "prompt": "Slow push-in"}}' ``` - `200` Credits it would cost now - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) ### Subidas #### POST /api/v1/uploads Upload a file (multipart field 'file', or the raw body) Images are re-encoded (metadata such as GPS is removed). The type is detected from the file contents. Limits: images 20 MB, video and audio MAX_UPLOAD_MB (1 GB by default). The body is streamed to a temp file on disk, never held in memory whole. | Name | In | Required | Description | |---|---|---|---| | filename | query | no | File name when sending the raw body | ```bash curl -s -X POST "https://staglight.ai/api/v1/uploads" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -F "file=@product.jpg" ``` - `201` Stored. Use the id in job params. - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `413` file_too_large - `415` unsupported_media: use JPG, PNG, WEBP, GIF, MP4, MOV, WEBM, MP3, WAV or M4A - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### POST /api/v1/uploads/from-url Import a file from a public link Direct file links only (no social media pages). Private and local addresses and redirects are refused. ```json { "url": "https://shop.example.com/images/sneaker.jpg" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/uploads/from-url" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://shop.example.com/images/sneaker.jpg"}' ``` - `201` Stored - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `413` file_too_large - `415` unsupported_media: use JPG, PNG, WEBP, GIF, MP4, MOV, WEBM, MP3, WAV or M4A - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) - `502` fetch_failed: the link could not be downloaded #### POST /api/v1/uploads/from-library Add a motion library clip to your files ```json { "id": "" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/uploads/from-library" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"id": ""}' ``` - `201` Stored - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) ### Archivos #### GET /api/v1/media Your files (uploads and results) | Name | In | Required | Description | |---|---|---|---| | kind | query | no | image \| video \| audio | | origin | query | no | upload \| generated \| download | | limit | query | no | | | before | query | no | | ```bash curl -s "https://staglight.ai/api/v1/media" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Newest first - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### GET /api/v1/media/{media_id} One file with fresh signed links | Name | In | Required | Description | |---|---|---|---| | media_id | path | sí | | ```bash curl -s "https://staglight.ai/api/v1/media/med_19a2b3c4d5e6f7a8b9c0d1" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` The file - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### DELETE /api/v1/media/{media_id} Delete a file | Name | In | Required | Description | |---|---|---|---| | media_id | path | sí | | ```bash curl -s -X DELETE "https://staglight.ai/api/v1/media/med_19a2b3c4d5e6f7a8b9c0d1" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Deleted; its links stop working - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) ### Trabajos #### POST /api/v1/jobs Run any model or tool Validates, prices and charges the job, then queues it. If it fails, the credits come back automatically. | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Any unique string up to 255 characters (a UUID v4 is ideal). Retrying with the same key and body within 24 h returns the first response without charging again. | ```json { "max_credits": 80, "op": "video.kling-3", "params": { "aspect_ratio": "9:16", "duration": 5, "first_frame": "med_19a2b3c4d5e6f7a8b9c0d1", "prompt": "Slow push-in on the sneaker on a white table" }, "title": "Sneaker hero 9:16" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/jobs" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"max_credits": 80, "op": "video.kling-3", "params": {"aspect_ratio": "9:16", "duration": 5, "first_frame": "med_19a2b3c4d5e6f7a8b9c0d1", "prompt": "Slow push-in on the sneaker on a white table"}, "title": "Sneaker hero 9:16"}' ``` - `202` Accepted and charged. Poll the Location until it finishes. - `400` Bad Idempotency-Key - `401` Missing or invalid API key - `402` insufficient_credits (with needed and balance) or daily_limit_reached for this API key. Nothing was charged. - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) - `503` Generation is paused for a few minutes. Nothing was charged. #### GET /api/v1/jobs Your jobs, newest first | Name | In | Required | Description | |---|---|---|---| | status | query | no | queued \| running \| succeeded \| failed \| canceled | | run_id | query | no | | | op | query | no | Only jobs of this model or tool | | ops | query | no | Only jobs of these models or tools, comma separated | | idempotency_key | query | no | Find the job a keyed request created | | limit | query | no | | | before | query | no | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/jobs" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Jobs - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### GET /api/v1/jobs/{job_id} One job (optionally wait for it to finish) | Name | In | Required | Description | |---|---|---|---| | job_id | path | sí | | | wait | query | no | Hold the request up to this many seconds until the job finishes | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/jobs/job_19a2b3c4d5e6f7a8b9c0d1?wait=30" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` The job - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### POST /api/v1/jobs/{job_id}/cancel Cancel a job that has not started (refunded) | Name | In | Required | Description | |---|---|---|---| | job_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s -X POST "https://staglight.ai/api/v1/jobs/job_19a2b3c4d5e6f7a8b9c0d1/cancel" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Canceled - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) ### Atajos para generar #### POST /api/v1/generate/image Generate an image (shortcut for op image.) `{"model": "nano-banana-pro", "prompt": "..."}`. Fields go at the top level or inside `params`. | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Any unique string up to 255 characters (a UUID v4 is ideal). Retrying with the same key and body within 24 h returns the first response without charging again. | ```json { "aspect_ratio": "4:5", "model": "nano-banana-pro", "prompt": "The red sneaker on a white paper backdrop, soft light", "reference_images": [ "med_19a2b3c4d5e6f7a8b9c0d1" ] } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/generate/image" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"aspect_ratio": "4:5", "model": "nano-banana-pro", "prompt": "The red sneaker on a white paper backdrop, soft light", "reference_images": ["med_19a2b3c4d5e6f7a8b9c0d1"]}' ``` - `202` Accepted and charged. Poll the Location until it finishes. - `400` Bad Idempotency-Key - `401` Missing or invalid API key - `402` insufficient_credits (with needed and balance) or daily_limit_reached for this API key. Nothing was charged. - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) - `503` Generation is paused for a few minutes. Nothing was charged. #### POST /api/v1/generate/video Generate a video (shortcut for op video.) `{"model": "kling-3", "prompt": "...", "first_frame": "med_...", "duration": 5}`. | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Any unique string up to 255 characters (a UUID v4 is ideal). Retrying with the same key and body within 24 h returns the first response without charging again. | ```json { "aspect_ratio": "4:5", "model": "nano-banana-pro", "prompt": "The red sneaker on a white paper backdrop, soft light", "reference_images": [ "med_19a2b3c4d5e6f7a8b9c0d1" ] } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/generate/video" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"aspect_ratio": "4:5", "model": "nano-banana-pro", "prompt": "The red sneaker on a white paper backdrop, soft light", "reference_images": ["med_19a2b3c4d5e6f7a8b9c0d1"]}' ``` - `202` Accepted and charged. Poll the Location until it finishes. - `400` Bad Idempotency-Key - `401` Missing or invalid API key - `402` insufficient_credits (with needed and balance) or daily_limit_reached for this API key. Nothing was charged. - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) - `503` Generation is paused for a few minutes. Nothing was charged. ### Formatos y ejecuciones #### GET /api/v1/formats Ad formats with their price per quality tier | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es or en for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/formats" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### GET /api/v1/formats/{format_id} One format with a step-by-step estimate | Name | In | Required | Description | |---|---|---|---| | format_id | path | sí | | | tier | query | no | draft \| standard \| premium | | aspect | query | no | | | lang | query | no | es or en for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/formats/product_hero" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### GET /api/v1/formats/{format_id}/series Your series or projects in this format, newest first | Name | In | Required | Description | |---|---|---|---| | format_id | path | sí | | ```bash curl -s "https://staglight.ai/api/v1/formats/product_hero/series" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### POST /api/v1/formats/{format_id}/series Start a series: settings, files, people, scenes and story kept between takes | Name | In | Required | Description | |---|---|---|---| | format_id | path | sí | | ```json { "name": "La abuela olorosa" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/formats/product_hero/series" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "La abuela olorosa"}' ``` - `201` Successful Response #### GET /api/v1/formats/{format_id}/series/{series_id} One series: what it remembers and its takes | Name | In | Required | Description | |---|---|---|---| | format_id | path | sí | | | series_id | path | sí | | | lang | query | no | es or en for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/formats/product_hero/series/{series_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### PATCH /api/v1/formats/{format_id}/series/{series_id} Change a series (name, notes, what comes next, settings) | Name | In | Required | Description | |---|---|---|---| | format_id | path | sí | | | series_id | path | sí | | ```json { "next": "People want her to meet the neighbour.", "notes": "She lives alone with her cat and hates soap." } ``` ```bash curl -s -X PATCH "https://staglight.ai/api/v1/formats/product_hero/series/{series_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"next": "People want her to meet the neighbour.", "notes": "She lives alone with her cat and hates soap."}' ``` - `200` Successful Response #### DELETE /api/v1/formats/{format_id}/series/{series_id} Delete a series: its memory goes, your files stay | Name | In | Required | Description | |---|---|---|---| | format_id | path | sí | | | series_id | path | sí | | ```bash curl -s -X DELETE "https://staglight.ai/api/v1/formats/product_hero/series/{series_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### POST /api/v1/runs Start an ad format run (the plan step is charged now) | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es or en for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```json { "format": "problem_solution", "options": { "aspect": "9:16", "lang": "es", "tier": "draft" }, "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"format": "problem_solution", "options": {"aspect": "9:16", "lang": "es", "tier": "draft"}, "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1"}' ``` - `202` Successful Response #### GET /api/v1/runs Your format runs, newest first | Name | In | Required | Description | |---|---|---|---| | limit | query | no | | | before | query | no | | | status | query | no | running \| awaiting_approval \| needs_attention \| succeeded \| failed \| canceled | | format | query | no | Only runs of this format, e.g. motion_remix | | series | query | no | Only runs of this series | | lang | query | no | es or en for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/runs" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### POST /api/v1/runs/estimate Price a run before starting it (free) | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es or en for names and labels. Defaults to your account language. | ```json { "format": "motion_remix", "inputs": { "clip": "med_19a2b3c4d5e6f7a8b9c0d1", "mode": "restyle", "styles": [ "claymation", "watercolour" ] } } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/estimate" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"format": "motion_remix", "inputs": {"clip": "med_19a2b3c4d5e6f7a8b9c0d1", "mode": "restyle", "styles": ["claymation", "watercolour"]}}' ``` - `200` Successful Response #### POST /api/v1/formats/script_runner/parse Script Runner: split a script into scenes and price them (free) Scenes with their lines, cast (from your characters library), product flag, model, allowed lengths and price, plus the whole run's estimate. Errors (with line numbers) come back in errors with a 200; nothing is charged. Send the same script and scenes to POST /runs (options.script, options.scenes). | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es or en for names and labels. Defaults to your account language. | ```json { "aspect": "9:16", "scenes": [ { "model": "veo-fast" }, { "product": true } ], "script": "=== CHARACTER === Ana\n=== SCENE: Kitchen ===\nAna pours coffee.\n=== DIALOGUE ===\nAna: My coffee used to go cold before I sat down.\n=== SCENE: Car ===\nAna: Not any more.", "tier": "draft" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/formats/script_runner/parse" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"aspect": "9:16", "scenes": [{"model": "veo-fast"}, {"product": true}], "script": "=== CHARACTER === Ana\n=== SCENE: Kitchen ===\nAna pours coffee.\n=== DIALOGUE ===\nAna: My coffee used to go cold before I sat down.\n=== SCENE: Car ===\nAna: Not any more.", "tier": "draft"}' ``` - `200` Successful Response #### POST /api/v1/runs/propose Propose a format, tier and options from a written brief (planning step charged) | Name | In | Required | Description | |---|---|---|---| | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```json { "brief": "UGC de 15 s para mi sérum de vitamina C, mujer de 30, tono cercano, para Reels", "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/propose" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"brief": "UGC de 15 s para mi sérum de vitamina C, mujer de 30, tono cercano, para Reels", "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1"}' ``` - `200` Successful Response #### POST /api/v1/runs/from-analysis Make the ad of an analysis with your product (script_runner run, the plan step is charged now) Starts a script_runner run whose script is the analysis's replication scenes (chosen hook first) and whose product is yours. Same price, approval steps and refunds as POST /runs with format script_runner; price it first with POST /runs/estimate. | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es or en for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```json { "analysis_id": "job_19a2b3c4d5e6f7a8b9c0d1", "hook_index": 2, "options": { "tier": "draft" }, "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/from-analysis" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"analysis_id": "job_19a2b3c4d5e6f7a8b9c0d1", "hook_index": 2, "options": {"tier": "draft"}, "product_id": "prd_19a2b3c4d5e6f7a8b9c0d1"}' ``` - `202` Successful Response #### GET /api/v1/analyses/{analysis_id}/script The script that Make this ad would start with (free) {script, notes, hook, hook_index, lang, aspect, format}: the script_runner inputs built from the analysis's replication block. The block itself is in data.replication of GET /api/v1/jobs/{id} for the analysis job. | Name | In | Required | Description | |---|---|---|---| | analysis_id | path | sí | | | hook_index | query | no | 0 to 4, from replication.hooks | ```bash curl -s "https://staglight.ai/api/v1/analyses/{analysis_id}/script" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### GET /api/v1/runs/{run_id} One run (optionally wait for a change) | Name | In | Required | Description | |---|---|---|---| | run_id | path | sí | | | wait | query | no | Hold up to this many seconds while it is running | | lang | query | no | es or en for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/runs/run_19a2b3c4d5e6f7a8b9c0d1?wait=30" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### GET /api/v1/runs/{run_id}/outputs.zip Every finished file of a run in one zip (free) The run's outputs (a Motion Remix run: one file per finished version) stored, not recompressed (they are already H.264), in run order. 404 until something is finished. | Name | In | Required | Description | |---|---|---|---| | run_id | path | sí | | ```bash curl -s "https://staglight.ai/api/v1/runs/run_19a2b3c4d5e6f7a8b9c0d1/outputs.zip" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### POST /api/v1/runs/{run_id}/approve Approve the step under review (may start paid steps) | Name | In | Required | Description | |---|---|---|---| | run_id | path | sí | | | lang | query | no | es or en for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```json { "edits": { "cta": "Pídelo hoy" }, "step": "plan" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/run_19a2b3c4d5e6f7a8b9c0d1/approve" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"edits": {"cta": "Pídelo hoy"}, "step": "plan"}' ``` - `200` Successful Response #### POST /api/v1/runs/{run_id}/redo New take of one item (charged again) | Name | In | Required | Description | |---|---|---|---| | run_id | path | sí | | | lang | query | no | es or en for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```json { "index": 1, "prompt": "Same scene, warmer morning light", "step": "keyframes" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/run_19a2b3c4d5e6f7a8b9c0d1/redo" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"index": 1, "prompt": "Same scene, warmer morning light", "step": "keyframes"}' ``` - `200` Successful Response #### POST /api/v1/runs/{run_id}/scenes Script Runner storyboard: edit, remove, undo or add a scene While the script or the storyboard waits for approval. Free except add at the storyboard (one still, storyboard.add_credits in GET /runs/{id}). | Name | In | Required | Description | |---|---|---|---| | run_id | path | sí | | | lang | query | no | es or en for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```json { "action": "edit", "index": 1, "scene": { "model": "veo-fast", "seconds": 8 } } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/run_19a2b3c4d5e6f7a8b9c0d1/scenes" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"action": "edit", "index": 1, "scene": {"model": "veo-fast", "seconds": 8}}' ``` - `200` Successful Response #### POST /api/v1/runs/{run_id}/cancel Cancel a run (jobs not started yet are refunded) | Name | In | Required | Description | |---|---|---|---| | run_id | path | sí | | | lang | query | no | es or en for names and labels. Defaults to your account language. | ```bash curl -s -X POST "https://staglight.ai/api/v1/runs/run_19a2b3c4d5e6f7a8b9c0d1/cancel" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response ### Productos #### GET /api/v1/products Your products (brand kit) | Name | In | Required | Description | |---|---|---|---| | limit | query | no | | | before | query | no | | ```bash curl -s "https://staglight.ai/api/v1/products" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Newest first - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### POST /api/v1/products Save a product ```json { "audience": "Corredores urbanos de 25 a 40", "benefits": [ "Pesa 210 g", "Suela que agarra en mojado" ], "description": "Zapatilla ligera de malla para correr a diario.", "lang": "es", "media_ids": [ "med_19a2b3c4d5e6f7a8b9c0d1" ], "name": "Zapatilla Runner Roja", "price_text": "59,90 €", "url": "https://shop.example.com/runner" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/products" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"audience": "Corredores urbanos de 25 a 40", "benefits": ["Pesa 210 g", "Suela que agarra en mojado"], "description": "Zapatilla ligera de malla para correr a diario.", "lang": "es", "media_ids": ["med_19a2b3c4d5e6f7a8b9c0d1"], "name": "Zapatilla Runner Roja", "price_text": "59,90 €", "url": "https://shop.example.com/runner"}' ``` - `201` Saved - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### GET /api/v1/products/{product_id} One product | Name | In | Required | Description | |---|---|---|---| | product_id | path | sí | | ```bash curl -s "https://staglight.ai/api/v1/products/prd_19a2b3c4d5e6f7a8b9c0d1" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` The product - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### PATCH /api/v1/products/{product_id} Change some fields of a product | Name | In | Required | Description | |---|---|---|---| | product_id | path | sí | | ```json { "price_text": "49,90 €" } ``` ```bash curl -s -X PATCH "https://staglight.ai/api/v1/products/prd_19a2b3c4d5e6f7a8b9c0d1" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"price_text": "49,90 €"}' ``` - `200` Updated - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) #### DELETE /api/v1/products/{product_id} Delete a product (its photos stay) | Name | In | Required | Description | |---|---|---|---| | product_id | path | sí | | ```bash curl -s -X DELETE "https://staglight.ai/api/v1/products/prd_19a2b3c4d5e6f7a8b9c0d1" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Deleted - `401` Missing or invalid API key - `403` csrf_failed (browser sessions only) - `404` Not found, or it belongs to another account - `429` rate_limited: wait retry_after seconds (also in the Retry-After header) ### Ad Studio #### GET /api/v1/studio Ad Studio: every studio with its from-price | Name | In | Required | Description | |---|---|---|---| | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/studio" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### GET /api/v1/studio/library Your saved inspiration ads (Recreate, Edit Product Photo) ```bash curl -s "https://staglight.ai/api/v1/studio/library" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### PUT /api/v1/studio/library Replace your saved inspiration ads ```bash curl -s -X PUT "https://staglight.ai/api/v1/studio/library" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` - `200` Successful Response - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field #### GET /api/v1/studio/{studio_id} One studio: inputs, cards with price, helpers | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/studio/{studio_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### DELETE /api/v1/studio/{studio_id}/user-cards/{card_id} Delete one of your saved cards in this studio | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | card_id | path | sí | | ```bash curl -s -X DELETE "https://staglight.ai/api/v1/studio/{studio_id}/user-cards/{card_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### GET /api/v1/studio/{studio_id}/series Your series in this studio, newest first | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | ```bash curl -s "https://staglight.ai/api/v1/studio/{studio_id}/series" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### POST /api/v1/studio/{studio_id}/series Start a series: settings, people, scenes and story kept between takes | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | ```json { "name": "La abuela olorosa" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/studio/{studio_id}/series" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "La abuela olorosa"}' ``` - `201` Successful Response - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field #### GET /api/v1/studio/{studio_id}/series/{series_id} One series: what it remembers and its episodes | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | series_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/studio/{studio_id}/series/{series_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### PATCH /api/v1/studio/{studio_id}/series/{series_id} Change a series (name, notes, what comes next, settings) | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | series_id | path | sí | | ```json { "next": "People want her to meet the neighbour.", "notes": "She lives alone with her cat and hates soap." } ``` ```bash curl -s -X PATCH "https://staglight.ai/api/v1/studio/{studio_id}/series/{series_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"next": "People want her to meet the neighbour.", "notes": "She lives alone with her cat and hates soap."}' ``` - `200` Successful Response - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field #### DELETE /api/v1/studio/{studio_id}/series/{series_id} Delete a series: its memory goes, your files stay | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | series_id | path | sí | | ```bash curl -s -X DELETE "https://staglight.ai/api/v1/studio/{studio_id}/series/{series_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### POST /api/v1/studio/{studio_id}/estimate Price a click before starting it (free) | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```json { "aspect": "4:5", "card": "hero", "inputs": { "language": "es", "niche": "vitamin C serum", "rating": "4.8/5 (230 reviews)", "resolution": "2K" }, "media": { "product": [ "med_19a2b3c4d5e6f7a8b9c0d1" ] }, "quality": "final", "real": [ "rating" ], "variants": 2 } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/studio/{studio_id}/estimate" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"aspect": "4:5", "card": "hero", "inputs": {"language": "es", "niche": "vitamin C serum", "rating": "4.8/5 (230 reviews)", "resolution": "2K"}, "media": {"product": ["med_19a2b3c4d5e6f7a8b9c0d1"]}, "quality": "final", "real": ["rating"], "variants": 2}' ``` - `200` Successful Response - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field #### POST /api/v1/studio/{studio_id}/check Free checks of a click (studios that have them, e.g. Ranking Shorts) | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```json { "aspect": "4:5", "card": "hero", "inputs": { "language": "es", "niche": "vitamin C serum", "rating": "4.8/5 (230 reviews)", "resolution": "2K" }, "media": { "product": [ "med_19a2b3c4d5e6f7a8b9c0d1" ] }, "quality": "final", "real": [ "rating" ], "variants": 2 } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/studio/{studio_id}/check" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"aspect": "4:5", "card": "hero", "inputs": {"language": "es", "niche": "vitamin C serum", "rating": "4.8/5 (230 reviews)", "resolution": "2K"}, "media": {"product": ["med_19a2b3c4d5e6f7a8b9c0d1"]}, "quality": "final", "real": ["rating"], "variants": 2}' ``` - `200` Successful Response - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field #### POST /api/v1/studio/{studio_id}/runs Start a studio click (each image is a charged job) | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Any unique string up to 255 characters (a UUID v4 is ideal). Retrying with the same key and body within 24 h returns the first response without charging again. | ```json { "aspect": "4:5", "card": "hero", "inputs": { "language": "es", "niche": "vitamin C serum", "rating": "4.8/5 (230 reviews)", "resolution": "2K" }, "media": { "product": [ "med_19a2b3c4d5e6f7a8b9c0d1" ] }, "quality": "final", "real": [ "rating" ], "variants": 2 } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/studio/{studio_id}/runs" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"aspect": "4:5", "card": "hero", "inputs": {"language": "es", "niche": "vitamin C serum", "rating": "4.8/5 (230 reviews)", "resolution": "2K"}, "media": {"product": ["med_19a2b3c4d5e6f7a8b9c0d1"]}, "quality": "final", "real": ["rating"], "variants": 2}' ``` - `202` Accepted and charged. Poll GET .../runs/{run_id} or each job. - `400` Bad Idempotency-Key - `402` insufficient_credits (with needed and balance) or daily_limit_reached for this API key. Nothing was charged. - `404` Not found, or it belongs to another account - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `422` invalid_request, with the offending field - `503` Generation is paused for a few minutes. Nothing was charged. #### GET /api/v1/studio/{studio_id}/runs Your earlier clicks in this studio, newest first | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | | limit | query | no | | | before | query | no | | | series | query | no | | ```bash curl -s "https://staglight.ai/api/v1/studio/{studio_id}/runs" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### GET /api/v1/studio/{studio_id}/runs/{run_id} One studio click with its jobs | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | run_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/studio/{studio_id}/runs/run_19a2b3c4d5e6f7a8b9c0d1" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### GET /api/v1/studio/{studio_id}/runs/{run_id}/outputs.zip Every finished file of a studio click in one zip (free) | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | run_id | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | ```bash curl -s "https://staglight.ai/api/v1/studio/{studio_id}/runs/run_19a2b3c4d5e6f7a8b9c0d1/outputs.zip" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response - `404` Not found, or it belongs to another account #### POST /api/v1/studio/{studio_id}/helpers/{name} Run a copy helper (1 or 2 credits) | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | name | path | sí | | | lang | query | no | es, en, de or pt for names and labels. Defaults to your account language. | | Idempotency-Key | header | no | Optional. Any unique string up to 255 characters (a UUID v4 is ideal). Retrying with the same key and body within 24 h returns the first response without charging again. | ```json { "payload": { "url": "shop.example.com" } } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/studio/{studio_id}/helpers/{name}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"payload": {"url": "shop.example.com"}}' ``` - `200` The finished job; its data holds the result - `202` Still running: poll GET /api/v1/jobs/{id} - `400` Bad Idempotency-Key - `402` insufficient_credits (with needed and balance) or daily_limit_reached for this API key. Nothing was charged. - `404` Not found, or it belongs to another account - `409` idempotency_mismatch, idempotency_in_progress, price_above_max or not_cancelable - `422` invalid_request, with the offending field - `503` Generation is paused for a few minutes. Nothing was charged. #### POST /api/v1/studio/{studio_id}/helpers/{name}/cancel Cancel a helper's page read (free) Cancel pressed while a page is read (the product link scan): the read stops at its next step and charges nothing; when its 1-credit job was already made it is canceled and refunded if it has not started. | Name | In | Required | Description | |---|---|---|---| | studio_id | path | sí | | | name | path | sí | | ```json { "token": "k3v9q2x7m1p4" } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/studio/{studio_id}/helpers/{name}/cancel" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"token": "k3v9q2x7m1p4"}' ``` - `200` Successful Response - `404` Not found, or it belongs to another account - `422` invalid_request, with the offending field ### Characters #### GET /api/v1/characters Your characters | Name | In | Required | Description | |---|---|---|---| | limit | query | no | | | before | query | no | | ```bash curl -s "https://staglight.ai/api/v1/characters" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### POST /api/v1/characters Save a character ```json { "description": "Woman in her 30s, curly dark hair, denim jacket", "images": { "front": "med_19a2b3c4d5e6f7a8b9c0d1" }, "likeness_consent": true, "name": "Ana", "voice": { "id": "hpp4J3VqNfWAUOO0d1Us", "speed": 1.0, "stability": 0.5 } } ``` ```bash curl -s -X POST "https://staglight.ai/api/v1/characters" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"description": "Woman in her 30s, curly dark hair, denim jacket", "images": {"front": "med_19a2b3c4d5e6f7a8b9c0d1"}, "likeness_consent": true, "name": "Ana", "voice": {"id": "hpp4J3VqNfWAUOO0d1Us", "speed": 1.0, "stability": 0.5}}' ``` - `201` Successful Response #### GET /api/v1/characters/{character_id} One character | Name | In | Required | Description | |---|---|---|---| | character_id | path | sí | | ```bash curl -s "https://staglight.ai/api/v1/characters/{character_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### PATCH /api/v1/characters/{character_id} Change some fields of a character | Name | In | Required | Description | |---|---|---|---| | character_id | path | sí | | ```bash curl -s -X PATCH "https://staglight.ai/api/v1/characters/{character_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` - `200` Successful Response #### DELETE /api/v1/characters/{character_id} Delete a character (its pictures stay in your files) | Name | In | Required | Description | |---|---|---|---| | character_id | path | sí | | ```bash curl -s -X DELETE "https://staglight.ai/api/v1/characters/{character_id}" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" ``` - `200` Successful Response #### POST /api/v1/characters/{character_id}/sheet Make a character sheet: front, side and close-up from one picture (charged once) Three images of the same person, priced together (sheet_credits) and charged when you click. Each image is refunded if it fails. The images replace the character's front, side and close-up when they finish. | Name | In | Required | Description | |---|---|---|---| | character_id | path | sí | | | Idempotency-Key | header | no | Optional. Same key and body within 24 h returns the first response, no new charge. | ```bash curl -s -X POST "https://staglight.ai/api/v1/characters/{character_id}/sheet" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{}' ``` - `202` Successful Response ### Other #### POST /api/v1/messages Send Message ```bash curl -s -X POST "https://staglight.ai/api/v1/messages" \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` - `201` Successful Response ## Conectar tu agente por MCP Claude Code, Codex, Cursor y apps de chat como claude.ai pueden usar Staglight como herramientas: estimar el precio, generar, consultar y descargar, con el mismo saldo que el estudio. ### Apps de chat en menos de un minuto claude.ai, Claude Desktop y otras apps de chat con conectores personalizados inician sesión con tu cuenta de Staglight (OAuth 2.1), así que nadie tiene que pegar una clave. Apruebas cada app una vez y le das un tope de gasto. #### Claude [Añadir a Claude](https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Staglight&connectorUrl=https%3A%2F%2Fstaglight.ai%2Fmcp) 1. Haz clic en el botón de arriba o, en Claude, abre Personalizar > Conectores > Añadir conector personalizado con el nombre Staglight y la URL `https://staglight.ai/mcp`. 2. Haz clic en Continuar, deja Iniciar sesión ahora y haz clic en Añadir; luego entra con tu cuenta de Staglight, elige qué puede hacer y su tope de gasto, y haz clic en Permitir. Con el plan gratuito puedes añadir un conector personalizado; en Team y Enterprise lo añade primero un propietario y tú haces clic en Conectar. 3. En un chat, abre + > Conectores y activa Staglight. Adjunta una foto del producto y pide: hazme un anuncio para este producto. #### ChatGPT 1. En ChatGPT en la web, abre Ajustes > Plugins y haz clic en + > Añadir servidor MCP personalizado. Hace falta un espacio Business, Enterprise o Edu que lo permita; en Pro solo puede leer. 2. Llámalo Staglight, pega la URL `https://staglight.ai/mcp`, elige OAuth, marca la casilla para continuar y haz clic en Crear como plugin. 3. Inicia sesión con tu cuenta de Staglight y haz clic en Permitir. 4. En un chat nuevo, escribe @, elige Staglight y pide tu anuncio. > Cada conexión aparece en [Ajustes > Conexiones](https://staglight.ai/app/ajustes#conexiones) con su tope de gasto (en 24 horas); Desconectar le quita el acceso al instante. Las herramientas que gastan, suben o cambian algo necesitan el permiso Crear anuncios y gastar créditos; una conexión de solo lectura puede ver pero no gastar. ### Servidor - URL: `https://staglight.ai/mcp` - Transporte: `Streamable HTTP` - Autenticación: `OAuth 2.1 · Bearer ` - Protocolo: `2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26` Crea una clave con límite diario en [el estudio](https://staglight.ai/app/api) y guárdala como `STAGLIGHT_API_KEY`. Terminal: ```bash export STAGLIGHT_API_KEY="sl_live_..." ``` ### Claude Code Un solo comando para todos los proyectos de este equipo. La terminal inserta la clave y Claude Code la guarda en `~/.claude.json`. Terminal: ```bash claude mcp add --transport http staglight https://staglight.ai/mcp \ --header "Authorization: Bearer $STAGLIGHT_API_KEY" --scope user ``` > ¿Prefieres iniciar sesión en vez de usar una clave? Ejecuta el comando sin la parte `--header`, escribe `/mcp` en Claude Code y elige staglight para iniciar sesión con tu cuenta de Staglight. Comprueba que se conectó: Terminal: ```bash claude mcp get staglight ``` Para compartirlo con un equipo en el repositorio, añade `.mcp.json`. Cada persona guarda la clave en su propia `STAGLIGHT_API_KEY`. .mcp.json: ```json { "mcpServers": { "staglight": { "type": "http", "url": "https://staglight.ai/mcp", "headers": { "Authorization": "Bearer ${STAGLIGHT_API_KEY}" }, "timeout": 600000 } } } ``` > Llama a la variable `STAGLIGHT_API_KEY`. Claude Code deja vacías en los encabezados remotos algunas variables de credenciales con nombres reservados, así que usa esta. ### Codex Terminal: ```bash codex mcp add staglight --url https://staglight.ai/mcp --bearer-token-env-var STAGLIGHT_API_KEY ``` O escríbelo a mano en la configuración de Codex: ~/.codex/config.toml: ```toml [mcp_servers.staglight] url = "https://staglight.ai/mcp" bearer_token_env_var = "STAGLIGHT_API_KEY" startup_timeout_sec = 20 tool_timeout_sec = 120 ``` > Codex corta una llamada a una herramienta a los 60 s por defecto. Todas las herramientas responden en menos de 50 s, y `get_job` espera 50 s como máximo. ### Cursor En `~/.cursor/mcp.json` para todos los proyectos, o en `.cursor/mcp.json` para uno: ~/.cursor/mcp.json: ```json { "mcpServers": { "staglight": { "url": "https://staglight.ai/mcp", "headers": { "Authorization": "Bearer ${env:STAGLIGHT_API_KEY}" } } } } ``` ### Claude Desktop y claude.ai claude.ai y Claude Desktop se conectan iniciando sesión con tu cuenta de Staglight: consulta [Apps de chat](#chat-apps). Si prefieres usar ahí una clave de API, usa como puente en tu equipo el paquete de la comunidad `mcp-remote` en `claude_desktop_config.json`: claude_desktop_config.json: ```json { "mcpServers": { "staglight": { "command": "npx", "args": [ "mcp-remote", "https://staglight.ai/mcp", "--header", "Authorization:${AUTH_HEADER}", "--transport", "http-only" ], "env": { "AUTH_HEADER": "Bearer sl_live_..." } } } } ``` > `mcp-remote` es un paquete de terceros que se ejecuta en tu equipo con tu clave. Revísalo antes de usarlo. ### Herramientas Las herramientas de pago aceptan `max_credits` e `idempotency_key`. Cada resultado trae un texto breve, los datos en JSON y, para archivos terminados, enlaces de descarga. | Herramienta | Qué hace | Precio | |---|---|---| | get_balance | Saldo, límite diario de la clave y lo que queda hoy. | Gratis | | buy_credits_link | Enlace para comprar créditos en el estudio. | Gratis | | list_models | Modelos y herramientas con sus campos y precio inicial. | Gratis | | estimate_cost | Precio exacto de una llamada antes de hacerla. | Gratis | | upload_from_url | Importa un archivo desde un enlace directo y devuelve su id. | Gratis | | upload_file | Guarda una foto o un clip corto que adjuntas en el chat (base64, hasta 12 MB) y devuelve su id. | Gratis | | upload_image | Lo mismo que upload_file. | Gratis | | list_media | Subidas y resultados con enlaces firmados. | Gratis | | generate_image | Imágenes de producto con Nano Banana, GPT Image, Seedream o Flux. | De pago | | generate_video | Clips con Kling, Veo, Seedance, Hailuo o Wan, además de avatares y control de movimiento. | De pago | | generate_voice | Voz en off con ElevenLabs. Si falla, se reintenta una vez con una voz de respaldo parecida sin cobro extra (sin tiempos por palabra); envía allow_fallback: false para recibir el reembolso en su lugar. | De pago | | generate_music | Música de fondo con Suno. | De pago | | upscale | Aumenta la resolución de una imagen o un video. | De pago | | remove_background | Recorta el producto (PNG transparente). | De pago | | add_captions | Incrusta en el video subtítulos sincronizados palabra por palabra. | De pago | | reburn_captions | Vuelve a incrustar los subtítulos con líneas editadas o un estilo nuevo, sin transcribir otra vez. Gratis, con un límite diario. | De pago | | merge_videos | Une clips en un solo video con una única relación de aspecto. | De pago | | clean_export | Copia sin datos de ubicación, dispositivo, edición ni modelo de IA; mantiene una nota de contenido con IA salvo que la desactives. | De pago | | analyze_ad | Evalúa un anuncio desde un archivo o un enlace de publicación y escribe nuevos ganchos y un guion para rehacerlo con tu producto. | De pago | | create_job | Ejecuta cualquier op de list_models. | De pago | | social_download | Descarga una publicación de TikTok, Instagram, Facebook o Shorts en tu biblioteca. Gratis, con un límite diario. | De pago | | list_characters | Lista tus personajes guardados con sus fotos y su voz, y el precio de una hoja de personaje. | Gratis | | get_character | Un personaje guardado con sus fotos y su voz. | Gratis | | create_character | Guarda una persona una sola vez (nombre, de 1 a 3 fotos, voz opcional) para usarla en las escenas de Script Runner. Requiere confirmar el derecho de imagen. | Gratis | | update_character | Cambia el nombre, la descripción, las fotos o la voz de un personaje. | Gratis | | delete_character | Borra un personaje guardado. | Gratis | | make_character_sheet | Dibuja de frente, de perfil y en primer plano a una persona a partir de una foto. De pago, se cobra una vez. | De pago | | parse_script | Lee un guion y muestra cada escena con su reparto, modelo, duración y precio. Gratis. | Gratis | | edit_scenes | Edita, quita, recupera o añade escenas de Script Runner antes de crear los clips. | De pago | | get_job | Estado y resultados, espera hasta 50 s. | Gratis | | list_jobs | Trabajos, también filtrados por idempotency_key si se agotó el tiempo de espera o por ejecución del Estudio de anuncios. | Gratis | | cancel_job | Cancela un trabajo que no ha empezado (reembolsado). | Gratis | | list_formats | Formatos de anuncio con precio por calidad. | Gratis | | list_products | Productos guardados para usar en anuncios. | Gratis | | create_product | Guarda un producto con su nombre y de 1 a 8 fotos, para usarlo en todos tus anuncios. | Gratis | | get_product | Un producto guardado con los enlaces de sus fotos. | Gratis | | create_ad | Empieza un anuncio completo a partir de un formato. Con auto llega al final dentro de max_credits. | De pago | | propose_ad | Propone formato y precio a partir de una descripción escrita. | De pago | | create_ad_from_brief | Propone y empieza el anuncio en una sola llamada. Con auto lo termina solo dentro de max_credits. | De pago | | get_ad | Estado de un anuncio en curso, espera hasta 50 s. | Gratis | | approve_ad_step | Aprueba un paso de revisión y pone en marcha los siguientes, o deja el resto en modo auto. | De pago | | redo_ad_step | Toma nueva de un elemento (se cobra otra vez). | De pago | | motion_remix | Una versión nueva de tu propio clip por personaje, producto o estilo: borradores, eliges, terminas. El modo reemplazar y una persona o cara como target piden likeness: true (desde el 31-10-2026); el cambio preciso se detiene en el paso mask para que lo revises. | De pago | | cancel_ad | Detiene un anuncio y reembolsa los trabajos que no han empezado. | Gratis | | studio_list | Los estudios del Estudio de anuncios con sus tipos, campos y precios. | Gratis | | studio_estimate | Precio exacto de un clic en el Estudio de anuncios, con tu saldo. Gratis. | Gratis | | studio_check | Hace las comprobaciones gratuitas de un estudio antes de pagar (Shorts de ranking: cada nivel y la variedad entre ellos). | Gratis | | studio_run | Crea imágenes del Estudio de anuncios: se cobra un trabajo por imagen y se reembolsa si falla. | De pago | | studio_helper | Ejecuta un asistente del Estudio de anuncios (un precio fijo pequeño, míralo en studio_list). link_scan lee la página de un producto y devuelve sus fotos como tus archivos subidos, el nombre y una línea de descripción. | De pago | | studio_series | La serie de un canal o el proyecto de una tienda: lo que recuerda y sus episodios. | Gratis | | studio_series_save | Empieza o cambia una serie: sus notas, lo que pidió la audiencia o volver a un episodio anterior. | Gratis | | ad_series | La serie o el proyecto de un formato: lo que recuerda y sus tomas. | Gratis | | ad_series_save | Empieza o cambia la serie de un formato: sus notas, lo que pidió tu audiencia o volver a una toma anterior. | Gratis | | studio_get_run | Estado de un clic en el Estudio de anuncios: cada trabajo (incluidos los pasos posteriores) y los archivos terminados. | Gratis | ### Reglas de gasto para agentes - Llama a `estimate_cost` antes de cualquier herramienta de pago. Es gratis y calcula el precio de la llamada exacta: `tool` más `arguments`. - Envía `max_credits` y un `idempotency_key` nuevo en cada llamada de pago. - Las herramientas de pago responden al momento con un `job_id` o `run_id`. Consulta `get_job` o `get_ad` con `wait_seconds=50`. - Si se agota el tiempo de espera, llama a `list_jobs` con el mismo `idempotency_key` antes de volver a pagar. - Los trabajos fallidos se reembolsan solos. Sin créditos, `buy_credits_link` da al usuario un enlace al estudio. Ningún pago pasa por el MCP. - Da a cada agente su propia clave con límite diario. Al llegar al límite recibe `daily_limit_reached` y se detiene. - Con `auto: true`, `create_ad` y `create_ad_from_brief` aprueban solos cada paso de revisión mientras todo el anuncio quepa en `max_credits`. Si el siguiente paso lo superara, el anuncio espera en ese paso con `auto_stopped` y no se cobra nada más. ### Errores Los errores de las herramientas llegan como resultado con `isError: true` y los mismos códigos que la API REST. Sin créditos incluye `needed`, `balance` y `topup_url`. Una clave que falta o es incorrecta da HTTP 401 con `WWW-Authenticate`. JSON: ```json { "content": [ { "type": "text", "text": "Error insufficient_credits: This needs 63 credits and the balance is 10. ..." } ], "structuredContent": { "error": { "code": "insufficient_credits", "message": "This needs 63 credits and the balance is 10. Buy credits to continue.", "status": 402, "needed": 63, "balance": 10, "charged": false, "topup_url": "https://staglight.ai/app/creditos?need=53" } }, "isError": true } ``` ### Prueba con curl El servidor responde JSON normal por POST, sin sesiones, así que curl funciona: Terminal: ```bash curl -s https://staglight.ai/mcp \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-11-25", "capabilities": {}, "clientInfo": {"name": "curl", "version": "1.0"}}}' ``` Terminal: ```bash curl -s https://staglight.ai/mcp \ -H "Authorization: Bearer $STAGLIGHT_API_KEY" \ -H "Content-Type: application/json" \ -H "MCP-Protocol-Version: 2025-11-25" \ -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_balance", "arguments": {}}}' ``` ## Kit para agentes Un prompt para pegar, una skill que tu agente carga solo y recetas de FFmpeg para terminar anuncios. ### Prompt para el agente Pégalo al empezar una sesión de Claude Code, Codex o Cursor, después de [conectar el servidor MCP](https://staglight.ai/es/docs/mcp). Prompt: ```text Haces anuncios para tiendas online con Staglight usando sus herramientas MCP (servidor "staglight"). Docs: https://staglight.ai/es/docs Reglas de gasto - Antes de algo de pago, dime el precio (estimate_cost es gratis) y pregúntame una vez. Nunca gastes más de lo que aprobé. - Envía max_credits y un idempotency_key nuevo (un UUID) en cada llamada de pago. - Las herramientas de pago responden al momento con un job_id o run_id. Consulta get_job, get_ad o studio_get_run con wait_seconds=50 hasta que termine. - Solo un enlace de producto ("hazme un anuncio para https://..."): studio_helper(studio=link_ad, name=link_scan, payload.url, siempre con un idempotency_key que el reintento repite, o el reintento vuelve a leer y a cobrar) lee esa página (el precio fijo y pequeño del análisis) y devuelve las fotos, el nombre y una línea; después studio_estimate y studio_run en link_ad con la mejor foto. - Si se agota el tiempo de espera o hay un error, nunca repitas a ciegas una llamada de pago: primero llama a list_jobs con el mismo idempotency_key. - Si se acaban los créditos, dame el enlace de buy_credits_link y para. Cómo trabajar - Si adjunto una foto o un clip del producto: upload_file y después create_product con su nombre y sus fotos. O usa list_products, o upload_from_url con un enlace directo al archivo. - Un anuncio en video terminado: estimate_cost para create_ad (tier "draft" salvo que pida más calidad), dime el precio y, cuando diga que sí, llama a create_ad con auto=true y max_credits = el precio que aprobé. Si mi pedido es poco concreto, usa create_ad_from_brief con auto=true y el presupuesto que aprobé. - Consulta get_ad hasta que esté succeeded y dame el archivo. Si se detiene (auto_stopped), dime por qué y cuánto cuesta seguir. - Imágenes de producto (carrusel de tienda, anuncios estáticos, fotos UGC): el Estudio de anuncios con studio_list, studio_estimate, studio_run y después studio_get_run. - Descarga los archivos terminados con curl -L -o en ./ads/ y termínalos con ffmpeg: 9:16 a 1080x1920, subtítulos, -14 LUFS. - Mantén la etiqueta de contenido generado con IA. Nunca presentes un video estilo creador como la reseña de un cliente real. ``` ### Pídelo con tus palabras Con el servidor MCP conectado, adjunta una foto del producto y di lo que quieres. El agente la sube, guarda el producto, te dice el precio, te pregunta una vez y te devuelve el archivo terminado. Por ejemplo: - "Hazme un anuncio UGC de 15 segundos de este sérum para Reels. Que no pase de 3 dólares." - "Aquí tienes 3 fotos de mi taza de cerámica. Guárdala como producto y hazme un video vertical del producto en español." - "Convierte esta foto en un carrusel para mi tienda: fondo blanco, una foto de ambiente y un primer plano de la etiqueta." - "Algo para TikTok que venda esta botella de agua a gente que va al gimnasio. Dime antes el precio." Tu visto bueno fija un tope de créditos para todo el anuncio: nunca gasta más y, si el siguiente paso lo superara, se detiene a preguntarte. ### Skill para Claude Code, Codex y Cursor La skill le dice a tu agente cuándo usar Staglight, las reglas de gasto y cómo terminar los anuncios. Los agentes la cargan solos cuando la tarea encaja. - [SKILL.md](https://staglight.ai/agent/staglight-ads/SKILL.md) para leerla primero. - [staglight-ads.zip](https://staglight.ai/agent/staglight-ads.zip) con la skill, las recetas de FFmpeg y un script para terminar anuncios. - Necesita el servidor MCP conectado, y curl y ffmpeg instalados en el equipo. #### Claude Code Terminal: ```bash mkdir -p ~/.claude/skills && curl -sL -o /tmp/staglight-ads.zip https://staglight.ai/agent/staglight-ads.zip \ && unzip -o /tmp/staglight-ads.zip -d ~/.claude/skills/ ``` #### Codex y Cursor Terminal: ```bash mkdir -p ~/.agents/skills && curl -sL -o /tmp/staglight-ads.zip https://staglight.ai/agent/staglight-ads.zip \ && unzip -o /tmp/staglight-ads.zip -d ~/.agents/skills/ ``` Claude Code carga la skill en la sesión que tienes abierta; otros agentes pueden necesitar una sesión nueva para verla. ### Archivos del plugin para Claude Code Para equipos con su propio marketplace de plugins: [la carpeta del plugin](https://staglight.ai/agent/staglight-plugin.zip) trae `.claude-plugin/plugin.json`, `.mcp.json` y la skill. Al instalarlo pide la clave y la guarda en el almacén seguro del sistema. Terminal: ```bash curl -sL -o staglight-plugin.zip https://staglight.ai/agent/staglight-plugin.zip && unzip -o staglight-plugin.zip claude plugin validate ./staglight ``` > Para una sola persona, el comando `claude mcp add` y la skill de arriba hacen lo mismo. ### Terminar anuncios con FFmpeg Descarga las tomas y termínalas en tu equipo. Salida: H.264 yuv420p, AAC a 48 kHz y `+faststart` para que el video empiece antes de cargarse entero. Los subtítulos necesitan FFmpeg compilado con libass. [finish_ad.sh](https://staglight.ai/agent/staglight-ads/scripts/finish_ad.sh) ajusta una toma al formato, deja el volumen en -14 LUFS en dos pasadas y añade faststart: Terminal: ```bash curl -sLO https://staglight.ai/agent/staglight-ads/scripts/finish_ad.sh bash finish_ad.sh take.mp4 final.mp4 9:16 ``` #### Inspeccionar un archivo Duración, tamaño, fotogramas por segundo y frecuencia de muestreo en JSON. Terminal: ```bash ffprobe -v error -show_entries format=duration:stream=codec_type,width,height,r_frame_rate,sample_rate -of json in.mp4 ``` #### Encajar en 9:16 con bandas Mantiene el cuadro entero y rellena hasta 1080x1920. Terminal: ```bash ffmpeg -i in.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:color=black,setsar=1,fps=30,format=yuv420p" \ -c:v libx264 -preset medium -crf 18 -c:a aac -b:a 192k -ar 48000 -ac 2 -movflags +faststart out_916.mp4 ``` #### Llenar el 9:16 recortando al centro Llena el cuadro y recorta los lados. Terminal: ```bash ffmpeg -i in.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1,fps=30,format=yuv420p" \ -c:v libx264 -crf 18 -c:a aac -b:a 192k -ar 48000 -movflags +faststart out_916.mp4 ``` #### 9:16 con fondo desenfocado Para tomas de producto hechas en 16:9 o 1:1. El mapa `0:a?` omite el audio si no lo hay. Terminal: ```bash ffmpeg -i in.mp4 -filter_complex "[0:v]split=2[bg][fg];[bg]scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,gblur=sigma=40[bg];[fg]scale=1080:1920:force_original_aspect_ratio=decrease[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2,setsar=1,fps=30,format=yuv420p[v]" \ -map "[v]" -map 0:a? -c:v libx264 -crf 18 -c:a aac -b:a 192k -movflags +faststart out_916.mp4 ``` #### Unir clips de tamaños distintos Una sola recodificación. El tercer clip no tiene sonido, así que recibe una pista en silencio igual de larga (5,04 s aquí, según ffprobe). Terminal: ```bash ffmpeg -i a.mp4 -i b.mp4 -i c.mp4 -filter_complex " [0:v]scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30,format=yuv420p[v0]; [1:v]scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30,format=yuv420p[v1]; [2:v]scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1,fps=30,format=yuv420p[v2]; [0:a]aresample=48000,aformat=channel_layouts=stereo[a0]; [1:a]aresample=48000,aformat=channel_layouts=stereo[a1]; anullsrc=r=48000:cl=stereo,atrim=0:5.04[a2]; [v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[v][a]" \ -map "[v]" -map "[a]" -c:v libx264 -crf 18 -preset medium -c:a aac -b:a 192k -movflags +faststart joined.mp4 ``` #### Incrustar subtítulos con estilo (ASS) Pon PlayResX 1080 y PlayResY 1920 en el encabezado del .ass para que los márgenes cuadren en 9:16. Usa fuentes con ñ, á, ¿ y ¡. Terminal: ```bash ffmpeg -i in.mp4 -vf "ass=captions.ass:fontsdir=./fonts" -c:v libx264 -crf 18 -c:a copy -movflags +faststart captioned.mp4 ``` #### Incrustar subtítulos SRT con estilo MarginV sube los subtítulos por encima de los botones de la plataforma. Terminal: ```bash ffmpeg -i in.mp4 -vf "subtitles=captions.srt:fontsdir=./fonts:force_style='FontName=Archivo,FontSize=14,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,BorderStyle=1,Outline=3,Alignment=2,MarginV=160'" \ -c:v libx264 -crf 18 -c:a copy -movflags +faststart captioned.mp4 ``` #### Volumen a -14 LUFS (dos pasadas) La primera pasada mide. Copia los valores medidos de loud.txt en la segunda. Terminal: ```bash ffmpeg -hide_banner -i in.mp4 -af loudnorm=I=-14:TP=-1.0:LRA=11:print_format=json -f null - 2> loud.txt ffmpeg -i in.mp4 -af "loudnorm=I=-14:TP=-1.0:LRA=11:measured_I=-20.3:measured_TP=-3.1:measured_LRA=6.2:measured_thresh=-30.6:offset=0.4:linear=true" \ -ar 48000 -c:v copy -c:a aac -b:a 192k out_loud.mp4 ``` #### Voz en off sobre música que baja La música baja mientras habla la voz y después la mezcla queda en -14 LUFS. Terminal: ```bash ffmpeg -i video.mp4 -i vo.wav -stream_loop -1 -i music.mp3 -filter_complex " [1:a]aresample=48000,aformat=channel_layouts=stereo,asplit=2[vo][vokey]; [2:a]aresample=48000,aformat=channel_layouts=stereo,volume=0.35[mus]; [mus][vokey]sidechaincompress=threshold=0.03:ratio=8:attack=20:release=400[ducked]; [vo][ducked]amix=inputs=2:duration=longest:dropout_transition=0:normalize=0,loudnorm=I=-14:TP=-1.0:LRA=11[a]" \ -map 0:v -map "[a]" -c:v copy -c:a aac -b:a 192k -ar 48000 -shortest -movflags +faststart final.mp4 ``` #### Logo Abajo a la derecha, por encima de la zona donde Reels y TikTok ponen sus botones. Ajusta el margen a tu ubicación. Terminal: ```bash ffmpeg -i in.mp4 -i logo.png -filter_complex "[1:v]scale=220:-1,format=rgba,colorchannelmixer=aa=0.85[lg];[0:v][lg]overlay=W-w-40:H-h-260" \ -c:v libx264 -crf 18 -c:a copy -movflags +faststart branded.mp4 ``` #### Recortar El primer comando es rápido y corta en fotogramas clave. El segundo es exacto al fotograma. Terminal: ```bash ffmpeg -ss 2.0 -i in.mp4 -t 10 -c copy cut_fast.mp4 ffmpeg -ss 2.0 -i in.mp4 -t 10 -c:v libx264 -crf 18 -c:a aac cut_exact.mp4 ``` #### Fotogramas Primer fotograma, último fotograma (para continuar un clip desde ahí) y una hoja de contactos para revisar una toma. Terminal: ```bash ffmpeg -i in.mp4 -frames:v 1 first.png ffmpeg -sseof -1 -i in.mp4 -update 1 -q:v 1 last.jpg ffmpeg -i in.mp4 -vf "fps=1/2,scale=270:-2,tile=4x3" -frames:v 1 contact.jpg ``` #### Congelar el último fotograma Dos segundos más para una pantalla final o una llamada a la acción. Terminal: ```bash ffmpeg -i in.mp4 -vf "tpad=stop_mode=clone:stop_duration=2" -af "apad=pad_dur=2" -c:v libx264 -crf 18 -c:a aac out.mp4 ``` #### Otros formatos 4:5 para el feed, 1:1 y 16:9 a partir de la misma toma. Terminal: ```bash ffmpeg -i in.mp4 -vf "scale=1080:1350:force_original_aspect_ratio=increase,crop=1080:1350,setsar=1" -c:v libx264 -crf 18 -c:a copy out_45.mp4 ffmpeg -i in.mp4 -vf "scale=1080:1080:force_original_aspect_ratio=increase,crop=1080:1080,setsar=1" -c:v libx264 -crf 18 -c:a copy out_11.mp4 ffmpeg -i in.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080,setsar=1" -c:v libx264 -crf 18 -c:a copy out_169.mp4 ``` #### Quitar los metadatos técnicos Solo quita las etiquetas de GPS, dispositivo y codificador. Mantén la etiqueta de contenido generado con IA en el anuncio. Terminal: ```bash ffmpeg -i in.mp4 -map 0 -map_metadata -1 -map_chapters -1 -c copy -fflags +bitexact out_clean.mp4 ```