# Referencia de la API

Se genera a partir del [documento OpenAPI](https://mobyvid.com/api/v1/openapi.json) actual, así que siempre coincide con el servidor.

- URL base: `https://mobyvid.com/api/v1`
- Autenticación: `Bearer <key>`
- Formato: `JSON`
- OpenAPI: `/api/v1/openapi.json`

¿Primera vez aquí? Empieza por la [guía rápida](https://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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": "<id>"
}
```

```bash
curl -s -X POST "https://mobyvid.com/api/v1/uploads/from-library" \
  -H "Authorization: Bearer $STAGLIGHT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": "<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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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>)

`{"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://mobyvid.com/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>)

`{"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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/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://mobyvid.com/api/v1/messages" \
  -H "Authorization: Bearer $STAGLIGHT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

- `201` Successful Response
