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 prefixNT. Paste Token + Database ID in Settings → Integrations → Notion in PanDev Metrics. Branches likefeature/NT-42 - descriptionwill 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.
- Open Notion in a browser and go to Settings → Connections → Develop or manage integrations.
- Select New integration.
- Fill in:
- Name:
PanDev Metrics - Associated workspace: your workspace
- Type: Internal
- Name:
- 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.
- Select Save.
- Copy the Internal Integration Token — it starts with
secret_. Keep it private.
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.
- Open the Notion database that holds your tasks.
- Select
…(top-right menu) → Connections → Add connections. - Find PanDev Metrics in the list and select it.
- Confirm.
Repeat for every database you want PanDev Metrics to sync.
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.
- Go to Settings → Integrations → Notion.
- Toggle Enable integration with Notion.
- Enter:
- Database ID: the 32-char UUID from the previous step
- Integration Token: the
secret_...value from Step 1
- Select Test Connection.
- 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.
Step 4 — Recommended Notion database schema
PanDev Metrics reads properties by case-insensitive name. None are strictly required, but the metrics you can compute depend on what's present.
| Notion property | Notion type | What PanDev reads | Required? |
|---|---|---|---|
| Name (or first Title column) | Title | issue.title | Yes (always present) |
ID (any name) | Unique ID with prefix NT | issue.project_key — the human-readable key like NT-42 used in branch names | Strongly recommended |
Status | Status | issue.status + mapped to IssueDefaultStatus | Recommended |
Assignee (or Owner, Responsible) | People | issue.assignee (email if available) | Optional |
Priority | Select | issue.priority | Optional |
Estimate (or Time Estimate) | Number (hours) | issue.original_time_estimate (converted to seconds) | Optional |
Time Spent | Number (hours) | Bumped by PanDev when a worklog is added | Created automatically on first worklog |
How to add the Unique ID property
- Open your database in Notion → select
+in the property header row → ID (under the "Advanced" group, sometimes labeled "Unique ID"). - In the property settings, set Prefix to
NT(or another short string of your choice — see theNOTION_ISSUE_PREFIXsetting on on-prem). - 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, resolved | DONE |
progress, doing, review, active, development, wip | IN_PROGRESS |
to do, todo, backlog, new, open, planned, not started | TO_DO |
| anything else | UNDEFINED |
This means In Review → IN_PROGRESS, Released to prod → DONE, Icebox → UNDEFINED. 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:
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.
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.
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:
- Open Dashboard → Tasks. Pages from your Notion database should appear with
tracker = notionandproject_key = NT-<n>. - Pick any page in your Notion database, read its ID (e.g.
NT-42), and create a branch namedfeature/NT-42 - test. Push at least one commit. - 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.
- 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):
- PanDev posts a comment on the Notion page in the form
+1.50h — fixed flaky test. - 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.
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
| Aspect | Jira (push) | Notion (pull) |
|---|---|---|
| How updates reach PanDev | Jira POSTs to PanDev's webhook on every issue event | PanDev queries Notion every 10 min for changed pages |
| Setup on tracker side | PanDev auto-registers webhooks via Jira API | None — just share the database with the integration |
| Latency for status changes | Near real-time (seconds) | Up to 10 minutes |
| Works behind NAT / firewall? | Requires PanDev to be reachable from Jira | Yes — PanDev makes outbound calls only |
| Worklog ingestion | Bidirectional (Jira worklog → PanDev) | One-way (PanDev → Notion only) |
| Tunable interval | Fixed (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 → … → Connections → Add 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.
- Connect your IDE plugin to capture coding time per Notion task
- Connect a Git integration so PanDev sees the branches that match
NT-prefixes - Performance indicators — see metrics computed from your Notion tasks
Related
Other task-tracker guides and comparison material.
- How-to: Connect Jira — push-model comparison
- How-to: Connect Yandex Tracker — alternative tracker