Grabaciones
Captura flujos de trabajo del usuario desde un navegador (o desde cualquier cliente que construyas), carga los eventos + capturas de pantalla, y deja que el pipeline de IA de SOPFlow redacte pasos SOP. Potencia la extensión Chrome de SOPFlow; la misma interfaz está abierta para tus propios clientes.
tRPC, no REST
La interfaz de grabación vive en POST /trpc/recording.<procedure> en lugar de /api/v1/*. Misma autenticación con Bearer key, solo una ruta base diferente. La carga de capturas de pantalla utiliza multipart regular en POST /api/v1/recordings/:id/screenshot/:seq.
Ciclo de vida
- create — obtén un id de grabación y la sesión comienza.
- uploadEvents — POST de lotes conforme el usuario interactúa (máximo 100 por llamada).
- screenshot — multipart POST para cualquier número de secuencia.
- finalize — el servidor cambia el estado a
processingy ejecuta el pipeline de IA. - getStatus — sondea hasta
ready(ofailed); los pasos generados están listos. - importToSOP — convierte borradores seleccionados en
sop_steps.
POST/trpc/recording.create
Abre una nueva sesión de grabación. Devuelve el recordingId que usarás en cada llamada posterior.
Campos del cuerpo
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| source | string | obligatorio | chrome_extension | desktop_app — solo para análisis y visualización. |
Ejemplo de respuesta
{
"result": {
"data": {
"recordingId": "31ab37ce-dce6-4590-a640-b175a1454055"
}
}
}POST/trpc/recording.uploadEvents
Añade un lote ordenado de eventos. sequenceNumber debe aumentar estrictamente en toda la grabación (y dentro de cada lote). Máximo 100 eventos por llamada.
Campos del cuerpo
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| recordingId | uuid | obligatorio | — |
| events | Event[] | obligatorio | 1–100 eventos. |
Event
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| sequenceNumber | integer | obligatorio | Aumenta estrictamente por grabación. |
| eventType | string | obligatorio | click | input | select | navigation | keyboard_shortcut | scroll | form_submit | context_menu | double_click | drag_drop | tab_switch | app_switch | file_upload |
| url | string | opcional | — |
| pageTitle | string | opcional | — |
| target | object | obligatorio | Metadatos del elemento: cssSelector, xpath, textContent, ariaLabel, elementType, etc. |
| eventData | object | opcional | Carga específica del tipo (valor de entrada, combinación de teclas, delta de desplazamiento, etc.). |
| screenshotKey | string | opcional | Establece si cargaste una captura de pantalla para este seq a través del endpoint multipart. |
| timestamp | integer | obligatorio | Unix ms. |
Ejemplo de respuesta
{ "result": { "data": { "inserted": 5 } } }POST/api/v1/recordings/:recordingId/screenshot/:seq
Carga multipart de una única imagen/webp ≤ 5 MB para un evento. La captura de pantalla se vincula al evento coincidente cuando (o si) llega.
Campos multipart
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| file | image/webp | obligatorio | Máximo 5 MB, solo webp. |
Ejemplo de respuesta
{ "objectKey": "recording_screenshots/<org>/<rec>/0.webp", "sizeBytes": 12480 }POST/trpc/recording.finalize
Deja de aceptar eventos e inicia el procesamiento de IA. Devuelve el id del trabajo. Los clientes con clave API deben consultar recording.getStatus; SSE requiere sesión y no expone trabajos creados por claves.
Campos del cuerpo
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| recordingId | uuid | obligatorio | — |
| durationMs | integer | opcional | Duración total de la grabación en milisegundos. |
Ejemplo de respuesta
{ "result": { "data": { "status": "processing", "jobId": "..." } } }GET/trpc/recording.getStatus
Sondea la finalización del procesamiento. Pasa input a través de una cadena de consulta (JSON codificado en URL).
Parámetro de consulta
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| input | JSON | obligatorio | JSON codificado en URL {"recordingId":"<uuid>"} |
Ejemplo de respuesta
{
"result": {
"data": {
"recording": {
"id": "31ab37ce-...",
"status": "ready",
"eventCount": 42,
"screenshotCount": 18,
"durationMs": 65234
},
"generatedSteps": [
{
"id": "...",
"stepNumber": 1,
"title": "Navigate to the Login page",
"description": "Open the SOPFlow login URL.",
"screenshotKey": "recording_screenshots/<org>/<rec>/0.webp",
"sourceEventIds": ["..."]
}
]
}
}
}POST/trpc/recording.importToSOP
Añade pasos generados seleccionados a una Fase kanban como sop_steps reales. La grabación se archiva automáticamente al éxito.
Campos del cuerpo
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| recordingId | uuid | obligatorio | — |
| sopVersionId | uuid | obligatorio | La versión a la que añadir (el servidor valida la propiedad). |
| phaseId | uuid | obligatorio | — |
| steps | Step[] | obligatorio | 1–50 pasos generados a importar. |
Step
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| generatedStepId | uuid | obligatorio | — |
| title | string | obligatorio | Editable — el servidor usa lo que envías, no el original. |
| description | string | null | opcional | — |
Ejemplo de respuesta
{ "result": { "data": { "createdSteps": [{ "id": "...", "title": "..." }] } } }Provisión de una clave para tu cliente
Para uso servidor-a-servidor, genera una clave API en Configuración → Claves API con los alcances read + write y guárdala en tu servidor de confianza. No incluyas una clave de servicio compartida en código público del navegador.
Para extensiones de navegador y clientes de escritorio que actúan en nombre de un usuario final, utiliza el puente post-OAuth:
POST/trpc/apiKeys.createForExtension
Genera una clave sk_live_… nueva en el Espacio de trabajo del usuario llamador, denominada 'Extensión Chrome (<browser>)'. Procedimiento de editor (editores y administradores elegibles pueden conectar su navegador); omite la puerta del plan api_access. La página /extension/connect de la aplicación web llama a esto después de que el usuario inicia sesión, luego redirige de vuelta a tu cliente con la clave en el fragmento de URL para que nunca llegue a un registro de acceso del servidor.
Campos del cuerpo
| Nombre | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| clientName | string | obligatorio | Etiqueta de visualización — mostrada en Configuración → Claves API (p. ej. 'Chrome', 'Mi Grabador'). |
Ejemplo de respuesta
{ "result": { "data": { "key": "sk_live_…", "prefix": "sk_live_abcd" } } }Ejemplo de extremo a extremo
# 1. Create a new recording session
curl -X POST https://sopflow.io/trpc/recording.create \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"chrome_extension"}'
# 2. Stream events as you capture them (max 100 per call)
curl -X POST https://sopflow.io/trpc/recording.uploadEvents \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"recordingId":"<from step 1>",
"events":[
{"sequenceNumber":0,"eventType":"click","url":"https://example.com",
"pageTitle":"Home","target":{"cssSelector":"button.cta",
"elementType":"BUTTON","textContent":"Sign in"},"timestamp":1730000000000}
]
}'
# 3. Optionally POST a screenshot for any sequenceNumber
curl -X POST \
https://sopflow.io/api/v1/recordings/<id>/screenshot/0 \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-F "file=@frame.webp;type=image/webp"
# 4. Finalize — kicks off the AI pipeline asynchronously
curl -X POST https://sopflow.io/trpc/recording.finalize \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"recordingId":"<id>","durationMs":65000}'
# 5. Poll for the result (status flips to "ready")
curl "https://sopflow.io/trpc/recording.getStatus?input=%7B%22recordingId%22%3A%22<id>%22%7D" \
-H "Authorization: Bearer sk_live_YOUR_KEY"Notas
- La privacidad es responsabilidad del cliente. El servidor almacena lo que sea
eventData.valueque envíes. La extensión Chrome enmascara campos de contraseña y campos de autocompletado de tarjetas de crédito antes de que salgan de la página; si construyes tu propio cliente, haz lo mismo. El pipeline realiza un barrido de expresiones regulares para tarjetas / SSNs / correos como defensa de última línea, pero no confíes en ello. - Límites de velocidad. tRPC usa el límite general de 300 solicitudes por minuto por IP, no el presupuesto REST por clave. Agrupa hasta 100 eventos y gestiona las respuestas 429.
- Recuperación de reinicio. Si la API se reinicia durante el procesamiento, la grabación se marca automáticamente como
faileden el siguiente arranque. Llama arecording.reprocesspara reintentar.