Upload attachments
Attach files to messages, notes and drafts using presigned uploads, register files that stay in your own storage, and download attachments.
Attachments are created in two steps: first you create an attachment record that describes the file, then you either upload the bytes with the presigned form Kustomer returns, or point Kustomer at a file you already host. Finally you reference the attachment from a message, note or draft.
Diagram source
sequenceDiagram
autonumber
participant You
participant API as Kustomer API
participant S as Upload URL
You->>API: POST /v1/attachments { name, contentType, contentLength }
API-->>You: 201 { data.id, meta.upload: { url, fields } }
You->>S: POST multipart/form-data (fields…, file)
S-->>You: 204 No Content
You->>API: POST /v1/conversations/{id}/messages { …, attachments: [{ _id, name, contentType, contentLength }] }1. Create the attachment record
post/v1/attachments
curl -X POST "https://acme.api.kustomerapp.com/v1/attachments" \
-H "Authorization: Bearer $KUSTOMER_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "invoice-4417.pdf", "contentType": "application/pdf", "contentLength": 48213 }'name, contentType and contentLength (in bytes) are required. The response includes the attachment id and a temporary upload policy:
{
"data": {
"id": "5a4d1a8a6d92880012ad2923",
"type": "attachment",
"attributes": { "name": "invoice-4417.pdf", "contentType": "application/pdf", "contentLength": 48213, "uploaded": false }
},
"meta": {
"upload": {
"url": "https://…",
"fields": {
"key": "attachments/…/5a4d1a8a6d92880012ad2923-invoice-4417.pdf",
"Content-Type": "application/pdf",
"Policy": "…",
"X-Amz-Signature": "…"
}
}
}
}2. Upload the file
Send a multipart/form-data POST to meta.upload.url. Include every key in meta.upload.fields as a form field, exactly as returned, and add the file last, under the name file. Don't send your Kustomer Authorization header to this URL.
# Build -F flags from meta.upload.fields, then append the file last
curl -X POST "$UPLOAD_URL" \
-F "key=$KEY" \
-F "Content-Type=application/pdf" \
-F "Policy=$POLICY" \
-F "X-Amz-Signature=$SIGNATURE" \
-F "file=@invoice-4417.pdf"The upload policy expires after a short time, so upload right after creating the record. contentLength must match the file you upload.
3. Attach it
Reference the attachment when you create the message or note. Messages accept attachment objects:
{
"channel": "email",
"app": "acme-billing",
"direction": "out",
"subject": "Your invoice",
"preview": "Hi Jane, your invoice for order #4417 is attached.",
"attachments": [
{ "_id": "5a4d1a8a6d92880012ad2923", "name": "invoice-4417.pdf", "contentType": "application/pdf", "contentLength": 48213 }
]
}Notes take the same shape. See Create note within conversation.
Files in your own storage
If files must stay in your storage, register them by URL instead of uploading. Pass externalUrl:
{
"name": "contract.pdf",
"contentType": "application/pdf",
"contentLength": 120934,
"externalUrl": "https://files.acme.example/contracts/8812.pdf",
"renderMode": "default"
}- No upload policy is returned, and the attachment is marked
uploaded: truestraight away. externalUrlmust be an absolutehttps://URL without credentials in it. Private and loopback hosts are rejected.- Kustomer doesn't fetch, scan, copy or delete the file. Keeping the URL working is up to you; a signed URL that expires will break the attachment.
Draft attachments
Drafts have their own attachment endpoint. The response's links.related is a presigned URL that you upload to with a PUT:
/v1/drafts/{id}/attachments
curl --upload-file invoice-4417.pdf "$PRESIGNED_URL"Downloading attachments
get/v1/messages/{message_id}/attachments/{id}
This works for inbound and outbound message attachments. The response's links.related is a temporary URL for the file content. Download it promptly and don't store the URL.
Limits and tips
- Create the attachment record and upload in one go. Records whose upload never completes stay
uploaded: false. - Set
contentTypeaccurately: agents' browsers use it to preview images and PDFs. - Attachment uploads count toward your rate limit only for the Kustomer API calls, not the upload itself.