/

Templates

karbone.templates manages templates stored on Carbone directly (/template and /templates). Most rendering does not need this: see the hash-first flow in Rendering, which uploads on demand. Use templates when you want explicit control — versioning, metadata, categories, tags, or cleanup.

Uploading

val uploaded =
  karbone.templates.upload(
    TemplateSource.file(Path.of("invoice.docx")),
    UploadOptions(name = "Invoice", category = "billing", tags = listOf("finance", "fr")),
  )

UploadOptions fields:

FieldMeaning
idVersioned mode only: attach this upload as a new version of an existing template.
versioningRequest versioned mode. Ignored by Community edition.
nameDisplay name (max UploadOptions.MAX_TEXT_LENGTH, 200, characters).
commentFree-text comment (same length limit).
categoryCategory name (same length limit).
tagsList of tags.
expireAtScheduled deletion instant; null means never.
deployedAtDeployment time used to pick the active version; null keeps the server default.
sampleA TemplateSample (data, complement, translations, enum) for Studio previews.

id, versioning, deployedAt and any versioning-related metadata are accepted but ignored by Carbone Community edition, which has no template versioning.

Legacy vs. versioned templates

upload returns a sealed UploadedTemplate:

Any of the three — legacy id, versioned template id, or version id — can be passed to render, download, update and delete in the same TemplateId / TemplateSource.id(...) slot; Carbone resolves whichever one it receives.

Download, update, delete

val file = karbone.templates.download(id)          // TemplateFile: content, fileName, contentType
val info = karbone.templates.update(id, TemplatePatch(name = "Invoice v2", tags = listOf("finance")))
karbone.templates.delete(id)

TemplatePatch fields are all nullable and mean “leave unchanged” when null; set expireAt = Instant.EPOCH to cancel a scheduled deletion.

Listing

val page: Page<TemplateInfo> = karbone.templates.list(ListTemplatesQuery(category = "billing", limit = 50))
// page.items, page.hasMore, page.nextCursor

karbone.templates.listAll(ListTemplatesQuery(category = "billing")).collect { info ->
  println(info.id)
}

list returns one Page (GET /templates); listAll returns a Flow<TemplateInfo> that follows nextCursor until hasMore is false, raising on the same Raise<KarboneError> used to collect it.

ListTemplatesQuery filters on id, versionId, category, origin (where the template came from — API, Studio, or a connector such as Salesforce), includeVersions, and free-text search, with limit capped at ListTemplatesQuery.MAX_LIMIT (100). See the API reference for the exhaustive TemplateOrigin values.

Template listing, like versioning, requires template management and may not be available on Community edition; see On-premise.

Categories and tags

val categories: List<String> = karbone.templates.categories()  // GET /templates/categories
val tags: List<String> = karbone.templates.tags()               // GET /templates/tags

Template identity

A legacy template’s id is deterministic: the SHA-256 hex digest of its bytes, computed the same way by Karbone (TemplateSource.sha256Hex) and by Carbone. Two uploads of byte-identical content get the same id.

A versioned template’s identity is split in two: a stable id for the template itself, and a versionId that changes with every new version (itself a content hash). Pick legacy ids for stateless, content-addressed templates; pick versioned ids when you need to update a template in place while keeping a stable reference to “the current invoice template”.