> ## Documentation Index
> Fetch the complete documentation index at: https://docs.autosend.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Download Attachment

> Retrieves a single attachment from an inbound message, referenced by its attachmentId or zero-based index. By default returns JSON metadata with a short-lived pre-signed download URL; pass download=true to stream the raw attachment bytes with the appropriate Content-Type and Content-Disposition headers.

<Note>
  This endpoint uses a standard **project API key** (`AS_` prefix). It returns a single attachment from an inbound message, identified either by its `attachmentId` (recommended, stable) or by its zero-based `index` from the message's `attachments` array.

  By default it returns **JSON metadata** with a short-lived, pre-signed download URL. Pass `?download=true` to stream the **raw bytes** instead, with `Content-Type` and `Content-Disposition: attachment; filename="…"` headers.
</Note>

<RequestExample>
  ```bash cURL (JSON) theme={null}
  curl --request GET \
    --url https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/att_60d5ec49f1b2c72d9c8b9999 \
    --header 'Authorization: Bearer as_your-api-key'
  ```

  ```python Python (JSON) theme={null}
  import requests

  url = "https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/att_60d5ec49f1b2c72d9c8b9999"

  headers = {
      "Authorization": "Bearer as_your-api-key"
  }

  response = requests.get(url, headers=headers)
  data = response.json()

  # Follow the pre-signed URL to download the file (no auth header needed).
  file_url = data["data"]["downloadUrl"]
  file = requests.get(file_url)
  with open(data["data"]["filename"], "wb") as f:
      f.write(file.content)
  ```

  ```javascript JavaScript (JSON) theme={null}
  const response = await fetch(
    'https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/att_60d5ec49f1b2c72d9c8b9999',
    {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer as_your-api-key'
      }
    }
  );

  const { data } = await response.json();

  // Follow the pre-signed URL to download the file (no auth header needed).
  const file = await fetch(data.downloadUrl);
  const blob = await file.blob();
  // Save or process the blob as needed
  ```

  ```bash cURL (stream) theme={null}
  curl --request GET \
    --url 'https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/0?download=true' \
    --header 'Authorization: Bearer as_your-api-key' \
    --output receipt.pdf
  ```

  ```python Python (stream) theme={null}
  import requests

  url = "https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/0"

  headers = {
      "Authorization": "Bearer as_your-api-key"
  }

  response = requests.get(url, headers=headers, params={"download": "true"})
  with open("receipt.pdf", "wb") as f:
      f.write(response.content)
  ```

  ```javascript JavaScript (stream) theme={null}
  const response = await fetch(
    'https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/0?download=true',
    {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer as_your-api-key'
      }
    }
  );

  const blob = await response.blob();
  // Save or process the blob as needed
  ```

  ```php PHP (stream) theme={null}
  <?php

  $messageId = '60d5ec49f1b2c72d9c8b1234';
  $index = 0;
  $url = "https://api.autosend.com/v1/inbound/messages/{$messageId}/attachments/{$index}?download=true";

  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'Authorization: Bearer as_your-api-key'
  ]);

  $content = curl_exec($ch);
  curl_close($ch);

  file_put_contents('receipt.pdf', $content);
  ?>
  ```

  ```go Go (stream) theme={null}
  package main

  import (
      "fmt"
      "io"
      "net/http"
      "os"
  )

  func main() {
      url := "https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/0?download=true"

      req, _ := http.NewRequest("GET", url, nil)
      req.Header.Set("Authorization", "Bearer as_your-api-key")

      client := &http.Client{}
      resp, err := client.Do(req)
      if err != nil {
          fmt.Println("Error:", err)
          return
      }
      defer resp.Body.Close()

      out, _ := os.Create("receipt.pdf")
      defer out.Close()
      io.Copy(out, resp.Body)
  }
  ```

  ```java Java (stream) theme={null}
  import java.io.InputStream;
  import java.io.FileOutputStream;
  import java.net.HttpURLConnection;
  import java.net.URL;

  public class DownloadAttachment {
      public static void main(String[] args) {
          try {
              URL url = new URL("https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/0?download=true");
              HttpURLConnection con = (HttpURLConnection) url.openConnection();

              con.setRequestMethod("GET");
              con.setRequestProperty("Authorization", "Bearer as_your-api-key");

              try (InputStream in = con.getInputStream();
                   FileOutputStream out = new FileOutputStream("receipt.pdf")) {
                  byte[] buffer = new byte[8192];
                  int n;
                  while ((n = in.read(buffer)) != -1) {
                      out.write(buffer, 0, n);
                  }
              }
              con.disconnect();
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  ```

  ```ruby Ruby (stream) theme={null}
  require 'net/http'
  require 'uri'

  uri = URI('https://api.autosend.com/v1/inbound/messages/60d5ec49f1b2c72d9c8b1234/attachments/0?download=true')

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true

  request = Net::HTTP::Get.new(uri)
  request['Authorization'] = 'Bearer as_your-api-key'

  response = http.request(request)
  File.open('receipt.pdf', 'wb') { |f| f.write(response.body) }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Response (JSON) theme={null}
  {
    "success": true,
    "data": {
      "attachmentId": "att_60d5ec49f1b2c72d9c8b9999",
      "filename": "receipt.pdf",
      "contentType": "application/pdf",
      "size": 20480,
      "downloadUrl": "https://s3.amazonaws.com/autosend-inbound/attachments/60d5ec49f1b2c72d9c8b1234/att_60d5ec49f1b2c72d9c8b9999.pdf?X-Amz-Signature=...",
      "expiresIn": 900
    }
  }
  ```

  ```text 200 Response (?download=true) theme={null}
  <binary attachment content>

  Content-Type: application/pdf
  Content-Disposition: attachment; filename="receipt.pdf"
  ```
</ResponseExample>

***

#### Authorizations

<ParamField path="Authorizations" type="string | header" required>
  Project API key header of the form Bearer `as_<key>`. You can also pass the key via the `x-api-key` header.
</ParamField>

### Path Parameters

<ParamField path="id" type="string" required>
  The unique identifier of the inbound message. The message must belong to the authenticated project.

  Example: `"60d5ec49f1b2c72d9c8b1234"`
</ParamField>

<ParamField path="idx" type="string" required>
  Identifies the attachment. Accepts either the attachment's `attachmentId` (recommended, stable across requests, e.g. `att_60d5ec49f1b2c72d9c8b9999`) or a zero-based index into the message's `attachments` array (back-compat, e.g. `0`).

  Example: `att_60d5ec49f1b2c72d9c8b9999`
</ParamField>

### Query Parameters

<ParamField query="download" type="boolean" default={false}>
  Controls the response format.

  * `false` (default): returns JSON metadata with a short-lived, pre-signed `downloadUrl`.
  * `true`: streams the raw attachment bytes with `Content-Type` and `Content-Disposition` headers.
</ParamField>

#### Response

<span className="text-sm">Attachment metadata retrieved successfully. With `?download=true`, the body is instead the raw binary content and the `Content-Type` and `Content-Disposition` response headers describe the file.</span>

<ResponseField name="success" type="boolean">
  Indicates if the request was successful

  Example: `true`
</ResponseField>

<ResponseField name="data" type="object">
  Attachment metadata and download URL

  <Expandable title="child attributes">
    <ResponseField name="data.attachmentId" type="string">
      Stable identifier for this attachment. Use it as the `{idx}` path parameter for repeatable references.
    </ResponseField>

    <ResponseField name="data.filename" type="string">
      Original file name of the attachment.
    </ResponseField>

    <ResponseField name="data.contentType" type="string">
      MIME type of the attachment (e.g. `application/pdf`).
    </ResponseField>

    <ResponseField name="data.size" type="integer">
      Size of the attachment in bytes.
    </ResponseField>

    <ResponseField name="data.downloadUrl" type="string">
      Pre-signed URL to download the file. It requires no authentication header and downloads with the correct filename. Treat it as short-lived and single-use; request a fresh one once it expires.
    </ResponseField>

    <ResponseField name="data.expiresIn" type="integer">
      Number of seconds the `downloadUrl` stays valid. Currently `900` (15 minutes).
    </ResponseField>
  </Expandable>
</ResponseField>

#### Error Responses

<ResponseField name="400 - Invalid parameters" type="object">
  Returned when `id` is not valid or `idx` is neither a non-negative integer nor a valid `attachmentId`.

  ```json theme={null}
  {
    "success": false,
    "error": {
        "message": "Invalid value",
      }
    
  }
  ```
</ResponseField>

<ResponseField name="404 - Message not found (INBOUND_EMAIL_NOT_FOUND)" type="object">
  Returned when the message does not exist or does not belong to the authenticated project.

  ```json theme={null}
  {
    "success": false,
    "error": {
      "message": "Inbound email not found"
    }
  }
  ```
</ResponseField>

<ResponseField name="404 - Attachment not found (ATTACHMENT_NOT_FOUND)" type="object">
  Returned when no attachment matches the given `attachmentId` or index.

  ```json theme={null}
  {
    "success": false,
    "error": {
      "message": "Attachment not found"
    }
  }
  ```
</ResponseField>

<ResponseField name="404 - Raw MIME not available (RAW_MIME_NOT_AVAILABLE)" type="object">
  Returned when the message's raw MIME source is not yet stored (the message may still be processing), so the attachment cannot be produced.

  ```json theme={null}
  {
    "success": false,
    "error": {
      "message": "Raw MIME is not yet available for this message"
    }
  }
  ```
</ResponseField>

<ResponseField name="500 - Download failed (INBOUND_DOWNLOAD_ATTACHMENT_FAILED)" type="object">
  Returned when an unexpected error occurs while producing the download URL or streaming the attachment.

  ```json theme={null}
  {
    "success": false,
    "error": {
      "message": "Failed to download attachment. Please try again."
    }
  }
  ```
</ResponseField>


## OpenAPI

````yaml GET /inbound/messages/{id}/attachments/{idx}
openapi: 3.1.0
info:
  title: AutoSend API
  description: >-
    AutoSend REST API for reading and replying to inbound emails received on a
    project's inbound-enabled domains. These endpoints use a standard project
    API key (AS_ prefix).
  version: 1.0.0
servers:
  - url: https://api.autosend.com/v1
security:
  - bearerAuth: []
paths:
  /inbound/messages/{id}/attachments/{idx}:
    get:
      summary: Download Attachment
      description: >-
        Retrieves a single attachment from an inbound message, referenced by its
        attachmentId or zero-based index. By default returns JSON metadata with
        a short-lived pre-signed download URL; pass download=true to stream the
        raw attachment bytes with the appropriate Content-Type and
        Content-Disposition headers.
components: {}

````