I Connected 8 Google APIs. Here's What Broke.

I Connected 8 Google APIs. Here's What Broke.

Building TaskNotch taught me more about OAuth, token refresh, and rate limits than any tutorial ever could.

November 20, 20242 min readby Arefin Khan

TaskNotch connects to Gmail, Calendar, Sheets, Docs, Drive, Tasks, Meet, and Slides. Eight APIs. One OAuth flow. Countless "why isn't this working" moments.

Here's what I actually learned.

The Scope Creep

Started with "just Gmail and Calendar." Ended with this monster:

const scopes = [ 'https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/calendar', 'https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/documents', 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/tasks', 'https://www.googleapis.com/auth/presentations', // Meet requires special handling... ];

Each scope you add is another thing that can break. Fun.

The Token Refresh Dance

Google tokens expire after 1 hour. Learned this the hard way when users started getting random 401s.

async function getValidToken(userId: string) { const tokens = await db.tokens.findUnique({ where: { userId } }); // The "oh no" check if (Date.now() > tokens.expiresAt - 60000) { // Refresh 1 min early to be safe return await refreshTheStupidToken(tokens.refreshToken); } return tokens.accessToken; }

That -60000 took me 3 hours to figure out. Tokens were expiring mid-request.

Rate Limits Are Real

Google has quotas. Hit them once, you remember forever.

async function withRetry<T>(fn: () => Promise<T>): Promise<T> { for (let attempt = 0; attempt < 3; attempt++) { try { return await fn(); } catch (error: any) { if (error.code === 429) { // Back off exponentially await sleep(Math.pow(2, attempt) * 1000); continue; } throw error; } } throw new Error('Google is mad at us'); }

The "It Works on My Account" Problem

Tested everything on my Google account. Shipped. Client's account had different settings. Nothing worked.

Lesson: Test with multiple accounts. Different org settings. Different locales. Different everything.

What Actually Worked

  1. One OAuth, multiple services — Get all scopes upfront. Re-auth is annoying.
  2. Centralized token management — One place to check expiry, one place to refresh.
  3. Aggressive caching — Don't hit the API if you don't have to.
  4. Error messages that help — "Gmail error" vs "Your Gmail token expired, reconnect in settings."

The Result

TaskNotch now handles:

  • Reading/sending emails
  • Creating calendar events
  • Manipulating spreadsheets
  • Generating docs
  • Managing drive files
  • Tracking tasks

All through natural language. The AI figures out which API to call.

Was it worth the pain? Check tasknotch.app and decide.