Skip to content

List attachments

The files that went out with a message, each with a signed link to download it.

http
GET /v1/emails/{id}/attachments

Requires a Full access API key.

Parameters

Cursor-paginated: limit (1–100, default 20), after, before.

Example

bash
curl "https://api.sendgrail.com/v1/emails/$ID/attachments" \
  -H "Authorization: Bearer $SENDGRAIL_API_KEY"
js
const res = await fetch(
  `https://api.sendgrail.com/v1/emails/${id}/attachments`,
  { headers: { Authorization: `Bearer ${process.env.SENDGRAIL_API_KEY}` } },
);
const { data } = await res.json();

// download_url needs no API key — hand it straight to a browser
const file = await fetch(data[0].download_url);

Response

json
{
  "object": "list",
  "has_more": false,
  "data": [
    {
      "id": "8e0fd050-661f-4b3c-8178-c4f291d1f751",
      "filename": "invoice.pdf",
      "content_type": "application/pdf",
      "size": 20418,
      "download_url": "https://api.sendgrail.com/v1/emails/…/download?expires=…&signature=…",
      "expires_at": "2026-07-14T10:09:15+00:00"
    }
  ]
}

The download URL

download_url is signed and short-lived (15 minutes, stated in expires_at). The signature is the authorisation — so:

  • the link carries no API key, and can be handed straight to a browser, an <img> tag, or a customer;
  • a leaked link exposes one file for fifteen minutes, not your account;
  • a tampered link is rejected with 403.

Fetch a fresh list when they expire; the ids are stable, the URLs are not.

Retention

Attachments are kept for 30 days after a send, then deleted. After that the metadata remains (you can still see what was attached) but the download returns 404 not_found.

This only affects your copy in the dashboard. The recipient's copy lives in their mailbox — it was delivered inside the message itself, and nothing we do to our storage can touch it.

Transactional email on your own domain.