# Create an attachment upload session

> **POST** `https://api.us.nylas.com/v3/grants/{grant_id}/attachment-uploads`

Source: https://developer.nylas.com/docs/reference/api/attachments/create-attachment-upload-session/

Create a resumable upload session for a large attachment (up to 150 MB). Returns a pre-signed URL
where you upload the file bytes directly using `PUT`.

Upload sessions expire **one hour** after creation. Once you upload the file to the returned URL,
call the [complete endpoint](/docs/reference/api/attachments/complete-attachment-upload-session/)
to finalize the upload. After completion, reference the `attachment_id` in a send or draft request.

**Supported providers:** Microsoft (Outlook / Exchange via Graph) only. Grants for Google, IMAP,
Yahoo, iCloud, and EWS are rejected with a `401 Unauthorized` error.

**Required Microsoft scopes** (at least one): `Mail.Send`, `Mail.ReadWrite`, or `Mail.ReadWrite.Shared`.

For the full flow, prerequisites, and error handling, see
[Send large attachments](/docs/v3/email/send-large-attachments/).

**Authentication:** ACCESS_TOKEN, NYLAS_API_KEY

## Parameters

### Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `grant_id` | string | Yes | The ID of the grant to create the upload session for. |

## Request body

Attachment upload session details.

Content-Type: application/json

- `filename` (string) **(required)** - The name of the file as it will appear in the email. No allowlist or sanitization is applied.
- `content_type` (string) **(required)** - The MIME type of the file (for example, `application/pdf`, `image/png`). No MIME allowlist is applied — any non-empty string is accepted and passed through to storage.
- `size` (integer) - Expected file size in bytes. Recommended — when provided, Nylas validates that the
uploaded object matches this size at completion. If omitted, the size-match check
is skipped and any non-zero upload is accepted. Maximum: `157286400` (150 MB).

## Responses

### 201 - Upload session created.

- `request_id` (string) - The request ID.
- `data` (object)
  - `attachment_id` (string) - Unique identifier for the upload session (UUID v4). Use this value when completing the session and when referencing the attachment in a send or draft.
  - `method` (string) - The HTTP method to use when uploading the file to `url`. Always `PUT`.
  - `url` (string) - Google Cloud Storage resumable upload URL. `PUT` the file bytes directly here — no Nylas authorization header is required, because this is a GCS-signed URL.
  - `headers` (object) - Headers to include when uploading to `url`.
  - `expires_at` (string) - When the upload session expires (RFC 3339). One hour from creation by default.
  - `max_size` (integer) - Maximum allowed file size in bytes.
  - `size` (integer) - Expected file size in bytes, echoing the request. `0` if `size` was not provided on session creation.
  - `content_type` (string) - MIME type of the file.
  - `filename` (string) - Name of the file.
  - `grant_id` (string) - The grant ID the upload session belongs to.

### 400 - Bad request. Returned when `filename` or `content_type` is missing, when `size` is
negative or zero, when `size` exceeds the 150 MB maximum, or when the request body is not valid JSON.

- `request_id` (string)
- `error` (object)
  - `type` (string)
  - `message` (string)

### 401 - Unauthorized. Returned when the grant cannot be resolved, the provider is not Microsoft,
or the grant lacks the required scopes (`Mail.Send`, `Mail.ReadWrite`, or `Mail.ReadWrite.Shared`).

- `request_id` (string)
- `error` (object)
  - `type` (string)
  - `message` (string)

### 500 - Internal error. Returned on storage or database failures (for example, the GCS resumable upload URL could not be initiated).

- `request_id` (string)
- `error` (object)
  - `type` (string)
  - `message` (string)

## Code samples

### cURL

```bash
curl --request POST \
  --url 'https://api.us.nylas.com/v3/grants/<GRANT_ID>/attachment-uploads' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer <NYLAS_API_KEY_OR_ACCESS_TOKEN>' \
  --data-raw '{
    "filename": "document.pdf",
    "content_type": "application/pdf",
    "size": 1048576
  }'
```

### Node.js SDK

```javascript
import Nylas from "nylas";

const nylas = new Nylas({
  apiKey: "<NYLAS_API_KEY>",
  apiUri: "<NYLAS_API_URI>",
});

async function createUploadSession() {
  try {
    const session = await nylas.attachments.createUploadSession({
      identifier: "<NYLAS_GRANT_ID>",
      requestBody: {
        filename: "quarterly-report.pdf",
        contentType: "application/pdf",
        size: 5242880,
      },
    });

    console.log("Upload session:", session);
  } catch (error) {
    console.error("Error creating upload session:", error);
  }
}

createUploadSession();

```
