# Attachments ## Pre-upload a file `client.Attachments.New(ctx, body) (*AttachmentNewResponse, error)` **post** `/v3/attachments` **This endpoint is optional.** You can send media by simply providing a URL in your message's media part — no pre-upload required. Use this endpoint only when you want to upload a file ahead of time for reuse or latency optimization. Returns a presigned upload URL and a permanent `attachment_id` you can reference in future messages. ## Step 1: Request an upload URL Call this endpoint with file metadata: ```json POST /v3/attachments { "filename": "photo.jpg", "content_type": "image/jpeg", "size_bytes": 1024000 } ``` The response includes an `upload_url` (valid for 15 minutes) and a permanent `attachment_id`. ## Step 2: Upload the file Make a PUT request to the `upload_url` with the raw file bytes as the request body. You **must** include all headers from `required_headers` exactly as returned — the presigned URL is signed with these values and S3 will reject the upload if they don't match. The request body is the binary file content — **not** JSON, **not** multipart form data. The file must equal `size_bytes` bytes (the value you declared in step 1). ```bash curl -X PUT "" \ -H "Content-Type: image/jpeg" \ -H "Content-Length: 1024000" \ --data-binary @photo.jpg ``` ## Step 3: Send a message with the attachment Reference the `attachment_id` in a media part. The ID never expires — use it in as many messages as you want. ```json POST /v3/chats { "from": "+15559876543", "to": ["+15551234567"], "message": { "parts": [ { "type": "media", "attachment_id": "" } ] } } ``` ## When to use this instead of a URL in the media part - Sending the same file to multiple recipients (avoids re-downloading each time) - Large files where you want to separate upload from message send - Latency-sensitive sends where the file should already be stored If you just need to send a file once, skip all of this and pass a `url` directly in the media part instead. **File Size Limit:** 100MB **Unsupported Types:** WebP, SVG, FLAC, OGG, and executable files are explicitly rejected. ### Parameters - `body AttachmentNewParams` - `ContentType param.Field[SupportedContentType]` Supported MIME types for file attachments and media URLs. **Images:** image/jpeg, image/png, image/gif, image/heic, image/heif, image/tiff, image/bmp, image/svg+xml, image/webp, image/x-icon **Videos:** video/mp4, video/quicktime, video/mpeg, video/mpeg2, video/x-msvideo, video/3gpp **Audio:** audio/mpeg, audio/x-m4a, audio/x-caf, audio/x-wav, audio/x-aiff, audio/aac, audio/midi, audio/amr **Documents:** application/pdf, text/plain, text/markdown, text/vcard, text/rtf, text/csv, text/html, text/calendar, text/xml, application/json, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/x-iwork-pages-sffpages, application/x-iwork-numbers-sffnumbers, application/x-iwork-keynote-sffkey, application/epub+zip, application/zip, application/x-gzip **Transcoded on delivery:** - `audio/x-caf` — CAF files are transcoded to `audio/mp4` for delivery. **Deprecated (accepted but transcoded):** - `audio/mp3` — Deprecated. Use `audio/mpeg` instead. Files sent as audio/mp3 will be delivered as audio/mpeg. - `audio/mp4` — Deprecated. Use `audio/x-m4a` instead. Files sent as audio/mp4 will be delivered as audio/x-m4a. - `audio/aiff` — Deprecated. Use `audio/x-aiff` instead. Files sent as audio/aiff will be delivered as audio/x-aiff. - `image/tiff` — Accepted, but TIFF images are transcoded to JPEG for delivery. **Unsupported:** FLAC, OGG, and executable files are explicitly rejected. - `Filename param.Field[string]` Name of the file to upload - `SizeBytes param.Field[int64]` Size of the file in bytes (max 100MB) ### Returns - `type AttachmentNewResponse struct{…}` - `AttachmentID string` Unique identifier for the attachment (for status checks via GET /v3/attachments/{id}) - `DownloadURL string` Permanent CDN URL for the file. Does not expire. Use the `attachment_id` to reference this file in media parts when sending messages. - `ExpiresAt Time` When the upload URL expires (15 minutes from now) - `HTTPMethod AttachmentNewResponseHTTPMethod` HTTP method to use for upload (always PUT) - `const AttachmentNewResponseHTTPMethodPut AttachmentNewResponseHTTPMethod = "PUT"` - `RequiredHeaders map[string, string]` HTTP headers that must be set on the upload request. The presigned URL is signed with these exact values — S3 will reject the upload if they don't match. - `UploadURL string` Presigned URL for uploading the file. PUT the raw binary file content to this URL with the `required_headers`. Do not JSON-encode or multipart-wrap the body. Expires after 15 minutes. ### Example ```go package main import ( "context" "fmt" "github.com/linq-team/linq-go" "github.com/linq-team/linq-go/option" ) func main() { client := linqgo.NewClient( option.WithAPIKey("My API Key"), ) attachment, err := client.Attachments.New(context.TODO(), linqgo.AttachmentNewParams{ ContentType: linqgo.SupportedContentTypeImageJpeg, Filename: "photo.jpg", SizeBytes: 1024000, }) if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", attachment.AttachmentID) } ``` #### Response ```json { "attachment_id": "550e8400-e29b-41d4-a716-446655440000", "upload_url": "https://uploads.linqapp.com/attachments/550e8400?X-Amz-Algorithm=AWS4-HMAC-SHA256&...", "download_url": "https://cdn.linqapp.com/uploads/partner-id/550e8400/photo.jpg", "http_method": "PUT", "expires_at": "2024-01-15T10:45:00Z", "required_headers": { "Content-Type": "image/jpeg", "Content-Length": "1024000" } } ``` ## Get attachment metadata `client.Attachments.Get(ctx, attachmentID) (*AttachmentGetResponse, error)` **get** `/v3/attachments/{attachmentId}` Retrieve metadata for a specific attachment including its status, file information, and URLs for downloading. ### Parameters - `attachmentID string` ### Returns - `type AttachmentGetResponse struct{…}` - `ID string` Unique identifier for the attachment (UUID) - `ContentType SupportedContentType` Supported MIME types for file attachments and media URLs. **Images:** image/jpeg, image/png, image/gif, image/heic, image/heif, image/tiff, image/bmp, image/svg+xml, image/webp, image/x-icon **Videos:** video/mp4, video/quicktime, video/mpeg, video/mpeg2, video/x-msvideo, video/3gpp **Audio:** audio/mpeg, audio/x-m4a, audio/x-caf, audio/x-wav, audio/x-aiff, audio/aac, audio/midi, audio/amr **Documents:** application/pdf, text/plain, text/markdown, text/vcard, text/rtf, text/csv, text/html, text/calendar, text/xml, application/json, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/x-iwork-pages-sffpages, application/x-iwork-numbers-sffnumbers, application/x-iwork-keynote-sffkey, application/epub+zip, application/zip, application/x-gzip **Transcoded on delivery:** - `audio/x-caf` — CAF files are transcoded to `audio/mp4` for delivery. **Deprecated (accepted but transcoded):** - `audio/mp3` — Deprecated. Use `audio/mpeg` instead. Files sent as audio/mp3 will be delivered as audio/mpeg. - `audio/mp4` — Deprecated. Use `audio/x-m4a` instead. Files sent as audio/mp4 will be delivered as audio/x-m4a. - `audio/aiff` — Deprecated. Use `audio/x-aiff` instead. Files sent as audio/aiff will be delivered as audio/x-aiff. - `image/tiff` — Accepted, but TIFF images are transcoded to JPEG for delivery. **Unsupported:** FLAC, OGG, and executable files are explicitly rejected. - `const SupportedContentTypeImageJpeg SupportedContentType = "image/jpeg"` - `const SupportedContentTypeImagePng SupportedContentType = "image/png"` - `const SupportedContentTypeImageGif SupportedContentType = "image/gif"` - `const SupportedContentTypeImageHeic SupportedContentType = "image/heic"` - `const SupportedContentTypeImageHeif SupportedContentType = "image/heif"` - `const SupportedContentTypeImageTiff SupportedContentType = "image/tiff"` - `const SupportedContentTypeImageBmp SupportedContentType = "image/bmp"` - `const SupportedContentTypeImageSvgXml SupportedContentType = "image/svg+xml"` - `const SupportedContentTypeImageWebp SupportedContentType = "image/webp"` - `const SupportedContentTypeImageXIcon SupportedContentType = "image/x-icon"` - `const SupportedContentTypeVideoMP4 SupportedContentType = "video/mp4"` - `const SupportedContentTypeVideoQuicktime SupportedContentType = "video/quicktime"` - `const SupportedContentTypeVideoMpeg SupportedContentType = "video/mpeg"` - `const SupportedContentTypeVideoMpeg2 SupportedContentType = "video/mpeg2"` - `const SupportedContentTypeVideoXM4v SupportedContentType = "video/x-m4v"` - `const SupportedContentTypeVideoXMsvideo SupportedContentType = "video/x-msvideo"` - `const SupportedContentTypeVideo3gpp SupportedContentType = "video/3gpp"` - `const SupportedContentTypeAudioMpeg SupportedContentType = "audio/mpeg"` - `const SupportedContentTypeAudioMP3 SupportedContentType = "audio/mp3"` - `const SupportedContentTypeAudioXM4a SupportedContentType = "audio/x-m4a"` - `const SupportedContentTypeAudioMP4 SupportedContentType = "audio/mp4"` - `const SupportedContentTypeAudioXCaf SupportedContentType = "audio/x-caf"` - `const SupportedContentTypeAudioXWav SupportedContentType = "audio/x-wav"` - `const SupportedContentTypeAudioXAiff SupportedContentType = "audio/x-aiff"` - `const SupportedContentTypeAudioAiff SupportedContentType = "audio/aiff"` - `const SupportedContentTypeAudioAac SupportedContentType = "audio/aac"` - `const SupportedContentTypeAudioMidi SupportedContentType = "audio/midi"` - `const SupportedContentTypeAudioAmr SupportedContentType = "audio/amr"` - `const SupportedContentTypeApplicationPdf SupportedContentType = "application/pdf"` - `const SupportedContentTypeTextPlain SupportedContentType = "text/plain"` - `const SupportedContentTypeTextMarkdown SupportedContentType = "text/markdown"` - `const SupportedContentTypeTextVcard SupportedContentType = "text/vcard"` - `const SupportedContentTypeTextRtf SupportedContentType = "text/rtf"` - `const SupportedContentTypeTextCsv SupportedContentType = "text/csv"` - `const SupportedContentTypeTextHTML SupportedContentType = "text/html"` - `const SupportedContentTypeTextCalendar SupportedContentType = "text/calendar"` - `const SupportedContentTypeApplicationMsword SupportedContentType = "application/msword"` - `const SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument SupportedContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"` - `const SupportedContentTypeApplicationVndMsExcel SupportedContentType = "application/vnd.ms-excel"` - `const SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet SupportedContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"` - `const SupportedContentTypeApplicationVndMsPowerpoint SupportedContentType = "application/vnd.ms-powerpoint"` - `const SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation SupportedContentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation"` - `const SupportedContentTypeApplicationXIworkPagesSffpages SupportedContentType = "application/x-iwork-pages-sffpages"` - `const SupportedContentTypeApplicationXIworkNumbersSffnumbers SupportedContentType = "application/x-iwork-numbers-sffnumbers"` - `const SupportedContentTypeApplicationXIworkKeynoteSffkey SupportedContentType = "application/x-iwork-keynote-sffkey"` - `const SupportedContentTypeApplicationEpubZip SupportedContentType = "application/epub+zip"` - `const SupportedContentTypeTextXml SupportedContentType = "text/xml"` - `const SupportedContentTypeApplicationJson SupportedContentType = "application/json"` - `const SupportedContentTypeApplicationZip SupportedContentType = "application/zip"` - `const SupportedContentTypeApplicationXGzip SupportedContentType = "application/x-gzip"` - `CreatedAt Time` When the attachment was created - `Filename string` Original filename of the attachment - `SizeBytes int64` Size of the attachment in bytes - `Status AttachmentGetResponseStatus` Current upload/processing status - `const AttachmentGetResponseStatusPending AttachmentGetResponseStatus = "pending"` - `const AttachmentGetResponseStatusComplete AttachmentGetResponseStatus = "complete"` - `const AttachmentGetResponseStatusFailed AttachmentGetResponseStatus = "failed"` - `DownloadURL string` URL to download the attachment ### Example ```go package main import ( "context" "fmt" "github.com/linq-team/linq-go" "github.com/linq-team/linq-go/option" ) func main() { client := linqgo.NewClient( option.WithAPIKey("My API Key"), ) attachment, err := client.Attachments.Get(context.TODO(), "abc12345-1234-5678-9abc-def012345678") if err != nil { panic(err.Error()) } fmt.Printf("%+v\n", attachment.ID) } ``` #### Response ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "filename": "photo.jpg", "content_type": "image/jpeg", "size_bytes": 1024000, "status": "complete", "download_url": "https://cdn.linqapp.com/attachments/550e8400-e29b-41d4-a716-446655440000/photo.jpg", "created_at": "2024-01-15T10:30:00Z" } ``` ## Domain Types ### Supported Content Type - `type SupportedContentType string` Supported MIME types for file attachments and media URLs. **Images:** image/jpeg, image/png, image/gif, image/heic, image/heif, image/tiff, image/bmp, image/svg+xml, image/webp, image/x-icon **Videos:** video/mp4, video/quicktime, video/mpeg, video/mpeg2, video/x-msvideo, video/3gpp **Audio:** audio/mpeg, audio/x-m4a, audio/x-caf, audio/x-wav, audio/x-aiff, audio/aac, audio/midi, audio/amr **Documents:** application/pdf, text/plain, text/markdown, text/vcard, text/rtf, text/csv, text/html, text/calendar, text/xml, application/json, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/x-iwork-pages-sffpages, application/x-iwork-numbers-sffnumbers, application/x-iwork-keynote-sffkey, application/epub+zip, application/zip, application/x-gzip **Transcoded on delivery:** - `audio/x-caf` — CAF files are transcoded to `audio/mp4` for delivery. **Deprecated (accepted but transcoded):** - `audio/mp3` — Deprecated. Use `audio/mpeg` instead. Files sent as audio/mp3 will be delivered as audio/mpeg. - `audio/mp4` — Deprecated. Use `audio/x-m4a` instead. Files sent as audio/mp4 will be delivered as audio/x-m4a. - `audio/aiff` — Deprecated. Use `audio/x-aiff` instead. Files sent as audio/aiff will be delivered as audio/x-aiff. - `image/tiff` — Accepted, but TIFF images are transcoded to JPEG for delivery. **Unsupported:** FLAC, OGG, and executable files are explicitly rejected. - `const SupportedContentTypeImageJpeg SupportedContentType = "image/jpeg"` - `const SupportedContentTypeImagePng SupportedContentType = "image/png"` - `const SupportedContentTypeImageGif SupportedContentType = "image/gif"` - `const SupportedContentTypeImageHeic SupportedContentType = "image/heic"` - `const SupportedContentTypeImageHeif SupportedContentType = "image/heif"` - `const SupportedContentTypeImageTiff SupportedContentType = "image/tiff"` - `const SupportedContentTypeImageBmp SupportedContentType = "image/bmp"` - `const SupportedContentTypeImageSvgXml SupportedContentType = "image/svg+xml"` - `const SupportedContentTypeImageWebp SupportedContentType = "image/webp"` - `const SupportedContentTypeImageXIcon SupportedContentType = "image/x-icon"` - `const SupportedContentTypeVideoMP4 SupportedContentType = "video/mp4"` - `const SupportedContentTypeVideoQuicktime SupportedContentType = "video/quicktime"` - `const SupportedContentTypeVideoMpeg SupportedContentType = "video/mpeg"` - `const SupportedContentTypeVideoMpeg2 SupportedContentType = "video/mpeg2"` - `const SupportedContentTypeVideoXM4v SupportedContentType = "video/x-m4v"` - `const SupportedContentTypeVideoXMsvideo SupportedContentType = "video/x-msvideo"` - `const SupportedContentTypeVideo3gpp SupportedContentType = "video/3gpp"` - `const SupportedContentTypeAudioMpeg SupportedContentType = "audio/mpeg"` - `const SupportedContentTypeAudioMP3 SupportedContentType = "audio/mp3"` - `const SupportedContentTypeAudioXM4a SupportedContentType = "audio/x-m4a"` - `const SupportedContentTypeAudioMP4 SupportedContentType = "audio/mp4"` - `const SupportedContentTypeAudioXCaf SupportedContentType = "audio/x-caf"` - `const SupportedContentTypeAudioXWav SupportedContentType = "audio/x-wav"` - `const SupportedContentTypeAudioXAiff SupportedContentType = "audio/x-aiff"` - `const SupportedContentTypeAudioAiff SupportedContentType = "audio/aiff"` - `const SupportedContentTypeAudioAac SupportedContentType = "audio/aac"` - `const SupportedContentTypeAudioMidi SupportedContentType = "audio/midi"` - `const SupportedContentTypeAudioAmr SupportedContentType = "audio/amr"` - `const SupportedContentTypeApplicationPdf SupportedContentType = "application/pdf"` - `const SupportedContentTypeTextPlain SupportedContentType = "text/plain"` - `const SupportedContentTypeTextMarkdown SupportedContentType = "text/markdown"` - `const SupportedContentTypeTextVcard SupportedContentType = "text/vcard"` - `const SupportedContentTypeTextRtf SupportedContentType = "text/rtf"` - `const SupportedContentTypeTextCsv SupportedContentType = "text/csv"` - `const SupportedContentTypeTextHTML SupportedContentType = "text/html"` - `const SupportedContentTypeTextCalendar SupportedContentType = "text/calendar"` - `const SupportedContentTypeApplicationMsword SupportedContentType = "application/msword"` - `const SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentWordprocessingmlDocument SupportedContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"` - `const SupportedContentTypeApplicationVndMsExcel SupportedContentType = "application/vnd.ms-excel"` - `const SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentSpreadsheetmlSheet SupportedContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"` - `const SupportedContentTypeApplicationVndMsPowerpoint SupportedContentType = "application/vnd.ms-powerpoint"` - `const SupportedContentTypeApplicationVndOpenxmlformatsOfficedocumentPresentationmlPresentation SupportedContentType = "application/vnd.openxmlformats-officedocument.presentationml.presentation"` - `const SupportedContentTypeApplicationXIworkPagesSffpages SupportedContentType = "application/x-iwork-pages-sffpages"` - `const SupportedContentTypeApplicationXIworkNumbersSffnumbers SupportedContentType = "application/x-iwork-numbers-sffnumbers"` - `const SupportedContentTypeApplicationXIworkKeynoteSffkey SupportedContentType = "application/x-iwork-keynote-sffkey"` - `const SupportedContentTypeApplicationEpubZip SupportedContentType = "application/epub+zip"` - `const SupportedContentTypeTextXml SupportedContentType = "text/xml"` - `const SupportedContentTypeApplicationJson SupportedContentType = "application/json"` - `const SupportedContentTypeApplicationZip SupportedContentType = "application/zip"` - `const SupportedContentTypeApplicationXGzip SupportedContentType = "application/x-gzip"`