Panel Information

Access Dashboard Panel Configurations

View and create visualization panels in dashboards including their layout, positioning, and configuration settings.

Get Dashboard Panels

GET /api/{tenantId}/{projectId}/dashboard/{dashboardId}/panels

Retrieves all visualization panels configured in a dashboard, including panel types, positions, dimensions, and configuration settings.

Path Parameters

Parameter Type Required Description
tenantId GUID Yes The tenant identifier
projectId GUID Yes The project identifier
dashboardId GUID Yes The dashboard identifier

Response (200 OK)

{
  "dashboardId": "880e8400-e29b-41d4-a716-446655440000",
  "panels": [
    {
      "panelId": "990e8400-e29b-41d4-a716-446655440000",
      "name": "Process Flow Chart",
      "panelType": "DashboardPanelProcessMap",
      "position": "Row: 1, Col: 1",
      "width": 6,
      "height": 4,
      "configuration": "{\"dataSource\": \"MainProcess\", \"visualization\": \"flow\"}"
    },
    {
      "panelId": "aa0e8400-e29b-41d4-a716-446655440000",
      "name": "KPI Summary",
      "panelType": "DashboardPanelSingleValue",
      "position": "Row: 1, Col: 7",
      "width": 3,
      "height": 2,
      "configuration": "{\"metric\": \"avgCycleTime\", \"format\": \"duration\"}"
    }
  ]
}

Response Fields

Field Type Description
dashboardId GUID The dashboard containing these panels
panels array List of panel objects

Panel Object Fields

Field Type Description
panelId GUID Unique identifier for the panel
name string Display title of the panel
panelType string Type of visualization (see Panel Types section)
position string Grid position as "Row: X, Col: Y"
width integer Panel width in grid units
height integer Panel height in grid units
configuration string JSON string containing panel-specific settings

Error Responses

Not Found (404):

{
  "Error": "Dashboard not found",
  "DashboardId": "880e8400-e29b-41d4-a716-446655440000"
}

Create Dashboard Panel

POST /api/{tenantId}/{projectId}/dashboard/{dashboardId}/panel

Creates a new visualization panel in a dashboard. The API automatically creates the appropriate selector block based on the panel type and settings provided.

Path Parameters

Parameter Type Required Description
tenantId GUID Yes The tenant identifier
projectId GUID Yes The project identifier
dashboardId GUID Yes The dashboard identifier

Request Body

{
  "title": "string (required)",
  "description": "string (optional)",
  "panelType": "string (required)",
  "blockId": "GUID (required for data panels)",
  "row": "integer (required, 0-based)",
  "column": "integer (required, 0-based)",
  "width": "integer (required, 1-12)",
  "height": "integer (required, 1-20)",
  "settings": "string (optional, JSON for selector configuration)"
}

Request Body Fields

Field Type Required Description
title string Yes Display title of the panel
description string No Optional description
panelType string Yes Panel type class name (see Panel Types section)
blockId GUID Yes* Calculator block ID to display (*not required for DashboardPanelDashboardNote)
row integer Yes Row position (0-based)
column integer Yes Column position (0-based)
width integer Yes Panel width in grid units (1-12)
height integer Yes Panel height in grid units (1-20)
settings string No JSON string with selector configuration

Response (201 Created)

{
  "panelId": "5b54172c-b15c-4dd9-bab6-6cfceb7389df",
  "title": "My KPI Panel",
  "dashboardPanelClassName": "DashboardPanelSingleValue",
  "row": 0,
  "column": 0,
  "width": 2,
  "height": 1,
  "blockId": "db0dd1b9-63b5-4754-92b1-2764f4a3fb68"
}

Note: The blockId in the response is the SELECTOR block ID, not the original calculator block ID. The API automatically creates a selector block that wraps the calculator.

Error Responses

Bad Request (400) - Missing Block:

{
  "Error": "VALIDATION_ERROR",
  "Message": "BlockId is required for panel type 'DashboardPanelSingleValue'"
}

Bad Request (400) - Invalid Panel Type:

{
  "Error": "VALIDATION_ERROR",
  "Message": "Invalid panel type 'InvalidType'. Valid types: DashboardPanelSingleValue, DashboardPanelCalculator, ..."
}

Bad Request (400) - Block Not Found:

{
  "Error": "VALIDATION_ERROR",
  "Message": "Block 'guid' does not exist"
}

Panel Types

mindzieStudio dashboards support the following panel types:

Panel Type Class Selector Created Description
DashboardPanelCalculator SelectorFullCalculator Full calculator output (process maps, trends, charts)
DashboardPanelSingleValue SelectorSingleValueFromLabel Single value / KPI card
DashboardPanelHorizontalBarChart SelectorMultiColumns Horizontal bar chart, ranked lists
DashboardPanelDataTable SelectorFullCalculator Data table display
DashboardPanelProcessMap SelectorFullCalculator Process map visualization
DashboardPanelDashboardNote (none) Text/note panel (no blockId required)
DashboardPanelRecommendationSentence (none) AI recommendation display

Panel Settings by Type

DashboardPanelSingleValue (KPI Cards)

When panelType is DashboardPanelSingleValue, the settings configure how to extract a single value from a calculator's output:

{
  "tableIndex": 0,
  "labelColumnName": "Name",
  "labelName": "Total Case Count",
  "valueColumnName": "Value",
  "formatText": "N0"
}
Setting Type Description
tableIndex integer Which output table to use (usually 0)
labelColumnName string Column containing labels (usually "Name")
labelName string The label to find (e.g., "Total Case Count")
valueColumnName string Column containing the value (usually "Value")
formatText string .NET format string (N0, F2, P0, etc.)

Best used with: CalculatorDataInformation, CalculatorOverview

DashboardPanelHorizontalBarChart (Bar Charts)

When panelType is DashboardPanelHorizontalBarChart, include columnNames in settings to trigger SelectorMultiColumns:

{
  "tableIndex": 0,
  "columnNames": ["ActivityName", "Count"],
  "sortColumnName": "Count",
  "sortAscending": false,
  "maxRows": 10
}
Setting Type Description
tableIndex integer Which output table to use
columnNames array Columns to include in chart (MUST match calculator output)
sortColumnName string Column to sort by
sortAscending boolean Sort direction
maxRows integer Maximum rows to display

IMPORTANT: Column names must exactly match the calculator's output columns. For example, CalculatorActivityFrequency uses the dataset's activity column name (e.g., "ActivityName"), not a generic "Activity".

Best used with: CalculatorActivityFrequency, CalculatorResourceFrequency

DashboardPanelCalculator (Full Visualizations)

For full calculator output (process maps, trends), no special settings are required:

{}

Or omit the settings parameter entirely.

Panel Architecture

Dashboard panels don't connect directly to calculator blocks. Instead, they use a three-layer architecture:

Panel.InputBlockId -> Selector Block -> Calculator Block (via parent_id)

Why Selectors? Selector blocks define HOW to display calculator output:

  • SelectorFullCalculator: Display entire output with visualization settings
  • SelectorSingleValueFromLabel: Extract one value by label lookup
  • SelectorMultiColumns: Extract specific columns with sorting/limiting

The API automatically creates the appropriate selector block when you create a panel pointing to a calculator.

Panel Layout System

Dashboard panels use a grid-based layout system:

  • Grid Units: 12-column grid system
  • Position: Row and column coordinates (0-based)
  • Size: Width (1-12 columns), Height (1-20 rows)
  • Responsive: Automatic scaling on different screen sizes

Implementation Examples

Get Dashboard Panels

cURL

curl -X GET "https://your-mindzie-instance.com/api/12345678-1234-1234-1234-123456789012/87654321-4321-4321-4321-210987654321/dashboard/880e8400-e29b-41d4-a716-446655440000/panels" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Create KPI Panel (Single Value)

curl -X POST "https://your-mindzie-instance.com/api/{tenantId}/{projectId}/dashboard/{dashboardId}/panel" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Total Cases",
    "panelType": "DashboardPanelSingleValue",
    "blockId": "calculator-data-information-guid",
    "row": 0,
    "column": 0,
    "width": 2,
    "height": 1,
    "settings": "{\"tableIndex\":0,\"labelColumnName\":\"Name\",\"labelName\":\"Total Case Count\",\"valueColumnName\":\"Value\",\"formatText\":\"N0\"}"
  }'

Create Horizontal Bar Chart

curl -X POST "https://your-mindzie-instance.com/api/{tenantId}/{projectId}/dashboard/{dashboardId}/panel" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Activity Distribution",
    "panelType": "DashboardPanelHorizontalBarChart",
    "blockId": "calculator-activity-frequency-guid",
    "row": 1,
    "column": 0,
    "width": 6,
    "height": 3,
    "settings": "{\"tableIndex\":0,\"columnNames\":[\"ActivityName\",\"Count\"],\"sortColumnName\":\"Count\",\"sortAscending\":false,\"maxRows\":10}"
  }'

Create Full Calculator Panel

curl -X POST "https://your-mindzie-instance.com/api/{tenantId}/{projectId}/dashboard/{dashboardId}/panel" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Case Count",
    "panelType": "DashboardPanelCalculator",
    "blockId": "calculator-case-count-guid",
    "row": 0,
    "column": 2,
    "width": 2,
    "height": 1
  }'

JavaScript/Node.js

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

async function getDashboardPanels(dashboardId, token) {
  const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/dashboard/${dashboardId}/panels`;

  const response = await fetch(url, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  if (response.ok) {
    return await response.json();
  } else if (response.status === 404) {
    throw new Error('Dashboard not found');
  } else {
    throw new Error(`Failed to get panels: ${response.status}`);
  }
}

async function createDashboardPanel(dashboardId, panelData, token) {
  const url = `${BASE_URL}/api/${TENANT_ID}/${PROJECT_ID}/dashboard/${dashboardId}/panel`;

  const response = await fetch(url, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(panelData)
  });

  if (response.ok) {
    return await response.json();
  } else {
    const error = await response.json();
    throw new Error(error.Message || `Failed to create panel: ${response.status}`);
  }
}

// Usage - Get panels
const panels = await getDashboardPanels('dashboard-guid', 'your-auth-token');
console.log(`Dashboard: ${panels.dashboardId}`);
console.log(`Panels: ${panels.panels.length}`);

// Usage - Create KPI panel
const newPanel = await createDashboardPanel('dashboard-guid', {
  title: 'Total Cases',
  panelType: 'DashboardPanelSingleValue',
  blockId: 'calculator-data-information-guid',
  row: 0,
  column: 0,
  width: 2,
  height: 1,
  settings: JSON.stringify({
    tableIndex: 0,
    labelColumnName: 'Name',
    labelName: 'Total Case Count',
    valueColumnName: 'Value',
    formatText: 'N0'
  })
}, 'your-auth-token');

console.log(`Created panel: ${newPanel.panelId}`);

Python

import requests
import json

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

def get_dashboard_panels(dashboard_id, token):
    """Get all panels in a dashboard."""
    url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/dashboard/{dashboard_id}/panels'
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }

    response = requests.get(url, headers=headers)

    if response.ok:
        return response.json()
    elif response.status_code == 404:
        raise Exception('Dashboard not found')
    else:
        raise Exception(f'Failed to get panels: {response.status_code}')


def create_dashboard_panel(dashboard_id, panel_data, token):
    """Create a new panel in a dashboard."""
    url = f'{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/dashboard/{dashboard_id}/panel'
    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }

    response = requests.post(url, headers=headers, json=panel_data)

    if response.ok:
        return response.json()
    else:
        error = response.json()
        raise Exception(error.get('Message', f'Failed to create panel: {response.status_code}'))


# Usage - Get panels
panels = get_dashboard_panels('dashboard-guid', 'your-auth-token')
print(f"Dashboard: {panels['dashboardId']}")
print(f"Panel count: {len(panels['panels'])}")

# Usage - Create KPI panel
settings = {
    'tableIndex': 0,
    'labelColumnName': 'Name',
    'labelName': 'Total Case Count',
    'valueColumnName': 'Value',
    'formatText': 'N0'
}

new_panel = create_dashboard_panel('dashboard-guid', {
    'title': 'Total Cases',
    'panelType': 'DashboardPanelSingleValue',
    'blockId': 'calculator-data-information-guid',
    'row': 0,
    'column': 0,
    'width': 2,
    'height': 1,
    'settings': json.dumps(settings)
}, 'your-auth-token')

print(f"Created panel: {new_panel['panelId']}")

C#

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class DashboardPanelsResponse
{
    public Guid DashboardId { get; set; }
    public List<PanelInfo> Panels { get; set; }
}

public class PanelInfo
{
    public Guid PanelId { get; set; }
    public string Name { get; set; }
    public string PanelType { get; set; }
    public string Position { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public string Configuration { get; set; }
}

public class CreatePanelRequest
{
    public string Title { get; set; }
    public string Description { get; set; }
    public string PanelType { get; set; }
    public Guid BlockId { get; set; }
    public int Row { get; set; }
    public int Column { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public string Settings { get; set; }
}

public class CreatePanelResponse
{
    public Guid PanelId { get; set; }
    public string Title { get; set; }
    public string DashboardPanelClassName { get; set; }
    public int Row { get; set; }
    public int Column { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public Guid BlockId { get; set; }
}

public class DashboardPanelClient
{
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl;
    private readonly Guid _tenantId;
    private readonly Guid _projectId;
    private readonly JsonSerializerOptions _jsonOptions;

    public DashboardPanelClient(string baseUrl, Guid tenantId, Guid projectId, string accessToken)
    {
        _baseUrl = baseUrl;
        _tenantId = tenantId;
        _projectId = projectId;
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Authorization =
            new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
        _jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
    }

    public async Task<DashboardPanelsResponse> GetDashboardPanelsAsync(Guid dashboardId)
    {
        var url = $"{_baseUrl}/api/{_tenantId}/{_projectId}/dashboard/{dashboardId}/panels";
        var response = await _httpClient.GetAsync(url);

        if (response.IsSuccessStatusCode)
        {
            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<DashboardPanelsResponse>(json, _jsonOptions);
        }
        else if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
        {
            throw new Exception($"Dashboard {dashboardId} not found");
        }

        throw new Exception($"Failed to get panels: {response.StatusCode}");
    }

    public async Task<CreatePanelResponse> CreatePanelAsync(Guid dashboardId, CreatePanelRequest request)
    {
        var url = $"{_baseUrl}/api/{_tenantId}/{_projectId}/dashboard/{dashboardId}/panel";
        var json = JsonSerializer.Serialize(request, _jsonOptions);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await _httpClient.PostAsync(url, content);

        if (response.IsSuccessStatusCode)
        {
            var responseJson = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<CreatePanelResponse>(responseJson, _jsonOptions);
        }

        var errorJson = await response.Content.ReadAsStringAsync();
        throw new Exception($"Failed to create panel: {errorJson}");
    }
}

// Usage
var client = new DashboardPanelClient(
    "https://your-mindzie-instance.com",
    Guid.Parse("12345678-1234-1234-1234-123456789012"),
    Guid.Parse("87654321-4321-4321-4321-210987654321"),
    "your-access-token");

// Get panels
var panels = await client.GetDashboardPanelsAsync(Guid.Parse("dashboard-guid"));
Console.WriteLine($"Dashboard: {panels.DashboardId}");
foreach (var panel in panels.Panels)
{
    Console.WriteLine($"- {panel.Name} ({panel.PanelType})");
}

// Create KPI panel
var newPanel = await client.CreatePanelAsync(Guid.Parse("dashboard-guid"), new CreatePanelRequest
{
    Title = "Total Cases",
    PanelType = "DashboardPanelSingleValue",
    BlockId = Guid.Parse("calculator-data-information-guid"),
    Row = 0,
    Column = 0,
    Width = 2,
    Height = 1,
    Settings = JsonSerializer.Serialize(new
    {
        tableIndex = 0,
        labelColumnName = "Name",
        labelName = "Total Case Count",
        valueColumnName = "Value",
        formatText = "N0"
    })
});

Console.WriteLine($"Created panel: {newPanel.PanelId}");

Important Notes

API Capabilities

  • Read Access: Use GET endpoint to retrieve panel configurations
  • Create Access: Use POST endpoint to create new panels with automatic selector block creation
  • Modify Access: Panel modification is currently done through the mindzieStudio UI
  • Delete Access: Panel deletion is currently done through the mindzieStudio UI

Configuration Parsing

The configuration field contains a JSON string that must be parsed to access settings.

Layout System

Panel positions use a row/column grid system with flexible sizing. Row and column values are 0-based when creating panels.