# POST /exports/templates

**Resource:** [Export Templates](./export-templates.md)  
**Scopes:** `exports:write`  
**Write operation:** yes

Create an export template. Define columns (root fields or relation fields), filters, optional sort, and output format.

## Parameters

| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `name` | body | string | yes | Template name. |
| `root_entity` | body | string | yes | One of: opportunity, contact, account, work_order. |
| `columns` | body | array | yes | Array of ExportColumn objects. Each has: id (uuid), source ("root" or "relation"), field (for root source, dotted path e.g. "name", "created_at", "metadata.cf_custom"), relation (for relation source, e.g. "primary_contact", "pipeline", "stage"), relation_mode ("primary", "first_n", "comma_joined", "explode"), relation_field (field on the related entity, e.g. "email", "name"), header (column label), format (optional: "date", "datetime", "currency", "boolean", "array"). |
| `filters` | body | array | no | Array of ExportFilter objects. Each has: id (uuid), field (dotted path), op, value. Canonical ops: eq, neq, in, not_in, gte, lte, between, contains (text substring), is_null, not_null. Tags use "in" (OR -- "has any of these tags") and "not_in" (NOR -- "has none of these tags"). Reference fields (pipeline_id, stage_id, assigned_to, status): in, not_in. Legacy: "not_contains" on tags is a back-compat alias for "not_in" -- new code should use "not_in". |
| `sort` | body | array | no | Array of ExportSortEntry objects: { column_id, direction: "asc"\|"desc" }. column_id must reference an ExportColumn.id from the columns array. Only root-source scalar columns can be sorted; relation columns are silently skipped. |
| `output` | body | object | no | ExportOutput config: { format: "xlsx"\|"csv", bom: boolean (CSV UTF-8 BOM, default true), filename_template: string (tokens: {name}, {YYYY}, {MM}, {DD}, {YYYY-MM-DD}) }. |

## Response example

```json
{
  "request": "curl -X POST \\\n  -H \"Authorization: Bearer tp_live_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Tagged PET leads - not VIP\",\n    \"root_entity\": \"opportunity\",\n    \"columns\": [\n      { \"id\": \"c1\", \"source\": \"root\", \"field\": \"name\", \"header\": \"Name\" },\n      { \"id\": \"c2\", \"source\": \"root\", \"field\": \"tags\", \"header\": \"Tags\", \"format\": \"array\" },\n      { \"id\": \"c3\", \"source\": \"relation\", \"relation\": \"primary_contact\", \"relation_field\": \"email\", \"relation_mode\": \"primary\", \"header\": \"Email\" }\n    ],\n    \"filters\": [\n      { \"id\": \"f1\", \"field\": \"tags\", \"op\": \"in\", \"value\": [\"PET\"] },\n      { \"id\": \"f2\", \"field\": \"tags\", \"op\": \"not_in\", \"value\": [\"VIP\"] }\n    ],\n    \"output\": { \"format\": \"xlsx\" }\n  }' \\\n  \"https://api.trustpager.com/functions/v1/api/v1/exports/templates\"",
  "response": "{\n  \"id\": \"3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n  \"name\": \"Tagged PET leads - not VIP\",\n  \"root_entity\": \"opportunity\",\n  \"columns\": [],\n  \"filters\": [],\n  \"output\": {\n    \"format\": \"xlsx\"\n  },\n  \"created_at\": \"2026-05-19T12:00:00Z\"\n}"
}
```

---
Base URL: `https://api.trustpager.com/functions/v1/api/v1` — Auth: `Authorization: Bearer YOUR_API_KEY`