gastandoya-api
Integrations that respect boundaries.
GastandoYa backend with Notion OAuth, database discovery and normalized expense reads.
Problem
Connect separate Notion accounts and normalize expenses for an iOS app.
My contribution
Development and maintenance of this personal project.
THE PIPELINE / SYSTEM MAP
gastandoya-api
From per-user OAuth to normalized expenses for the iOS app.
Step 1 / 6
iOS app
Start authorization and consume backend endpoints with the documented headers.
Step 2 / 6
Backend & OAuth
Start authorization, validate state on callback and exchange the code for a token on the server.
Step 3 / 6
Per-user connection
UserNotionConnectionStore uses KV when configured or memory as fallback. Tokens are not sent to the client.
Step 4 / 6
Database discovery
Discover databases through Blocks API or Search API and handle pagination and selection.
Step 5 / 6
Expense service
Query the selected database and normalize records into ExpenseDTO.
Step 6 / 6
ExpenseDTO → iOS
The app receives normalized data; the OAuth callback returns through an intermediate deep link.
Connections stay on the server; the client consumes an expense contract.
Connections and conditions
- iOS app → Backend & OAuthAuthorizes the connection
- Backend & OAuth → Per-user connectionStores token on server
- Per-user connection → Database discoveryProvides Notion connection
- Database discovery → Expense serviceConfigured database
- Expense service → ExpenseDTO → iOSNormalizes response
- ExpenseDTO → iOS → iOS appDisplays expenses
Illustrative walkthrough of documented components; it does not run the projects. Sources reviewed on 2026-10-28.
Explore components or play the walkthrough.
Engineering decision
User connections stay in the backend; the client receives normalized data.
Trade-off
Discovery and pagination must handle pages with no database or multiple choices.
Evidence
The backend provides per-user OAuth connections, database discovery and normalized expenses; its README documents the iOS integration flow.
Project documentation ↗