Get Notion Database Schema
Fetch a database's property schema from Notion - property names, types, options for select/status fields
Source Code
const [databaseId] = process.argv.slice(2);
if (!databaseId) {
console.error("Error: databaseId argument is required");
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",
};
/**
* Extract options from select/multi_select/status properties
*/
function extractOptions(propertyConfig) {
if (propertyConfig.options) {
return propertyConfig.options.map((opt) => ({
name: opt.name,
color: opt.color,
}));
}
// Status properties have options in a nested structure
if (propertyConfig.status?.options) {
return propertyConfig.status.options.map((opt) => ({
name: opt.name,
color: opt.color,
}));
}
return null;
}
/**
* Extract relevant config from a property based on its type
*/
function extractPropertyConfig(name, config) {
const prop = {
name,
type: config.type,
};
// Add type-specific details
switch (config.type) {
case "select":
case "multi_select":
prop.options = extractOptions(config[config.type]);
break;
case "status":
prop.options = extractOptions(config);
// Status also has groups
if (config.status?.groups) {
prop.groups = config.status.groups.map((g) => ({
name: g.name,
color: g.color,
optionIds: g.option_ids,
}));
}
break;
case "number":
if (config.number?.format) {
prop.format = config.number.format;
}
break;
case "formula":
if (config.formula?.expression) {
prop.expression = config.formula.expression;
}
break;
case "relation":
if (config.relation?.database_id) {
prop.relatedDatabaseId = config.relation.database_id;
}
break;
case "rollup":
if (config.rollup) {
prop.rollupConfig = {
relationPropertyName: config.rollup.relation_property_name,
rollupPropertyName: config.rollup.rollup_property_name,
function: config.rollup.function,
};
}
break;
}
return prop;
}
console.log(`Fetching schema for database ${databaseId}...`);
try {
const response = await fetch(`${NOTION_API}/databases/${databaseId}`, {
method: "GET",
headers,
});
if (!response.ok) {
const errorText = await response.text();
if (response.status === 404) {
console.error(
`Database not found. Make sure the database is shared with the Notion integration.`
);
} else if (response.status === 401) {
console.error(`Unauthorized. Check your Notion API token.`);
} else {
console.error(`API error ${response.status}: ${errorText.slice(0, 200)}`);
}
process.exit(1);
}
const database = await response.json();
// Extract database title
const title = database.title?.[0]?.plain_text || "Untitled Database";
// Extract and organize properties
const properties = {};
const dateProperties = [];
const selectProperties = [];
const statusProperties = [];
for (const [propName, propConfig] of Object.entries(
database.properties || {}
)) {
const prop = extractPropertyConfig(propName, propConfig);
properties[propName] = prop;
// Track properties by type for quick reference
if (prop.type === "date") {
dateProperties.push(propName);
} else if (prop.type === "select") {
selectProperties.push(propName);
} else if (prop.type === "status") {
statusProperties.push(propName);
}
}
const schema = {
id: databaseId,
title,
url: database.url,
properties,
// Quick reference for view-critical properties
summary: {
dateProperties,
selectProperties,
statusProperties,
propertyCount: Object.keys(properties).length,
},
};
console.log(`\n✓ Database: ${title}`);
console.log(` Properties: ${schema.summary.propertyCount}`);
if (dateProperties.length > 0) {
console.log(` Date properties: ${dateProperties.join(", ")}`);
console.log(` → Use one of these for Calendar/Timeline views`);
} else {
console.log(` ⚠ No date properties - cannot use Calendar/Timeline views`);
}
if (statusProperties.length > 0) {
console.log(` Status properties: ${statusProperties.join(", ")}`);
console.log(` → Use one of these for Board view grouping`);
} else if (selectProperties.length > 0) {
console.log(` Select properties: ${selectProperties.join(", ")}`);
console.log(` → Use one of these for Board view grouping`);
}
// Output full schema as JSON
console.log(`\nSchema:`);
console.log(JSON.stringify(schema, null, 2));
} catch (error) {
console.error(`Failed to fetch database schema: ${error.message}`);
process.exit(1);
}