Notion integration โ free at notion.so/my-integrations โ "New integration" โ copy the secret token
Notion database ID โ create a full-page database in Notion, open it, copy the ID from the URL: notion.so/YOUR-DATABASE-ID?v=...
Cloudflare Worker proxy โ free at workers.cloudflare.com โ deploy the worker code shown in the Settings tab
Add your integration to the database: open the database in Notion โ ยทยทยท menu โ "Add connections" โ select your integration
Receipt image
๐งพ
Click to upload or drag & drop โ multiple OK
or Ctrl+V
or paste text
Manual entry
Not synced yet
Period
to
Roll up grocery subcategories into "Groceries"
Categories
Spending breakdown
Monthly trend
AI insights
Select a period and click below.
Item lookup database
Maps Costco item numbers & receipt codes to full product names. Used automatically when parsing โ unknown items trigger a Gemini web search.
Item #
Receipt name
Full product name
Category
No items match.
1 ยท Gemini API key (free โ handles receipt parsing)
Get a free key at aistudio.google.com/apikey โ sign in with Google โ "Get API key" โ copy it.
Free tier: 1,500 requests/day, supports image upload.
Delete the default code and paste the code below โ click "Deploy"
Copy your worker URL (looks like your-worker.your-subdomain.workers.dev) and paste it below
export default {
async fetch(request, env) {
const ALLOWED = "YOUR_SITE_ORIGIN"; // e.g. "null" for local file, or your domain
if (request.method === "OPTIONS") {
return new Response(null, { headers: corsHeaders(ALLOWED) });
}
const url = new URL(request.url);
const target = url.searchParams.get("target");
if (!target || !target.startsWith("https://api.notion.com/")) {
return new Response("Bad target", { status: 400 });
}
const body = request.method !== "GET" ? await request.text() : undefined;
const headers = {};
for (const [k, v] of request.headers.entries()) {
if (k.toLowerCase() !== "host") headers[k] = v;
}
const resp = await fetch(target, { method: request.method, headers, body });
const respBody = await resp.text();
return new Response(respBody, {
status: resp.status,
headers: { ...corsHeaders(ALLOWED), "content-type": "application/json" }
});
}
};
function corsHeaders(origin) {
return {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,PATCH,DELETE,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type,Authorization,Notion-Version"
};
}
3 ยท Notion integration (free โ stores your transactions)
Step A: Create an integration at notion.so/my-integrations โ "New integration" โ copy the Internal Integration Token.
Step B: In Notion, create a new full-page database. Open it โ the URL looks like: notion.so/YOUR-DATABASE-ID?v=...
Copy the 32-character ID before the ?v=.
Step C: In the database, click ยทยทยท โ "Add connections" โ select your integration.
Step D: Click "Create Notion database" below โ this sets up the right columns automatically.
Data
"Push historical data" sends your two existing Costco trips (Jan 31 + Feb 13, 2026) to Notion.