---
title: "Submit confirmed column mappings for a pending template"
method: PUT
path: "/templates/{id}"
tags: ["Template"]
---

# Submit confirmed column mappings for a pending template

`PUT /templates/{id}`

Records the consumer-confirmed column-to-field mappings for an `in-progress` template by creating a column record for every entry in `fields`. This is step 2 of the legacy three-step upload flow: it must follow `POST /templates` and precede `PUT /templates/{id}/approve`.

**When to use:** Call this after reviewing the suggestions returned by `POST /templates` and constructing the final mapping payload. Do not use it on templates created via the single-step or scratch flows - those are already approved; use `PATCH /templates/{id}/single-step` or `PATCH /templates/{id}/scratch` to change them.

**How:** Supply `{id}` and the required `tenant-id` header. The body's `fields` must map every header column of the template's stored `template.csv` (unmapped columns cause a 400; columns to ignore must be sent with the `[skipped]` sentinel as `mappedKey`), and each non-skipped entry's `mappedKey` must be a known system field unless `mappedEntity` is provided. `jobType` selects the system-field catalog used for validation, so it must match the template's own type; `GROUP` requires the tenant's `supportGroupRosters` configuration.

**Returns:** An echo of the confirmed `fields` in a `TemplateUpdateRequest`-shaped object whose `jobType` is always `null` - this is the endpoint's actual, intentional response shape. Side effect: one roster-template-column record is created per entry; repeat calls append further column records rather than replacing earlier ones, so this endpoint should be called once per template.

## Path parameters

- `id` string, required

## Headers

- `tenant-id` string, required

## Request body

- TemplateUpdateRequest — Confirmed column-to-field mappings for a template. Used as the request body of `PUT /templates/{id}` and `PUT /templates/{id}/approve`; `PUT /templates/{id}` also echoes this shape back as its response.
  - `jobType` 'PRACTITIONER' | 'FACILITY' | 'GROUP'
  - `fields` Field[] — Column mappings to record. Must contain one entry for every header column of the template's stored `template.csv` (unmapped columns cause a 400); columns to ignore must be sent with the `[skipped]` sentinel as `mappedKey`. Each non-skipped entry's `mappedKey` must be a known system field unless `mappedEntity` is provided.
    - `name` string — CSV column header this mapping applies to, exactly as it appears in the roster file.
    - `mappedKey` string — Key of the Certify system field this column maps to, from the field catalog returned by `GET /templates/fields`. The sentinel `[skipped]` marks a column the user explicitly chose not to map: skipped columns persist in the template/mappings CSVs but are excluded from the generated validation schema.
    - `mappedEntity` string — Entity that owns the mapped attribute (for example `practitioner` or `location`). When set, `mappedKey` is accepted as-is instead of being validated against the system-field catalog.
    - `entityGroup` string — Group label linking columns that belong to the same repeating entity instance (a multiple-value group), so related columns are ingested together.
    - `isRequired` boolean — Whether every roster row must supply a value for this column; drives the `required` constraint in the generated validation schema.
    - `isStaticField` boolean — Catalog metadata: whether the mapped system field is a static (fixed-value) field rather than one populated from roster data.
    - `isSingleSelect` boolean — Catalog metadata: whether the mapped system field accepts a single value from a fixed option list.
    - `validationRegex` string — Regular expression applied to this column's values during roster validation. Rows whose values do not match are rejected.
    - `description` string — Human-readable description of the mapped system field, from the field catalog.
    - `enum` string[] — Allowed values for enum-type system fields; roster values outside this list fail validation. Absent for free-form fields.
    - `separator` string — Literal separator character used to split a single cell value into multiple tokens for multi-value attributes. Blank or absent defaults to a comma at schema-generation time.
    - `singleSelect` boolean
    - `skipped` boolean

## Response `200`

The confirmed column mappings, echoed back. `jobType` is always `null` on the response.

- TemplateUpdateRequest — Confirmed column-to-field mappings for a template. Used as the request body of `PUT /templates/{id}` and `PUT /templates/{id}/approve`; `PUT /templates/{id}` also echoes this shape back as its response.
  - `jobType` 'PRACTITIONER' | 'FACILITY' | 'GROUP'
  - `fields` Field[] — Column mappings to record. Must contain one entry for every header column of the template's stored `template.csv` (unmapped columns cause a 400); columns to ignore must be sent with the `[skipped]` sentinel as `mappedKey`. Each non-skipped entry's `mappedKey` must be a known system field unless `mappedEntity` is provided.
    - `name` string — CSV column header this mapping applies to, exactly as it appears in the roster file.
    - `mappedKey` string — Key of the Certify system field this column maps to, from the field catalog returned by `GET /templates/fields`. The sentinel `[skipped]` marks a column the user explicitly chose not to map: skipped columns persist in the template/mappings CSVs but are excluded from the generated validation schema.
    - `mappedEntity` string — Entity that owns the mapped attribute (for example `practitioner` or `location`). When set, `mappedKey` is accepted as-is instead of being validated against the system-field catalog.
    - `entityGroup` string — Group label linking columns that belong to the same repeating entity instance (a multiple-value group), so related columns are ingested together.
    - `isRequired` boolean — Whether every roster row must supply a value for this column; drives the `required` constraint in the generated validation schema.
    - `isStaticField` boolean — Catalog metadata: whether the mapped system field is a static (fixed-value) field rather than one populated from roster data.
    - `isSingleSelect` boolean — Catalog metadata: whether the mapped system field accepts a single value from a fixed option list.
    - `validationRegex` string — Regular expression applied to this column's values during roster validation. Rows whose values do not match are rejected.
    - `description` string — Human-readable description of the mapped system field, from the field catalog.
    - `enum` string[] — Allowed values for enum-type system fields; roster values outside this list fail validation. Absent for free-form fields.
    - `separator` string — Literal separator character used to split a single cell value into multiple tokens for multi-value attributes. Blank or absent defaults to a comma at schema-generation time.
    - `singleSelect` boolean
    - `skipped` boolean

## Other responses

- `400` — A column of the stored `template.csv` is missing from `fields`, a `mappedKey` is not a known system field, or the requested `GROUP` type is not enabled for the tenant. Each entry in `errors` names the offending column in `title` and the cause in `reason`; fix the payload and retry.
- `401` — Authentication required - supply a valid bearer token.
- `403` — The authenticated user lacks the `UPDATE_TEMPLATE` permission.
- `500` — Unexpected server-side failure (for example a GCS or data-layer outage). Retrying after a partial failure may duplicate column records; verify with `GET /templates/{id}/columns` before retrying.

---

[API](https://skmtc.net/certifyos/apis/certify-api-layer.md) · [All operations](https://skmtc.net/certifyos/apis/certify-api-layer/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/certifyos/certify-api-layer/revisions/563848e0ecc0/schema)
