---
title: "Create an egress template with mapping CSV"
method: POST
path: "/api/v1/egress-templates"
tags: ["EgressTemplate"]
---

# Create an egress template with mapping CSV

`POST /api/v1/egress-templates`

Uploads a CSV column-mapping file and associated metadata to define a new egress template for data export.

When to use: call this when no existing template covers the target tenant and entity type. To replace the CSV or update metadata on a template that already exists, use `PUT /api/v1/egress-templates/{templateId}` instead.

Preconditions: `tenant-id` header must be present and non-blank (returns 400 if missing). `templateName` and `entityType` are required form fields; `entityType` must be one of `practitioner`, `facility`, `group`. `status` on creation is limited to `draft` or `active` — `inactive` is rejected with 400 at create time.

Defaults applied when omitted: `outputFormat` -> `csv`, `separator` -> `,`, `status` -> `draft`, `scheduleEnabled` -> `false`, `scheduleFrequency` -> `daily`, `scheduleTime` -> `02:00`, `scheduleTimezone` -> `UTC` (the `scheduleFrequency`/`scheduleTime` defaults are skipped when `scheduleCron` is supplied).

Schedule field rules: `scheduleFrequency` accepts `daily`, `weekly`, `monthly`, or `custom`. `scheduleCron` (Quartz cron syntax, not Unix cron) is required when `scheduleFrequency=custom` and is rejected for any other frequency. `scheduleTime` (24-hour `HH:mm`) is required for `daily`/`weekly`/`monthly`. `scheduleDayOfWeek` (1 = Sunday ... 7 = Saturday) is required, and only allowed, for `weekly`. `scheduleDayOfMonth` (1-31) is required, and only allowed, for `monthly`.

CSV constraints: maximum file size is 5 MB; exceeding this returns 400. Column attribute paths are validated against the entity type's field schema.

Side effects: the CSV is uploaded to GCS before the template record is written. If the data-store write fails after a successful GCS upload, the GCS object is rolled back so no orphaned file is left behind. Not idempotent — each successful call creates a new template.

Returns: the created template, including the server-assigned `id`, `version` set to 1, and `mappingsCsvUrl` pointing at the uploaded CSV in GCS.

## Headers

- `tenant-id` string
- `x-user-id` string

## Response `201`

The newly created egress template, with server-assigned id, version=1, and the mappings CSV's GCS URL

- EgressTemplateResponse
  - `id` string — Server-assigned unique identifier of the template.
  - `tenantId` string — ID of the tenant that owns this template.
  - `createdAt` string, date-time
  - `createdBy` string — ID of the user who created the template.
  - `updatedAt` string, date-time
  - `updatedBy` string — ID of the user who last updated the template.
  - `templateName` string — Human-readable template name.
  - `description` string — Free-text description of the template's purpose.
  - `entityType` string — Entity type this template maps: `practitioner`, `facility`, or `group`. Immutable after creation.
  - `outputFormat` string — Output file format produced by exports run from this template, e.g. `csv`.
  - `separator` string — Delimiter used in the output CSV.
  - `status` string — Template lifecycle status: `draft`, `active`, or `inactive` (soft-deleted).
  - `version` integer — Version number, incremented on each successful update. Not incremented by delete.
  - `mappingsCsvUrl` string — GCS URL of the current mapping CSV for this template version.
  - `rowExpansionKeys` JsonNode
    - `empty` boolean
    - `valueNode` boolean
    - `containerNode` boolean
    - `missingNode` boolean
    - `array` boolean
    - `object` boolean
    - `nodeType` 'ARRAY' | 'BINARY' | 'BOOLEAN' | 'MISSING' | 'NULL' | 'NUMBER' | 'OBJECT' | 'POJO' | 'STRING'
    - `pojo` boolean
    - `number` boolean
    - `integralNumber` boolean
    - `floatingPointNumber` boolean
    - `short` boolean
    - `int` boolean
    - `long` boolean
    - `float` boolean
    - `double` boolean
    - `bigDecimal` boolean
    - `bigInteger` boolean
    - `textual` boolean
    - `boolean` boolean
    - `null` boolean
    - `binary` boolean
  - `extExportConfig` JsonNode
    - `empty` boolean
    - `valueNode` boolean
    - `containerNode` boolean
    - `missingNode` boolean
    - `array` boolean
    - `object` boolean
    - `nodeType` 'ARRAY' | 'BINARY' | 'BOOLEAN' | 'MISSING' | 'NULL' | 'NUMBER' | 'OBJECT' | 'POJO' | 'STRING'
    - `pojo` boolean
    - `number` boolean
    - `integralNumber` boolean
    - `floatingPointNumber` boolean
    - `short` boolean
    - `int` boolean
    - `long` boolean
    - `float` boolean
    - `double` boolean
    - `bigDecimal` boolean
    - `bigInteger` boolean
    - `textual` boolean
    - `boolean` boolean
    - `null` boolean
    - `binary` boolean
  - `scheduleEnabled` boolean — Whether scheduled (unattended) exports are enabled for this template.
  - `scheduleFrequency` string — Schedule cadence: `daily`, `weekly`, `monthly`, or `custom`. Null when no schedule is configured.
  - `scheduleTime` string — Time of day the schedule runs, 24-hour `HH:mm`. Null when scheduleFrequency is `custom` or no schedule is configured.
  - `scheduleDayOfWeek` integer — Day of week the schedule runs: 1 = Sunday ... 7 = Saturday. Only set when scheduleFrequency=`weekly`.
  - `scheduleDayOfMonth` integer — Day of month (1-31) the schedule runs. Only set when scheduleFrequency=`monthly`.
  - `scheduleCron` string — Quartz cron expression (6-7 fields, not standard 5-field Unix cron) defining the schedule. Only set when scheduleFrequency=`custom`.
  - `scheduleTimezone` string — IANA timezone identifier the schedule runs in, e.g. `America/New_York`.
  - `scheduleDaysOfWeek` string — Comma-separated days of week the schedule runs: 1 = Sunday ... 7 = Saturday. Only set when scheduleFrequency=`weekly`.
  - `scheduleInterval` integer — Interval in hours between runs (1, 2, 3, 4, 6, 8 or 12 — divisors of 24). Only set when scheduleFrequency=`hourly`.
  - `lastExportAt` string, date-time
  - `nextExportAt` string, date-time
  - `metadata` JsonNode
    - `empty` boolean
    - `valueNode` boolean
    - `containerNode` boolean
    - `missingNode` boolean
    - `array` boolean
    - `object` boolean
    - `nodeType` 'ARRAY' | 'BINARY' | 'BOOLEAN' | 'MISSING' | 'NULL' | 'NUMBER' | 'OBJECT' | 'POJO' | 'STRING'
    - `pojo` boolean
    - `number` boolean
    - `integralNumber` boolean
    - `floatingPointNumber` boolean
    - `short` boolean
    - `int` boolean
    - `long` boolean
    - `float` boolean
    - `double` boolean
    - `bigDecimal` boolean
    - `bigInteger` boolean
    - `textual` boolean
    - `boolean` boolean
    - `null` boolean
    - `binary` boolean
  - `jobType` string — Derived export trigger type for the Activity Center UI: `SCHEDULED` when a schedule is enabled, `MANUAL` otherwise. Not persisted by the data store.
  - `createdByName` string — Display name resolved from createdBy, when resolvable. Null if resolution failed or has not been attempted; callers should fall back to createdByEmail then createdBy in that case.
  - `createdByEmail` string — Email resolved from createdBy, when resolvable. Null if resolution failed or has not been attempted; used as the display fallback between createdByName and the raw createdBy id.
  - `bqExportEnabled` boolean
  - `bqTableName` string
  - `bqDataset` string

## Other responses

- `400` — The request is missing required fields, references an unsupported entityType/status, the CSV failed to parse or exceeds 5 MB, or schedule fields violate the frequency's rules; the error message states which field and why
- `401` — The request is missing a valid bearer token; re-authenticate and retry
- `403` — The authenticated caller lacks the create-template permission for this tenant

---

[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)
