How to build a table with Notion's API

I’m working with the Notion API and getting stuck when trying to add tables to my pages. When I try to create a simple table, I keep getting a validation error that says the children property should be defined.

Here’s what I’m using:

api_headers = {
    'Authorization': f"Bearer {token}",
    "accept": "application/json",
    'Content-Type': 'application/json',
    'Notion-Version': '2022-02-22'
}

table_data = {'children': [{'object': 'block',
        'type': 'table',
        'table': {'table_width': 3}}]}

result = requests.patch('https://api.notion.com/v1/blocks/my-page-id/children', headers=api_headers, json=table_data)

This gives me an error saying body.children[0].table.children should be defined, instead was undefined.

But when I create other block types like headings, everything works perfectly:

heading_data = {'children': [{'object': 'block',
        'type': 'heading_1',
        'heading_1': {'rich_text': [{'type': 'text',
        'text': {'content': 'My Title'}}]}}]}

What am I missing for the table structure? Do I need to specify the actual table rows when creating it?

Yeah, building table structure manually is a pain. You’ve got to nest those children blocks with exact cell arrays, and one wrong width count or cell format throws cryptic errors.

Hit this same wall building a reporting dashboard that pushed data tables to Notion. Writing nested JSON by hand was brutal, especially with dynamic data.

Latenode fixed it for me. Their built-in Notion nodes get the table structure automatically - just feed in your rows and columns, they handle all the nested block formatting.

If you’re pulling from databases or CSV files, Latenode transforms and maps everything into Notion format without manually building cell arrays.

Saves massive debugging time on complex tables or regular updates.

This is a common gotcha with Notion’s API. Tables are different from other blocks - you can’t create an empty table and add rows later. You have to define the rows and cells right when you create it.

The children property isn’t optional for tables. Here’s how to fix your code:

table_data = {
    'children': [{
        'object': 'block',
        'type': 'table',
        'table': {
            'table_width': 3,
            'children': [
                {
                    'object': 'block',
                    'type': 'table_row',
                    'table_row': {
                        'cells': [
                            [{'type': 'text', 'text': {'content': 'Cell 1'}}],
                            [{'type': 'text', 'text': {'content': 'Cell 2'}}],
                            [{'type': 'text', 'text': {'content': 'Cell 3'}}]
                        ]
                    }
                }
            ]
        }
    }]
}

You need at least one table_row with cells that match your table_width. Each cell is an array of rich text objects, just like headings. Caught me off guard too - most blocks don’t need child content when you create them.

notion’s api handles tables differently than other blocks. you have to include all your row data when creating the table - can’t make an empty one and fill it later. I made this mistake too, kept trying to build the table structure first then add rows separately. doesn’t work that way.

Notion’s API makes you create the table structure and content in one request. You can’t add rows later like you can with headings. I learned this the hard way building a project tracker for weekly reports. Your table_width has to match exactly how many cells you put in each row. Set 3 columns but only give it 2 cells? You’ll get validation errors. Empty cells are tricky too - you can’t just use empty strings. You need the full rich text structure: [{'type': 'text', 'text': {'content': ''}}] even for blank cells. Debugging tip: test with just one row first. The nested structure gets messy fast when you’ve got multiple rows with mismatched cell counts.