Files
coder/docs/reference/api/templatebuilder.md
T
Jeremy RuppelandCoder Agent 51ac968d5a feat: wire up Template Builder session telemetry endpoint (#27124)
`TemplateBuilderSession` telemetry types and telemetry-server ingestion
were added in earlier PRs (#25082, coder/coder-telemetry-server#41), but
no code ever produced session events. This adds the missing producer.

**Backend**: `POST /api/v2/templatebuilder/sessions` reports wizard
entry and compose completion events directly via
`api.Telemetry.Report()`, using the same inline pattern as
`NetworkEvents` and `UserTailnetConnections`. No database migration or
`createSnapshot()` changes needed. RBAC requires `policy.ActionCreate`
on `ResourceTemplate.AnyOrganization()`, matching the compose endpoint.

**Frontend**: The template builder wizard fires `wizard_entry` on page
mount and `compose_completion` on create success or failure. A
client-generated session ID (UUID) correlates the two events for the
same wizard visit, enabling precise funnel analysis and abandonment
detection in BigQuery. Duration is tracked via `Date.now()` in the
wizard state.

Closes https://linear.app/codercom/issue/DEVEX-599

<details>
<summary>Implementation plan</summary>

## Root Cause Analysis

The DEVEX-599 ticket diagnosis suggested missing DB tables, queries, and
`eg.Go` blocks. That diagnosis assumes the DB-backed periodic snapshot
path is required. It is not. Investigation shows two telemetry reporting
patterns in the codebase:

1. **DB-backed periodic snapshots** (`createSnapshot()` with `eg.Go`
blocks): Used for durable entities like workspaces, templates, users.
2. **Direct inline reporting**
(`api.Telemetry.Report(&telemetry.Snapshot{...})`): Used for ephemeral
events like `NetworkEvents`, `UserTailnetConnections`, `CLIInvocations`.

Template builder sessions are ephemeral events, so the direct inline
reporting pattern is the correct fit.

## Backend Changes

- `codersdk/templatebuilder.go`: `TemplateBuilderSessionRequest` type
with `SessionID`, `EventType` enum, `TemplateBuilderSession()` client
method
- `coderd/coderd.go`: Route registration in `/templatebuilder` group
- `coderd/templatebuilder_handler.go`: Handler with RBAC check, request
validation, session ID fallback, and inline telemetry report
- `coderd/templatebuilder_handler_test.go`: Tests for wizard entry,
compose completion, invalid event type, disabled feature, and member
RBAC rejection

## Frontend Changes

- `site/src/api/api.ts`: `recordTemplateBuilderSession` API method
- `site/src/api/queries/templateBuilder.ts`: React Query mutation
- `site/src/pages/TemplateBuilder/wizardState.ts`: `sessionId` and
`enteredAt` fields, `createWizardState()` factory for per-mount
initialization
- `site/src/pages/TemplateBuilder/TemplateBuilderPageView.tsx`:
`sessionId` prop, `useReducer` initializer form
- `site/src/pages/TemplateBuilder/TemplateBuilderPage.tsx`: Telemetry
calls for wizard entry (on mount) and compose completion (on create
success/failure)

</details>

> 🤖 Generated by Coder Agents

---------

Co-authored-by: Coder Agent <agent@coder.com>
2026-07-27 16:10:40 -04:00

10 KiB
Generated

TemplateBuilder

List template builder base templates

Code samples

# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templatebuilder/bases \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'

GET /api/v2/templatebuilder/bases

Example responses

200 Response

{
  "bases": [
    {
      "description": "string",
      "icon": "string",
      "id": "string",
      "name": "string",
      "os": "string",
      "prerequisites": "string",
      "variables": [
        {
          "default": [
            0
          ],
          "description": "string",
          "name": "string",
          "required": true,
          "sensitive": true,
          "type": "string"
        }
      ]
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK codersdk.TemplateBuilderBasesResponse

To perform this operation, you must be authenticated. Learn more.

Compose template from base and modules

Code samples

# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templatebuilder/compose \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'

POST /api/v2/templatebuilder/compose

Body parameter

{
  "base_template_id": "string",
  "base_variable_values": {
    "property1": "string",
    "property2": "string"
  },
  "modules": [
    {
      "id": "string",
      "variables": {
        "property1": "string",
        "property2": "string"
      }
    }
  ]
}

Parameters

Name In Type Required Description
body body codersdk.TemplateBuilderComposeRequest true Compose request

Responses

Status Meaning Description Schema
200 OK OK

To perform this operation, you must be authenticated. Learn more.

Compose and create a template

Code samples

# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templatebuilder/compose/template \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'

POST /api/v2/templatebuilder/compose/template

Body parameter

{
  "base_template_id": "string",
  "base_variable_values": {
    "property1": "string",
    "property2": "string"
  },
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "modules": [
    {
      "id": "string",
      "variables": {
        "property1": "string",
        "property2": "string"
      }
    }
  ],
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "provisioner_tags": {
    "property1": "string",
    "property2": "string"
  }
}

Parameters

Name In Type Required Description
body body codersdk.TemplateBuilderCreateTemplateRequest true Create template request

Example responses

201 Response

{
  "template": {
    "active_user_count": 0,
    "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
    "activity_bump_ms": 0,
    "allow_user_autostart": true,
    "allow_user_autostop": true,
    "allow_user_cancel_workspace_jobs": true,
    "autostart_requirement": {
      "days_of_week": [
        "monday"
      ]
    },
    "autostop_requirement": {
      "days_of_week": [
        "monday"
      ],
      "weeks": 0
    },
    "build_time_stats": {
      "property1": {
        "p50": 123,
        "p95": 146
      },
      "property2": {
        "p50": 123,
        "p95": 146
      }
    },
    "cors_behavior": "simple",
    "created_at": "2019-08-24T14:15:22Z",
    "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
    "created_by_name": "string",
    "default_ttl_ms": 0,
    "deleted": true,
    "deprecated": true,
    "deprecation_message": "string",
    "description": "string",
    "disable_module_cache": true,
    "display_name": "string",
    "failure_ttl_ms": 0,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "max_port_share_level": "owner",
    "name": "string",
    "organization_display_name": "string",
    "organization_icon": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "provisioner": "terraform",
    "require_active_version": true,
    "time_til_autostop_notify_ms": 0,
    "time_til_dormant_autodelete_ms": 0,
    "time_til_dormant_ms": 0,
    "updated_at": "2019-08-24T14:15:22Z",
    "use_classic_parameter_flow": true
  }
}

Responses

Status Meaning Description Schema
201 Created Created codersdk.TemplateBuilderCreateTemplateResponse
400 Bad Request Bad Request codersdk.Response
404 Not Found Not Found codersdk.Response
409 Conflict Conflict codersdk.Response
504 Gateway Time-out Gateway Timeout codersdk.Response

To perform this operation, you must be authenticated. Learn more.

List template builder modules

Code samples

# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templatebuilder/modules \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'

GET /api/v2/templatebuilder/modules

Parameters

Name In Type Required Description
base query string false Base template example ID for OS-compatibility filtering

Example responses

200 Response

{
  "modules": [
    {
      "category": "string",
      "compatible_os": [
        "string"
      ],
      "conflicts_with": [
        "string"
      ],
      "description": "string",
      "display_name": "string",
      "icon": "string",
      "id": "string",
      "variables": [
        {
          "default": [
            0
          ],
          "description": "string",
          "name": "string",
          "required": true,
          "sensitive": true,
          "type": "string"
        }
      ],
      "version": "string"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK codersdk.TemplateBuilderModulesResponse

To perform this operation, you must be authenticated. Learn more.

Report a template builder session event

Code samples

# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templatebuilder/sessions \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'

POST /api/v2/templatebuilder/sessions

Body parameter

{
  "base_template_id": "string",
  "duration_seconds": 0,
  "event_type": "wizard_entry",
  "module_ids": [
    "string"
  ],
  "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  "success": true
}

Parameters

Name In Type Required Description
body body codersdk.TemplateBuilderSessionRequest true Session event

Responses

Status Meaning Description Schema
204 No Content No Content

To perform this operation, you must be authenticated. Learn more.