# Convenciones

> URL base, formato de los campos, paginación, jobs asíncronos y enlaces que expiran: las reglas que valen en toda ruta.

Las mismas reglas valen en todas las rutas. Léelas una vez y la [referencia](/reference) se vuelve predecible.

## URL base

```text
https://api.cut.pro/api/v1
```

Solo HTTPS. La versión es parte de la ruta.

## Solicitud

Envía el cuerpo en JSON con `Content-Type: application/json`. Las rutas también aceptan `application/x-www-form-urlencoded` y `multipart/form-data` con los mismos campos, lo que ayuda en herramientas no-code.

## Campos

| Regla | Ejemplo |
|---|---|
| Todo campo es `snake_case` | `credits_cost`, `output_resolution` |
| El id del propio recurso es siempre `id` | `{ "id": "7412908371004912" }` |
| Una referencia a otro recurso lleva su nombre | `video_id`, `edit_id`, `connection_id` |
| Los IDs son strings | guárdalos como string, nunca los conviertas a número |
| Fecha y hora en ISO 8601, UTC | `"2026-10-29T18:04:51.000Z"` |
| Duración y posición en el video en segundos | `"start_time": 42.5` |
| Un campo sin valor viene como `null`, no desaparece | `"completed_at": null` |

La única excepción es `metadata` en `POST /posts`: las claves ahí son las de cada red (`privacyLevel`, `categoryId`, `privacyStatus`) y van a la plataforma tal como las escribiste.

## Estado y error

`status` describe en qué punto está un job y viene en minúsculas: `queued`, `processing`, `completed`, `failed`.

`code` describe qué salió mal y viene en mayúsculas: `INSUFFICIENT_CREDITS`, `SUBMISSION_EXPIRED`. Todo error tiene el mismo cuerpo, sin mensaje en texto:

```json
{ "code": "INSUFFICIENT_CREDITS", "extra": { "credits_needed": 121, "current_balance": 40 } }
```

Haz un `switch` sobre el `code` y tradúcelo para tu interfaz. Ve [Errores](/es/errors).

## Listas y paginación

Toda lista responde con el nombre del recurso y un bloque `pagination`:

```json
{
  "clips": [{ "id": "7412908412887301" }],
  "pagination": {
    "current_page": 1,
    "total_pages": 3,
    "total_count": 52,
    "has_next_page": true,
    "has_previous_page": false,
    "limit": 20
  }
}
```

Pagina con `page` (empieza en 1) y `limit` (máximo 100). El valor predeterminado de `limit` cambia por ruta y está en la referencia de cada una.

```bash
curl "https://api.cut.pro/api/v1/renders?page=2&limit=100" \
  -H "X-Api-Key: $CUTPRO_API_KEY"
```

Avanza mientras `has_next_page` sea `true`.

## Jobs asíncronos

Clipping, render, post, transcripción, generación y persona no terminan en la respuesta. La creación devuelve un `id` y consultas hasta el final:

1. Crea el job y guarda el `id`.
2. Consulta la ruta de lectura del job cada 5 a 10 segundos.
3. Detente cuando el `status` llegue a un estado final.

| Job | Ruta de lectura | Estados finales |
|---|---|---|
| Clipping | `GET /clips/{videoId}/submissions/{submissionId}` | `completed`, `failed` |
| Render | `GET /renders/{renderId}` | `completed`, `failed`, `cancelled`, `expired` |
| Post | `GET /posts/{id}` | `completed`, `partial`, `failed`, `cancelled` |
| Transcripción | `GET /transcriptions/{transcriptionId}` | `ready`, `no_speech`, `failed` |
| Generación | `GET /generations/{id}` | `ready`, `failed` |

Ese ritmo cabe de sobra en el [límite de solicitudes](/es/rate-limits). La API no envía webhooks: el fin de un job siempre se descubre consultando.

## Enlaces que expiran

| Qué | Vigencia |
|---|---|
| `download_url`, `play_url` y `thumbnail_url` de un clip | corta: pídelos de nuevo cuando vayas a usarlos |
| Enlace de `GET /renders/{renderId}/download` | 1 hora |
| Archivo MP4 de un render | definida por el plan, en `render_expiry_hours` de `GET /renders/limits` |
| Edición (`edit_id`) | no expira |

No guardes enlaces firmados en tu base de datos. Guarda el `id` y pide el enlace en el momento. Si el MP4 ya fue eliminado, `POST /renders` con el `edit_id` genera uno nuevo.

## Especificación OpenAPI

La especificación completa está en [`https://api.cut.pro/api/v1/openapi.json`](https://api.cut.pro/api/v1/openapi.json). Úsala para generar un cliente tipado, importar en Postman o Insomnia, o dar contexto a un agente de código.
