Semaphor

Dashboard Validation API

Validate dashboards against database schemas via the Semaphor API

Overview

The Dashboard Validation API checks dashboards against their actual database schemas to identify broken fields, invalid filters, missing connections, and other configuration issues. Use it to programmatically audit dashboard health.

Base path:

https://semaphor.cloud/api/v1/dashboard

All endpoints require a Bearer token with project_id scope.


Example: Validate a Dashboard via API

1. Get a project token

curl -X POST https://semaphor.cloud/api/v1/token \
  -H "Content-Type: application/json" \
  -d '{
    "type": "project",
    "projectId": "your-project-id",
    "projectSecret": "your-project-secret",
    "orgUserId": "your-org-user-id"
  }'

2. Validate a dashboard

curl -X POST https://semaphor.cloud/api/v1/dashboard/validate \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "dashboardId": "d_abc123"
  }'

Expected Response:

{
  "dashboardId": "d_abc123",
  "dashboardTitle": "Sales Dashboard",
  "isValid": true,
  "validatedAt": "2026-03-22T10:00:00.000Z",
  "summary": {
    "totalCards": 5,
    "validCards": 5,
    "invalidCards": 0,
    "totalFields": 20,
    "validFields": 20,
    "invalidFields": 0
  },
  "cardResults": [],
  "filterResults": [],
  "resourceResults": {
    "connections": [],
    "datasets": [],
    "datamodels": []
  }
}

Validate Single Dashboard

POST /dashboard/validate

  • Validates a dashboard's fields, filters, joins, and resources against the database schema.
  • The dashboard must belong to the same project as the token.

Request Body:

{
  "dashboardId": "d_abc123",
  "options": {
    "validateFilters": true,
    "validateJoins": true,
    "validateAIContext": true,
    "validateAssistantProfile": true,
    "validateLinkedVisuals": true,
    "includeAvailableColumns": true,
    "includeSuggestions": true,
    "maxSuggestionsPerField": 3
  }
}

Required Fields:

  • dashboardId: The ID of the dashboard to validate

Optional Fields:

  • options: Validation options (all default to true except maxSuggestionsPerField which defaults to 3)

Example Request:

curl -X POST https://semaphor.cloud/api/v1/dashboard/validate \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "dashboardId": "d_abc123",
    "options": {
      "validateFilters": true,
      "validateJoins": true,
      "includeSuggestions": true
    }
  }'

Example Response:

{
  "dashboardId": "d_abc123",
  "dashboardTitle": "Sales Dashboard",
  "isValid": false,
  "validatedAt": "2026-03-22T10:00:00.000Z",
  "summary": {
    "totalCards": 5,
    "validCards": 3,
    "invalidCards": 2,
    "totalFields": 20,
    "validFields": 18,
    "invalidFields": 2,
    "totalFilters": 3,
    "validFilters": 3,
    "invalidFilters": 0,
    "totalJoins": 1,
    "validJoins": 1,
    "invalidJoins": 0,
    "totalConnections": 2,
    "validConnections": 2,
    "invalidConnections": 0,
    "totalDatasets": 1,
    "validDatasets": 1,
    "invalidDatasets": 0,
    "totalDatamodels": 0,
    "validDatamodels": 0,
    "invalidDatamodels": 0,
    "aiContextValid": true,
    "assistantProfileValid": true
  },
  "cardResults": [
    {
      "cardId": "card_001",
      "cardTitle": "Revenue by Region",
      "sheetId": "sheet_1",
      "sheetTitle": "Overview",
      "isValid": false,
      "connectionId": "c_xyz",
      "dataSourceType": "table",
      "dataSourceName": "orders",
      "fieldResults": [
        {
          "fieldId": "field_1",
          "fieldName": "region_name",
          "fieldRole": "groupby",
          "entityName": "orders",
          "isValid": false,
          "errorType": "column_not_found",
          "errorMessage": "Column 'region_name' not found in table 'orders'",
          "availableColumns": ["region", "region_code", "region_id"],
          "suggestion": "region"
        }
      ]
    }
  ],
  "filterResults": [],
  "resourceResults": {
    "connections": [
      {
        "connectionId": "c_xyz",
        "connectionName": "Production DB",
        "isValid": true,
        "usedByCards": ["card_001", "card_002"]
      }
    ],
    "datasets": [],
    "datamodels": []
  }
}

Validate All Dashboards

POST /dashboard/validate-all

  • Validates all dashboards in a project at once.
  • Catches per-dashboard errors without failing the entire batch.

Request Body:

{
  "projectId": "p_abc123",
  "options": {
    "validateFilters": true,
    "validateJoins": true
  },
  "filter": {
    "type": "organization"
  }
}

Optional Fields:

  • projectId: Defaults to the token's project. Returns 403 if it differs from the token's project.
  • options: Same validation options as single validate.
  • filter: Narrow which dashboards to validate.
    • type: "organization" | "tenant" | "all" | "all-tenants"
    • tenantId: Required when type is "tenant"

Example Request:

curl -X POST https://semaphor.cloud/api/v1/dashboard/validate-all \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "p_abc123",
    "filter": {
      "type": "organization"
    }
  }'

Example Response:

{
  "projectId": "p_abc123",
  "validatedAt": "2026-03-22T10:00:00.000Z",
  "summary": {
    "totalDashboards": 12,
    "validDashboards": 9,
    "invalidDashboards": 3
  },
  "dashboardResults": [
    {
      "dashboardId": "d_abc123",
      "dashboardTitle": "Sales Dashboard",
      "isValid": true,
      "validatedAt": "2026-03-22T10:00:00.000Z",
      "summary": {
        "totalCards": 5,
        "validCards": 5,
        "invalidCards": 0,
        "totalFields": 20,
        "validFields": 20,
        "invalidFields": 0
      },
      "cardResults": [],
      "filterResults": [],
      "resourceResults": {
        "connections": [],
        "datasets": [],
        "datamodels": []
      }
    }
  ]
}

Validation Options Reference

OptionTypeDefaultDescription
validateFiltersbooleantrueCheck dashboard filter fields against the schema
validateJoinsbooleantrueCheck join keys exist in their respective tables
validateAIContextbooleantrueValidate AI assistant context configuration
validateAssistantProfilebooleantrueValidate linked assistant profile exists
validateLinkedVisualsbooleantrueCheck that linked saved visuals are valid
includeAvailableColumnsbooleantrueInclude list of available columns in error results
includeSuggestionsbooleantrueSuggest closest matching column names for invalid fields
maxSuggestionsPerFieldnumber3Maximum number of column suggestions per invalid field

Error Handling

400 Bad Request:

{
  "error": "Invalid JSON body"
}
{
  "error": "dashboardId is required"
}
{
  "error": "Dashboard has no template"
}
{
  "error": "Failed to parse dashboard template"
}

401 Unauthorized:

{
  "error": "Authentication failed"
}
{
  "error": "project_id is missing in the token"
}

403 Forbidden:

{
  "error": "Forbidden: project scope mismatch"
}

404 Not Found:

{
  "error": "Dashboard not found"
}

500 Internal Server Error:

{
  "error": "Validation failed"
}

Notes

  • All endpoints require authentication (Bearer token with project_id scope)
  • All options default to true -- pass false to skip specific checks
  • Bulk validation handles dashboards without templates gracefully by marking them invalid
  • Bulk validation catches per-dashboard errors without failing the entire batch
  • When includeSuggestions is enabled, the response includes closest-matching column names for invalid fields
  • All timestamps are returned in ISO 8601 format

On this page