Skip to content
All docs

Notion setup

Credential: Internal connection

The Notion connector creates pages as rows of a database you point it at. Everything it writes stays private to your workspace — Notion has no publish-to-web API, so nothing here is ever a live web page.

Use this when Notion is where your team reviews and edits drafts, and something else publishes them.

Step 1 - create an internal connection

You must be a workspace owner.

  1. Go to notion.so/profile/integrations → New integration (internal), and pick your workspace.

  2. On the Configuration tab, enable all three capabilities:

    Capability Without it
    Read content BirchSeek cannot find its own prior page, so refreshes duplicate
    Insert content The first publish fails
    Update content Every refresh re-publish fails
  3. Copy the Installation access token.

Step 2 - share the database with the connection

A new connection has no page access at all. Until you do this, every call returns 404.

Open your blog database in Notion → ••• → Connections → + Add connection → pick your integration. (You can also do it from the integration’s Content access tab.)

Step 3 - add a “BirchSeek ID” column

Your database needs one Text property that BirchSeek owns. It writes the article’s id there and uses it to find the page again on the next run.

This is required, and there is no weaker fallback. Notion has no external-id concept for API-created pages, and its documented filter set has no title filter and no URL filter — a Text column is the only thing that can be matched exactly. Without it, a refresh could not find its own page and would create a second row every time.

Call it BirchSeek ID (any name works) and leave it alone. If someone clears it by hand, BirchSeek can still find the page by the id it recorded last time, and it re-writes the column to heal it.

Step 4 - connect in BirchSeek

Setting Required Notes
Database URL yes Paste the database’s Notion URL; the id is extracted for you
Title property yes Your database’s title column (usually Name)
BirchSeek ID property yes The Text column from step 3
Status property no A Select or Status column used as a draft flag
Draft status value no e.g. Draft. For a Status column the option must already exist
Slug property no Must be a Text column, not a URL column
Meta description no Must be a Text column
Canonical property no A URL column; informational only, not an SEO canonical
Tags property no A Multi-select column
Date property no A Date column

If you ever re-point this connector at a different database, paste the new URL and re-test. BirchSeek verifies that the data source it has pinned really belongs to the database you configured, and refuses rather than quietly continuing to write into the old one.

Step 5 - send a test

Send a test calls GET /v1/users/me (isolating a bad token) and then reads the database’s schema, which is what proves Read content is actually enabled. It checks every configured property exists and has the right type, and reports them in one message.

It can only verify Read. Insert and Update have no harmless probe, so enable them in step 1 and take the note seriously.

What BirchSeek writes

Per article, via POST /v1/pages with parent.data_source_id:

  • your title property, the BirchSeek ID, and whichever optional properties you mapped
  • the article body as Notion-flavored Markdown in one request — headings, lists, quotes, tables, code blocks and links all convert natively
  • the article’s verified claims as a ## Sources list. This is the same block every connector publishing to your own site writes, composed once before any connector sees it (a syndicated copy to dev.to, Hashnode or Medium carries it too); Notion is only the target that moves it, because a list of sources belongs below the FAQ rather than between the article and it. Notion has no footnotes, no frontmatter and no citation field, so the body is the one place it could go here anyway. The block is on by default, and there is no switch for it in the dashboard: it is a project setting called append_sources_section, and the only way to change it today is PATCH /v1/projects/{id} carrying the whole settings object, because that request replaces the object rather than merging into it.

On a refresh run the page’s properties are patched and its body is replaced wholesale, so the regenerated article actually lands.

The one thing that can lose your work

The page body is machine-owned. A refresh replaces it entirely.

If you nest a sub-page or a sub-database under a BirchSeek page, Notion refuses to replace the body unless BirchSeek explicitly allows deleting that content. BirchSeek tries without the flag first, and only escalates when Notion says it must — at which point your nested sub-pages are deleted.

Keep your own notes in a property, or in a page that is not a child of a BirchSeek page.

Caveats

  • Nothing published here is public. Notion has no publish-to-web endpoint, public_url comes back null, and the notion.so/… URL is a workspace deep link that anyone outside your workspace cannot open. BirchSeek never reports a live URL for this connector, and never treats it as a syndication target.
  • No canonical. Notion cannot express one. If you map a URL property, it is a note for whoever reads the row, not an SEO signal.
  • Limits. A page is capped at 500 KB and 1000 blocks; any single text value at 2000 characters; multi-select at 100 items. BirchSeek checks these before sending.

Troubleshooting

  • 404 naming your connection - the database was never shared with it. Step 2. Notion’s own message tells you exactly this and BirchSeek passes it through verbatim.
  • 401 unauthorized - the token is wrong or was regenerated. Paste a new one.
  • 403 restricted_resource - a capability toggle is off. Step 1.
  • “is not part of notion database …” - the connector was re-pointed at a different database. Clear the resolved data source in the form and re-test.
  • 409 conflict_error - a transient save collision inside Notion. Retried automatically.