Populate all lines for a station in the Notion StationLine database.
The user will provide: $ARGUMENTS (a station name, e.g. "Shinjuku", "Shimbashi", "Ikebukuro")
-
Find the station in the Notion Stations database by matching the name. The station name format is
"English 日本語"(e.g."Shinjuku 新宿"). If the station doesn't exist, create it with a 🚉 emoji icon. -
Check existing StationLine entries for the station to avoid creating duplicates.
-
Research all lines passing through this station by searching the web. For each line, find:
- Line name (English with macrons, e.g. "Chūō Rapid", "Ōedo")
- Line code (e.g. JY, G, M, OH, KO)
- Station number on that line (e.g. 17, 8, 27)
-
Determine badge style from the line code:
- JR lines (codes starting with J, like JY, JK, JO, JT, JC, JE, JH, JA, JB, JS, etc.) use
jrestyle (square badges) - Private railways with multi-letter codes (OH, KO, TY, DT, etc.) use
jrestyle (square badges) - Metro/subway lines with single-letter codes (G, M, A, Z, H, E, S, etc.) use
tssnstyle (circle badges) - Yurikamome (U) uses
ykstyle (solid circle badges)
- JR lines (codes starting with J, like JY, JK, JO, JT, JC, JE, JH, JA, JB, JS, etc.) use
-
Get or create lines in the Lines database. Set line icons to
{BASE}/{style}/{code}.png?size=120. -
Create StationLine entries for each line, with:
- A relation to the station
- A relation to the line
- The stop number
- An icon set to the badge PNG:
{BASE}/{style}/{code}/{number}.png?size=120
-
Set icons on any existing StationLine entries that are missing badge icons.
-
Research the station's coordinates (latitude/longitude). Then set the Place property on all StationLine entries for this station (both new and existing) using the Notion private API (see "Setting Place on StationLine" below).
-
Show a summary of what was created.
Read the token from .env file (NOTION_TOKEN=...).
- Notion API base:
https://api.notion.com/v1 - Notion-Version header:
2022-06-28 - Badge API base:
https://jdan--73a2eeba09df11f1a30442dde27851f2.web.val.run
- Stations:
3076fc0faa7d8093b3afce6b0c25966d - Lines:
3076fc0faa7d8073b3eed1db67a8bcbc - StationLine:
3076fc0faa7d80bda742cc7fa4041b06
POST /pages
{
"parent": {"database_id": "<STATIONLINE_DB>"},
"icon": {"type": "external", "external": {"url": "<badge_url>"}},
"properties": {
"Name": {"title": [{"text": {"content": " "}}]},
"Station": {"relation": [{"id": "<station_id>"}]},
"Line": {"relation": [{"id": "<line_id>"}]},
"Stop": {"number": <stop_number>}
}
}
POST /pages
{
"parent": {"database_id": "<LINES_DB>"},
"icon": {"type": "external", "external": {"url": "<line_badge_url>"}},
"properties": {
"Name": {"title": [{"text": {"content": "Line Name"}}]}
}
}
The Place property (dsOX) on StationLine entries is not writable via the public Notion API. Use the private API instead. Read token_v2 from .env (NOTION_TOKEN_V2=...).
POST https://www.notion.so/api/v3/saveTransactionsFanout
Headers:
Content-Type: application/json
Cookie: token_v2=<NOTION_TOKEN_V2>
x-notion-space-id: e8bd2e4a-c367-4d7e-8c8b-ef47b27ac37a
x-notion-active-user-header: 84cb4838-4dc9-4d38-8cf8-c186b662dee9
notion-client-version: 23.13.20260214.1755
notion-audit-log-platform: web
Body:
{
"requestId": "<uuid>",
"transactions": [{
"id": "<uuid>",
"spaceId": "e8bd2e4a-c367-4d7e-8c8b-ef47b27ac37a",
"debug": {"userAction": "BlockPropertyValueOverlay.handlePlaceChange"},
"operations": [
{
"pointer": {"table": "block", "id": "<stationline_page_id>", "spaceId": "e8bd2e4a-c367-4d7e-8c8b-ef47b27ac37a"},
"path": ["properties", "dsOX"],
"command": "set",
"args": [["\u2023", [["plc", {"lat": <lat>, "lon": <lon>, "name": "<Station Name>"}]]]]
},
{
"pointer": {"table": "block", "id": "<stationline_page_id>", "spaceId": "e8bd2e4a-c367-4d7e-8c8b-ef47b27ac37a"},
"path": [],
"command": "update",
"args": {"last_edited_time": <epoch_ms>, "last_edited_by_id": "84cb4838-4dc9-4d38-8cf8-c186b662dee9", "last_edited_by_table": "notion_user"}
}
]
}],
"unretryable_error_behavior": "continue"
}
The name field should be the English station name (e.g. "Shinjuku Station"). The awsPlaceId and address fields are optional and can be omitted. Since all StationLine entries for one station share the same coordinates, look up the lat/lon once and apply to all entries.
- Use a single Python script with
urllib.requestfor all API calls (no external dependencies). - Zero-pad stop numbers in badge URLs (e.g.
01,02). - Always query existing lines before creating — match by name to avoid duplicates.
- Always check existing StationLine entries for the station before creating duplicates.
- When checking for existing StationLine entries, look up each entry's Line relation to identify which lines are already linked.