Create attachment
/v1/attachmentsorg.permission.note.createorg.permission.message.createThe API key or user must hold at least one of them. Legacy roles still work; prefer the others for new keys.
Creates a new attachment document.
Uploading attachments (default S3 path)
When externalUrl is omitted, the response includes a temporary upload policy. Upload the file by sending a multi-part POST request to the URL found in the response object's meta.upload.url property.
The request must be accompanied by the key/value pairs found in meta.upload.fields as standard form keys. The file should be included as the last key under the name "file".
External attachments (host-owned storage)
When externalUrl is provided (HTTPS only; credentials-in-URL are rejected), Kustomer registers an attachment that points at that URL. No S3 upload policy is returned (meta.upload is omitted), uploaded is true, and later reads return links.related as the registered URL. Kustomer does not fetch, scan, own, or delete the external bytes; URL lifetime is the host's responsibility.
Optional renderMode (only with externalUrl):
default(or omitted): clients may open/download vialinks.related(same as today).metadata_only: client-facing responses expose attachment metadata only —links.relatedis omitted and the storage URL is never returned. Clients (SDKs, classic web, Agent Desktop) do not receive enough data to render or open the file; show a non-interactive uploaded placeholder instead.
Attachments
An attachment is a file, such as an image, PDF or recording, attached to a message, note, draft, forward or custom object comment. Kustomer stores a record describing the file, and you upload or download the bytes through short-lived signed URLs.
Files show up throughout the agent desktop: a photo a customer sent in chat, a PDF on an outbound email, a screenshot in an internal note. In the API, each file is an attachment record with name, contentType and contentLength (in bytes), plus a link to the object that carries it. The file's bytes never travel through the regular API: you upload them to, and download them from, temporary signed URLs that Kustomer hands you. Attachments on inbound messages are created by Kustomer when the message arrives.
Two upload styles
Which flow you use depends on what the file is going on.
| Attaching to | How |
|---|---|
| A message or note | Create the record with POST /v1/attachments, upload the file to meta.upload.url as a multipart form with every field from meta.upload.fields and the file last, then list the attachment in the message or note's attachments. |
| A draft or forward | Create the attachment under the draft or forward. Its links.related is a signed URL that you upload the file to with a single PUT. |
Upload immediately, because the upload URL expires; a record whose upload never completes stays uploaded: false. With POST /v1/attachments you can instead register a file you host by passing externalUrl (absolute https://, no credentials). Kustomer then stores only the link and never fetches or deletes the file. Add renderMode: "metadata_only" to keep that URL from ever being returned, so agents see only the file name and size. The attachments guide walks through every step with code.
Reading files
The record's links.related is a temporary download URL. Download the file promptly and don't store the URL. GET /v1/attachments/{id} covers outbound files only, so read files that customers sent through their message, which works for both directions. To find every file in a thread, use GET /v1/conversations/{id}/attachments.
Comments are internal notes on custom objects. Their files are set through the comment's attachments field, and the comment attachment endpoints read or remove them. A redacted comment attachment returns 410 Gone when you request it with redirect=true. Attachments removed through message redaction are marked redacted: true.
Which endpoint to use
| To | Call |
|---|---|
| Create a file record for a message or note | POST /v1/attachments |
| Read, rename or mark a file redacted | GET or PUT /v1/attachments/{id} |
| Download a message's file | GET /v1/messages/{message_id}/attachments/{id} |
| Add, list, read or remove a draft's files | POST or GET /v1/drafts/{id}/attachments, GET or DELETE /v1/drafts/{id}/attachments/{attachmentId} |
| Add, list, read or remove a forward's files | POST or GET /v1/forwards/{id}/attachments, GET or DELETE /v1/forwards/{id}/attachments/{attachmentId} |
| List, read or remove a comment's files | GET or DELETE /v1/comments/{id}/attachments, GET or DELETE /v1/comments/{id}/attachments/{attachmentId} |
Set contentType accurately, because the agent desktop uses it to preview images and PDFs, and make contentLength match the file you upload. PUT /v1/attachments/{id} creates the record if it doesn't exist and needs message update permission. WhatsApp drafts accept only certain media types; see Create draft for customer.
Request body
application/jsonrequiredOptional HTTPS URL for host-owned storage. When present, creates an external attachment with no S3 upload policy. Must be absolute HTTPS without credentials; Kustomer also rejects private/loopback hosts.
"https://customer-storage.example/report.pdf"Only valid with externalUrl. default (or omitted) exposes links.related for client open/download. metadata_only withholds all client-usable download URLs so UIs can show metadata only.
"default""metadata_only"Example "metadata_only"Responses
Created
Create response meta — S3 includes upload policy; external omits it.