Notion API block modification not working properly

I’m having trouble modifying content in my Notion blocks using their API. I followed the documentation but the text content stays the same after sending update requests.

import json
import requests
import os
from dotenv import load_dotenv, find_dotenv

def update_notion_block():
    load_dotenv(find_dotenv())
    api_token = os.environ.get("NOTION_TOKEN")
    target_block = os.environ.get("TARGET_BLOCK")
    
    request_headers = {
        "Authorization": f"Bearer {api_token}",
        "Notion-Version": "2021-08-16",
        "Content-Type": "application/json"
    }

    updated_content = {
        "paragraph": {
            "text": [{
                "text": {
                    "content": "updated text here"
                }
            }]
        }
    }

    api_endpoint = f"https://api.notion.com/v1/blocks/{target_block}"
    response = requests.patch(api_endpoint, headers=request_headers, json=updated_content)
    
    print(f"Status: {response.status_code}")
    print(json.dumps(response.json(), indent=2))

if __name__ == "__main__":
    update_notion_block()

The response shows status 200 but the original text remains unchanged:

{
  "paragraph": {
    "text": [
      {
        "type": "text",
        "text": {
          "content": "original text here",
          "link": null
        },
        "annotations": {
          "bold": false,
          "italic": false,
          "strikethrough": false,
          "underline": false,
          "code": false,
          "color": "default"
        }
      }
    ]
  }
}

What am I missing in my implementation?

check your notion-version header - that 2021-08-16 version is old and could be the problem. update it to “2022-06-28” or newer. also double-check your block permissions. sometimes the api call looks like it worked but nothing actually changes if your integration can’t write to that page.

Classic mismatch between block type and your update payload. Hit this same issue last year building a knowledge base sync tool. You’re probably assuming it’s a paragraph block when it’s actually a heading_1, heading_2, or bulleted_list_item. Do a GET request first to grab the block and check its actual structure. The response shows you the exact type and current format. Then match your payload exactly to what that block type expects. I’ve seen blocks that look like plain text in the UI but are actually headings - totally different payload structure needed. Some block types also need extra required fields beyond just text content, so checking the current structure upfront saves tons of debugging time.

Had this exact problem a few months ago and it drove me nuts for hours. Your payload’s missing the type field in the text object. Notion needs you to specify the text type explicitly when updating paragraph blocks through the API, even though it feels redundant.

Try this for your updated_content:

updated_content = {
    "paragraph": {
        "text": [{
            "type": "text",
            "text": {
                "content": "updated text here"
            }
        }]
    }
}

Double-check you’re hitting the right block ID too - nested blocks can be a pain to identify. I’d grab the block details first to confirm the structure before trying to update. That 200 response is misleading since Notion returns success even when your payload doesn’t match their schema perfectly.