Gestión de Cuadernos

Operaciones completas CRUD para administrar cuadernos dentro de investigaciones. Todas las operaciones de modificación cargan automáticamente el proyecto en la caché compartida.


Listar Cuadernos

GET /api/{tenantId}/{projectId}/notebook/investigation/{investigationId}

Devuelve todos los cuadernos dentro de una investigación.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
investigationId GUID Identificador de la investigación

Respuesta (200 OK)

[
  {
    "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
    "investigationId": "11111111-2222-3333-4444-555555555555",
    "name": "Main",
    "description": "Primary analysis notebook",
    "dateCreated": "2024-01-15T10:30:00Z",
    "dateModified": "2024-01-20T14:45:00Z",
    "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "modifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "notebookType": 0,
    "notebookOrder": 1.0,
    "lastExecutionDuration": 2.5,
    "blockCount": 12
  },
  {
    "notebookId": "bbbbbbbb-cccc-dddd-eeee-ffffffffffff",
    "investigationId": "11111111-2222-3333-4444-555555555555",
    "name": "Variant Analysis",
    "description": "Process variant exploration",
    "dateCreated": "2024-01-16T09:00:00Z",
    "dateModified": "2024-01-18T11:30:00Z",
    "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "modifiedBy": null,
    "notebookType": 0,
    "notebookOrder": 2.0,
    "lastExecutionDuration": 1.2,
    "blockCount": 8
  }
]

Respuestas de Error

No Encontrado (404)

{
  "Error": "Investigation not found",
  "InvestigationId": "11111111-2222-3333-4444-555555555555"
}

Obtener Cuaderno

GET /api/{tenantId}/{projectId}/notebook/{notebookId}

Devuelve información detallada de un cuaderno específico.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
notebookId GUID Identificador del cuaderno

Respuesta (200 OK)

{
  "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "name": "Main",
  "description": "Primary analysis notebook",
  "dateCreated": "2024-01-15T10:30:00Z",
  "dateModified": "2024-01-20T14:45:00Z",
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "modifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "notebookType": 0,
  "notebookOrder": 1.0,
  "lastExecutionDuration": 2.5,
  "blockCount": 12
}

Crear Cuaderno

POST /api/{tenantId}/{projectId}/notebook/investigation/{investigationId}

Crea un nuevo cuaderno vacío en la investigación.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
investigationId GUID Identificador de la investigación

Cuerpo de la Solicitud

{
  "name": "Process Analysis",
  "description": "Detailed process analysis workflow",
  "notebookType": 0
}

Campos de la Solicitud

Campo Tipo Requerido Descripción
name string Nombre del cuaderno (único dentro de la investigación)
description string No Descripción del cuaderno
notebookType integer No Tipo (0=Estándar, por defecto)

Respuesta (201 Created)

{
  "notebookId": "cccccccc-dddd-eeee-ffff-000000000000",
  "investigationId": "11111111-2222-3333-4444-555555555555",
  "name": "Process Analysis",
  "description": "Detailed process analysis workflow",
  "dateCreated": "2024-03-01T10:00:00Z",
  "dateModified": "2024-03-01T10:00:00Z",
  "createdBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "modifiedBy": null,
  "notebookType": 0,
  "notebookOrder": 3.0,
  "lastExecutionDuration": 0,
  "blockCount": 0
}

Respuestas de Error

Solicitud Incorrecta (400)

{
  "Error": "Failed to create notebook. The name may already exist in this investigation."
}

Crear desde Plantilla

POST /api/{tenantId}/{projectId}/notebook/investigation/{investigationId}/from-template

Crea un cuaderno a partir de una plantilla predefinida, incluyendo todos los bloques y configuraciones.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
investigationId GUID Identificador de la investigación

Cuerpo de la Solicitud

{
  "templateId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "name": "Process Discovery Analysis",
  "description": "Analysis using Process Discovery template"
}

Campos de la Solicitud

Campo Tipo Requerido Descripción
templateId GUID Plantilla a usar
name string No Sobrescribir nombre de plantilla
description string No Sobrescribir descripción de plantilla

Respuesta (201 Created)

Devuelve el cuaderno creado con bloques de la plantilla.

Respuestas de Error

No Encontrado (404)

{
  "Error": "Template not found"
}

Actualizar Cuaderno

PUT /api/{tenantId}/{projectId}/notebook/{notebookId}

Actualiza los metadatos del cuaderno. Soporta bloqueo optimista mediante DateModified.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
notebookId GUID Identificador del cuaderno

Cuerpo de la Solicitud

{
  "name": "Updated Notebook Name",
  "description": "Updated description",
  "notebookOrder": 2.5,
  "dateModified": "2024-01-20T14:45:00Z"
}

Campos de la Solicitud

Campo Tipo Requerido Descripción
name string Nombre del cuaderno
description string No Descripción del cuaderno
notebookOrder decimal No Orden de visualización
dateModified datetime No Para bloqueo optimista

Respuesta (200 OK)

Devuelve el cuaderno actualizado.

Bloqueo Optimista

Si se proporciona dateModified y no coincide con el valor actual del servidor, devuelve 409 Conflict:

{
  "Error": "CONFLICT",
  "Message": "Notebook was modified by another user since you last fetched it",
  "YourDateModified": "2024-01-20T14:45:00Z",
  "CurrentDateModified": "2024-01-21T09:30:00Z",
  "ModifiedBy": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "Resolution": "GET /api/{tenantId}/{projectId}/notebook/{notebookId} to fetch current state, then retry"
}

Eliminar Cuaderno

DELETE /api/{tenantId}/{projectId}/notebook/{notebookId}

Elimina permanentemente un cuaderno y todos sus bloques.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
notebookId GUID Identificador del cuaderno

Respuesta (200 OK)

{
  "Message": "Notebook successfully deleted",
  "NotebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}

Copiar Cuaderno

POST /api/{tenantId}/{projectId}/notebook/{notebookId}/copy

Crea una copia completa de un cuaderno incluyendo todos los bloques. Puede copiarse a la misma o diferente investigación.

Parámetros de Ruta

Parámetro Tipo Requerido Descripción
tenantId GUID Identificador del tenant
projectId GUID Identificador del proyecto
notebookId GUID Identificador del cuaderno fuente

Cuerpo de la Solicitud

{
  "name": "Copy of Main Analysis",
  "destinationInvestigationId": "22222222-3333-4444-5555-666666666666"
}

Campos de la Solicitud

Campo Tipo Requerido Descripción
name string No Nombre para la copia (por defecto: "Copy of ")
destinationInvestigationId GUID No Investigación destino (por defecto: misma investigación)

Respuesta (201 Created)

Devuelve la copia recién creada del cuaderno.


Obtener URL Compartible

GET /api/{tenantId}/{projectId}/notebook/{notebookId}/url

Genera una URL compartible para acceso directo al cuaderno en la interfaz de usuario.

Respuesta (200 OK)

{
  "notebookId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "url": "https://your-mindzie-instance.com/investigation/12345678/87654321/11111111/notebook/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "relativePath": "/investigation/12345678/87654321/11111111/notebook/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "expiresAt": null
}

Ejemplos de Implementación

Python

import requests

BASE_URL = 'https://your-mindzie-instance.com'
TENANT_ID = '12345678-1234-1234-1234-123456789012'
PROJECT_ID = '87654321-4321-4321-4321-210987654321'

class NotebookManager:
    def __init__(self, api_key):
        self.headers = {
            'Authorization': f'Bearer {api_key}',
            'Content-Type': 'application/json'
        }

    def list_notebooks(self, investigation_id):
        """Listar todos los cuadernos en una investigación."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/investigation/{investigation_id}'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def get_notebook(self, notebook_id):
        """Obtener detalles del cuaderno."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def create_notebook(self, investigation_id, name, description=None):
        """Crear un nuevo cuaderno."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/investigation/{investigation_id}'
        data = {'name': name, 'description': description}
        response = requests.post(url, json=data, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def create_from_template(self, investigation_id, template_id, name=None):
        """Crear cuaderno desde plantilla."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/investigation/{investigation_id}/from-template'
        data = {'templateId': template_id, 'name': name}
        response = requests.post(url, json=data, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def update_notebook(self, notebook_id, name, description=None, date_modified=None):
        """Actualizar cuaderno con bloqueo optimista."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}'
        data = {'name': name, 'description': description}
        if date_modified:
            data['dateModified'] = date_modified
        response = requests.put(url, json=data, headers=self.headers)
        if response.status_code == 409:
            conflict = response.json()
            raise Exception(f"Conflict: {conflict['Message']}")
        response.raise_for_status()
        return response.json()

    def delete_notebook(self, notebook_id):
        """Eliminar un cuaderno."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}'
        response = requests.delete(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def copy_notebook(self, notebook_id, name=None, destination_investigation=None):
        """Copiar un cuaderno."""
        url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}/copy'
        data = {'name': name}
        if destination_investigation:
            data['destinationInvestigationId'] = destination_investigation
        response = requests.post(url, json=data, headers=self.headers)
        response.raise_for_status()
        return response.json()

# Uso
manager = NotebookManager('your-api-key')
investigation_id = '11111111-2222-3333-4444-555555555555'

# Listar cuadernos
notebooks = manager.list_notebooks(investigation_id)
print(f"Found {len(notebooks)} notebooks")

# Crear un cuaderno
notebook = manager.create_notebook(investigation_id, 'New Analysis', 'My workflow')
print(f"Created notebook: {notebook['notebookId']}")

# Copiar el cuaderno
copy = manager.copy_notebook(notebook['notebookId'], 'Copy of New Analysis')
print(f"Created copy: {copy['notebookId']}")

# Actualizar con bloqueo optimista
try:
    updated = manager.update_notebook(
        notebook['notebookId'],
        'Renamed Analysis',
        date_modified=notebook['dateModified']
    )
except Exception as e:
    print(f"Update failed: {e}")

JavaScript/Node.js

const BASE_URL = 'https://your-mindzie-instance.com';
const TENANT_ID = '12345678-1234-1234-1234-123456789012';
const PROJECT_ID = '87654321-4321-4321-4321-210987654321';

class NotebookManager {
  constructor(apiKey) {
    this.headers = {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json'
    };
  }

  async listNotebooks(investigationId) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/investigation/${investigationId}`;
    const response = await fetch(url, { headers: this.headers });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return response.json();
  }

  async createNotebook(investigationId, name, description = null) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/investigation/${investigationId}`;
    const response = await fetch(url, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({ name, description })
    });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return response.json();
  }

  async updateNotebook(notebookId, name, description = null, dateModified = null) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/${notebookId}`;
    const body = { name, description };
    if (dateModified) body.dateModified = dateModified;

    const response = await fetch(url, {
      method: 'PUT',
      headers: this.headers,
      body: JSON.stringify(body)
    });

    if (response.status === 409) {
      const conflict = await response.json();
      throw new Error(`Conflict: ${conflict.Message}`);
    }
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return response.json();
  }

  async deleteNotebook(notebookId) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/${notebookId}`;
    const response = await fetch(url, {
      method: 'DELETE',
      headers: this.headers
    });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return response.json();
  }

  async copyNotebook(notebookId, name = null, destinationInvestigationId = null) {
    const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/notebook/${notebookId}/copy`;
    const body = {};
    if (name) body.name = name;
    if (destinationInvestigationId) body.destinationInvestigationId = destinationInvestigationId;

    const response = await fetch(url, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify(body)
    });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return response.json();
  }
}

// Uso
const manager = new NotebookManager('your-api-key');
const investigationId = '11111111-2222-3333-4444-555555555555';

// Listar cuadernos
const notebooks = await manager.listNotebooks(investigationId);
console.log(`Found ${notebooks.length} notebooks`);

// Crear y copiar
const notebook = await manager.createNotebook(investigationId, 'New Analysis');
const copy = await manager.copyNotebook(notebook.notebookId, 'Copy of Analysis');

Buenas Prácticas

  1. Carga Automática: No cargues explícitamente proyectos para CRUD de cuadernos; es automático
  2. Bloqueo Optimista: Incluye dateModified en las actualizaciones para detectar conflictos
  3. Plantillas: Usa plantillas para flujos de trabajo de análisis consistentes
  4. Nombres: Usa nombres descriptivos y únicos dentro de cada investigación
  5. Limpieza: Elimina cuadernos no usados para mantener organizadas las investigaciones