Skip to main content
Version: v2 (current)

Connect Notion as a task tracker

import Head from '@docusaurus/Head';

TL;DR. Create an Internal Integration in Notion, copy the secret_... token, share the target database with the integration, and add a Unique ID property to that database with prefix NT. Paste Token + Database ID in Settings → Integrations → Notion in PanDev Metrics. Branches like feature/NT-42 - description will then link to the corresponding Notion page. Takes about 5 minutes.

How Notion integration works

Unlike Jira or ClickUp, Notion does not push events to PanDev Metrics. The integration polls Notion every 10 minutes via the NotionSyncCronJob, fetches pages updated since the last watermark, and upserts them into the issue table. This pull-only model means nothing to configure on Notion's side beyond pasting a token and sharing a database — no webhooks, no callback URLs, no public endpoints.

Before you begin

Set up access in both systems before opening PanDev Metrics — the integration takes about 5 minutes once these prerequisites are in place.

  • A Notion workspace where you have admin rights (required to create integrations).
  • A Notion database (not a regular page) that holds your tasks.
  • PanDev Metrics 5.7 or newer with a tenant admin role.
  • Optional: agree on a short ID convention with your team for branch names (see Branch naming).

Step 1 — Create an Internal Integration in Notion

PanDev Metrics authenticates against Notion with an Internal Integration Token. Generate one in your Notion workspace settings.

  1. Open Notion in a browser and go to Settings → Connections → Develop or manage integrations.
  2. Select New integration.
  3. Fill in:
    • Name: PanDev Metrics
    • Associated workspace: your workspace
    • Type: Internal
  4. Under Capabilities, enable Read content, Update content, and Insert content. Read-only is not enough — PanDev writes worklog comments and bumps the Time Spent property.
  5. Select Save.
  6. Copy the Internal Integration Token — it starts with secret_. Keep it private.
Internal vs Public integration

Always pick Internal. Public integrations require an OAuth callback URL, which adds setup complexity and is unnecessary for self-hosted task tracking.

Step 2 — Share the target database with the integration

The integration token alone does not grant access to anything. You must explicitly grant the integration access to each database.

  1. Open the Notion database that holds your tasks.
  2. Select (top-right menu) → ConnectionsAdd connections.
  3. Find PanDev Metrics in the list and select it.
  4. Confirm.

Repeat for every database you want PanDev Metrics to sync.

How to find the Database ID

Copy the database URL. It looks like https://www.notion.so/acme/My-Tasks-1f3a9c2e8b7d4f5a8e2b1c4d6e9a0f3b?v=.... The Database ID is the 32-character segment right before ?v= — for example 1f3a9c2e8b7d4f5a8e2b1c4d6e9a0f3b. Strip dashes if any are present.

Step 3 — Connect in PanDev Metrics

With the token in hand and the database shared, finish the setup in PanDev Metrics.

  1. Go to Settings → Integrations → Notion.
  2. Toggle Enable integration with Notion.
  3. Enter:
    • Database ID: the 32-char UUID from the previous step
    • Integration Token: the secret_... value from Step 1
  4. Select Test Connection.
  5. When the test passes, select Save.

The first sync runs on the next cron tick (within 10 minutes). To force an immediate pull, hit POST /api/v1/notion/sync/{departmentId} from the API explorer.

PanDev Metrics reads properties by case-insensitive name. None are strictly required, but the metrics you can compute depend on what's present.

Notion propertyNotion typeWhat PanDev readsRequired?
Name (or first Title column)Titleissue.titleYes (always present)
ID (any name)Unique ID with prefix NTissue.project_key — the human-readable key like NT-42 used in branch namesStrongly recommended
StatusStatusissue.status + mapped to IssueDefaultStatusRecommended
Assignee (or Owner, Responsible)Peopleissue.assignee (email if available)Optional
PrioritySelectissue.priorityOptional
Estimate (or Time Estimate)Number (hours)issue.original_time_estimate (converted to seconds)Optional
Time SpentNumber (hours)Bumped by PanDev when a worklog is addedCreated automatically on first worklog

How to add the Unique ID property

  1. Open your database in Notion → select + in the property header row → ID (under the "Advanced" group, sometimes labeled "Unique ID").
  2. In the property settings, set Prefix to NT (or another short string of your choice — see the NOTION_ISSUE_PREFIX setting on on-prem).
  3. Notion automatically assigns the next available number to every existing page and every new page (NT-1, NT-2, NT-3, …). You cannot edit these numbers; that's by design — they are permanent identifiers, exactly what you want for git branch naming.

You can show or hide the ID column in any database view without affecting branch linking — PanDev reads it through the API, regardless of view visibility.

Status mapping

PanDev maps your free-form Notion statuses to one of three default buckets via keyword matching:

Notion status name contains...Maps to
done, complete, closed, released, shipped, resolvedDONE
progress, doing, review, active, development, wipIN_PROGRESS
to do, todo, backlog, new, open, planned, not startedTO_DO
anything elseUNDEFINED

This means In ReviewIN_PROGRESS, Released to prodDONE, IceboxUNDEFINED. Rename your Notion statuses if the default mapping does not match your flow.

Critical: branch naming convention

This is the most important rule for the integration to deliver value. Once your Notion database has a Unique ID property with prefix NT, every page has a clean human-readable key like NT-1, NT-42, NT-1337. Put that key in your branch name.

Format your feature branches as:

Branch naming
feature/NT-<id-number> - description
bugfix/NT-<id-number> - description

Examples:

feature/NT-42 - notion-integration
bugfix/NT-1337 - fix-status-mapping
hotfix/NT-7 - critical-prod-issue

PanDev's regex matches NT-<number> (case-insensitive) inside the branch name, looks up the matching page in the issue table by project_key = 'NT-42', and links the branch to that Notion page. The prefix is configurable per department via the NOTION_ISSUE_PREFIX setting (default NT) — match it to whatever prefix you set on the Notion Unique ID property.

Where do you see the ID in Notion?

Open any page in the database and look at the page header — the ID property shows the assigned NT-42 right next to the page title. You can also display the ID column in any table view for quick reference when naming branches.

Without the NT- prefix, branches will not link to Notion pages

Commits and pull requests on branches that do not contain NT-<id> will appear in PanDev Metrics as unlinked. They still count toward coding-time metrics, but PanDev cannot attribute them to a specific Notion task, so per-task analytics (Cycle Time, Time in Status, Lead Time) will be empty for those tasks.

Step 5 — Verify

After saving the settings and the first cron tick:

  1. Open Dashboard → Tasks. Pages from your Notion database should appear with tracker = notion and project_key = NT-<n>.
  2. Pick any page in your Notion database, read its ID (e.g. NT-42), and create a branch named feature/NT-42 - test. Push at least one commit.
  3. Within a few minutes, the branch should appear linked to the Notion page in the Branches table, with the page title showing in the Task column.
  4. The page's URL in PanDev should resolve to the matching Notion page and open it.

How worklog is recorded

Notion has no native worklog endpoint, so PanDev simulates one. When a worklog event arrives (from IDE telemetry, manual log, or any addWorklog API call):

  1. PanDev posts a comment on the Notion page in the form +1.50h — fixed flaky test.
  2. PanDev increments the Time Spent number property on the page by the worklog duration in hours.

Both actions use the same Integration Token. Comments carry no product-name prefix — this keeps the Notion page neutral for customers running PanDev Metrics under a white-label rebrand.

One-way only

PanDev writes worklog data into Notion but does not read worklog from Notion. Notion's API does not expose a worklog stream, so adding a time-spent entry directly inside Notion will not be reflected back in PanDev Metrics. Always log time through PanDev (IDE plugin or API).

Notion vs Jira: sync model comparison

AspectJira (push)Notion (pull)
How updates reach PanDevJira POSTs to PanDev's webhook on every issue eventPanDev queries Notion every 10 min for changed pages
Setup on tracker sidePanDev auto-registers webhooks via Jira APINone — just share the database with the integration
Latency for status changesNear real-time (seconds)Up to 10 minutes
Works behind NAT / firewall?Requires PanDev to be reachable from JiraYes — PanDev makes outbound calls only
Worklog ingestionBidirectional (Jira worklog → PanDev)One-way (PanDev → Notion only)
Tunable intervalFixed (webhook-driven)NOTION_SYNC_CRON env var (on-prem)

The pull model trades a few minutes of latency for zero configuration complexity on the Notion side. For most analytics use cases — daily/weekly dashboards, cycle-time reports — this is invisible. If you need second-level reaction to status changes, use Jira instead.

Troubleshooting

These are the most common errors during setup, with the fix for each.

Test Connection returns 401 "notion.auth"

The token is wrong or the integration was deleted. Re-create the Internal Integration in Notion, paste the new secret_... token, and test again. Tokens cannot be reused across workspaces.

Test Connection passes, but no pages appear after 10 minutes

The database is not shared with the integration. Open the database in Notion → ConnectionsAdd connections → select PanDev Metrics. The connection test only verifies the token; it does not check database access.

Pages appear but Status is always UNDEFINED

Your status property name is not Status (case-insensitive) or your status values do not contain the expected keywords. Rename the property to Status and rename status values to include words like In Progress, Done, To Do. See the Status mapping table.

Branches do not link to Notion pages

Branch name does not contain NT-<id> or the <id> is shorter than 6 characters. Rename the branch to feature/NT-<page-short-id> - description (at least 6 chars after NT-) and push at least one new commit.

Worklog comment posted but Time Spent property not updated

The Time Spent property does not exist or is not of type Number on the page. Add a number property named Time Spent to the database. Existing pages will get the property automatically on next update.

FAQ

Common questions from teams setting up the Notion integration for the first time.

How do I find the ID for a Notion page to put in a branch name?

Open the page in Notion — the ID property shows the assigned key (e.g. NT-42) in the page header right next to the title. You can also show the ID column in any table view of the database for quick reference. Copy that key as-is into your branch name: feature/NT-42 - description. The prefix matches what you configured on the Notion Unique ID property; PanDev's default is NT and is configurable via the NOTION_ISSUE_PREFIX setting.

What if my Notion database has no Unique ID property yet?

Add one — it takes 5 seconds and the integration still works during the transition. Open the database in Notion → + in the property header → ID (under Advanced) → set Prefix to NT. Notion immediately assigns NT-1, NT-2, … to every existing page; from then on every new page gets the next number automatically. Existing branches with NT-<long-id> fall back to UUID-fragment matching, but new branches should use the clean NT-<number> form.

Where do I change the polling interval?

The default is every 10 minutes. On on-prem deployments, set the NOTION_SYNC_CRON environment variable to a standard Spring cron expression — for example 0 */5 * * * * for every 5 minutes or 0 0 */1 * * * for hourly. Restart the PanDev Metrics container for the change to take effect. On SaaS the interval is fixed.

What happens if I rename a Status value in Notion?

Nothing breaks. PanDev re-reads the status name on every sync and re-applies keyword matching. If the new name no longer matches any keyword, the page's default_status becomes UNDEFINED until you rename it again. Historical IssueStatusPeriod records are not rewritten — they keep the status name as it was at write time.

Can I use Notion without a Status property?

Yes, but you lose status-based metrics. Pages will be synced with their title, assignee, and other readable properties, but all DORA and cycle-time charts that depend on status transitions will be empty. We strongly recommend adding a Status property even if it has only two values (Open and Done).

Can a single PanDev department sync multiple Notion databases?

Not today. Each department holds one NOTION_DATABASE_ID. To track multiple databases, create separate departments in PanDev or merge your Notion databases first. Multi-database support is on the roadmap.

Does PanDev see private Notion pages I have not shared with the integration?

No. The Notion API enforces the share scope strictly. PanDev sees only pages inside databases you explicitly added the integration to via Connections → Add connections. Removing the connection in Notion immediately revokes PanDev's access.

How do I rotate the Integration Token?

Create a new internal integration in Notion (or regenerate the token on the existing one), share your database with it, then update the Integration Token field in Settings → Integrations → Notion in PanDev Metrics. Select Test Connection to confirm, then Save. The old token can be deleted from Notion immediately afterwards.

Next steps

Once Notion is connected, layer on the data sources PanDev needs for full task-to-metric attribution.

Other task-tracker guides and comparison material.