May 30, 2025 by simo
If you have used the Notion API before May 2025 and needed to upload files, you found out you couldn't upload files directly; you could only link to externally hosted files (e.g., Google Drive, Dropbox, or similar file storage service).
Now, the Notion API also supports direct (and indirect) file uploads. This means you can upload files to Notion properties or blocks via the API without needing an external hosting service. It can be useful for automated workflows that involve file generation and storage. For example, automatically generating and attaching invoices to your dedicated Notion database, or uploading contract files to Notion, and all the other possible use cases you can imagine. This post explains everything you need to know about the Notion File Upload API.
There are two types of file uploads via the Notion API:
Uploaded files can be attached to file
, image
, pdf
, audio
, and video
block types. You can also set a file_upload
on a page’s cover or icon, or in files
properties in pages under a database.
Downloading a file you’ve uploaded. Aside from making the file available in the Notion app, attaching a File Upload to a page also allows you to retrieve the page in the API to get a temporary URL to access the file. After the
expiry_time
shown in the response (generally 1 hour), the page (or block, or database) must be fetched again to generate a new URL.Notion doesn’t provide any permanent download links for files you’ve uploaded.
— source: documentation
There are three steps (three API calls) to upload a file to Notion via the API:
Create a file upload: This generates a file upload ID, which you will use in the following step to upload the file to Notion. Use the mode
body parameter to define if it’s a single-part upload (file <20MB), multi-part (file >20MB), or external_url (you upload the file from an external URL). Include the other parameters based on your needs as per the documentation.
Upload the file: Now that you have the file_upload_id, you will include it in the URL for the request to upload the file to Notion. For this request, use the Content-Type
header with multipart/form-data
as its value. Include the file
parameter in the body of the request, and optionally part_number
(for multi-part uploads — i.e., files > 20MB).
Attach the file to a block/property: Use the API endpoint to update/append a block or create/update a database item and include the file data in your request. See details below.
This step uses standard Notion API endpoints; there’s no special upload-specific API for attaching. Just pass a
file
object with atype
offile_upload
and include theid
you received earlier.You can reuse the same
file_upload
ID across multiple pages or blocks. Upload once, attach many times.Files must be attached to a page or block within 1 hour of creation, or they’ll be automatically deleted.
— source: documentation
Direct upload means uploading a file directly to Notion via multipart/form-data
requests, not using an external URL. If a file is <20MB in size, you can upload it with one request. For larger files (>20MB), you will first split the file into smaller parts (Notion recommends 10MB each), and then upload it across multiple multipart/form-data
requests.
For direct uploads, the three steps written in the previous section is all you need. Here is a more detailed breakdown of each step:
Create a file upload. This generates a unique upload ID and URL, which you will use in the next request (step 2).
Example cURL:
curl --request POST \\
--url '[<https://api.notion.com/v1/file_uploads>](<https://api.notion.com/v1/file_uploads>)' \\
-H 'Authorization: Bearer ntn_****' \\
-H 'Content-Type: application/json' \\
-H 'Notion-Version: 2022-06-28' \\
--data '{}'
Upload the file. Use the upload ID or URL from step 1 to send the binary file to Notion. Make sure to include the Content-Type
header as multipart/form-data
. Include the file
key in the form fields of the request.
Example cURL:
curl --request POST \\
--url '<https://api.notion.com/v1/file_uploads/a3f9d3e2-1abc-42de-b904-badc0ffee000/send>' \\
-H 'Authorization: Bearer ntn_****' \\
-H 'Notion-Version: 2022-06-28' \\
-H 'Content-Type: multipart/form-data' \\
-F "file=@path/to-file.gif"
Attach the file to a Notion block. Do this within 1 hour from the file upload request, else the file upload will be automatically deleted.
Once the file’s
status
isuploaded
, you can attach it to Notion content using thefile_upload
ID. This ID can be passed anywhere a File object is accepted — including properties on database pages and content blocks like images or files.This step uses standard Notion API endpoints; there’s no special upload-specific API for attaching. Just pass a
file
object with atype
offile_upload
and include theid
you received earlier.— source: documentation