Create/Update Notion Content
Create a page, database entry, inline database, or update existing content
Source Code
import fs from "fs";
const [parentType, parentOrPageId, propertiesJson, contentPath = ""] =
process.argv.slice(2);
if (
!parentType ||
!["database", "page", "inline_database", "update"].includes(parentType)
) {
console.error(
"Error: parentType must be 'database', 'page', 'inline_database', or 'update'"
);
process.exit(1);
}
if (!parentOrPageId) {
console.error("Error: parentOrPageId is required");
process.exit(1);
}
if (!propertiesJson) {
console.error("Error: propertiesJson is required");
process.exit(1);
}
let properties;
try {
properties = JSON.parse(propertiesJson);
} catch (e) {
console.error("Error parsing properties JSON:", e.message);
process.exit(1);
}
let blocks = [];
if (contentPath) {
try {
const contentData = fs.readFileSync(contentPath, "utf-8");
blocks = JSON.parse(contentData);
if (!Array.isArray(blocks)) {
blocks = [blocks];
}
} catch (e) {
console.error(`Error reading content file: ${e.message}`);
process.exit(1);
}
}
const NOTION_API = "https://api.notion.com/v1";
const headers = {
Authorization: "Bearer PLACEHOLDER_TOKEN",
"Content-Type": "application/json",
"Notion-Version": "2022-06-28",
};
try {
let result;
if (parentType === "update") {
// Update existing page
console.log(`Updating page ${parentOrPageId}...`);
const updateBody = { properties };
// Handle icon if provided
if (properties.icon) {
updateBody.icon = { type: "emoji", emoji: properties.icon };
delete updateBody.properties.icon;
}
const res = await fetch(`${NOTION_API}/pages/${parentOrPageId}`, {
method: "PATCH",
headers,
body: JSON.stringify(updateBody),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Update failed: ${res.status}`);
console.error(errorText);
throw new Error(`Update failed: ${res.status}`);
}
result = await res.json();
// Append blocks if provided
if (blocks.length > 0) {
console.log(` Appending ${blocks.length} blocks...`);
const appendRes = await fetch(
`${NOTION_API}/blocks/${parentOrPageId}/children`,
{
method: "PATCH",
headers,
body: JSON.stringify({ children: blocks }),
}
);
if (!appendRes.ok) {
console.error(`Warning: Failed to append blocks: ${appendRes.status}`);
}
}
console.log(`✓ Updated page`);
} else if (parentType === "database") {
// Create entry in database
console.log(`Creating entry in database ${parentOrPageId}...`);
const body = {
parent: { database_id: parentOrPageId },
properties,
};
if (blocks.length > 0) {
body.children = blocks;
console.log(` With ${blocks.length} content blocks`);
}
const res = await fetch(`${NOTION_API}/pages`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Create failed: ${res.status}`);
console.error(errorText);
throw new Error(`Create failed: ${res.status}`);
}
result = await res.json();
console.log(`✓ Created database entry`);
} else if (parentType === "inline_database") {
// Create inline database under a page
const title = properties.title || "Untitled Database";
console.log(
`Creating inline database "${title}" under ${parentOrPageId}...`
);
// properties.schema defines the database columns
// Format: { "Column Name": { type: "select", options: [...] }, ... }
const schema = properties.schema || {};
// Build database properties from schema
const dbProperties = {
// Title column is required
Name: { title: {} },
};
for (const [colName, colDef] of Object.entries(schema)) {
if (colName === "Name") continue; // Skip, already added
switch (colDef.type) {
case "text":
case "rich_text":
dbProperties[colName] = { rich_text: {} };
break;
case "number":
dbProperties[colName] = {
number: { format: colDef.format || "number" },
};
break;
case "select":
dbProperties[colName] = {
select: {
options: (colDef.options || []).map((opt) =>
typeof opt === "string" ? { name: opt } : opt
),
},
};
break;
case "multi_select":
dbProperties[colName] = {
multi_select: {
options: (colDef.options || []).map((opt) =>
typeof opt === "string" ? { name: opt } : opt
),
},
};
break;
case "status":
dbProperties[colName] = { status: {} };
break;
case "date":
dbProperties[colName] = { date: {} };
break;
case "checkbox":
dbProperties[colName] = { checkbox: {} };
break;
case "url":
dbProperties[colName] = { url: {} };
break;
case "email":
dbProperties[colName] = { email: {} };
break;
case "phone_number":
dbProperties[colName] = { phone_number: {} };
break;
default:
dbProperties[colName] = { rich_text: {} };
}
}
const body = {
parent: { page_id: parentOrPageId },
title: [{ type: "text", text: { content: title } }],
properties: dbProperties,
is_inline: true,
};
if (properties.icon) {
body.icon = { type: "emoji", emoji: properties.icon };
}
const res = await fetch(`${NOTION_API}/databases`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Create failed: ${res.status}`);
console.error(errorText);
throw new Error(`Create failed: ${res.status}`);
}
result = await res.json();
console.log(`✓ Created inline database`);
} else {
// Create page under parent page
const title = properties.title || "Untitled";
console.log(`Creating page "${title}" under ${parentOrPageId}...`);
const body = {
parent: { page_id: parentOrPageId },
properties: {
title: {
title: [{ text: { content: title } }],
},
},
};
if (properties.icon) {
body.icon = { type: "emoji", emoji: properties.icon };
}
if (blocks.length > 0) {
body.children = blocks;
console.log(` With ${blocks.length} content blocks`);
}
const res = await fetch(`${NOTION_API}/pages`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Create failed: ${res.status}`);
console.error(errorText);
throw new Error(`Create failed: ${res.status}`);
}
result = await res.json();
console.log(`✓ Created page`);
}
// Extract title from result
let title;
if (parentType === "inline_database") {
// Database title is in result.title array
title = result.title?.[0]?.plain_text || "Untitled Database";
} else {
// Page title is in properties
const titleProp = Object.values(result.properties || {}).find(
(p) => p.type === "title"
);
title = titleProp?.title?.[0]?.plain_text || "Untitled";
}
console.log(` Title: ${title}`);
console.log(` URL: ${result.url}`);
console.log(` ID: ${result.id}`);
console.log(
JSON.stringify({
success: true,
action: parentType === "update" ? "updated" : "created",
parentType,
id: result.id,
url: result.url,
title,
blocksAdded: blocks.length,
})
);
} catch (error) {
console.error("Error:", error.message);
throw error;
} import fs from "fs";
const [parentType, parentOrPageId, propertiesJson, contentPath = ""] =
process.argv.slice(2);
if (
!parentType ||
!["database", "page", "inline_database", "update"].includes(parentType)
) {
console.error(
"Error: parentType must be 'database', 'page', 'inline_database', or 'update'"
);
process.exit(1);
}
if (!parentOrPageId) {
console.error("Error: parentOrPageId is required");
process.exit(1);
}
if (!propertiesJson) {
console.error("Error: propertiesJson is required");
process.exit(1);
}
let properties;
try {
properties = JSON.parse(propertiesJson);
} catch (e) {
console.error("Error parsing properties JSON:", e.message);
process.exit(1);
}
let blocks = [];
if (contentPath) {
try {
const contentData = fs.readFileSync(contentPath, "utf-8");
blocks = JSON.parse(contentData);
if (!Array.isArray(blocks)) {
blocks = [blocks];
}
} catch (e) {
console.error(`Error reading content file: ${e.message}`);
process.exit(1);
}
}
const NOTION_API = "https://api.notion.com/v1";
const headers = {
Authorization: "Bearer PLACEHOLDER_TOKEN",
"Content-Type": "application/json",
"Notion-Version": "2022-06-28",
};
try {
let result;
if (parentType === "update") {
// Update existing page
console.log(`Updating page ${parentOrPageId}...`);
const updateBody = { properties };
// Handle icon if provided
if (properties.icon) {
updateBody.icon = { type: "emoji", emoji: properties.icon };
delete updateBody.properties.icon;
}
const res = await fetch(`${NOTION_API}/pages/${parentOrPageId}`, {
method: "PATCH",
headers,
body: JSON.stringify(updateBody),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Update failed: ${res.status}`);
console.error(errorText);
throw new Error(`Update failed: ${res.status}`);
}
result = await res.json();
// Append blocks if provided
if (blocks.length > 0) {
console.log(` Appending ${blocks.length} blocks...`);
const appendRes = await fetch(
`${NOTION_API}/blocks/${parentOrPageId}/children`,
{
method: "PATCH",
headers,
body: JSON.stringify({ children: blocks }),
}
);
if (!appendRes.ok) {
console.error(`Warning: Failed to append blocks: ${appendRes.status}`);
}
}
console.log(`✓ Updated page`);
} else if (parentType === "database") {
// Create entry in database
console.log(`Creating entry in database ${parentOrPageId}...`);
const body = {
parent: { database_id: parentOrPageId },
properties,
};
if (blocks.length > 0) {
body.children = blocks;
console.log(` With ${blocks.length} content blocks`);
}
const res = await fetch(`${NOTION_API}/pages`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Create failed: ${res.status}`);
console.error(errorText);
throw new Error(`Create failed: ${res.status}`);
}
result = await res.json();
console.log(`✓ Created database entry`);
} else if (parentType === "inline_database") {
// Create inline database under a page
const title = properties.title || "Untitled Database";
console.log(
`Creating inline database "${title}" under ${parentOrPageId}...`
);
// properties.schema defines the database columns
// Format: { "Column Name": { type: "select", options: [...] }, ... }
const schema = properties.schema || {};
// Build database properties from schema
const dbProperties = {
// Title column is required
Name: { title: {} },
};
for (const [colName, colDef] of Object.entries(schema)) {
if (colName === "Name") continue; // Skip, already added
switch (colDef.type) {
case "text":
case "rich_text":
dbProperties[colName] = { rich_text: {} };
break;
case "number":
dbProperties[colName] = {
number: { format: colDef.format || "number" },
};
break;
case "select":
dbProperties[colName] = {
select: {
options: (colDef.options || []).map((opt) =>
typeof opt === "string" ? { name: opt } : opt
),
},
};
break;
case "multi_select":
dbProperties[colName] = {
multi_select: {
options: (colDef.options || []).map((opt) =>
typeof opt === "string" ? { name: opt } : opt
),
},
};
break;
case "status":
dbProperties[colName] = { status: {} };
break;
case "date":
dbProperties[colName] = { date: {} };
break;
case "checkbox":
dbProperties[colName] = { checkbox: {} };
break;
case "url":
dbProperties[colName] = { url: {} };
break;
case "email":
dbProperties[colName] = { email: {} };
break;
case "phone_number":
dbProperties[colName] = { phone_number: {} };
break;
default:
dbProperties[colName] = { rich_text: {} };
}
}
const body = {
parent: { page_id: parentOrPageId },
title: [{ type: "text", text: { content: title } }],
properties: dbProperties,
is_inline: true,
};
if (properties.icon) {
body.icon = { type: "emoji", emoji: properties.icon };
}
const res = await fetch(`${NOTION_API}/databases`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Create failed: ${res.status}`);
console.error(errorText);
throw new Error(`Create failed: ${res.status}`);
}
result = await res.json();
console.log(`✓ Created inline database`);
} else {
// Create page under parent page
const title = properties.title || "Untitled";
console.log(`Creating page "${title}" under ${parentOrPageId}...`);
const body = {
parent: { page_id: parentOrPageId },
properties: {
title: {
title: [{ text: { content: title } }],
},
},
};
if (properties.icon) {
body.icon = { type: "emoji", emoji: properties.icon };
}
if (blocks.length > 0) {
body.children = blocks;
console.log(` With ${blocks.length} content blocks`);
}
const res = await fetch(`${NOTION_API}/pages`, {
method: "POST",
headers,
body: JSON.stringify(body),
});
if (!res.ok) {
const errorText = await res.text();
console.error(`Create failed: ${res.status}`);
console.error(errorText);
throw new Error(`Create failed: ${res.status}`);
}
result = await res.json();
console.log(`✓ Created page`);
}
// Extract title from result
let title;
if (parentType === "inline_database") {
// Database title is in result.title array
title = result.title?.[0]?.plain_text || "Untitled Database";
} else {
// Page title is in properties
const titleProp = Object.values(result.properties || {}).find(
(p) => p.type === "title"
);
title = titleProp?.title?.[0]?.plain_text || "Untitled";
}
console.log(` Title: ${title}`);
console.log(` URL: ${result.url}`);
console.log(` ID: ${result.id}`);
console.log(
JSON.stringify({
success: true,
action: parentType === "update" ? "updated" : "created",
parentType,
id: result.id,
url: result.url,
title,
blocksAdded: blocks.length,
})
);
} catch (error) {
console.error("Error:", error.message);
throw error;
}