Command Center Tabular Data Contracts
Command Center generic table, chart, statistic, curve, transform, and agent-facing data consumers consume a canonical tabular frame:
core.tabular_frame@v1
If you are building a FastAPI route that returns generic tabular data for Command Center, use the SDK models in:
mainsequence.client.command_center.data_models
The primary response model is:
TabularFrameResponse
This model is the SDK boundary for core.tabular_frame@v1. It is not tied to one widget
implementation.
Canonical Frame Shape
TabularFrameResponse contains:
statuserrorcolumnsrowsfieldsmetasource
Required fields:
statuscolumnsrows
Optional fields:
errorfieldsmetasource
Top-level fields should stay generic. Source-specific runtime details belong under
source.context, not beside status, columns, and rows.
SDK Models
Use these generic SDK models for canonical tabular output:
TabularFrameResponseTabularFrameFieldResponseTabularFrameMetaResponseTabularFrameSourceResponseTabularTimeSeriesMetaResponse
These models keep the API boundary explicit and let FastAPI validate the response before Command Center consumes it.
Minimal Example
from fastapi import APIRouter
from mainsequence.client.command_center.data_models import (
TabularFrameFieldResponse,
TabularFrameResponse,
TabularFrameSourceResponse,
)
router = APIRouter()
@router.get(
"/workspace/customers",
response_model=TabularFrameResponse,
)
def get_customers_frame() -> TabularFrameResponse:
rows = [
{"customer_code": "ACME", "name": "Acme Capital", "region": "US"},
{"customer_code": "BETA", "name": "Beta Treasury", "region": "EU"},
]
return TabularFrameResponse(
status="ready",
columns=["customer_code", "name", "region"],
rows=rows,
fields=[
TabularFrameFieldResponse(
key="customer_code",
label="Customer Code",
type="string",
provenance="manual",
),
TabularFrameFieldResponse(
key="name",
label="Name",
type="string",
provenance="manual",
),
TabularFrameFieldResponse(
key="region",
label="Region",
type="string",
provenance="manual",
),
],
source=TabularFrameSourceResponse(
kind="api",
label="Customers API",
),
)
Source Context
Keep source-specific details in source.context.
from mainsequence.client.command_center.data_models import (
TabularFrameResponse,
TabularFrameSourceResponse,
)
frame = TabularFrameResponse(
status="ready",
columns=["x", "y"],
rows=[{"x": 1, "y": 2.5}],
source=TabularFrameSourceResponse(
kind="connection-query",
id="customers-query",
label="Customers query",
context={
"limit": 100,
"rangeStartMs": 1710000000000,
"rangeEndMs": 1710086400000,
},
),
)
This keeps the canonical frame stable while preserving source metadata that some workflows need.
Time-Series Metadata
When a tabular frame is meant for chart, curve, or time-aware consumers, include meta.timeSeries.
from mainsequence.client.command_center.data_models import (
TabularFrameMetaResponse,
TabularFrameResponse,
TabularTimeSeriesMetaResponse,
)
frame = TabularFrameResponse(
status="ready",
columns=["timestamp", "price"],
rows=[
{"timestamp": 1710000000000, "price": 101.4},
{"timestamp": 1710086400000, "price": 102.1},
],
meta=TabularFrameMetaResponse(
timeSeries=TabularTimeSeriesMetaResponse(
shape="long",
timeField="timestamp",
sorted=True,
valueField="price",
),
),
)
timeUnit defaults to ms and timezone defaults to UTC.
Adapter From API
Adapter from API providers can either:
- return
TabularFrameResponsedirectly from an operation, or - return provider-native JSON and declare a
core.tabular_frame@v1response mapping in the well-known Command Center contract
Generic Command Center consumers should not be bound to provider-native JSON without an exact
mapping into core.tabular_frame@v1.
Validation Rules
Before claiming an API returns canonical Command Center tabular data, verify:
- the route declares
response_model=TabularFrameResponse columnscontains the ordered field keys consumers need- every row is an object keyed by column name
fieldsdescribes important schema and formatting detailsmeta.timeSeriesis present for time-aware consumers- source-specific fields live in
source.context - no widget-specific or source-specific fields are added at the top level