Convenciones

Mapa de puntos finales del producto, convenciones de solicitud, paginación, conflictos y errores.


Las operaciones protegidas del producto bajo /v1 usan Authorization: Bearer <access-token>. La API de revisión de IA, en POST /v1/reviews, usa una clave de API dedicada y sus propias convenciones de solicitudes, reintentos y errores.

Mapa de puntos finales principales

Dominio Principales criterios de valoración
Casos GET/POST /v1/cases, GET/PATCH /v1/cases/:id, cesionario, ACL, transferencias, candidatos/grafo de transferencias, cerrar, reabrir, review (GET/POST /v1/cases/:id/report, GET /v1/cases/:id/report/history, POST /v1/cases/:id/report/actions)
Tareas GET/POST /v1/cases/:id/tasks, GET /v1/tasks, actualizar, asignatario, cerrar, reabrir
Registros GET/POST /v1/cases/:id/records (GET admite expansión de alcance a través de transferencias); PATCH/DELETE /v1/records/:recordId
Libros de jugadas GET/POST /v1/playbooks, GET/DELETE /v1/playbooks/:id, versiones, /access, /owner, rutas de token compartido
Alias del playbook GET/PUT /v1/aliases, DELETE /v1/aliases/:alias; /v1/aliases/resolve resuelve referencias pb:
Sugerencias GET/POST /v1/playbooks/:id/suggestions, GET /v1/suggestions, obtener, actualizar, resolver
Informes GET/POST /v1/reports/personal, GET /v1/reports/personal/history, GET /v1/reports/personal/:reportId, GET/POST /v1/teams/:teamId/report, GET /v1/teams/:teamId/report/history, POST /v1/reports/:reportId/actions
Administración espacios de trabajo, miembros del espacio de trabajo, equipos, miembros del equipo, créditos, tokens CLI y MCP

La creación y la navegación dentro del recurso padre siguen la propiedad: las tareas y los registros viven bajo su caso y las sugerencias bajo su playbook. Las listas de tareas entre casos y de sugerencias entre playbooks permanecen como vistas de bandeja de entrada de nivel superior. Las operaciones de alias son de nivel superior porque (ownerId, alias) identifica el recurso del namespace. Cada namespace personal o de workspace administrado puede asignar un alias a cualquier playbook legible. El alias del propietario del playbook se muestra como oficial; un alias de terceros se devuelve solo en el contexto de su propietario. Use assignedTo=me para sus tareas. Para las sugerencias, view=sent lista las que envió y view=inbox las de los playbooks que gestiona; ambas requieren autenticación.

Contexto y paginación

Los puntos finales administrativos admitidos toman workspaceId como parámetro de consulta. Las rutas de dominio de producto resuelven el contexto del actor a partir de la credencial del portador. Nunca asuma que un espacio de trabajo CLI seleccionado localmente se aplica a una solicitud HTTP sin formato.

Las operaciones de lista utilizan pageSize y un cursor opaco. Conserve el cursor exactamente; no lo construyas ni lo decodifiques. Los registros utilizan pedidos estables (createdAt, id) y aceptan order=asc|desc. Los filtros de registro siempre intersectan el acceso al caso en vivo de la persona que llama.

Mutaciones

Los cuerpos de mutación llevan idempotencyKey. Reutilice una clave solo para una solicitud idéntica después de una falla de la red o una respuesta incierta. Las mutaciones de caso y tarea incluyen expectedLockVersion; la publicación de un playbook incluye baseVersionId. Una falta de coincidencia devuelve un conflicto para que el cliente pueda volver a leer y reconstruir la intención desde un estado nuevo.

Las solicitudes de cerrar tarea y cerrar caso pueden incluir nuevos registros, lo que permite que la transición de estado y los resultados duraderos finales se comprometan juntos.

Entrada y selección de playbook

PATCH /v1/cases/{caseId} acepta title, input y versionId opcionales, junto con expectedLockVersion e idempotencyKey obligatorios. Indique al menos un campo editable. Use versionId para adjuntar o sustituir una versión legible y no archivada de un playbook en un caso abierto (open), null para quitar el playbook u omita el campo para conservar la selección actual. Se requiere edición del caso; reabra primero los casos cerrados.

Cada actualización de título, entrada o playbook valida la entrada resultante contra el esquema de la versión seleccionada, si hay un playbook. Enviar input sustituye el objeto completo; omitirlo reutiliza la entrada actual. La selección del playbook y la sustitución opcional de entrada se guardan juntas; si falla la validación, no se guarda ninguna. Quitar el playbook conserva la entrada sin aplicar el esquema anterior.

{
	"versionId": "<version-uuid>",
	"input": { "customer": "Acme" },
	"expectedLockVersion": 1,
	"idempotencyKey": "<new-uuid>"
}

Para quitar el playbook, envíe "versionId": null con la última versión de bloqueo y una nueva clave de idempotencia.

Adjuntar, sustituir o quitar un playbook crea una actividad del sistema con las versiones anterior y seleccionada, según corresponda. Se conservan las tareas, los registros y los informes existentes; las tareas mantienen sus referencias originales a pasos.

Errores

| Estado | Significado |
| ------ | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 400 | parámetro, consulta, JSON, valor no admitido o error de validación del esquema de solicitud con formato incorrecto |
| 401 | credenciales de portador faltantes, caducadas o no válidas |
| 402 | créditos insuficientes en el contexto resuelto |
| 403 | autenticado pero no autorizado para la operación |
| 404 | recurso faltante u oculto intencionalmente |
| 409 | versión base, versión de bloqueo, ciclo de vida o conflicto de unicidad |
| 429 | tarifa limitada; retroceder antes de volver a intentarlo |
| 5xx | servidor o fallo ascendente | Vuelva a intentar las respuestas 429 y transitorias 5xx con retroceso exponencial limitado. No vuelva a intentar automáticamente respuestas de validación, autorización o conflicto. Para un conflicto, lea el estado actual y obtenga el juicio humano o del agente antes de emitir una nueva mutación. |

Fuentes externas

POST   /v1/cases/{caseId}/sources
POST   /v1/cases/{caseId}/sources/{sourceId}/refresh
DELETE /v1/cases/{caseId}/sources/{sourceId}
GET    /v1/cases/{caseId}/sources/{sourceId}

Vincule un hilo de Slack, un mensaje/hilo de Discord o un archivo nativo de Google Docs, Sheets o Slides con su cuenta conectada en el espacio activo. Slack y Discord requieren un espacio de trabajo; Google Drive admite espacios personales y de trabajo. Primero conecte Google Drive y seleccione el archivo con Google Picker en Web; una URL por sí sola no concede acceso. Las fuentes de Google Drive usan la clave de proveedor gdrive. Vincular y desvincular cuestan 2 créditos cada uno; la captura inicial está incluida al vincular. Cada actualización manual o automática completada cuesta 1 crédito a la cuenta de facturación de ese caso. Los casos cerrados solo se actualizan por solicitud explícita. Encolar, fallar, paginar y reintentar no tienen costo; las solicitudes agrupadas en una captura generan un solo cargo para ese caso. case get incluye sources solo para colaboradores de trabajo. Las lecturas usan capturas guardadas; compruebe el estado y las fechas. Si se omite contenido, obtenga la fuente completa más reciente con su ID. No se conserva contenido histórico. Las fuentes son independientes de los registros y no se incluyen en respuestas públicas. Consulte Slack, Discord y Google Drive para compartir, actualizar automáticamente y eliminar capturas.

El cuerpo para vincular contiene url e idempotencyKey; actualizar y desvincular usan idempotencyKey. Todos requieren acceso de trabajo al caso; vincular requiere un caso abierto. La lectura de una fuente usa sourceId y devuelve el último contenido guardado sin consultar al proveedor. Los tipos de registro son note, output, activity, agreement y agreement; no existe un tipo de registro source.

La configuración explícita de creación y los cambios de acceso usan access: { visibility, grants }: visibilidad restricted/public y claves UUID de usuarios o equipos, o correos de usuarios registrados, con valores viewer/editor. Los correos se resuelven a UUID antes de guardar; las respuestas usan UUID. Un correo no registrado o roles en conflicto para el mismo usuario resuelto rechazan toda la operación. Cada cambio reemplaza el objeto completo; conserve los permisos ajenos al cambio e incluya el suyo si desea mantenerlo. Los propietarios conservan la gestión independientemente de los permisos. Los responsables y mantenedores no reciben acceso implícito. Los editores pueden consultar y reemplazar permisos, conservar al menos un editor explícito al cambiar permisos, archivar y restaurar. El JSON normal omite mapas privados; los editores pueden obtenerlos con access-get. Consulte Acceso e identidad.

Los Casos públicos muestran el título, entrada, Tareas, Registros y traspasos legibles actuales, incluidas las incorporaciones posteriores. Conservan referencias públicas de autores y responsables, pero omiten permisos privados, fuentes vinculadas, informes y resúmenes de Review y configuración privada. La publicación permite solo leer. Los lectores explícitos también pueden leer Casos privados y sus fuentes; escribir requiere edición.

Copie una versión publicada legible para adaptarla de forma independiente. La copia tiene contenido y versiones propios; no hereda permisos, borradores, Casos, sugerencias, alias, estrellas ni historial, y las ediciones nunca se sincronizan. Elija los permisos explícitamente; omita ownerId para usar el Espacio activo o su cuenta personal. copiedFrom registra el origen inmediato y su versión inmutable; sourceAccessible indica si aún puede leerlo. Las listas muestran solo copias legibles. Copiar cuesta lo mismo que crear un Playbook.

POST /v1/playbooks/:id/copies requiere sourceVersionId e idempotencyKey, acepta ownerId y title opcionales y usa las opciones de acceso inicial. GET /v1/playbooks/:id/copies acepta pageSize y cursor.

Un equipo puede conectar varios espacios de trabajo. Solo los participantes del equipo que sean propietarios o administradores de su espacio conectado pueden enviar, listar o revocar invitaciones al equipo. El destinatario inicia sesión con el correo de la invitación y elige un espacio existente o crea uno; el remitente no elige el destino. Aceptar conecta el espacio y añade al destinatario, no a todos sus miembros. Aceptar en un espacio ya conectado al equipo devuelve HTTP 409 sin consumir la invitación. Use la gestión de miembros del equipo para añadir participantes en ese espacio. Cada espacio administra sus participantes. Un mismo usuario puede participar desde varios espacios; eliminar su membresía en uno conserva su participación en los demás. Desconectar elimina su conexión y participantes sin afectar las demás. El acceso mediante el equipo requiere que el espacio de participación y el origen del recurso sigan conectados. Los permisos directos a usuarios permanecen. Las invitaciones caducan a los catorce días; reenviar cierra la anterior. La conexión no elimina los requisitos de suscripción del espacio.

POST/GET /v1/teams/:teamId/invitations?workspaceId=... (POST: { "emails": ["customer@example.com"] }); DELETE /v1/teams/:teamId/invitations/:invitationId; DELETE /v1/teams/:teamId/connection; GET /v1/invitations/:token; POST /v1/invitations/:token/accept?workspaceId=....

Se eliminan las rutas de mutación /acl; use /access con configuración anidada. Las invitaciones de equipo requieren autenticación y no usan claves de idempotencia de recursos. Crear un espacio admite teamInvitationToken opcional para conectar y participar atómicamente.

Propiedad, responsabilidad y ciclo de vida

Playbooks y Casos tienen una cuenta propietaria de Usuario o Espacio de trabajo (ownerId), que también paga su uso. El propietario personal tiene todos los derechos; los Owners y Admins actuales ejercen esos derechos para un Espacio de trabajo. Los demás miembros necesitan permisos explícitos de usuario o Equipo, o visibilidad pública para leer contenido publicado. La membresía por sí sola no concede acceso. Al eliminar un miembro, se revocan sus permisos directos sobre los recursos propiedad de ese Espacio, incluidos los completados y archivados. Si la eliminación dejara algún recurso sin editor explícito, añada primero otro usuario o equipo editor, incluidos los recursos completados o archivados. Se conservan los permisos sobre recursos personales y de otros Espacios. Los permisos de Equipo y administración dependen de la membresía actual. El SSO obligatorio se aplica a los miembros; los usuarios externos con permisos directos usan la autenticación normal de Epismo. El acceso de Equipo entre espacios verifica el SSO del espacio de participación. Los listados usan permisos explícitos y la visibilidad pública admitida; la propiedad por sí sola no incluye un recurso.

Omita ownerId al crear o copiar para usar el Espacio de trabajo activo, o su cuenta personal si no hay uno seleccionado. La selección explícita también requiere autorización. Cuando hay un Espacio seleccionado, incluido el predeterminado de la conexión, la creación requiere exactamente una opción: private: true, teamIds no vacío o access. En el espacio personal puede omitirse la configuración. El permiso de edición del Equipo cubre al creador sin añadir un permiso directo redundante; se conserva un permiso directo solicitado explícitamente. Mantener o tener asignado un recurso no sustituye los permisos.

Archivar es distinto de cerrar. Los editores y propietarios pueden archivar desde Web, CLI, API o MCP. Los Casos archivados salen de vistas activas, recuentos y grafos y no pueden abrirse, pero conservan su trabajo. Liste con archived=true (case list --archived) para obtener el UUID y la última versión de bloqueo; restaurar conserva estado, responsables y permisos. Solo un propietario puede eliminar definitivamente un Caso archivado, con el último expectedLockVersion. Se eliminan sus Tareas, Registros, Fuentes y enlaces; otros Casos y el contenido original del proveedor permanecen.

Las Sugerencias pertenecen al Playbook padre actual y no tienen propietario ni permisos históricos independientes. authorId identifica al creador y baseVersionId conserva la referencia de contenido inmutable para evaluar la mejora. La lectura requiere acceso actual al padre; archivarlo oculta sus Sugerencias hasta restaurarlo. Los autores pueden editar sus propuestas abiertas mientras mantengan acceso; los editores actuales del Playbook pueden adoptar o rechazar propuestas. Tras una transferencia, las propuestas existentes siguen los permisos actuales del padre. Publique el resultado antes de marcar la propuesta como aplicada.

POST   /v1/playbooks/{playbookId}/restore
PATCH  /v1/playbooks/{playbookId}/assignee
POST   /v1/cases/{caseId}/archive
POST   /v1/cases/{caseId}/restore
DELETE /v1/cases/{caseId}
POST   /v1/workspaces/{workspaceId}/member-handover

Antes de eliminar un miembro, un Owner o Admin puede previsualizar y ejecutar el traspaso de Casos, mantenimiento de Playbooks y permisos. Las aprobaciones abiertas se transfieren solo si se solicita; las completadas y la autoría permanecen como historial. Elija un sucesor actual y revise la vista previa. workspace member handover <workspace-id> --member-id <user-id> --successor-id <user-id> previsualiza por defecto; use --preview=false para ejecutar y conceder edición explícita al sucesor. Elimine la membresía por separado con workspace member delete --workspace-id <workspace-id> <user-id> y repita el traspaso con --preview=false --finalize para limpiar cambios intermedios. Finalize exige que la membresía ya esté eliminada; no elimina al miembro. La eliminación revoca la autoridad correspondiente del Equipo y de administración del Espacio. El traspaso inicial conserva los permisos directos; la eliminación los revoca sobre los recursos de ese Espacio y la finalización repite la limpieza de permisos añadidos entretanto. Se conservan los permisos personales y de otros Espacios.

La solicitud HTTP de traspaso usa ahora memberId, successorId y transferApprovals. La respuesta contiene los recuentos cases, playbooks, tasks, approvals y suggestions. El comando de traspaso de CLI necesita una versión compatible con este contrato.

Transfiera la propiedad de un Caso con epismo_case_owner_transfer, case owner transfer <case-id> --owner-id <account-id> --lock-version <n> o PATCH /v1/cases/{caseId}/owner (ownerId, expectedLockVersion, idempotencyKey). Requiere propiedad actual. Un Caso personal puede pasar al Espacio conectado; si es público, también exige gestión del Espacio de destino. Un Caso del Espacio puede pasar a su creador o a un Owner de ese Espacio. Se rechazan transferencias entre usuarios o entre Espacios. Se conservan asignación y permisos, cambia la cuenta de facturación y se borran los informes de Review derivados. Reasignar por sí solo no realiza estos cambios de propiedad.

La asignación de Playbooks usa assignedTo, como la de Casos, y mantiene assignedTo en las respuestas. Use epismo_playbook_assign, playbook assign <playbook-id> --assigned-to <user-id> o PATCH /v1/playbooks/{playbookId}/assignee. Requiere propiedad y edición previa para el destinatario.

Consultar evaluaciones guardadas

GET /v1/cases/{caseId} incluye los últimos report y reportJob accesibles sin cargar el historial ni ejecutar IA. GET /v1/cases/{caseId}/report/history devuelve resúmenes reports del más reciente al más antiguo y un nextCursor opcional; usa pageSize (20 por defecto, máximo 100) y cursor para paginar. GET /v1/cases/{caseId}/report?reportId=REPORT_ID lee una evaluación completa seleccionada; omite reportId para obtener el último informe y el trabajo de generación.

El historial exige acceso de trabajo actual al caso y devuelve solo evaluaciones que coinciden con la audiencia compartida actual. Los lectores públicos no reciben informes ni resúmenes. Los informes reemplazados tienen historical: true y son de solo lectura: crear o descartar una propuesta pendiente de uno devuelve HTTP 409. Lee el informe más reciente y reconsidera la propuesta antes de actuar. Los cambios de evidencia por sí solos siguen mostrando un aviso orientativo de reevaluación.

Informes personales y de equipo

Los informes personales son privados para quien los generó en la cuenta de facturación activa. Los informes de equipo y las decisiones sobre propuestas se comparten con los miembros actuales desde el espacio activo. Consulta AI review para los criterios de selección, salud, historial y permisos de los informes.

Operación Personal Equipo
Generar POST /v1/reports/personal POST /v1/teams/{teamId}/report
Leer último/trabajo/guardado GET /v1/reports/personal GET /v1/teams/{teamId}/report
Historial GET /v1/reports/personal/history GET /v1/teams/{teamId}/report/history
Atender propuesta POST /v1/reports/{reportId}/actions POST /v1/reports/{reportId}/actions

La generación recibe un UUID idempotencyKey y devuelve HTTP 202 con un trabajo. La lectura devuelve ReportResponse (report, job opcional, historical); selecciona jobId o reportId, nunca ambos. El historial admite pageSize y cursor. Las acciones reciben proposalId, action (create o dismiss) y feedback opcional al descartar; usan el contenido guardado sin cambios y no reciben idempotencyKey. El ID del equipo viene de la ruta; el espacio y la autoridad de facturación vienen de la autenticación.