Spaces:
Sleeping
Sleeping
Ticket Comment Attachments - Frontend Guide
What We Built
Comments now support image and document attachments. The API returns enriched attachment data so you don't need extra calls.
Upload Flow
1. Upload File First
POST /api/v1/documents/upload
Content-Type: multipart/form-data
file: <binary>
entity_type: "ticket"
entity_id: "ticket-uuid"
document_type: "comment_attachment"
document_category: "operational"
Response:
{
"id": "doc-uuid",
"file_name": "photo.jpg",
"file_url": "https://storage.../photo.jpg"
}
2. Create Comment with Attachment
POST /api/v1/tickets/{ticket_id}/comments
{
"comment_text": "Found this issue",
"is_internal": true,
"comment_type": "issue",
"attachment_document_ids": ["doc-uuid"]
}
Response Structure
{
"id": "comment-uuid",
"comment_text": "Found this issue",
"attachment_document_ids": ["doc-uuid"],
"attachments": [
{
"id": "doc-uuid",
"file_name": "photo.jpg",
"file_type": "image/jpeg",
"file_url": "https://storage.../photo.jpg",
"file_size": 245678,
"is_image": true
}
]
}
Key Fields
attachment_document_ids: Array of document UUIDsattachments: Full attachment details (auto-populated)attachments[].is_image: Boolean flag - use this to filter images vs other filesattachments[].file_url: Direct URL - ready to use in<img>or download links
Multiple Attachments
{
"comment_text": "Before and after photos",
"attachment_document_ids": ["doc-1", "doc-2", "doc-3"]
}
All attachments returned in attachments array.
Mobile Example (React Native)
// Upload image
const formData = new FormData();
formData.append('file', {
uri: photo.uri,
type: 'image/jpeg',
name: 'photo.jpg'
});
formData.append('entity_type', 'ticket');
formData.append('entity_id', ticketId);
formData.append('document_type', 'comment_attachment');
const uploadRes = await api.post('/documents/upload', formData);
// Create comment
await api.post(`/tickets/${ticketId}/comments`, {
comment_text: "Found damaged cable",
is_internal: true,
comment_type: "issue",
attachment_document_ids: [uploadRes.data.id]
});
Web Example (React)
// Upload file
const formData = new FormData();
formData.append('file', file);
formData.append('entity_type', 'ticket');
formData.append('entity_id', ticketId);
formData.append('document_type', 'comment_attachment');
const uploadRes = await api.post('/documents/upload', formData);
// Create comment
await api.post(`/tickets/${ticketId}/comments`, {
comment_text: "See attached diagram",
is_internal: true,
comment_type: "resolution",
attachment_document_ids: [uploadRes.data.id]
});
Display Logic
// Separate images from other files
const images = comment.attachments.filter(a => a.is_image);
const files = comment.attachments.filter(a => !a.is_image);
// Render images
images.forEach(img => {
// <img src={img.file_url} alt={img.file_name} />
});
// Render file links
files.forEach(file => {
// <a href={file.file_url} download={file.file_name}>{file.file_name}</a>
});
Notes
- Upload files BEFORE creating comment
- Max file size and allowed types handled by
/documents/uploadendpoint - Images auto-detected via MIME type (
image/*) - File URLs are permanent and CDN-backed
- No need to fetch attachment details separately - included in comment response