This page lists every external, third-party API Safe2Go's server code actually calls (found by auditing server/services/ and server/routes/ directly — not a guess), what each is used for, and its real published free-tier limit as of 2026-09-21. Free-tier terms change without notice on the provider's side; the "checked" date on each card is when that number was last verified against the provider's own pricing/docs page, not when it was set.
Geocoding (address → coordinates) — tried in this fallback order
1. LocationIQ
5,000 req/day, 2 req/sec
Used by: geocode.js primary geocoding tier.
We send: the free-text search query, result limit. We ask for: forward-geocode search results (/v1/search) — we read each match's lat, lon, and display_name (split into name + sub-address).
Source: locationiq.com/pricing — checked 2026-09-21
2. OpenCage
2,500 req/day, 1 req/sec
Used by: geocode.js fallback tier. Free trial accounts are deleted after 3 months of inactivity.
We send: the free-text search query, result limit, no_annotations=1 (we don't need OpenCage's extra timezone/currency annotations). We ask for: each result's geometry.lat/lng and formatted address string.
Source: opencagedata.com/pricing — checked 2026-09-21
3. TomTom (Geocoding)
20,000 req/month
Used by: geocode.js fallback tier, and separately for traffic speed data (see below — same key, shared quota).
We send: the free-text search query, result limit. We ask for: each result's position.lat/lon and address.freeformAddress.
Source: docs.tomtom.com/pricing — checked 2026-09-21
4. Mappls (MapmyIndia)
Not publicly documented
Used by: geocode.js India-specific autosuggest/geocoding tier — catches real hyperlocal colony/address names (e.g. "Satyam Enclave, Sahibabad") no free/government source carries.
We send: the free-text query, and the searcher's own bias lat/lng if known (only affects ranking, never gates whether Mappls is consulted — see code comment on why). We ask for: Autosuggest candidates (placeName, placeAddress, eLoc) — note Mappls' Autosuggest does NOT return coordinates directly, so each candidate's address text is re-resolved to real lat/lng via a separate Photon call.
Mappls does not publish an exact free-tier request quota anywhere on its pricing or developer pages — only "start for free." The actual limit is only visible inside your own Mappls console account. Worth checking there directly since this is India's primary geocoding fallback.
Checked: about.mappls.com/api, developer.mappls.com — 2026-09-21
Correction (2026-09-21): this card previously said Google Maps was also used for geocoding in geocode.js — that was wrong. A direct grep of the codebase confirms GOOGLE_MAPS_API_KEY is used ONLY in traffic.js/routes/traffic.js, for the Directions API's traffic-aware ETA — never for geocoding. There is no Google geocoding code path in Safe2Go at all. Moved to the Traffic section below, where it actually belongs.
Nominatim (OpenStreetMap) — free, no key
1 req/sec (app-wide, not per-user)
Used by: geocode.js as a no-key forward-search fallback, and as the ONLY source for reverse geocoding (pin-drop → address) — its reverse endpoint already gives clean house-number/road results.
We send (forward): free-text query, result limit, addressdetails=1, a real identifying User-Agent (Safe2Go/1.0, required by Nominatim's own usage policy). We ask for: lat/lon and display_name per result.
This is a shared community service with no SLA — the 1 req/sec cap applies to Safe2Go's entire user base combined, not per visitor. Real outages have happened before (see project memory on Overpass/Nominatim rate-limiting).
Source: operations.osmfoundation.org/policies/nominatim — checked 2026-09-21
Photon (Komoot) — free, no key
No published fixed quota (fair-use)
Used by: geocode.js as the PRIMARY forward-search tier (better fuzzy/typo/POI matching and proximity bias than Nominatim's exact left-anchored matching) — also used internally to resolve Mappls' address-only candidates into real coordinates.
We send: free-text query, result limit, optional lat/lon proximity bias. We ask for: GeoJSON features — we read geometry.coordinates and properties (name, street, housenumber, city, state, country) to build a display name.
Points of Interest (POI) fallback
Geoapify
3,000 credits/day
Used by: poiFallback.js — last-resort nearest-transit-stop lookup, only called when Overpass + the GTFS database + OSM PostGIS all come back empty for a point (not fired on every request).
We send: lat/lng, a 3-category filter (public_transport.train,subway,tram), search radius, proximity bias. We ask for: the single nearest matching place's name, lat/lon, distance, and category.
Source: geoapify.com/pricing — checked 2026-09-21
Foursquare Places
500 free Pro calls/month (cut from 10,000)
Used by: poiFallback.js — same last-resort role as Geoapify, tried alongside/after it.
We send: lat/lng, search radius (capped 100km), free-text query "train station" (chosen over a numeric category ID since Foursquare's category reference couldn't be verified live). We ask for: the nearest result's name, latitude/longitude, distance, fsq_place_id.
Real, current risk: Foursquare cut its free Pro-tier allowance from 10,000 to 500 calls/month effective June 1, 2026 — already in effect now. If Safe2Go relies on this for regular POI traffic, it may already be hitting this ceiling far sooner than before. Premium fields (photos/tips/hours/ratings) have no free tier at all.
Source: Foursquare's own developer change notice — checked 2026-09-21
Traffic
TomTom Traffic (Incidents/Flow)
2,500 req/month
Used by: traffic.js. Note: much lower than TomTom's geocoding limit (20,000/month) — same account, separate per-SKU quota.
We send (flow): a single lat/lng point, unit=KMPH. We ask for: currentSpeed, freeFlowSpeed, confidence, currentTravelTime vs freeFlowTravelTime — used to compute a congestion ratio and delay in seconds. We send (incidents): a bounding box around a point + radius. We ask for: incident type, description, delay, affected road segment.
Source: docs.tomtom.com/pricing — checked 2026-09-21
Google Directions (traffic fallback)
10,000 free calls/month (Essentials plan)
Used by: traffic.js, only when TOMTOM_API_KEY is unset or TomTom's own call fails — route-level traffic-aware ETA, not point-level speed like TomTom. Confirmed via direct grep: this is Google's only role in Safe2Go — there is no Google geocoding code path anywhere in this app.
We send: origin lat/lng, destination lat/lng, departure_time=now, traffic_model=best_guess. We ask for: the route leg's normal duration vs. duration_in_traffic, and distance — used to compute a congestion ratio and delay in seconds (an approximate current speed is derived from distance ÷ traffic time, since Directions doesn't return a speed field directly).
Code comment is now outdated: traffic.js's own comment says "$200/mo credit ≈ 40k calls free" — that was Google's old flat-credit model. Google moved to a tiered Essentials/Pro/Enterprise structure; Essentials now gives 10,000 free calls/month per SKU (Pro: 5,000; Enterprise: 1,000), not a $200 credit pool. Worth updating that comment.
Source: mapsplatform.google.com/pricing — checked 2026-09-21
Routing (self-hosted / free public)
Valhalla (self-hosted, Hetzner)
No external limit — it's yours
Used by: valhallaRoute.js. Not a third-party API at all — runs on 178.104.175.3. Real constraint is that server's own CPU/RAM, not any quota.
We send: origin/destination lat/lng, travel mode. We ask for: the route's distance, duration, and per-maneuver detail — including maneuver type 28 (ferry) used by tonight's ferry-crossing detection fix.
OSRM public demo server
Unpublished fair-use, shared community server
Used by: osrm.js as a cross-check against Valhalla (see the ferry-detection fix from 2026-09-21). No SLA, no key, can be slow/unavailable under load.
We send: origin/destination lat/lng, steps=true (needed to detect non-driving segments, e.g. a ferry leg). We ask for: total distance/duration, plus each step's mode and distance — summed for any step where mode isn't "driving" to compute real ferry-segment length.
AI / LLM
Groq (openai/gpt-oss-120b)
30 req/min, 1,000 req/day, 8,000 tokens/min, 200,000 tokens/day
Used by: routes/ai.js (the exact model is hardcoded as MODEL = 'openai/gpt-oss-120b') — the in-app chat assistant.
We send: the user's chat messages, a system prompt, and a tool definition (plan_journey) the model can invoke with a free-text destination/origin and preferred transport modes. We ask for: the model's text reply, or a tool-call request — which the server then executes itself (real geocoding + the real route planner, not the LLM inventing route data) and feeds the real result back to the model to describe to the user.
1,000 requests/day is a real, fairly tight ceiling if this powers a user-facing chat/assist feature at any real traffic volume. Also see project memory: Groq has deprecated models with no notice before — verify via GET /v1/models periodically.
Source: console.groq.com/docs/rate-limits — checked 2026-09-21
Payments & Identity — not quota-limited the same way
Stripe
Pay-per-transaction, no free request quota
Used by: billing.js. Stripe isn't rate-limited in the "runs out of free calls" sense — it charges a percentage fee per real transaction, with a separate high API-call rate limit (100 req/sec live mode) that's irrelevant at Safe2Go's scale.
Google OAuth
Not meaningfully rate-limited at this scale
Used by: auth.js for sign-in. Google doesn't publish a consumer-facing quota for standard OAuth sign-in traffic.
Gmail SMTP
500 emails/day (regular Gmail account)
Used by: whatever sends real emails via GMAIL_USER/GMAIL_APP_PASSWORD (e.g. password resets). If this is a regular Gmail account (not Google Workspace, which allows 2,000/day), 500/day is the real ceiling.
Misc
ipwho.is (IP geolocation)
1,000 req/day per client
Source: ipwho.io rate-limit docs — checked 2026-09-21