Skip to main content

Attachments FAQ

Should I use /upload or /from-url?

SituationEndpoint
You have the bytes locally (file on disk, Buffer, Blob, generated PDF, etc.)/upload
The file is already publicly hosted at a URL/from-url
You have a URL but it's not publicly reachable (intranet, private bucket without a presigned URL)Download it yourself, then use /upload
You need a MIME type that's not on the URL-fetch allowlist/upload (broader allowlist)

There's no penalty for picking the wrong one -- the response shape is identical. But /from-url is usually cheaper for you (no bytes leave your network) and benefits from per-tenant URL deduplication.

How long are attachments stored?

Attachments are deleted 90 days after their last use. Each time an attachment is referenced in a message or campaign, its "last used" timestamp is updated. Unused attachments -- those uploaded but never sent, or last sent more than 90 days ago -- become eligible for cleanup.

90-day retention

If you need to keep an attachment alive, just send it (or reference it in a campaign) at least once every 90 days. Otherwise the UUID will eventually stop resolving and message sends that reference it will fail.

You can also free storage explicitly at any time with DELETE /api/v1/attachments/{id}.

Email snapshots are independent

Attachments included on an outbound email reply are snapshotted at send time -- the email keeps its own copy of the file. So if an email goes out today and the original attachment is later deleted (by you or by 90-day retention), the email's copy remains intact and downloadable from the conversation forever.

Can I share attachments across channels?

Yes. The same UUID can be sent to a WhatsApp contact and an Email recipient (and a Telegram contact, and a Live Chat session, etc.) -- assuming the file type is supported on each channel. You don't need to re-upload per channel.

For example, an image/jpeg attachment works on WhatsApp, Telegram, Messenger, Instagram, Email and Live Chat. A video/quicktime attachment is fine on Email but may need transcoding for some channels -- see Send Media Messages for the per-channel matrix.

Can two tenants share an attachment?

No. Every attachment row carries a tenant_id and is only resolvable inside that tenant. If two tenants happen to upload the exact same bytes, they get two separate attachment records.

What does the dedup actually compare?

The full URL string, byte-for-byte (after Pydantic URL normalization), per tenant. https://x.com/a.jpg and https://x.com/a.jpg?v=2 are different URLs and dedup independently. That's the basis of the force-refresh trick.

What's the difference between download_url and public_url?

FieldAuthWhen to use
download_urlRequires messages:read (proxied through your tenant)In-app rendering for your own users / agents. Same-origin from your dashboard so cookies flow.
public_urlNone -- capability-style URL, the path UUIDs are the secret (~256 bits combined)Outbound contexts where an external service must fetch the bytes. Example: WhatsApp template image.link, third-party webhook payloads.

For sending messages via SendSeven you don't need either of these -- just pass the id in attachments[] and the channel adapter handles delivery.

Are uploads scanned for malware?

The upload pipeline enforces a magic-byte check (the file content must match the declared MIME type) and an extension blocklist (no .exe, .bat, .sh, .php, etc.). There is no AV scan today. Treat attachments accepted by the API as "well-formed media", not "verified safe".

Why was my /messages request rejected with 422 when I passed a URL?

attachments[] only accepts UUIDs. Pass URLs through POST /api/v1/attachments/from-url first, then send the returned UUID. See Use an Attachment in a Message.