# How to Automate Notion Content Publishing using the API

- Tool: API Automations
- Difficulty: Advanced
- Fix time: 1-2 hours
- Compatibility: Free — internal Notion integration with Read content and Update content capabilities; requires public HTTPS webhook endpoint
- Last updated: May 2026

## TL;DR

Automate a Notion-to-CMS publishing pipeline: subscribe to page.updated webhooks, then recursively fetch all blocks with GET /v1/blocks/{id}/children (100 blocks per page, must recurse for nested content), transform block types to HTML or Markdown, and push to an external CMS API. Critical: image block URLs expire in ~1 hour — download and re-upload images immediately. A 30-block article with toggles can require 10+ paginated block-children requests. Rate limit: 3 req/s.

## Best practices

- Download image URLs immediately after fetching blocks — they expire in ~1 hour and you cannot re-fetch them without another API call
- Depth-limit recursive block fetching to 5 levels as a safety guard against pathological nesting
- Never re-process a 'Ready to Publish' page that has already been published — check for a 'Published' status before starting the pipeline
- Store the WordPress post URL back in the Notion page after publishing using PATCH /v1/pages/{id} with a URL property
- Handle unknown block types gracefully — skip them and log the type so you can add support later
- Return 200 from the webhook handler immediately and process the full pipeline asynchronously
- Use the Notion block ID as the image filename to create a deterministic mapping between Notion content and CMS media

## Frequently asked questions

### Why do I get 403 errors when accessing Notion image URLs?

Notion stores images on AWS S3 with time-limited signed URLs that expire after approximately 1 hour. After expiry, S3 returns 403 Access Denied. The solution is to download images immediately after fetching the blocks that contain them — never wait, never cache the URL. In production, upload the downloaded image to your own CDN or S3 bucket and use the permanent URL in your CMS.

### How many API calls does it take to publish a typical blog post?

A 20-block article without nesting requires approximately 4 calls: 1 webhook trigger follow-up (GET /v1/pages/{id}), 1-2 block children pages (GET /v1/blocks/{id}/children), and 1 status update (PATCH /v1/pages/{id}). A 50-block article with 5 nested toggles and a table requires 8-12 calls just for block fetching. Each image download is an additional external HTTP call (not rate-limited by Notion).

### What block types require recursive fetching?

Any block where has_children is true requires a follow-up GET /v1/blocks/{id}/children call. Common types: toggle, column_list (then each column block), table (then each table_row), callout (sometimes), synced_block. Leaf blocks (paragraph, heading, image, code, divider) never have children. Skip recursion for child_page and child_database to avoid infinite loops.

### Can I convert Notion blocks to Markdown instead of HTML?

Yes. Instead of wrapping content in HTML tags, use Markdown equivalents: # for heading_1, ## for heading_2, > for quote, ** ** for bold, * * for italic, ` ` for inline code, ```lang for code blocks, - for bulleted_list_item, 1. for numbered_list_item. The same block iteration and rich text extraction logic applies — just change the output format.

### Is the Notion API free for content pipeline automation?

Yes. The Notion API is free with no paid tier. The only limitation is the 3 req/s rate limit, which is the same for all plan levels. The webhook system (used for real-time detection) is in public beta but free to use.

### How do I handle Notion synced blocks in the pipeline?

Synced blocks (type: synced_block) have has_children: true and contain a synced_from object pointing to the original block ID. Fetch the children of the synced_block's own ID — Notion automatically returns the synced content. Do not follow the synced_from reference directly, as that points to the source block which may be in a different page.

### What is the difference between Notion-Version: 2025-09-03 and 2026-03-11?

In version 2026-03-11, two things changed: 'archived' property on pages was renamed to 'in_trash', and the 'after' string parameter for PATCH /v1/blocks/{id}/children was replaced by a 'position' object. For read-only operations like block fetching and page reading, both versions work identically. Pin to 2025-09-03 for stability unless you need position-based block insertion.

### Can RapidDev build a custom Notion content publishing pipeline?

Yes. RapidDev has built 600+ apps including automated content pipelines from Notion to WordPress, Webflow, and headless CMSes. We handle recursive block traversal, image CDN migration, and CMS field mapping. Visit rapidevelopers.com for a free consultation.

---

Source: https://www.rapidevelopers.com/api-automations/how-to-automate-notion-content-publishing-using-the-api
© RapidDev — https://www.rapidevelopers.com/api-automations/how-to-automate-notion-content-publishing-using-the-api
