Updated Oct 2026

Google reviews API in Java: three ways, with working code

Google has two reviews APIs with different jobs. The Places API returns up to 5 public reviews of any place for an API key. The Business Profile API returns every review of the locations you own and lets you reply, through OAuth, after Google approves your Cloud project. Both below in Java 17+ with java.net.http and Jackson, no framework, then the same through Prisma for Google plus 50+ other platforms. Python, Node.js and PHP versions: Python, Node.js, PHP.

xml
<!-- pom.xml -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.17.2</version></dependency>
<dependency><groupId>com.google.auth</groupId><artifactId>google-auth-library-oauth2-http</artifactId><version>1.24.1</version></dependency>

1. Places API: 5 reviews of any place (API key)

Create a key restricted to the Places API (New) (how) and find the place ID.

java
import java.net.URI;
import java.net.http.*;
import com.fasterxml.jackson.databind.*;

public class PlacesReviews {
  public static void main(String[] args) throws Exception {
    String placeId = "ChIJN1t_tDeuEmsRUsoyG83frY4";
    HttpClient http = HttpClient.newHttpClient();
    HttpRequest req = HttpRequest.newBuilder(URI.create("https://places.googleapis.com/v1/places/" + placeId))
        .header("X-Goog-Api-Key", System.getenv("GOOGLE_MAPS_API_KEY"))
        .header("X-Goog-FieldMask", "displayName,rating,userRatingCount,reviews")
        .GET().build();
    HttpResponse<String> res = http.send(req, HttpResponse.BodyHandlers.ofString());
    if (res.statusCode() != 200) throw new RuntimeException(res.statusCode() + " " + res.body());
    JsonNode place = new ObjectMapper().readTree(res.body());
    System.out.println(place.path("displayName").path("text").asText() + " " + place.path("rating").asDouble() + " (" + place.path("userRatingCount").asInt() + ")");
    for (JsonNode r : place.path("reviews"))
      System.out.println(r.path("rating").asInt() + " " + r.path("authorAttribution").path("displayName").asText() + ": " + r.path("text").path("text").asText(""));
  }
}

At most 5 reviews, chosen by Google, no owner replies, no way to post one, billed per request as Place Details with the Pro fields. Right for a “what people say” block, wrong for managing your reviews.

2. Business Profile API: every review of your locations, with replies (OAuth)

Prerequisites: a Cloud project with the Business Profile APIs enabled and access approved by Google (quota 0 until then), an OAuth client, and a refresh token obtained once by an owner or manager of the profile (any OAuth flow; the Google auth library handles the refresh).

java
import java.net.URI;
import java.net.http.*;
import java.util.*;
import com.fasterxml.jackson.databind.*;
import com.google.auth.oauth2.*;

public class BusinessProfileReviews {
  static final HttpClient http = HttpClient.newHttpClient();
  static final ObjectMapper json = new ObjectMapper();
  static String token;

  static JsonNode get(String url) throws Exception {
    HttpRequest req = HttpRequest.newBuilder(URI.create(url)).header("Authorization", "Bearer " + token).GET().build();
    HttpResponse<String> res = http.send(req, HttpResponse.BodyHandlers.ofString());
    if (res.statusCode() != 200) throw new RuntimeException(res.statusCode() + " " + res.body());
    return json.readTree(res.body());
  }

  public static void main(String[] args) throws Exception {
    UserCredentials creds = UserCredentials.newBuilder()
        .setClientId(System.getenv("GOOGLE_CLIENT_ID")).setClientSecret(System.getenv("GOOGLE_CLIENT_SECRET"))
        .setRefreshToken(System.getenv("GOOGLE_REFRESH_TOKEN")).build();
    creds.refreshIfExpired();
    token = creds.getAccessToken().getTokenValue();   // scope: https://www.googleapis.com/auth/business.manage

    String account = get("https://mybusinessaccountmanagement.googleapis.com/v1/accounts").path("accounts").get(0).path("name").asText();
    String location = get("https://mybusinessbusinessinformation.googleapis.com/v1/" + account + "/locations?readMask=name,title").path("locations").get(0).path("name").asText();

    Map<String, Integer> stars = Map.of("ONE", 1, "TWO", 2, "THREE", 3, "FOUR", 4, "FIVE", 5);
    String pageToken = null;
    do {
      String url = "https://mybusiness.googleapis.com/v4/" + account + "/" + location + "/reviews?pageSize=50" + (pageToken != null ? "&pageToken=" + pageToken : "");
      JsonNode page = get(url);
      for (JsonNode r : page.path("reviews"))
        System.out.println(stars.get(r.path("starRating").asText()) + " " + r.path("reviewer").path("displayName").asText() + ": " + r.path("comment").asText("") + (r.has("reviewReply") ? " [replied]" : ""));
      pageToken = page.hasNonNull("nextPageToken") ? page.get("nextPageToken").asText() : null;
    } while (pageToken != null);
  }
}

Reply, edit, delete

java
String reviewName = r.path("name").asText();   // accounts/…/locations/…/reviews/…
String body = json.writeValueAsString(Map.of("comment", "Thank you, Laura. We've passed your note to the kitchen team."));
HttpRequest put = HttpRequest.newBuilder(URI.create("https://mybusiness.googleapis.com/v4/" + reviewName + "/reply"))
    .header("Authorization", "Bearer " + token).header("Content-Type", "application/json")
    .PUT(HttpRequest.BodyPublishers.ofString(body)).build();
http.send(put, HttpResponse.BodyHandlers.ofString());
// the same PUT edits an existing reply; DELETE on …/reply removes it

Limits: 300 queries per minute per project, 10 reply edits per minute per profile, 4,096 bytes per reply; ratings arrive as the enum ONE…FIVE. Backoff and 429s: quota guide.

3. Prisma: one key, Google and 50+ other platforms

java
HttpClient http = HttpClient.newHttpClient();
ObjectMapper json = new ObjectMapper();
String key = "Bearer " + System.getenv("PRISMA_API_KEY");

HttpRequest list = HttpRequest.newBuilder(URI.create("https://api.prismareviews.com/v1/reviews?has_reply=false&limit=100"))
    .header("Authorization", key).GET().build();
JsonNode page = json.readTree(http.send(list, HttpResponse.BodyHandlers.ofString()).body());
for (JsonNode r : page.path("data"))
  System.out.println(r.path("platform").asText() + " " + r.path("rating").asInt() + " " + r.path("author").asText("") + ": " + r.path("text").asText(""));

String reviewId = page.path("data").get(0).path("id").asText();
HttpRequest reply = HttpRequest.newBuilder(URI.create("https://api.prismareviews.com/v1/reviews/" + reviewId + "/reply"))
    .header("Authorization", key).header("Content-Type", "application/json").header("Idempotency-Key", UUID.randomUUID().toString())
    .POST(HttpRequest.BodyPublishers.ofString(json.writeValueAsString(Map.of("text", "Thank you, Laura. We've passed your note to the kitchen team.")))).build();
http.send(reply, HttpResponse.BodyHandlers.ofString());

Same fields on every platform, rating always 1 to 5, the reply with its status, a review.created webhook instead of polling, Idempotency-Key so a retried reply never posts twice, and test keys that return sample data before any account is connected. Reference: reviews, replies, webhooks.

What’s true today: Prisma reads Google reviews from the Google Maps listing (public, read-only) while Google reviews Prisma’s Business Profile API application; replies on Google through Prisma start when that approval arrives. Replies already work by API on the App Store, Google Play, Judge.me, eBay, Trusted Shops, eKomi and others (Platforms).

FAQ

Is there a Java client library for the Google reviews API?

Google publishes Java clients for the Business Profile account and business-information APIs, but reviews still live on the v4 endpoints, so most teams use google-auth-library-oauth2-http for the token and a plain HTTP client for the calls. The Places API is one HTTPS request with an API key.

Why does my Java code get 429 with quota 0?

Because the Cloud project hasn’t been approved for Business Profile API access yet. Until Google approves the application, the quota is 0 queries per minute; after approval it is 300.

Can I reply to Google reviews from Java?

Yes, with the Business Profile API: PUT accounts/{a}/locations/{l}/reviews/{r}/reply with a JSON body {"comment": "..."}, authenticated as an owner or manager of the profile, after approval. The same PUT edits; DELETE removes the reply.

One HTTP client, every platform.

Get API key

2 locations free. Test keys return sample reviews, so the code above runs today.

Get your API key in a minute

Free Spark plan: 2 locations, no card. Test keys return sample data on all 58 platforms, so you can build before connecting a real one.