Question

Using a webhook to get a Notion page body

  • 8 December 2023
  • 11 replies
  • 467 views

Userlevel 2
Badge +1

I’ve seen a feature request to have the Notion page body available as part of the update database action and that would be super handy here.

What I’ve gathered via the Notion API documentation is that it’s possible using a webhook to get the Notion page body. ChatGPT told me to use the pages endpoint but according to this page, I should be using the blocks endpoint. 

I tried the pages endpoint but for whatever reason the page ID i provided wasn’t working even though I verified it against the page ID when I looked at the page URL in my browser. I did notice that the page title was coming through in the URL so I tried including that in the get request using the pages endpoint and that still gave an error.

So I’ve tried using the page ID in the {block ID} portion of the retrieve block children endpoint (reference linked above), but that didn’t work either. I probably have the wrong ID being used.

Does anyone have any experience using Notions API to pull the Notion page body? 

I appreciate your help!


This post has been closed for comments. Please create a new post if you need help or have a question about this topic.

11 replies

Userlevel 6
Badge +8

Hi @blueprintbrian!

A couple of thoughts / questions:

  1. I believe doing what you’re trying to achieve is going to be very difficult using the Webhooks by Zapier app and would opt for using code instead, as it’s going to require looping through each of the block children (you correctly identified that that is what you need to get the content) and manipulating each one - theoretically, this could be done with Looping by Zapier, but I expect it would be pretty painful.
  2. Do you need to make updates to the same page every time or will this Zap be dynamic and make changes to many different pages throughout your Notion account?
  3. Can you please share a screenshot of the error(s) you’re getting when you run this webhook? OR copy/paste the error message so we can know what the system says is wrong?
Userlevel 2
Badge +1

@Todd Harper, thanks for the reply. 

My zap triggers from someone clicking a checkbox property on a database item. I then want to grab the body of that database item and send it somewhere else (I already figured out that part). So it’s just this part of getting the body of the database item that I need.

Userlevel 6
Badge +8

Yah, definitely possible with a code step. Below is the code I used to perform the action in this brief video. Difficult to advise on more specifics for you without screenshots or recordings of your data, how you’d like to manipulate it, and where you want it to go.

output = {};

let results = [];

const appKey = ""; // ADD YOUR OWN NOTION INTEGRATION SECRET KEY BETWEEN THE QUOTES
const pageId = ""; // ADD YOUR OWN ORIGINATING PAGE ID BETWEEN THE QUOTES
let appData = "";

try {
const appResp = await fetch(
`https://api.notion.com/v1/blocks/${pageId}/children`, {
method: 'GET',
headers: {
'Notion-Version': '2022-06-28',
'Authorization': 'Bearer ' + appKey
}
}
);

appData = await appResp.text();
appData = JSON.parse(appData);
results = appData.results;
} catch (e) {
console.log(e.message);
}

for (let i = 0; i < results.length; i++) {
const type = results[i].type;
results[i][type].rich_text[0].text.content = results[i][type].rich_text[0].text.content.replace(/\bbody\b/g, "lollapalooza");
results[i][type].rich_text[0].plain_text = results[i][type].rich_text[0].text.content;
}

try {
const appResp = await fetch(
`https://api.notion.com/v1/blocks/${pageId}/children`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'Notion-Version': '2022-06-28',
'Authorization': 'Bearer ' + appKey
},
body: JSON.stringify({
'children': results
})
}
);

appData = await appResp.text();
appData = JSON.parse(appData);
} catch (e) {
console.log(e.message);
}

 

Userlevel 2
Badge +1

Thanks again for responding.

By no means am I a software engineer, but if I understand correctly, if I define the input data as {pageID} then I can input something like 

const pageID = “{pageID}”

Would that be correct? 

I ask because the page ID comes from a previous action step.

Also, is the code you wrote in javascript? 

Userlevel 6
Badge +8

Yes, the code is Javascript :)

I would define the input data as pageId (without the curly braces and keeping the d lowercase).

Then in the code, you’ll replace the quotes for the page ID with inputData.pageId, so the full line is:

const pageId = inputData.pageId;

Note that there are no longer any quotes.

Also note that for your purposes, since you are just copy/pasting the body from one place to another, you will likely not need the for loop (the block of code seen below):

for (let i = 0; i < results.length; i++) {
const type = results[i].type;
results[i][type].rich_text[0].text.content = results[i][type].rich_text[0].text.content.replace(/\bbody\b/g, "lollapalooza");
results[i][type].rich_text[0].plain_text = results[i][type].rich_text[0].text.content;
}

Also, in the last section of code, you’ll want to replace ${pageId} with the actual ID of the page you’re copying to, as seen below. If you leave ${pageId}, you’ll just be appending it to the original page, as you saw in my demo video. If the page you’re copying to is the same every time this operation happens, that’s easy. If it’s dynamic, you’ll want to define another variable like secondPageId and add it with the dollar sign and curly braces in that block of code (ie. ${secondPageId}).

try {
const appResp = await fetch(
`https://api.notion.com/v1/blocks/id-of-page-you-are-copying-to/children`, {

 

Userlevel 2
Badge +1

You’re the man. 

I’m not actually copying the data to another page in Notion. It’s going into a note in Karbon (another software). 

So I guess I wouldn’t even need the try function?

Userlevel 6
Badge +8

Oh! In that case, you’d want to do something like this (following the first try/catch block):

output.results = "";

for (let i = 0; i < results.length; i++) {
const type = results[i].type;
if (results[i][type].rich_text.length > 0) {
output.results += `${results[i][type].rich_text[0].plain_text}\n`;
}
}

And then yes, you are correct that you could eliminate the second try/catch block :)

Userlevel 2
Badge +1

So I took your code and ran it through ChatGPT and the zap step does succeed, however, it keeps giving the following logs info based on the below code: INFO Cannot read properties of undefined (reading 'length')

I have no idea what this means 🤷

output = {};

const appKey = "my secret key"; // Your Notion integration secret key
const pageId = inputData.pageId; // Your originating page ID

try {
const appResp = await fetch(
`https://api.notion.com/v1/blocks/${pageId}/children`, {
method: 'GET',
headers: {
'Notion-Version': '2022-06-28',
'Authorization': 'Bearer ' + appKey
}
}
);

const appData = await appResp.json();
let results = appData.results;

output.results = "";

for (let i = 0; i < results.length; i++) {
const block = results[i];
if (block && block.type) {
const blockType = block.type;
const blockContent = block[blockType];

// Log the block content for debugging
console.log(`Block ${i} Type: ${blockType}`, blockContent);

if (blockContent && blockContent.hasOwnProperty('rich_text') && Array.isArray(blockContent.rich_text)) {
for (let j = 0; j < blockContent.rich_text.length; j++) {
if (blockContent.rich_text[j] && blockContent.rich_text[j].hasOwnProperty('plain_text')) {
output.results += `${blockContent.rich_text[j].plain_text}\n`;
}
}
} else {
console.log(`Block ${i} of type '${blockType}' does not have rich_text array or is not formatted as expected.`);
}
} else {
console.log(`Block ${i} is missing type or is not structured as expected.`);
}
}
} catch (e) {
console.log(e.message);
}

 

Userlevel 6
Badge +8

Can you add the following line of code just before output.results = “”; ?

output.appData = appData;

And then take screenshots of what appears under “App Data” in your test results. Note that it will include data from your document, so if there is any personally identifiable or sensitive information, please be sure to redact it before posting.

Userlevel 2
Badge +1

Object = error

Status = 404 

Code = object_not_found

Message = Could not find block with ID: “my page id”. Make sure the relevant pages and databases are shared with your integration.

Request ID = a number 

Userlevel 6
Badge +8

Ah. Okay, so Notion has a slightly inconvenient feature when it comes to automation via code. You actually need to manually share a page with the integration. Here’s a video walking you through this (along with a workaround so that you don’t need to do this manual process for every page in your database): https://www.loom.com/share/cbd0922733b04bf2b34d2e114c8e5697?sid=5b88b76a-0ac7-4287-bfcf-0ccc5655407a