Skip to main content
Version: 2.3

Attachment

Attachments are files (contracts, screenshots, invoices, reports, exports, etc.) linked to records across tSM (e.g., Tickets, Customers, Orders). They centralize evidence and generated outputs directly on the record where teams work:

  • Customer service: screenshots, call recordings, email exports on tickets
  • Sales/CRM: signed contracts, proposals, meeting notes
  • Operations: invoices, delivery notes, device configs, audit PDFs
  • Integrations: documents generated by workflows or received from external systems

Attachments support structured metadata for search and compliance, privacy flags for client visibility, optional previews/thumbnails, and retention via lifecycle.

Related concepts (documented in the overview):
Every supporting entity is linked to a parent using ownerType and ownerId, and may be further categorized by an entityType (here: attachmentType).


Storage​

Attachments in tSM separate metadata from binary content. tSM stores searchable metadata such as name, description, mimeType, attachmentType, formData, auditInfo, and linkage (ownerType, ownerId, optional related entities). The actual file bytes are persisted in a pluggable storage backend.

Supported storage backends

  • Database – convenient for development and small demos only. Not recommended for production due to DB bloat and I/O characteristics.

  • Filesystem – production-ready default. The storage must be shared across all DMS microservice instances (e.g., NFS, SMB, object storage mounted as a POSIX share).

    • Files are organized into buckets; the bucket name is recorded on the attachment for deterministic placement and maintenance.
  • SharePoint – files live on a SharePoint drive.

    • tSM keeps pointers to the physical location; you may still use attachment fields like bucket and path to record the resolved SharePoint container/folder.
  • Custom – integrate with a third-party DMS or proprietary store.

    • Use bucket and path to hold locator hints if applicable.
    • Any extra metadata required by the external system can be placed into formData (validated by the selected attachmentType form).

Buckets & paths

  • For filesystem storage, buckets are the primary sharding/organization unit (e.g., by domain, year, tenant).
  • For SharePoint and Custom storage, you can still populate bucket/path to reflect the real target (site/library/folder or vendor-specific path) so that UI and jobs can route, display, and maintain files consistently.

Lifecycle & archiving

  • The lifecycle attribute governs retention and visibility:

    • LIVE – active, frequently accessed content.
    • ARCHIVED – retained for compliance/cost control; typically moved to a separate partition or cheaper/slower storage tier.
  • Archiving policy can be cascade-driven or time-based:

    • If the owning record is archived, all its attachments should be archived as well (recommended default).
    • You may also apply time-based rules (e.g., archive after N days); custom logic may apply per tenant or per attachmentType.
  • While archived, metadata remain queryable; retrieval of binaries may be slower or gated by policy, depending on the backend.

Typical Flows​

1) Upload a small file (inline content)​

Use inline Base64 only for small files. For large files, prefer the dedicated binary APIs.

@dms.attachment.create({
"ownerType": "Ticket",
"ownerId": #ticket.id,
"attachmentType": "Screenshot",
"name": "error-dialog.png",
"mimeType": "image/png",
"data": #pngBytes.encodeBase64(),
"formData": {
"capturedAt": #now(),
"environment": "UAT"
},
"private": true
})

2) Generate a PDF with Output Management and attach it​

#with(
#pdf = @formatterPublicService.generateBase64("InvoiceLayout", "pdf", {
customer: #order.customer,
order: #order
})
).do(
@dms.attachment.create({
"ownerType": "Order",
"ownerId": #order.id,
"attachmentType": "Invoice",
"name": "Invoice_" + #order.number + ".pdf",
"mimeType": "application/pdf",
"data": #pdf,
"formData": {
"invoiceNumber": #order.number,
"fiscalYear": #order.created.date.year
}
})
)
@dms.attachmentRelatedEntity.create({
"attachmentId": #attachment.id,
"name": "Also linked to ticket",
"refType": "Ticket",
"refId": #ticket.id,
"data": { "relation": "also-affected" }
})

4) Fetch an attachment with on-demand content/thumbnail​

@dms.attachment.get(#id, {"expand": ["Content", "Thumbnail"]})

⚠️ Performance tip: Don’t expand Content in list views; fetch it on demand.


Business & Governance​

  • Classification — attachmentType (code table) defines purpose (e.g., Contract, Invoice, Screenshot), UI icon, optional form for formData, and optional path rules.
  • Metadata — formData follows the form specified by attachmentType for consistent validation and better search/reporting.
  • Visibility — private = true for internal-only; combine with Sharing/roles for precise access control.
  • Lifecycle — mark as ARCHIVED to enforce retention or hide from active views without hard deletion.
  • Storage — bucket and optional computed path allow deterministic, policy-driven storage locationing.

Reference​

Attachment (attributes)​

FieldTypeRequiredRead-onlyDescription / NotesExample
idUUID––Unique identifier. Not intended for end-user display.3f2b…
ownerTypeStringYes–Parent record type (e.g., Ticket, Customer, Order).Ticket
ownerIdStringYes–Parent record ID.12345
nameString––File name incl. extension.contract.pdf
descriptionString––User-facing description / tooltip.Signed MSA
mimeTypeString––Standard MIME type.application/pdf
dataString (Base64)––Only when expanded (Content). Use only for small files.JVBERi0x…
thumbnailString (Base64)––Only when expanded (Thumbnail).iVBORw0K…
relatedEntitiesList––Additional links beyond the owner (see Attachment Related Entity).—
sizeDecimal–YesComputed file size.2048
sizeUnitString–YesUnit of size (B, KB, MB, …).KB
dateDate–Yes (default)Creation date (defaults to now).2025-01-01T10:00:00Z
formDataJSON––Structured metadata validated by the attachmentType form.{ "invoiceNumber": "INV-001" }
attachmentTypeString––Code from Attachment Type registry.Invoice
bucketString––Logical storage bucket; used by backends (FS/object store).orders
privateBoolean––Client visibility toggle.true
lifecycleEnum––LIVE or ARCHIVED.LIVE
auditInfoObject––Standard audit fields (created by/at, updated by/at).—
pathString––Optional resolved path (may be computed)./orders/2025/0001

Expansions

  • Content — includes data
  • Thumbnail — includes thumbnail

Lifecycle values

  • LIVE, ARCHIVED

Used to link an attachment to additional records beyond its owner (e.g., the same PDF linked to both a Ticket and an Order).

FieldTypeRequiredDescription
idUUID–Identifier of the relation row.
attachmentIdUUIDYesAttachment being linked.
nameString (1–255)YesDisplay name of the link.
refIdString–ID of the referenced record.
refTypeString–Type of the referenced record (e.g., Ticket, Order).
dataMap–Optional metadata for the relation (e.g., purpose, weight).
auditInfoObject–Standard audit fields.

Attachment Type (code table)​

Defines allowed attachmentType values and behavior (UI icon, form for formData, optional path expression).

FieldTypeRequiredRead-onlyNotes
codeStringYes–Unique ASCII code (no spaces). Used in APIs & configs.
nameStringYes–Display name for users.
descriptionString––Tooltip/long description.
validityFrom / validityToDate––Controls whether the type is currently valid.
validBoolean–YesComputed from validity; not stored.
localizationDataObject––Translations for attributes (e.g., name, description).
formString––Name of the form used to validate formData.
iconString––UI icon identifier.
dataTagsList<String>––Search labels / tags.
configMap––Arbitrary configuration.
pathExpressionString (SpEL)––Computes display/storage path for attachments of this type.

Example pathExpression

'/orders/' + #root.formData?.year + '/' + #root.formData?.number

Good Practices​

  • Classify attachments (attachmentType) and enforce metadata (formData) for better search, audit, and automation.
  • Prefer binary endpoints for large files; keep Base64 (data) for small/quick uploads.
  • Expand on demand (Content, Thumbnail) to minimize payloads in list screens.
  • Use private and Sharing together when client visibility must be restricted.
  • Archive rather than delete when you need retention/history.

See Also​

  • Supporting Entities – Overview (ownership & typing model)
  • Output Management – generate documents to attach
  • Sharing – access control and collaboration
  • SpEL Clients – configuration & usage