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 usingownerTypeandownerId, and may be further categorized by anentityType(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
bucketandpathto record the resolved SharePoint container/folder.
- tSM keeps pointers to the physical location; you may still use attachment fields like
-
Custom – integrate with a third-party DMS or proprietary store.
- Use
bucketandpathto hold locator hints if applicable. - Any extra metadata required by the external system can be placed into
formData(validated by the selectedattachmentTypeform).
- Use
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/pathto 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
lifecycleattribute 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
}
})
)
3) Link the same file to another record (related entity)
@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
Contentin list views; fetch it on demand.
Business & Governance
- Classification —
attachmentType(code table) defines purpose (e.g.,Contract,Invoice,Screenshot), UI icon, optional form forformData, and optional path rules. - Metadata —
formDatafollows the form specified byattachmentTypefor consistent validation and better search/reporting. - Visibility —
private = truefor internal-only; combine with Sharing/roles for precise access control. - Lifecycle — mark as
ARCHIVEDto enforce retention or hide from active views without hard deletion. - Storage —
bucketand optional computedpathallow deterministic, policy-driven storage locationing.
Reference
Attachment (attributes)
| Field | Type | Required | Read-only | Description / Notes | Example |
|---|---|---|---|---|---|
id | UUID |