Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ihfaz297/MND/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The MND system uses several Google Cloud APIs:
  • Distance Matrix API - Calculate travel times between locations (backend)
  • Directions API - Route instructions (optional)
  • Maps JavaScript API - Web map display (frontend, optional)
  • Maps SDK for Android - Mobile map display (Flutter Android)
  • Maps SDK for iOS - Mobile map display (Flutter iOS)

Google Cloud Console Setup

1. Create Google Cloud Project

  1. Go to Google Cloud Console
  2. Sign in with your Google account
  3. Click Select a projectNew Project
  4. Enter project details:
    • Project name: MND Bus Routing
    • Organization: (optional)
  5. Click Create

2. Enable Billing

Google Cloud APIs require a billing account, but you get $200 free credit per month.
  1. Go to Billing
  2. Click Link a billing account
  3. Create a new billing account or select existing
  4. Enter payment information
Free tier:
  • $200/month free credit
  • Distance Matrix: ~700 requests/month free
  • After credit: $5-10 per 1,000 requests

3. Enable APIs

Go to APIs & Services → Library Enable these APIs:

Distance Matrix API (Required)

  1. Search for “Distance Matrix API”
  2. Click Distance Matrix API
  3. Click Enable

Directions API (Optional)

  1. Search for “Directions API”
  2. Click Directions API
  3. Click Enable

Maps JavaScript API (Optional - Web)

  1. Search for “Maps JavaScript API”
  2. Click Maps JavaScript API
  3. Click Enable

Maps SDK for Android (Optional - Mobile)

  1. Search for “Maps SDK for Android”
  2. Click Maps SDK for Android
  3. Click Enable

Maps SDK for iOS (Optional - Mobile)

  1. Search for “Maps SDK for iOS”
  2. Click Maps SDK for iOS
  3. Click Enable

Creating API Keys

1. Create Credentials

  1. Go to APIs & Services → Credentials
  2. Click Create CredentialsAPI key
  3. New API key is created and displayed
Restrict your API key immediately! Unrestricted keys can be stolen and abused.

2. Backend API Key (Distance Matrix)

Restrict to Distance Matrix API:
  1. Click Restrict Key next to your newly created key
  2. Name: “Backend - Distance Matrix”
  3. Under API restrictions:
    • Select Restrict key
    • Check ✓ Distance Matrix API
    • Check ✓ Directions API (if using)
  4. Under Application restrictions:
    • Select IP addresses
    • Add your server IP: 203.0.113.42
    • For development, add: 0.0.0.0/0 (remove in production!)
  5. Click Save
Copy the API key and add to .env:
GOOGLE_DM_API_KEY=AIzaSyAaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQ

3. Web Frontend API Key (Maps JavaScript)

Restrict to Maps JavaScript API:
  1. Create another API key
  2. Name: “Web Frontend - Maps”
  3. Under API restrictions:
    • Select Restrict key
    • Check ✓ Maps JavaScript API
  4. Under Application restrictions:
    • Select HTTP referrers (web sites)
    • Add your domain: https://yourdomain.com/*
    • For development, add: http://localhost:5173/*
  5. Click Save
Add to frontend .env:
VITE_GOOGLE_MAPS_API_KEY=AIzaSyBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqR

4. Mobile API Key (Android/iOS)

Restrict to Mobile Maps SDKs:
  1. Create another API key
  2. Name: “Mobile - Maps”
  3. Under API restrictions:
    • Select Restrict key
    • Check ✓ Maps SDK for Android
    • Check ✓ Maps SDK for iOS
  4. Under Application restrictions:
    • Select Android apps
    • Add your package name: com.yourcompany.mnd_flutter
    • Add SHA-1 fingerprint (see below)
  5. Click Save
Get SHA-1 fingerprint:
# Debug keystore
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

# Release keystore
keytool -list -v -keystore ~/mnd-release-key.jks -alias mnd
Copy the SHA-1 value and add to API key restrictions. Add to Flutter .env:
GOOGLE_MAPS_API_KEY=AIzaSyCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrS

API Key Security Best Practices

Never Commit API Keys

Add to .gitignore:
.env
.env.local
.env.production
.env.development

Use Different Keys for Each Environment

  • Development: Unrestricted or localhost-only
  • Staging: Restricted to staging domain
  • Production: Restricted to production domain/IP

Rotate Keys Regularly

Rotate API keys every 90 days:
  1. Create new API key
  2. Update application configuration
  3. Test thoroughly
  4. Delete old key

Monitor API Usage

Set up billing alerts:
  1. Go to Billing → Budgets & alerts
  2. Click Create Budget
  3. Set budget amount: $50/month
  4. Set alert thresholds: 50%, 75%, 90%, 100%
  5. Add email for notifications

Quota Management

Free Tier Limits

Distance Matrix API:
  • $200 credit/month ≈ 700-1,000 requests
  • After credit: $5-10 per 1,000 requests
Maps JavaScript API:
  • Dynamic Maps: $7 per 1,000 loads
  • Static Maps: $2 per 1,000 loads
  • First 28,500 loads free

Quota Monitoring

Check usage in Google Cloud Console → APIs & Services → Dashboard Real-time monitoring:
// Backend tracks quota internally
import { distanceMatrixClient } from './infra/distanceMatrixClient';

const stats = distanceMatrixClient.getStats();
console.log(`Monthly usage: ${stats.monthlyCount}/700`);
See Monitoring for detailed quota tracking.

Set Quota Limits

Prevent unexpected charges:
  1. Go to APIs & Services → Distance Matrix API → Quotas
  2. Click Queries per day
  3. Edit quota:
    • Set to 50 requests/day (development)
    • Set to 100 requests/day (production)
  4. Click Save
The backend has built-in limits (700/month, 50/day) but Google Cloud quotas provide an additional safety net.

Caching Strategy

The MND backend caches Distance Matrix results to minimize API calls.

Cache Configuration

In src/infra/distanceMatrixClient.ts:
private readonly CACHE_TTL_DAYS = 7;  // Cache for 7 days

Cache Benefits

  • Reduces API calls: 80-90% cache hit rate achievable
  • Faster responses: No network latency
  • Cost savings: Free cached results

Cache Key Format

const cacheKey = `${originNodeId}|${destNodeId}|${mode}`;
// Example: "TILAGOR|CAMPUS|driving"

Pre-warming Cache

Populate cache with common routes:
npm run populate-edges
This script:
  1. Reads all node pairs from nodes.json
  2. Calls Distance Matrix API for each pair
  3. Caches results in memory and edges.json
  4. Respects quota limits
Manual pre-warm:
import { distanceMatrixClient } from './infra/distanceMatrixClient';

const commonRoutes = [
  ['TILAGOR', 'CAMPUS', 'driving'],
  ['CAMPUS', 'TILAGOR', 'driving'],
  ['NAIORPUL', 'CAMPUS', 'driving'],
  ['SHIBGONJ', 'CAMPUS', 'driving']
];

await distanceMatrixClient.prewarmCache(commonRoutes);

Cache Invalidation

Cache expires after 7 days. To force refresh:
distanceMatrixClient.clearCache();

Distance Matrix API Details

Request Format

const response = await axios.get(
  'https://maps.googleapis.com/maps/api/distancematrix/json',
  {
    params: {
      origins: 'Tilagor, Sylhet, Bangladesh',
      destinations: 'Campus, Sylhet, Bangladesh',
      mode: 'driving',
      key: process.env.GOOGLE_DM_API_KEY
    }
  }
);

Parameters

origins
string
required
Starting location (address or coordinates).Examples:
  • "Tilagor, Sylhet, Bangladesh"
  • "24.8949,91.8687"
destinations
string
required
Ending location (address or coordinates).
mode
string
default:"driving"
Travel mode.Valid values:
  • driving - Car/bus routes
  • walking - Pedestrian routes
  • bicycling - Bike routes
  • transit - Public transit (requires transit API)
key
string
required
Your API key.

Response Format

{
  "status": "OK",
  "rows": [{
    "elements": [{
      "status": "OK",
      "distance": {
        "value": 3598,
        "text": "3.6 km"
      },
      "duration": {
        "value": 780,
        "text": "13 mins"
      }
    }]
  }]
}
Extract values:
const element = response.data.rows[0].elements[0];
const distanceMeters = element.distance.value;  // 3598
const durationSeconds = element.duration.value;  // 780

Error Handling

Common status codes:
  • OK - Success
  • ZERO_RESULTS - No route found
  • OVER_QUERY_LIMIT - Quota exceeded
  • REQUEST_DENIED - Invalid API key or restrictions
  • INVALID_REQUEST - Missing parameters
  • UNKNOWN_ERROR - Server error, retry
Handle errors:
if (response.data.status !== 'OK') {
  console.error(`Distance Matrix error: ${response.data.status}`);
  return {
    ok: false,
    errorMessage: `API status: ${response.data.status}`
  };
}

Testing API Setup

Test Distance Matrix API

Create a test script:
cd MND-backend
npx tsx src/scripts/verify-api.ts
Or manually:
curl "https://maps.googleapis.com/maps/api/distancematrix/json?origins=Tilagor,Sylhet,Bangladesh&destinations=Campus,Sylhet,Bangladesh&mode=driving&key=YOUR_API_KEY"
Expected response:
{
  "status": "OK",
  "rows": [...]
}
Error responses:
{
  "status": "REQUEST_DENIED",
  "error_message": "The provided API key is invalid."
}
{
  "status": "OVER_QUERY_LIMIT",
  "error_message": "You have exceeded your daily request quota for this API."
}

Test Maps JavaScript API

Create test.html:
<!DOCTYPE html>
<html>
<head>
  <title>Test Maps API</title>
  <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_WEB_API_KEY"></script>
  <style>
    #map { height: 400px; }
  </style>
</head>
<body>
  <div id="map"></div>
  <script>
    function initMap() {
      const map = new google.maps.Map(document.getElementById('map'), {
        center: { lat: 24.8949, lng: 91.8687 },
        zoom: 13
      });
    }
    initMap();
  </script>
</body>
</html>
Open in browser. If map displays, API is working.

API Cost Estimation

Distance Matrix API

Free tier: $200/month = ~700-1,000 requests Pricing tiers:
  • 0-100,000 requests: $5 per 1,000 requests
  • 100,001-500,000: $4 per 1,000 requests
  • 500,001+: Contact sales
Example calculation:
Monthly requests: 700
Cache hit rate: 85%
Actual API calls: 700 * 0.15 = 105
Cost: $0 (within free tier)

Maps JavaScript API

Free tier: 28,500 map loads/month Pricing:
  • Dynamic Maps: $7 per 1,000 loads
  • Static Maps: $2 per 1,000 loads
Example calculation:
Monthly users: 500
Avg sessions/user: 3
Total loads: 1,500
Cost: $0 (within free tier)

Troubleshooting

”REQUEST_DENIED” Error

Causes:
  • API not enabled in Cloud Console
  • API key invalid
  • API key restrictions blocking request
Solutions:
  1. Verify API is enabled: Enable APIs
  2. Check API key is correct
  3. Review key restrictions (IP, referrer, bundle ID)

“OVER_QUERY_LIMIT” Error

Causes:
  • Exceeded quota limit
  • Billing not enabled
Solutions:
  1. Check quota usage
  2. Verify billing account is linked
  3. Increase quota limits
  4. Implement caching (already done in MND)

Quota Exceeded But Usage Looks Low

Possible causes:
  • Multiple projects using same billing account
  • Quota reset happens monthly, not daily
  • Cache not working (check cache hit rate)
Check cache effectiveness:
distanceMatrixClient.printStats();
Should show 80%+ cache hit rate.

API Key Not Working on Mobile

Android:
  • Verify package name matches: com.yourcompany.mnd_flutter
  • Check SHA-1 fingerprint is correct
  • Use release keystore SHA-1 for production
iOS:
  • Verify bundle identifier matches
  • Check API key is added to AppDelegate.swift
  • Ensure Maps SDK for iOS is enabled

Production Checklist

  • Google Cloud project created
  • Billing account linked
  • Distance Matrix API enabled
  • Backend API key created and restricted
  • Web API key created (if using maps)
  • Mobile API key created (if using Flutter)
  • API keys restricted by IP/domain/bundle ID
  • API keys stored in .env (not committed to git)
  • Quota limits configured
  • Billing alerts set up ($50 threshold)
  • Cache strategy implemented
  • API tested successfully
  • Monitoring configured

Next Steps

Build docs developers (and LLMs) love