# API HTTP

Base: `https://api.editorbrain.com`. Las rutas de cliente usan `/v1`. Esta guía explica las operaciones y los contratos principales del código revisado; consulta [versiones](https://editorbrain.com/docs/versiones) para disponibilidad. No es una especificación OpenAPI ni promete endpoints administrativos a los clientes.

## Autenticación y alcance

Para una credencial de API autorizada:

```http
Authorization: Bearer TU_CREDENCIAL
Content-Type: application/json
```

Mantén el secreto en tu gestor de credenciales. El workspace se deriva de la autorización; enviar otro `workspaceId` no concede acceso. En la versión publicada, las claves están ligadas al espacio autorizado. Las conexiones OAuth pueden estar limitadas adicionalmente por permisos del miembro y alcance de equipo.

- `reader`: consultas permitidas por su alcance.
- `editor`: escrituras permitidas; no implica acceso a todas las operaciones de gasto.
- `owner`: administración del espacio, sin acceso automático a otros espacios ni al laboratorio interno.

La sesión web usa su propio flujo y protecciones; no copies cookies del navegador para construir una integración. La configuración de notificaciones, cuenta, registro y recuperación pertenece a ese flujo web. Usa el consentimiento de dispositivo del CLI o el OAuth del MCP para conectar agentes.

## Primera consulta

```sh
curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $EDITORBRAIN_API_KEY" \
  https://api.editorbrain.com/v1/me
```

El ejemplo supone que el gestor de secretos ya suministró la variable. No escribas su valor en el comando ni actives trazas del shell. `/v1/me` devuelve identidad, workspace, ámbito y límites; no presupongas que la forma exacta será idéntica para un miembro de equipo restringido.

## Leer el contexto de una edición

```http
POST /v1/workflow/check
```

```json
{"projectId":"mi-proyecto"}
```

La respuesta incluye modo de revisión, preferencias resueltas, `editorialSnapshot`, integraciones y versiones del contexto. Si pasas `previousVersion` y `previousContextVersion`, revisa tanto `changed` como `contextChanged`. Un cambio documental no se detecta solamente con la versión de preferencias de revisión.

`interaction`, agregado después de 0.39.1, describe cómo consultar/revisar sin imponer un wizard. Tolera su ausencia en APIs anteriores. El servidor registra un recibo de lectura; no certifica que el agente entendió o editó el video.

## Documentos y concurrencia

```http
GET /v1/documents/videos/mi-proyecto/brief.md
PUT /v1/documents/videos/mi-proyecto/brief.md
```

Cuerpo de la escritura:

```json
{"content":"# Objetivo\nExplicar el producto con claridad.\n","expectedRevision":3}
```

Usa la revisión que acabas de leer; `0` crea un documento nuevo. El ejemplo `3` es ilustrativo, no un valor que puedas reutilizar en cualquier cuenta. La respuesta devuelve la nueva revisión y hash.

Ante un conflicto 409: vuelve a leer, conserva cambios ajenos, recompón la intención del usuario y envía una escritura con la revisión actual. No reintentes la misma escritura a ciegas. Codifica cada segmento de la ruta con `encodeURIComponent`; conserva las barras que separan carpetas. No se aceptan rutas de archivos arbitrarios del servidor.

## Buscar desde un brief

```http
POST /v1/search/brief
```

```json
{
  "projectId":"mi-proyecto",
  "mode":"both",
  "brief":{
    "source":{"kind":"script","summary":"Comparación de dos formas de organizar tareas","inspected":["script"],"coverage":"Guion completo leído"},
    "goal":"Explicar cuándo conviene cada opción",
    "audience":"Profesionales que empiezan con IA",
    "tone":"Claro y cercano",
    "pacing":"Ágil con pausas para leer",
    "availableAssets":["Capturas propias"],
    "missingAssets":[],
    "hardConstraints":["Conservar colores de marca"],
    "uncertainty":[],
    "styleQuery":"comparación visual con demostración",
    "eventQueries":["contraste entre dos alternativas"]
  }
}
```

`inspected` y `coverage` deben describir una inspección real. La API recupera candidatos; no realiza ni aprueba la decisión creativa. `detail` es `summary` por defecto; solicita `full` solo si necesitas más evidencia. `search/edit` es análisis explícito opcional, no fallback automático.

## Índice de operaciones

Las rutas siguientes requieren autorización salvo `/health`. `{id}`, `{project}`, `{revision}` y `{path}` son marcadores. Los cuerpos exactos de muchas operaciones están también en las herramientas equivalentes de la [referencia MCP](https://editorbrain.com/docs/mcp-tools); en REST, los IDs de la ruta no siempre se repiten en el cuerpo. La tabla no describe rutas internas de operación, callbacks de proveedores ni URLs firmadas.

### Identidad, marcas y documentos

| Método | Ruta | Entrada / propósito |
| --- | --- | --- |
| GET | `/health` | Estado básico y versión; no prueba proveedores |
| GET | `/v1/me` | Identidad, espacio y límites |
| GET | `/v1/brands` | `limit`, `after`; marcas accesibles |
| GET | `/v1/projects` | `brand`, `limit`, `after`; proyectos accesibles |
| GET | `/v1/documents` | `prefix`; listado acotado |
| GET / PUT | `/v1/documents/{path}` | Leer (opcional `revision`) o escribir `content`, `expectedRevision` |
| GET | `/v1/history` | `path`, opcional `before` |
| POST | `/v1/history/restore` | `path`, revisión fuente y `expectedRevision` actual |
| GET | `/v1/projects/{project}/style-policy` | Effective rules/hashes and project decisions; verification not assessed (next release) |
| POST | `/v1/projects/{project}/resolve` | Contexto efectivo |
| POST | `/v1/projects/{project}/export` | `adapter`: neutral, hyperframes o remotion |
| GET / POST | `/v1/keys` | Owner: listar o crear con `label`, `role` |
| DELETE | `/v1/keys/{id}` | Owner: revocar clave; no la propia activa |

### Preferencias, memoria y revisión editorial

| Método | Ruta | Entrada / propósito |
| --- | --- | --- |
| GET / PUT | `/v1/workflow` | Leer; escribir `mode`, `expectedRevision` |
| POST | `/v1/workflow/check` | `projectId`, versiones previas, `previousSourceHashes` (hasta256) y `questionNeeds` opcionales |
| GET | `/v1/integrations` | Preferencias personales del miembro |
| PUT | `/v1/integrations/{provider}` | Configuración validada y revisión esperada |
| GET | `/v1/brain` | `brandId`; estado de propuesta del cerebro |
| POST | `/v1/brain/prepare` | Preparar propuesta; disponibilidad y consumo propios |
| POST | `/v1/brain/accept` | Aceptar propuesta revisada con sus precondiciones |
| GET / POST | `/v1/memory` | Consulta por `scope`, `scopeId`; cambio de entradas con revisión |
| POST | `/v1/memory/promote` | Promoción explícita de aprendizaje a un ámbito |
| POST | `/v1/feedback` | Registrar observación de proyecto |
| GET | `/v1/improvements` | `brandId`; propuestas de mejora |
| POST | `/v1/improvements/settings` | Configuración de propuestas |
| POST | `/v1/improvements/run` | Solicitar propuesta para `brandId`; comprobar disponibilidad |
| POST | `/v1/improvements/accept` | Aceptar una propuesta concreta con revisión |
| GET / POST | `/v1/product-learning` | Consentimiento separado para aprendizaje del producto |
| POST | `/v1/product-learning/signals` | Señal acotada bajo consentimiento |

### Bibliotecas

| Método | Ruta | Entrada / propósito |
| --- | --- | --- |
| POST | `/v1/search/brief` | Brief del agente; ver ejemplo superior |
| GET | `/v1/style-sources/{id}/source` | `version`, `sha256`; código de estilo autorizado con enlace temporal |
| POST | `/v1/search/edit` | Análisis de edición solicitado explícitamente |
| GET | `/v1/library` | `query`, `limit`, `after` |
| GET | `/v1/library/{id}` | Ficha y evidencias accesibles |
| GET | `/v1/library/{id}/documents` | `path`, opcional `sha256` |
| GET | `/v1/library/{id}/media/{sha256}` | Bytes de un medio autorizado |
| GET | `/v1/narrative` | `query`, `kind`, `channel`, `limit` |
| GET | `/v1/library/{id}/narrative` | `eventOffset`, `relationOffset`, `limit`, `sha256` |
| GET | `/v1/style-packs` | Estilos disponibles |
| POST | `/v1/projects/{project}/recommend-styles` | Recomendaciones según material/capacidades |
| POST | `/v1/projects/{project}/preview-direction` | Preparar dirección, no render |
| GET | `/v1/media-styles` | `category`: image o motion |
| GET | `/v1/media-styles/{id}` | `version` de receta |
| GET | `/v1/motion-components` | `q`; componentes locales reutilizables |
| GET | `/v1/motion-components/{id}` | `version` de componente |
| GET | `/v1/authored-motion` | `q`, `limit`, `after`, `version`, `material`, `funcion`, `encuadre`, `tresD` |
| GET | `/v1/authored-motion/{id}` | `version` de escena |
| GET | `/v1/authored-motion/{id}/preview` | `version`, `ratio`, `kind`, opcional `preset`; enlace de preview |
| GET / HEAD | `/v1/authored-motion/{id}/media` | Preview autorizada con versión/formato; bytes |
| GET | `/v1/authored-motion/{id}/source` | `version`, `sha256` del bundle; enlace de fuente |
| GET / PUT | `/v1/library-favorites` | Leer por `brandId`; guardar/quitar selección del miembro |
| GET | `/v1/sfx/catalog` | `brandId`, `bankId`; explorar banco accesible |
| GET / HEAD | `/v1/sfx/preview` | Preview con identidad de banco/sonido devuelta por catálogo |
| GET | `/v1/sfx/search` | `projectId`, `query`, `bankId`, `limit`, `sceneRole` |
| GET | `/v1/sfx/get` | Proyecto, banco, `soundId`, `catalogSha256` y rol de escena |
| POST | `/v1/sfx/check` | `projectId` en query; plan y hash de contexto en cuerpo |

### Material, almacenamiento y herramientas

| Método | Ruta | Entrada / propósito |
| --- | --- | --- |
| GET | `/v1/resources/guide` | Campos y usos de material reutilizable |
| GET | `/v1/resources` | `query`, `brand`, `kind`, `state`, `limit`, `after` |
| GET / PUT | `/v1/resources/{id}` | Leer o guardar `resource`, `expectedRevision`, confirmación aplicable |
| GET / PUT | `/v1/resources/{id}/index` | Segmentos (`offset`, `limit`) o guardar índice versionado |
| GET | `/v1/assets` | `limit`, `cursor`; archivos accesibles |
| PUT | `/v1/assets/{sha256}` | Bytes, tipo y longitud; `name`, `purpose`, `projectId`, `sourceSha256` |
| GET / HEAD | `/v1/assets/{sha256}` | Descargar o consultar archivo |
| GET | `/v1/storage` | Cuota, uso y candidatos de limpieza |
| GET | `/v1/storage/preview-upload` | `sha256`, `bytes`, `projectId`; plan previo |
| POST | `/v1/storage/cleanup` | Selección explícita validada; protege archivos necesarios |
| GET | `/v1/studio/catalog` | Herramientas, precios, permisos y disponibilidad |
| GET | `/v1/studio/voices` | Catálogo público de alias Vox; filtros `q`, `language`, `accent`, `gender` |
| GET | `/v1/studio/voices/{id}/preview` | Muestra de catálogo con autenticación, cuando exista; no genera narración |
| GET | `/v1/studio/voice-selection` | Exactamente uno de `brandId` o `projectId`; selección, herencia, ruta canónica y revisión |
| PUT | `/v1/studio/voice-selection` | `brandId` o `projectId`, `voiceId`, `expectedRevision`; modifica solo `audio.json.voice` |
| POST | `/v1/studio/quotes` | Solicitud Tempo/Prism/Vox/Aura; cotización |
| POST | `/v1/studio/jobs` | `quoteId`, `maxCredits`, `userConfirmed`, lease de lote si aplica |
| GET | `/v1/studio/jobs` | Historial; `after` |
| GET | `/v1/studio/jobs/{id}` | Estado y resultados; consultar sin duplicar |
| GET | `/v1/billing/status` | Saldo, plan, oferta y disponibilidad |
| POST | `/v1/billing/checkout` | Oferta e intento autorizados; requiere propietario habilitado |
| POST | `/v1/billing/portal` | Portal de membresía/pago habilitado |
| POST | `/v1/billing/welcome` | Beneficio inicial sujeto a elegibilidad |
| POST | `/v1/billing/reward` | `rewardId`; beneficio elegible, no créditos arbitrarios |

### Proyectos, lotes, feedback y equipos

| Método | Ruta | Entrada / propósito |
| --- | --- | --- |
| GET | `/v1/projects/progress` | `ids` separados por coma; resumen |
| GET / POST | `/v1/projects/{project}/progress` | Leer o cambiar con versión esperada y confirmación aplicable |
| GET / POST | `/v1/batches` | Listar (`after`) o crear lote de proyectos existentes |
| GET / POST | `/v1/batches/{id}` | Estado o acción con revisión esperada |
| POST | `/v1/batches/{id}/lease` | Claim/renew/release/attention de turno |
| GET / POST | `/v1/projects/{project}/production-reviews` | Listar (`after`) o registrar revisión |
| DELETE | `/v1/projects/{project}/production-reviews/{revision}` | Revocar revisión |
| GET | `/v1/projects/{project}/production-reviews/{revision}/transcript` | Transcripción de esa versión |
| POST | `/v1/projects/{project}/production-reviews/{revision}/approve` | Confirmación del usuario y contexto exacto |
| POST | `/v1/projects/{project}/production-reviews/{revision}/changes` | Cambio localizado y contexto exacto |
| GET | `/v1/projects/{project}/production-feedback` | `status`, `revisionId`, `after` |
| POST | `/v1/projects/{project}/production-feedback/{id}/resolve` | Evidencia de la corrección y nueva versión |
| GET / POST | `/v1/reviews` | Listar por `projectId` o crear enlace explícito de revisión |
| DELETE | `/v1/reviews/{id}` | Revocar enlace |
| GET | `/v1/team` | Alcance y capacidades del miembro |
| GET | `/v1/team/members` | Integrantes e invitaciones; solo propietario |
| PATCH | `/v1/team/members/{id}` | Solo propietario: `{expectedRevision,grants:[{kind,scopeId}],userConfirmed:true}`; sustituye concesiones con control de concurrencia |
| DELETE | `/v1/team/members/{id}` | Retirar miembro autorizado |
| POST | `/v1/team/invitations` | Invitar correo con tipo/alcance; envía correo real |
| DELETE | `/v1/team/invitations/{id}` | Revocar invitación |
| POST | `/v1/team/preview` | Browser autenticado: `{token}`, destinatario verificado; muestra alcance sin aceptar |
| POST | `/v1/team/accept` | Browser autenticado: `{token}`; aceptación explícita, selecciona el espacio compartido |
| GET | `/v1/team/projects` | Proyectos accesibles al equipo |
| GET | `/v1/team/projects/{project}/reviews` | Versiones compartidas; `after` |
| GET | `/v1/team/projects/{project}/reviews/{revision}/comments` | Comentarios públicos de esta versión, `after`, `nextCursor`; acceso revalidado en cada página |
| POST | `/v1/team/projects/{project}/reviews/{revision}/share` | Compartir o retirar versión según acción |
| POST | `/v1/team/projects/{project}/reviews/{revision}/comment` | Comentario y momento opcional |
| POST | `/v1/team/projects/{project}/reviews/{revision}/approve` | Aprobación explícita de versión/contexto |

`GET /v1/team/members` incluye `permissionsRevision` para cada colaborador
restringido. Usa ese valor como `expectedRevision` al guardar la lista completa de
1–100 concesiones (`brand_editor` o `project_reviewer`); no envíes un workspace ID.
`team_permissions_changed` (409) exige releer y reconciliar. Guardar invalida enlaces
anteriores. Si el miembro queda solo como revisor, revoca sus conexiones de agente;
no borra archivos. Para quitar todos los accesos usa DELETE.

## Paginación

No todos los endpoints usan el mismo cursor. Devuelve al mismo endpoint el valor recibido con los mismos filtros. En motion, `after` es opaco y está ligado a consulta/facetas/versión. Si construyes URLs con `URLSearchParams`, pasa el cursor original y deja que esa función lo codifique una vez. No uses `decodeURIComponent` sobre él.

Un cambio de filtro comienza una consulta nueva. Una lista vacía no equivale a pérdida de permisos ni prueba que no exista material en otra página. No amplíes la búsqueda a otro cliente para rellenarla.

## Archivos y URLs temporales

Una subida de assets requiere `Content-Length` entre 1 byte y 90 MiB y un MIME aceptado (MP4/MOV/WebM, PNG/JPEG/WebP, MP3/WAV/M4A/OGG). El ID es el SHA-256 de los bytes; el servicio lo verifica. La cuota del espacio puede ser menor que el tamaño máximo técnico.

Los archivos se autorizan por espacio/proyecto, no por conocer el hash. Guarda IDs y hashes, no URLs firmadas temporales. Cuando venza un enlace, vuelve a solicitarlo con la credencial apropiada. En descargas parciales, respeta `Range`, 206 y 416.

## Errores y reintentos

Formato de error HTTP habitual:

```json
{"error":{"code":"revision_conflict","message":"El documento cambió; vuelve a leerlo."}}
```

El texto del ejemplo es ilustrativo. Usa `error.code`, estado HTTP y `error.recovery` cuando exista; no hagas parsing del mensaje. 401: autenticación; 403: permisos; 404: recurso no accesible; 409: conflicto; 413/415: tamaño/formato; 429: espera; 503: capacidad no disponible. La API añade `Retry-After` en respuestas 429.

Los GET se pueden reintentar con espera acotada cuando el fallo sea transitorio. No reintentes un POST de gasto por un timeout sin consultar el intento original. Para Studio conserva `quoteId`/job ID; para pagos conserva el ID de intento. No inventes un header universal de idempotencia: cada operación define su mecanismo.

## Descubrir y retomar proyectos

Este contrato requiere API **0.45.0 o posterior**. Comprueba su [disponibilidad](https://editorbrain.com/docs/versiones) antes de depender de estas rutas.
`GET /v1/projects` admite `brand`,
`query`, `updatedSince`, `updatedBefore`, `sort=recent|id`, `limit` y `after`.
Las fechas son ISO UTC; el intervalo incluye el inicio y excluye el final.
La consulta compara literalmente ID/nombre/tema. `lastActivityAt` usa tiempos
servidor de documentos y progreso. `checkpoint` resume el último hito con su
revisión/hash y fecha servidor, no la fecha declarada por el agente; no implica
aprobación. Continúa con `nextCursor` sin modificarlo y conserva filtros y espacio.
Es un listado vivo: deduplica por ID y reinicia sin cursor para una lectura nueva.
Se aplican los permisos actuales de marca/proyecto en cada página. No hay un
filtro de proyectos archivados; un hito `completed` no oculta el proyecto.

`GET /v1/projects/ID/continuity` reúne contexto, checkpoint, revisiones, feedback
pendiente, lote, trabajos y catálogo de assets autorizados. Cada sección indica
`available` con `value`, o `unavailable` con el motivo; las listas acotadas declaran
`complete`/`nextCursor`. Los jobs Studio pertenecen a la conexión actual y Render
al usuario actual. No se exponen proveedores ni rutas privadas del dispositivo.
La consulta no inicia trabajos, refresca facturación ni descarga medios.
El registro de carpetas de cada dispositivo es privado y no forma parte de esta API.
`lastApprovedReview` recupera la última aprobación histórica aunque no aparezca
en la primera página. Solo `effectiveApproval=true` confirma que sigue vigente;
puede haberse invalidado por cambios de contexto, feedback o disponibilidad.

Acepta `reviewsAfter`, `feedbackAfter` y `studioAfter` para continuar esas listas.
Un 409 `continuity_changed` exige repetir la lectura, porque el contexto cambió.
Un recurso catalogado no acredita sus bytes ni equivale a un enlace público:
para recuperarlo usa el endpoint de descarga autorizado y verifica su hash.
Las preferencias guardadas no conceden permiso de gasto.

Los checkpoints v1 y v2 viajan por la API existente de documentos, con su revisión
esperada. V2 conserva versión declarada, artefactos relativos, dependencias,
comando orientativo y hashes del contexto; nunca se ejecuta contenido guardado.
La historia y restauración usan los endpoints existentes de documentos: restaurar
crea una nueva revisión, no borra versiones previas ni altera aprobaciones.

## Mapa de tareas y orientación compacta

`GET /v1/guide/tasks` devuelve los temas públicos de ayuda; `?topic=sonido`
devuelve una ruta con comandos, herramientas y referencias. Requiere la sesión
autenticada habitual; no busca recursos, ejecuta tareas ni anuncia capacidades
privadas. Los handlers de cada operación siguen comprobando sus permisos.

`POST /v1/workflow/check` admite `detail: "summary" | "full"`. La respuesta
completa sigue siendo el default. El resumen tiene
`kind: "editorbrain.workflow-summary"`, `coverage` explícita y el camino de
vuelta al detalle; no contiene un `editorialSnapshot` completo.
`nextActions` sólo orienta, incluso cuando hay recursos sin registrar.
