API Documentation
Cached Google reviews for your website. Create an account, add a site with your Place ID and website URL, subscribe, and you'll get a key to use in the API. Use the Find Place ID tool to look up your business.
What this does
We fetch your Google reviews from Google Places, cache them, and serve them to your website via a simple API. Reviews are kept fresh automatically: whenever your site requests reviews and they're older than 24 hours, we fetch the latest from Google and merge them into the cache. Over time the cache grows (Google returns up to 5 per fetch; we accumulate them). Your site calls us with your key, we return the reviews. No Google API key needed on your side.
You get: total review count (userRatingCount), average rating, individual reviews with author names and text, and links so visitors can verify every review on Google — and leave one themselves.
How to get reviews
One endpoint. Your key goes in the URL — no API key header. Get your key from the account page after creating a site and subscribing. Use query parameters to control what you get.
GET https://reviews.overunity.ca/api/reviews/{OVERUNITY_KEY}?limit=1&sort=latest Example (curl):
curl "https://reviews.overunity.ca/api/reviews/$OVERUNITY_KEY?limit=1" Important: Fetch from your backend or serverless function. Keep your key in environment variables; never expose it in client-side JavaScript.
Query parameters
Control which reviews you get and how they're ordered:
limit
Return at most N reviews. Default: all. Use limit=1 for "show the latest review".
?limit=1sort
latest (default) — newest first. random — shuffle. Use with limit=1 for a random review.
?sort=random&limit=1since
Only return reviews published on or after this date (ISO 8601). E.g. last 30 days: since=2025-02-04.
?since=2025-02-01Implementation guide
Common patterns — use the right URL and you're done:
Total reviews & rating
userRatingCount = total on Google (e.g. 127). rating = average (e.g. 4.8). Display "4.8 stars from 127 reviews". Link "View all 127 on Google" to googleMapsPlaceUrl.
Show the latest review
?limit=1 — returns the most recent. No client-side logic needed.
/api/reviews/{key}?limit=1Show a random review
?sort=random&limit=1 — different review on each request. Rotates automatically.
/api/reviews/{key}?sort=random&limit=1Show all cached reviews
No params, or ?limit=10 for the 10 most recent. We accumulate reviews over time (daily merge); you may have dozens or hundreds cached.
Google links — verify, review, explore
The response includes three types of Google links:
googleMapsPlaceUrl — the business's Google Maps listing. Use for "See all reviews on Google" or "View on Google Maps".
googleWriteReviewUrl — opens Google's write-a-review dialog directly. Use for a "Write a Review" call-to-action button.
reviews[n].googleMapsUri — links to that specific review on Google. Add a small ↗ icon to each review card so visitors can verify it's real.
Response format
Full structure returned by GET /api/reviews/{key}:
{
"key": "your-key",
"placeId": "ChIJ...",
"businessName": "Your Business Name",
"rating": 4.8,
"userRatingCount": 127,
"googleMapsPlaceUrl": "https://www.google.com/maps/search/?api=1&query_place_id=ChIJ...",
"googleWriteReviewUrl": "https://search.google.com/local/writereview?placeid=ChIJ...",
"reviews": [
{
"author": "John D.",
"rating": 5,
"text": "Great service! Highly recommend.",
"relativeTime": "2 weeks ago",
"publishTime": "2025-02-15T12:00:00.000Z",
"authorPhotoUri": "https://...",
"googleMapsUri": "https://www.google.com/maps/..."
}
],
"fetchedAt": "2025-03-05T03:00:00.000Z",
"stale": false,
"source": "google_places",
"poweredBy": { "text": "Powered by OverUnity", "url": "https://reviews.overunity.ca" }
} userRatingCount — Total reviews on Google (can be hundreds). This is the real count, not the length of the reviews array.
reviews — Array of cached reviews (filtered/sorted/limited by query params). We merge new reviews daily; the cache grows over time. Each review has author, rating, text, relativeTime, publishTime, authorPhotoUri, googleMapsUri.
googleMapsPlaceUrl — Direct link to your Google Business / Maps listing. Use for "See all reviews on Google".
googleWriteReviewUrl — Opens Google's review submission dialog directly. Use for a "Write a Review" button.
googleMapsUri (per review) — Link to that specific review on Google. Use for individual review verification.
poweredBy — Display a small "Powered by OverUnity" link at the bottom of the reviews section (required).
Drop this into Cursor, Claude, ChatGPT, Warp, or any AI coding assistant to implement the full integration automatically.
You are implementing Google reviews display for a website using the Overunity Reviews API.
## Service
Overunity Reviews (https://reviews.overunity.ca) fetches, caches, and serves Google Maps
business reviews via a simple JSON API. No Google API key is needed on your end. All Google API
calls happen server-side at Overunity. Reviews are kept fresh automatically.
## Credentials
Add to .env — value provided by the site owner / Overunity:
OVERUNITY_KEY=your-key # 32-char key derived from Place ID + website URL
## Endpoint
GET https://reviews.overunity.ca/api/reviews/{OVERUNITY_KEY}
No API key header. The key in the URL authenticates the request.
CRITICAL: Always fetch server-side. Never call this from browser/client JavaScript.
Use a Next.js server component, SvelteKit +page.server.ts, API route, or serverless function.
## Query Parameters (all optional)
?limit=N Return at most N reviews (e.g. limit=3 for a reviews section)
?sort=latest Newest first (default)
?sort=random Random order — use with limit=1 for a rotating testimonial widget
?since=YYYY-MM-DD Only reviews published on or after this ISO date
## Full Response Shape
{
"key": "your-key",
"placeId": "ChIJ...",
"businessName": "Business Name", // Official name from Google
"rating": 4.8, // Google average rating (float, 1.0–5.0)
"userRatingCount": 127, // Total reviews on Google (often 100s)
// NOTE: NOT the same as reviews.length
"googleMapsPlaceUrl": "https://...", // → "See all reviews on Google" / "View on Google Maps"
"googleWriteReviewUrl": "https://...", // → "Write a review" CTA (opens Google review dialog)
"fetchedAt": "2025-03-05T03:00:00Z", // ISO timestamp of last Google fetch
"stale": false, // true if cache couldn't be refreshed
"source": "google_places",
"poweredBy": { "text": "Powered by OverUnity", "url": "https://reviews.overunity.ca" }, // Display at bottom (required)
"reviews": [
{
"author": "Jane S.", // Reviewer's Google display name
"rating": 5, // Integer 1–5
"text": "Amazing service!", // Full review text
"relativeTime": "2 weeks ago", // Human-readable string from Google — use for display
"publishTime": "2025-02-15T12:00:00.000Z", // ISO date — use for filtering or sorting
"authorPhotoUri": "https://...", // Google profile photo URL; may be null
"googleMapsUri": "https://..." // Direct link to this specific review on Google
}
]
}
## UI Implementation — What to Build
### Business summary / rating block
- Render the star rating visually (e.g. ★★★★★ filled/empty based on rating value)
- Display: "{rating} · {userRatingCount} Google reviews"
- Link "View all reviews on Google" → googleMapsPlaceUrl (target="_blank", rel="noopener")
- CTA button: "Write a Review" → googleWriteReviewUrl (target="_blank", rel="noopener")
### Review cards
- Show: author name + avatar (authorPhotoUri, circular, null-safe), star rating, review text, relativeTime
- Add a small "↗ View on Google" link per card using googleMapsUri — this builds trust
- Truncate long review text with a "Read more" toggle if needed
### "See all reviews" CTA
- Button or text link → googleMapsPlaceUrl — takes the user to the full Google listing
### Empty / error state (always handle this)
- Condition: !data || data.reviews.length === 0 || data.stale === true
- Show graceful fallback: "Reviews temporarily unavailable" or similar
- Never crash; the API will always return a valid JSON object
### Attribution (required)
Display a small "Powered by OverUnity" link at the bottom of the reviews section. The API returns `poweredBy: { text, url }`.
Use subtle styling: ~11px font, muted color (#6b7280 or similar). Example:
<a href="https://reviews.overunity.ca" target="_blank" rel="noopener" style="font-size:11px;color:#6b7280;">Powered by OverUnity</a>
## Server-side Fetch Examples
### SvelteKit (+page.server.ts or +layout.server.ts)
import { env } from '$env/dynamic/private';
export async function load({ fetch }) {
try {
const res = await fetch(
`https://reviews.overunity.ca/api/reviews/${env.OVERUNITY_KEY}`
);
if (!res.ok) return { reviews: null };
return { reviews: await res.json() };
} catch {
return { reviews: null };
}
}
### Next.js App Router (server component)
const res = await fetch(
`https://reviews.overunity.ca/api/reviews/${process.env.OVERUNITY_KEY}`,
{ next: { revalidate: 3600 } } // Re-fetch at most every hour
);
const reviews = res.ok ? await res.json() : null;
### Next.js API Route (/app/api/reviews/route.js)
export async function GET() {
const res = await fetch(
`https://reviews.overunity.ca/api/reviews/${process.env.OVERUNITY_KEY}`
);
return Response.json(res.ok ? await res.json() : { reviews: [], stale: true });
}
### WordPress / PHP
$response = wp_remote_get(
'https://reviews.overunity.ca/api/reviews/' . getenv('OVERUNITY_KEY')
);
$data = json_decode(wp_remote_retrieve_body($response), true);
### Node.js / Express
const res = await fetch(
`https://reviews.overunity.ca/api/reviews/${process.env.OVERUNITY_KEY}`
);
const data = await res.json();
## HTTP Error Codes
404 — Key not found (check OVERUNITY_KEY)
503 — Service temporarily unavailable (show fallback UI)Get your key
Go to Account, enter your email to sign in or create an account, add a site with your Place ID and website URL, subscribe, and you'll get your key. Need help? Get in touch.