Attachments
Upload email attachments to Supabase Storage and reference them in outbound emails
Upload files to MisarMail's attachment storage and get back signed URLs to reference in your emails. Files are stored in a per-user Supabase Storage bucket and served via time-limited signed URLs.
Requires an active MisarMail session (dashboard only). Base URL: https://api.misar.io/mail.
Upload attachments
/mail/attachments/uploadSubmit one or more files as a multipart/form-data upload using the repeated field name files. Up to 5 files per request, 10 MB each. Uploads are checked against your account's storage quota before writing.
Request body (multipart/form-data)
filesfile[]bodyrequiredOne or more files (field name repeated). Max 5 files, 10 MB each. Allowed MIME types: application/pdf, image/png, image/jpeg, image/gif, image/webp, text/plain, text/csv, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document (.docx), application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (.xlsx), application/zip.
Response fields
successbooleantrue when every file uploaded successfully.
urlsstring[]Signed URLs (one per uploaded file, in order), each valid for 1 hour.
curl -X POST https://api.misar.io/mail/attachments/upload \
-F "files=@/path/to/invoice-june-2025.pdf" \
-F "files=@/path/to/terms.pdf"{
"success": true,
"urls": [
"https://supabase-mail.misar.io/storage/v1/object/sign/email-attachments/<user_id>/invoice-june-2025.pdf?token=eyJ...",
"https://supabase-mail.misar.io/storage/v1/object/sign/email-attachments/<user_id>/terms.pdf?token=eyJ..."
]
}Limits
| Constraint | Value |
|---|---|
| Max files per request | 5 |
| Max file size | 10 MB each |
| URL validity | 1 hour |
| Storage bucket | email-attachments (scoped per user) |
Signed URLs expire after 1 hour. Upload attachments as close as possible to send time — if you need to reference a file in a later send, re-upload it to obtain a fresh signed URL.
Using the URL in an email
After uploading, reference a returned URL in your email HTML as a download link or inline image.
As a download link
<a href="{{attachment_url}}">Download your invoice (PDF)</a>
As an inline image
<img src="{{attachment_url}}" alt="Product diagram" width="600" />
For brand logos and reused images, use a CDN-hosted URL directly in your template HTML instead of uploading to attachment storage each time.
Example
curl -X POST https://api.misar.io/mail/attachments/upload \
-F "files=@/path/to/invoice-june-2025.pdf"async function uploadAttachments(files: File[]) {
const formData = new FormData();
for (const file of files) formData.append("files", file);
const res = await fetch("/api/attachments/upload", {
method: "POST",
credentials: "include",
body: formData,
// Do NOT set Content-Type — the browser sets it with the boundary automatically
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.error ?? "Upload failed");
}
return res.json() as Promise<{ success: boolean; urls: string[] }>;
}Status codes
- 200 — OK. All files uploaded;
urlsreturned. - 400 — Bad request.
No files provided,Maximum 5 files allowed,File "<name>" exceeds 10MB limit, orFile type "<type>" is not allowed for "<name>". - 401 — Unauthorized. No active session.
- 413 — Payload Too Large. The upload would exceed your account's storage quota.
- 500 — Server error.
Failed to upload "<name>"orFailed to get URL for "<name>"— retry.