Skip to main content

Drafts

Endpoints for managing template drafts. The draft workflow allows safe editing of templates without affecting the published version.

Draft Workflow Overview

  1. Create draft - Creates a copy of the template for editing
  2. Edit draft - Modify files, processors, inputs, settings
  3. Commit draft - Publish changes to the original template
  4. 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 editingId pointing 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 reference
  • type - Template engine type
  • settings - Handler settings
  • letterheadId - Letterhead reference
  • handler - Output handler
  • handlerOptions - 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