Skip to content

Reports And Templates

Shape stored analysis answers into deterministic JSON or Markdown reports without running analysis again.

This guide shows you how to shape stored analysis answers into a report using blocks, columns, grouping, sorting, and JSON mappings.

The report template language controls presentation only. It does not change the analysis answer, evidence, result state, limitations, or provenance. Stored templates use this language, and rerender requests can provide an inline presentation view.

This language renders analysis answers. The findings-to-report adapter for an audit view is planned and is not an admitted kind.

Answer To Report Lifecycle

  1. Profile instructions and answer_specs produce named answers. Each answer_specs[].answer_key is the stable name of one answer.
  2. answer_specs[].fields define the typed answer data inside that named answer. Fields describe semantic data; they are not report layout.
  3. A report template selects and formats existing answer data with answer_key, field columns, labels, grouping, sorting, or JSON mapping.
  4. Rerender is presentation-only. It reads stored answers and creates a new view or format. It does not re-run analysis, change answer data, or change evidence, uncertainty, limitations, or provenance.

Where To Use Templates

Use a template in one of these requests:

  • POST /api/v1alpha1/runs with stored profile_id and report_template_id references, plus optional immutable versions, for a new analysis run. Inline profiles and templates are not accepted there.
  • POST /api/v1alpha1/report-templates to store a reusable template.
  • POST /api/v1alpha1/report-templates/{report_template_id}/versions to append an immutable version.
  • POST /api/v1alpha1/runs/{run_id}/reports to render a new view from stored answers without reanalysis. This is the endpoint that accepts an inline report_template.

The public request uses answer_key, group_by, sort_by, sort_direction, field_labels, and columns. The wire key field_labels is also called fieldLabels in DTOs. The answer data paths used by a JSON mapping use the answer contract names, such as result_state and values.0.value.

Template Shape

Every template has a language and one or more blocks. A block selects one named answer with answer_key and gives the output block a label.

{
  "language": "en",
  "blocks": [
    {
      "type": "timeline",
      "answer_key": "inspection_timeline",
      "label": "Inspection timeline",
      "columns": [
        {"key": "activity", "label": "Activity"},
        {"key": "zone", "label": "Zone"}
      ]
    },
    {
      "type": "narrative",
      "answer_key": "inspection_summary",
      "label": "Summary"
    }
  ]
}

For a rerender template, id and version are optional presentation metadata. Stored templates have a server-assigned resource identity and immutable version. Run creation references those stored values; it does not accept the template body.

answer_key identifies the answer produced by the profile. A field key such as activity identifies an existing typed field inside that answer; it is not another answer key. Blocks present those existing fields and never create semantic fields.

Block Types

timeline renders timestamped events. Use it for an answer with events and optional event attributes.

narrative renders the answer narrative as prose.

table renders answer values, enumeration items, series points, or comparison points as rows. Use it when callers need explicit columns, grouping, or sorting.

value renders the first reportable value set as a compact field list. Use it for a small summary rather than a row table.

json renders a caller-defined JSON object from allowlisted answer paths. It is useful when a consumer needs a stable machine-readable shape.

The supported block types are timeline, narrative, table, value, and json. Unknown block types and unknown block keys are rejected with HTTP 422. The language has no open-ended extension keys and does not execute arbitrary template code.

Semantic Intervals And Processing Chunks

For a timeline answer, the analysis model selects semantic intervals from the profile instructions and indexed evidence. The returned start_ms and end_ms values describe user-facing events. DeepFrame may inspect the media in internal processing chunks, but those implementation windows are not events and are not exposed as report blocks. If an interval is unclear, the answer keeps uncertain or a limitation instead of inventing precision.

Columns, Groups, And Sorts

columns is an ordered list of {key, label} values. The order in the template is the order in JSON and Markdown output. If columns is omitted, the renderer derives columns from the answer fields in source order.

group_by copies a field into the rendered row or event group. sort_by orders rows or events by that field. sort_direction is asc or desc and defaults to ascending when sort_by is present. Equal values keep their source order.

{
  "type": "table",
  "answer_key": "warehouse_metrics",
  "label": "Metrics by zone",
  "group_by": "zone",
  "sort_by": "value",
  "sort_direction": "desc",
  "columns": [
    {"key": "zone", "label": "Zone"},
    {"key": "value", "label": "Count"}
  ]
}

The older field_labels key (called fieldLabels in DTOs) remains valid only for timeline blocks. It is a selecting-and-relabeling fallback for canonical columns: when columns is absent, each key must match an existing timeline attribute in the selected answer, and its label changes presentation text only. It cannot create a semantic field. Do not send both field_labels and columns in one timeline block. Use columns for new templates and for table or value blocks.

JSON Mapping

The mapping object maps a safe output path to a source path in the public answer projection. Mapping keys are sorted before rendering, so the same answers and template produce the same bytes.

{
  "type": "json",
  "answer_key": "warehouse_metrics",
  "label": "Consumer payload",
  "mapping": {
    "status": "result_state",
    "summary": "narrative",
    "first_count": "values.0.value",
    "first_evidence": "values.0.evidence.0.id"
  }
}

The JSON projection contains answer values, result state, limitations, coverage state, and evidence references. It does not expose model identity, stage identity, execution provenance, or signal-manifest identity. Mappings rooted at provenance, stages, stage, or signal_manifest_ref are rejected.

Missing Fields And Diagnostics

If a requested column, group, sort field, or JSON source is absent, the renderer does not silently drop the construct. It keeps the report document and adds a block-level missing_field diagnostic with the field and path. Inspect diagnostics before treating a report as complete.

An answer that is missing required answer data, evidence, or binding references still fails closed with a problem detail. Unknown template constructs fail at the template boundary with HTTP 422.

Worked Example

The following request stores a reusable template with all presentation features:

curl --fail-with-body -X POST "$BASE_URL/api/v1alpha1/report-templates" \
  -H "Authorization: Bearer $DEEPFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: template-create-20260824-01" \
  -d '{
    "name": "Warehouse summary",
    "description": "Compact operational report",
    "language": "en",
    "blocks": [
      {
        "type": "table",
        "answer_key": "warehouse_metrics",
        "label": "Metrics by zone",
        "group_by": "zone",
        "sort_by": "value",
        "sort_direction": "desc",
        "columns": [
          {"key": "zone", "label": "Zone"},
          {"key": "value", "label": "Count"}
        ]
      },
      {
        "type": "json",
        "answer_key": "warehouse_metrics",
        "label": "Machine payload",
        "mapping": {
          "status": "result_state",
          "count": "values.0.value"
        }
      }
    ]
  }'

After the run completes, render the stored answers with a new format or view. This does not call the analysis engine again:

curl --fail-with-body -X POST "$BASE_URL/api/v1alpha1/runs/$RUN_ID/reports" \
  -H "Authorization: Bearer $DEEPFRAME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: report-rerender-20260824-01" \
  -d '{
    "report_template": {
      "language": "en",
      "blocks": [
        {
          "type": "json",
          "answer_key": "warehouse_metrics",
          "label": "Export",
          "mapping": {
            "status": "result_state",
            "count": "values.0.value"
          }
        }
      ]
    },
    "formats": ["json", "markdown"]
  }'

The output is a presentation projection of the stored canonical answers. It does not reanalyze the video.

On this page