How to Upload a File or Image Using the Notion API

Finn Greig

Want to add your own file or image to a database or page in Notion using their API? Unfortunately this is not (officially) supported yet:

"For files and URLs hosted outside of Notion, we support retrieving the link as well as updating it to a different link. We don't currently support uploading files to Notion through the API, however, for files already uploaded to Notion, we support retrieving the file URL." - https://developers.notion.com/reference/file-object#externally-hosted-files-vs-files-hosted-by-notion

However, there is a workaround we could use - base64 data URIs. If those work for page icons, then there's no reason why they can't work for file uploads right? Unfortunately this is not the case. When I tried using a base64 data URI directly in their API this is what I got back:

{
  "object": "error",
  "status": 400,
  "code": "validation_error",
  "message": "Content creation Failed. Fix the following: \nInvalid image url."
}

There's a workaround we can do however, which uses a low-code integration platform called Pipedream, which is similar to Zapier or Make (formerly Integromat).

Here's the workflow I'm using:

Screenshot of Pipedream workflow

The code is available here.

Here's an example of how I did it using a text file that contains "Hello World!":

  1. Upload an image to a tool like this file to base64 converter (make sure you select "Data URI" as the output format)

  2. Copy the output. It should look something like this: data:file/plain;base64,SGVsbG8gV29ybGQh

  3. Perform your API request with the data URI wrapped up with your Pipedream URL:

curl 'https://api.notion.com/v1/pages' \ -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \ -H "Content-Type: application/json" \ -H "Notion-Version: 2022-02-22" \ --data '{ "parent": { "database_id": "d9824bdc84454327be8b5b47500af6ce" }, "properties": { "Name": { "title": [ { "text": { "content": "Test" } } ] } }, "children": [ { "object": "block", "type": "file", "file": { "type": "external", "external": { "url": "https://eoz4qft7xt8bz0.m.pipedream.net/?uri=data:file/plain;base64,SGVsbG8gV29ybGQh" } } } ] }'

You should get a 200 OK:

{
  "object": "page",
  "id": "3d86e8d5-dd14-407d-a9b2-fed49233cf8d"
}

And your file should be on your page:

Screenshot of Notion page showing file inside

While the file name isn't pretty and this won't work for files that aren't small (URL length constraints), it's an easy way to get a file into Notion using only their API without touching the web application. Keep in mind however that when this file is accessed a request with the data will be made to an external server - this may or may not be suitable for your purposes.