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

---
id: 6b3d6fe1-df93-485b-91ab-a9df45472afb
---

# Files API

> Learn how to upload and manage files in your HubSpot account using the files API.

export const Tag = ({children, type = 'default', className = ''}) => {
  return <span className={`tag tag-${type} ${className}`.trim()}>
      {children}
    </span>;
};

export const ScopesList = ({scopes = [], description = "This API requires one of the following scopes:"}) => {
  if (!scopes || scopes.length === 0) {
    return null;
  }
  const sortedScopes = scopes.sort((a, b) => a.localeCompare(b));
  return <div>
      <div className="text-sm mb-2">{description}</div>
      <div>
        {sortedScopes.map((scope, index) => <div key={index}>
            <code>
              <span className="text-xs">{scope}</span>
            </code>
          </div>)}
      </div>
    </div>;
};

<Accordion title="Scope requirements">
  <ScopesList
    scopes={[
  'files',
  'files.ui_hidden.read'
]}
  />
</Accordion>

Use HubSpot's files tool to store files in HubSpot for both internal and external use. For example, you can use the files tools to:

* Insert uploaded images into content such as emails, blog posts, and website pages.
* [Attach files to records using the notes APIs](#attach-a-file-to-a-record).
* Store branding assets, such as logos, icons, and banners.

You can access the files tool from [within HubSpot](https://knowledge.hubspot.com/files/upload-files-to-use-in-your-hubspot-content) or via the files API. Learn more about [supported file types and sizes](https://knowledge.hubspot.com/files/supported-file-types), including compatibility with other HubSpot tools.

## Upload a file

Files can be uploaded using a multipart/form-data `POST` request to `files/2026-03/files` with the following fields. While a specific folder ID is not required at upload, it's recommended to upload files into a folder and not the root directory. Folder requirements at upload are subject to change.

| Field                                   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `file` <Tag type="error">Required</Tag> | The file to upload. Uploaded files are subject to the limits and supported formats outlined in [this Knowledge Base article](https://knowledge.hubspot.com/files/supported-file-types).                                                                                                                                                                                                                                                                                                                                                                     |
| `options`                               | A JSON object that controls the file's privacy and whether it can be indexed by search engines. This field contains two sub-properties: `access`, which is required, and `ttl`, which specifies a time period after which the file will be automatically deleted. If you're using the `ttl` field:<ul><li>The minimum period that must be set is 1 day.</li><li>The maximum period that can be set is 1 year.</li><li>After the set period, the file will be permanently deleted. After deletion, the file cannot be recovered or restored.</li></ul><br /> |
| `folderId`                              | The ID of the folder that the file will be uploaded to. Either this field <u>or</u> `folderPath` must be provided in your request (but <u>not</u> both).                                                                                                                                                                                                                                                                                                                                                                                                    |
| `folderPath`                            | The path of the folder that the file will be uploaded to. Either this field <u>or</u> `folderId` must be provided in your request (but <u>not</u> both).                                                                                                                                                                                                                                                                                                                                                                                                    |
| `fileName`                              | The name of the file. If no name is specified, a name will be generated from the file's content.                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `charsetHunch`                          | Character set encoding for the uploaded file. If not provided, it will be derived from the file.                                                                                                                                                                                                                                                                                                                                                                                                                                                            |

As an example, if you wanted to upload a file with the following criteria to your HubSpot account:

* **File name:** `cat.png`
* **Destination folder in the HubSpot file manager:** `/library/cat_archive`
* **File accessibility in HubSpot:** privately accessible

The following headers and request body would need to be part of your request:

```shell theme={null}
curl --request POST \
  --url 'https://api.hubapi.com/files/2026-03/files?=' \
  --header 'Authorization: Bearer pat-na1-00000000-0000-0000-0000-000000000000' \
  --header 'Content-type: multipart/form-data' \
  --form file=@/Users/person/Downloads/cat.png \
  --form 'options={"access": "PRIVATE"}' \
  --form folderPath=/library/cat_archive
```

A successful `201` response will include the `id` and `parentFolderId` of the uploaded file, which you can use to retrieve the file via a `GET` request.

```json theme={null}
{
  "id": "122692044085",
  "createdAt": "2023-06-28T17:56:45.393Z",
  "updatedAt": "2023-06-28T17:56:45.393Z",
  "archived": false,
  "parentFolderId": "122692510820",
  "name": "cat",
  "path": "/library/cat_archive/cat.png",
  "size": 24574,
  "height": 219,
  "width": 225,
  "encoding": "png",
  "type": "IMG",
  "extension": "png",
  "defaultHostingUrl": "https://12345.fs1.hubspotusercontent-na1.net/hubfs/12345/library/cat_archive/cat.png",
  "url": "https://12345.fs1.hubspotusercontent-na1.net/hubfs/12345/library/cat_archive/cat.png",
  "isUsableInContent": true,
  "access": "PRIVATE"
}
```

## Retrieve a file

To download a file from the file manager, send a `GET` request to `/v3/files/{fileId}/download`. When using this endpoint, the file will be downloaded as a direct download attachment.

Generally, it is recommended to use this endpoint to download [files with sensitive data](https://knowledge.hubspot.com/account-security/store-sensitive-data) from HubSpot to your integration or private app. For other file types:

* If you have a file with public visibility, it is recommended to use the public file URL to access or download the file. This can be retrieved from the [file metadata](https://developers.hubspot.com/docs/api-reference/latest/cms/source-code/get-file-metadata).
* If you have a file with private visibility, it is recommended to retrieve the [signed URL](https://developers.hubspot.com/docs/api-reference/legacy/files/files/get-signed-url) to access or download the file.

When using this endpoint, the following error responses may be returned:

* If a file is missing or a fetch error has occurred, a `404` error response will be returned.
* If a file download has exceeded the permitted rate limit, a `429` error response will be returned.
* If a private app or integration does not have the required scopes, a `403` error response will be returned. To use this endpoint with sensitive data, the private app or integration will need the `FILE_MANAGER_SENSITIVE_ACCESS` scope.

## Check a file's upload status

If you're importing a file from a URL to your file manager using a `POST` request to `files/2026-03/files/import-from-url/async`, you can review the upload status of the file.

To do so, use a `GET` request to `files/2026-03/files/import-from-url/async/tasks/{taskId}/status`.

After making this request, you'll receive one of the following replies:

* `PENDING`: the file is in the queue to be uploaded. The import process has not yet started.
* `PROCESSING`: the file is in the process of being uploaded.
* `CANCELED`: the upload has been canceled and the file will not be uploaded. To import the file to your HubSpot account, you'll need to upload the file again.
* `COMPLETE`: the file has been uploaded to the files tool successfully. The uploaded file will appear in your files tool.

## View a file's details

To review the details of a file that's been uploaded to the files tool, make a `GET` request to `files/2026-03/files/{fileId}`. This will return the file with details such as name, height and width, encoding, the URL, and more.

If a file is set to private, the returned URL will result in a `404` error. To get a viewable URL of the file, you can make a `GET` request to `/files/2026-03/files/{fileId}/signed-url`. When making this request, you can include `property` parameters to return specific properties such as height and width.

## Update a file

To replace an existing file with new file data, make a `PUT` request to `/files/2026-03/files/{fileId}`. For example, you can use this endpoint to change image content rather than having to upload a new file and update that file's references in your content.

To update file properties on an existing file, make a `PATCH` request to `/files/2026-03/files/{fileId}`. You can update properties such as the file name. However, you cannot update the create date of a file. By default, `createdAt` will always reflect the date that the file was originally created in HubSpot.

## Delete a file

To delete a file, make a `DELETE` request to `/files/2026-03/files/{fileId}`. This will mark the file as deleted and make the content of the file inaccessible.

To permanently delete a file using a GDPR-compliant delete, make a `DELETE` request to `/files/2026-03/files/{fileId}/gdpr-delete`. This will permanently delete the file's content and metadata within 7 days.

If a file is not GDPR deleted, its contents will remain on HubSpot's servers in a private state where no one can access it. To ensure file contents are fully deleted, use the GDPR delete functionality.

## Create a folder

To create a folder, make a `POST` request to `files/2026-03/folders`. When making the request, you can include the fields provided in the table below.

| Field                                   | Type   | Description                                                                                                                                                                 |
| --------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name` <Tag type="error">Required</Tag> | String | Name of the folder you want to create.                                                                                                                                      |
| `parentFolderId`                        | String | To create the folder within an existing folder, include this field with the existing folder's ID. `parentFolderId` and `parentFolderPath` cannot be set at the same time.   |
| `parentFolderPath`                      | String | To create the folder within an existing folder, include this field with the existing folder's path. `parentFolderId` and `parentFolderPath` cannot be set at the same time. |

For example, a `POST` request to `/files/2026-03/folders` with the following request body would create a new folder called "myNewFolder" in the parent folder with an ID of `12345`.

```json theme={null}
{
  "name": "myNewFolder",
  "parentFolderId": 12345
}
```

## Attach a file to a record

When you [add a file to a record in HubSpot](https://knowledge.hubspot.com/records/add-and-remove-attachments-from-records), it creates a note with the file attached and adds it to the record timeline. To add a file to a record via API, you can [create a note](/api-reference/latest/crm/activities/notes/guide) associated with a record and attach the file to the note.

1. [Upload the file](#upload-a-file) to the file manager. Copy the `id` value from the response as it'll be used to attach the file to the note.
2. Retrieve the `associationTypeId` for the object and notes. You'll use this ID to associate the record when creating the note. For default objects, you can refer to [this list of type IDs for note associations](/api-reference/latest/crm/associations/associate-records/guide#note-to-object). For objects not listed, you can make a `GET` request to `/crm/associations/2026-03/notes/{toObjectType}/labels` and copy the `typeId` from the response.
3. Retrieve the record ID (`hs_object_id`) of the record to which you want to attach the file. Use the [objects API](/guides/crm/using-object-apis#retrieve-records) to retrieve records.
4. Create a note, associate it with a record, and attach the file. Make a `POST` request to `/crm/objects/2026-03/notes`. In the request body, include an `associations` object with the `id` of the record to associate with the note, and a `properties` object with the `id` of the file to attach.

For example, to attach a file to a note on a contact record, you'd make a `POST` request to `/crm/objects/2026-03/notes` with the following request body:

```json theme={null}
{
  "associations": [
    {
      "to": {
        "id": "{hs_object_id}"
      },
      "types": [
        {
          "associationCategory": "HUBSPOT_DEFINED",
          "associationTypeId": 202
        }
      ]
    }
  ],
  "properties": {
    "hs_note_body": "Example note",
    "hs_timestamp": "2021-11-12T15:48:22Z",
    "hs_attachment_ids": "{fileId}"
  }
}
```

## Changes in v3

If you've been using the previous version of this API, v3 has the following changes:

* All files uploaded through the API will be visible in the files dashboard and the files picker. Hidden files cannot be created. However, private files and non-indexable files can still be created.
* Listing files will not return hidden or deleted files. However, a much broader range of filters can be applied. Hidden files can still be fetched by ID, but require a new scope: `files_ui_hidden.read`.
* Multiple files cannot be uploaded with a single request.
* Folder update actions like moving and renaming are now asynchronous. Each request will return a token that can be used to check the status of the folder edit.
* Endpoints that create or replace files require you to provide access levels for the files. These access levels are:
  * `PUBLIC_INDEXABLE`**:** file is publicly accessible by anyone who has the URL. Search engines can index the file.
  * `PUBLIC_NOT_INDEXABLE`**:** file is publicly accessible by anyone who has the URL. The X-Robots-Tag: noindex header will be sent whenever the file is retrieved, instructing search engines not to index the file.
  * **`PRIVATE`:** file is not publicly accessible. Requires a signed URL to display content. Search engines cannot index the file.
* Endpoints that create files allow for a level of duplicate detections as part of the file's upload options.

  * `ENTIRE_PORTAL`**:** search for a duplicate file in the account.
  * `EXACT_FOLDER`**:** search for a duplicate file in the provided folder.
  * `NONE`**:** do not run any duplicate validation.
  * `REJECT`**:** reject the upload if a duplicate is found.
  * `RETURN_EXISTING`**:** if a duplicate file is found, do not upload a new file and return the found duplicate instead.
  * Duplicate detection works on a `duplicateValidationScope`, which affects how we search for a duplicate.
  * This also requires a `duplicateValidationStrategy`, which dictates what happens if a duplicate is found.
