Drafts
Endpoints for managing template drafts. The draft workflow allows safe editing of templates without affecting the published version.
Draft Workflow Overview
- Create draft - Creates a copy of the template for editing
- Edit draft - Modify files, processors, inputs, settings
- Commit draft - Publish changes to the original template
- Delete draft - Discard changes
Only one draft can exist per template at a time. Drafts copy all files, processors, and inputs from the original template.
POST /api/templates/{id}/_edit
Create a draft copy of a template, or return existing draft if one already exists.
Authentication: Required (session)
Pre-blocks: template.lookup(params.id), permission.template.write(pre.template)
Response:
{
"id": "draft-xyz",
"tenant": "acme",
"name": "Monthly Report",
"description": "Generate monthly sales reports",
"type": "nunjucks",
"handler": "pdf",
"handlerOptions": {
"pageSize": "letter",
"margin": "1in"
},
"ownerId": "john",
"slug": "monthly-report",
"editingId": "abc123",
"templateFileId": "file-789",
"createdAt": "2024-01-15T14:22:00Z",
"updatedAt": "2024-01-15T14:22:00Z",
"_links": {
"self": { "href": "/api/templates/draft-xyz" },
"inf:commit-draft": { "href": "/api/templates/abc123/draft/_commit" },
"inf:original": { "href": "/api/templates/abc123" }
}
}
Notes:
- If a draft already exists for this template, returns the existing draft
- The draft copies all files, processors, and inputs from the original
- File IDs are updated in settings (PDF header/footer references)
- Returns the draft template with
editingIdpointing to the original
GET /api/templates/{id}/draft
Get the draft for a template.
Authentication: Required (session)
Pre-blocks: template.lookup(params.id), template.draft(pre.template.id)
Response:
{
"id": "draft-xyz",
"name": "Monthly Report",
"editingId": "abc123",
"templateFileId": "file-789",
"type": "nunjucks",
"handler": "pdf",
"settings": {},
"_links": {
"self": { "href": "/api/templates/draft-xyz" },
"inf:original": { "href": "/api/templates/abc123" },
"inf:commit-draft": { "href": "/api/templates/abc123/draft/_commit" }
}
}
Error Response:
Returns 404 Not Found if no draft exists for this template.
POST /api/templates/{id}/draft/_commit
Commit a draft, applying all changes to the original template and deleting the draft.
Authentication: Required (session)
Pre-blocks: template.lookup(params.id), permission.template.write(pre.template), template.draft(pre.template.id)
Response:
Returns the original template object with committed changes.
{
"id": "abc123",
"name": "Monthly Report",
"description": "Generate monthly sales reports",
"type": "nunjucks",
"handler": "pdf",
"templateFileId": "file-123",
"editingId": null,
"updatedAt": "2024-01-15T15:00:00Z"
}
Side Effects:
- All draft fields copied to original template
- Draft files replace original files
- Draft processors replace original processors
- Draft inputs replace original inputs
- Draft is deleted
- Activity log entry created for template update
DELETE /api/templates/{id}/draft
Delete a draft, discarding all changes.
Authentication: Required (session)
Pre-blocks: template.lookup(params.id), permission.template.write(pre.template), template.draft(pre.template.id)
Response:
Returns 204 No Content on successful deletion.
Side Effects:
- Draft template is deleted
- All draft files are deleted
- All draft processors and inputs are deleted
- Original template remains unchanged
Draft Field Synchronization
When creating a draft, the following fields are copied from the original template:
templateFileId- Primary template file referencetype- Template engine typesettings- Handler settingsletterheadId- Letterhead referencehandler- Output handlerhandlerOptions- Handler options
All files are copied with updated references in settings (e.g., PDF header/footer file IDs).
Editing Workflow Example
// 1. Create draft
POST /api/templates/abc123/_edit
// Returns: { id: "draft-xyz", editingId: "abc123", ... }
// 2. Modify draft - update files
PUT /api/templates/draft-xyz/files/file-123/contents
// Body: <updated template content>
// 3. Modify draft - add processor
POST /api/templates/draft-xyz/processors
// Body: { type: "dataset", datasetId: "ds-456", ... }
// 4. Modify draft - update settings
PUT /api/templates/draft-xyz/settings
// Body: { pdf: { pageSize: "legal" } }
// 5. Commit draft
POST /api/templates/abc123/draft/_commit
// Returns updated original template
// OR: Discard draft
DELETE /api/templates/abc123/draft
Draft Constraints
- Only one draft per template at a time
- Drafts cannot have their own drafts (no nested drafts)
- Draft and original share the same owner
- Committing a draft requires
permission.template.write - Deleting a draft requires
permission.template.write