Skip to main content

Data APIs

Use the Data APIs when your product owns the user interface and needs governed DashQ analytics as JSON. The native API covers the same dashboard and widget registry used by DashQ embeds.

End-to-end flow

  1. Authenticate the user in your application.
  2. Resolve the allowed account, user, properties, and product features on your backend.
  3. Create a short-lived session with POST /api/v1/widgets/session.
  4. Discover permitted surfaces with GET /api/v1/dashboards/catalog and GET /api/v1/widgets/catalog.
  5. Fetch a widget with POST /api/v1/widgets/{widget_id}/data.
  6. Use dictionary APIs for definitions, formula/SQL logic, grain, join keys, and lineage.
  7. Validate and allowlist the upstream response before returning it to your frontend.

Issuance uses x-api-key; subsequent catalog and data calls use X-Widget-Session-Token. Both credentials stay on the backend.

Create a scoped session

const access = await loadDashqEntitlements(authenticatedUser.id);

const response = await fetch(`${process.env.DASHQ_GATEWAY_BASE_URL}/api/v1/widgets/session`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.DASHQ_GATEWAY_API_KEY,
},
body: JSON.stringify({
accountId: access.accountId,
userId: access.dashqUserId,
requestedWidgetIds: access.widgetIds,
}),
});

if (!response.ok) throw new Error("Unable to create DashQ widget session");
const session = await response.json();

Do not accept accountId, userId, or an unrestricted widget list directly from the browser. A browser can request a supported view; your backend must intersect that request with stored entitlements.

Dashboard catalog

The scoped dashboard catalog currently exposes six foundation surfaces:

Dashboard IDSurfacePrimary audience
portfolio_foundation_v1Portfolio PerformanceExecutives and owners
lead_to_lease_foundation_v1Lead-to-LeaseLeasing leadership
tour_foundation_v1Tour PerformanceLeasing managers
application_foundation_v1Application OperationsOperations and compliance
marketing_foundation_v1Marketing / AcquisitionMarketing teams
communication_foundation_v1Communication PerformanceLeasing and operations

Each manifest describes its target view, audience, sections, included and pending modules, widget presentation metadata, and filter capabilities. Render from the catalog instead of maintaining a second dashboard registry.

Widget coverage

The current registry contains 58 widgets. The session-scoped catalog remains authoritative because the registry and account availability can change.

Current families include:

  • Lead-to-lease funnels, daily trends, summaries, and journey detail.
  • Portfolio inventory, occupancy, risk positioning, availability, and unit detail.
  • Marketing source flow, source quality, UTM coverage, and attribution.
  • Application performance, processing benchmarks, stage timelines, loss reasons, detail, and tenant demographics.
  • Tour scheduling, monthly outcomes, unit-type performance, property/representative effectiveness, and appointment detail.
  • Email/text AI performance, AI handoff reasons, and Voice AI performance.
  • Communication channel mix, inbound/outbound calls, first-response time, and representative usage.
  • Portfolio map and geographic KPI widgets.

Each widget catalog entry supplies:

  • id, title, description, and kind
  • semantic model and required fields
  • allowed filters and metrics
  • presentation information used by compatible dashboards

Filters and pagination

Common fields are startDate, endDate, buildingIds, limit, and offset. Depending on the widget, the catalog may also allow buildingPropertyIds, representativeIds, unitTypes/unitType, stage, source, or leaseAttributionMode.

Read allowed_filters before sending optional fields. The runtime validates requested properties and representatives against the governed session scope; client validation improves errors but does not replace that server check.

Sorting is not supported by the native widget endpoint. Use the widget's defined order and limit/offset. Table widgets may also return pagination metadata.

Fetch widget data

const response = await fetch(
`${process.env.DASHQ_GATEWAY_BASE_URL}/api/v1/widgets/${encodeURIComponent(widgetId)}/data`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Widget-Session-Token": session.sessionToken,
},
body: JSON.stringify({
startDate: filters.startDate,
endDate: filters.endDate,
buildingIds: intersect(filters.buildingIds, access.buildingIds),
limit: Math.min(filters.limit ?? 31, 90),
offset: Math.max(filters.offset ?? 0, 0),
}),
},
);

const payload = await response.json();
if (!response.ok) throw new Error(payload.error || "DashQ widget request failed");

return {
widgetId: payload.widgetId,
meta: pickAllowedMeta(payload.meta),
data: payload.data.map(toClientRow),
};

Dictionary metadata

Use the Data Dictionary for the public interactive snapshot or these endpoints for runtime visibility-aware metadata:

  • GET /api/v1/dictionary/categories
  • GET /api/v1/dictionary/terms?query=&category=&limit=&offset=
  • GET /api/v1/dictionary/terms/{term_id}

Terms can include formula, grain, cadence, usage, notes, calculation explanation, lineage, and linked reporting assets. Field assets can include fully qualified paths, descriptions, SQL expressions, data type, nullability, table grain, primary/join keys, date columns, time-zone rules, access scope, refresh cadence, and upstream model lineage.

Use these definitions when labeling metrics, explaining calculations, choosing joins, or generating AI answers. A missing asset can be a visibility boundary; it is not proof that the underlying model does not exist.

Response and caching rules

  • Validate status and JSON shape before reading fields.
  • Return only the fields needed by the client component.
  • Never log x-api-key, widget sessions, signed URLs, cookies, prompts, or raw rows.
  • Bound dates, rows, payload size, request time, and retries.
  • Cache only when the key contains the full account/user/property/widget/filter scope and retention is permitted.
  • Invalidate or segregate caches when entitlements change.
  • Treat 403 as a boundary; never retry with a wider account, property, or widget set.

Continue with the complete API reference, catalog discovery, and security requirements.