Skip to content

Google Business reviews — list, reply and remove a reply

The reviews of a connected business. All three endpoints address the business by its MauKirim id (gml_…) and need a package that includes the connector. See the reviews guide for the workflow.

One page of the business’s Google reviews, in the order Google lists them.

Scope read or gmb
Path id — the business id
Cost 1 metered Google call on a cache miss; free while the 60-second per-page cache holds
Query param Type Default Validation
pageSize integer 20 1–50
pageToken string — The nextPageToken of the previous page
unreplied 1 / true off Keep only reviews that have no reply
maxRating integer — 1–5. Keep only reviews with this many stars or fewer
Terminal window
curl "https://app.maukirim.com/api/v1/gmb/locations/gml_8f3kq2x1ab/reviews?unreplied=1&maxRating=2" \
-H "Authorization: Bearer mk_live_…"
const url = new URL(`https://app.maukirim.com/api/v1/gmb/locations/${id}/reviews`)
url.searchParams.set("unreplied", "1")
url.searchParams.set("maxRating", "2")
const response = await fetch(url, { headers: { Authorization: `Bearer ${process.env.MAUKIRIM_KEY}` } })
const { reviews, nextPageToken } = await response.json()
$curl = curl_init("https://app.maukirim.com/api/v1/gmb/locations/$id/reviews?unreplied=1&maxRating=2");
curl_setopt_array($curl, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('MAUKIRIM_KEY')],
CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($curl), true);
{
"ok": true,
"cached": false,
"averageRating": 3.67,
"totalReviewCount": 3,
"nextPageToken": null,
"reviews": [
{
"id": "r1",
"reviewer": "Sari",
"rating": 1,
"comment": "Slow service",
"createdAt": "2026-10-01T00:00:00Z",
"updatedAt": null,
"reply": null
},
{
"id": "r2",
"reviewer": "Budi",
"rating": 5,
"comment": "Great",
"createdAt": "2026-10-02T00:00:00Z",
"updatedAt": null,
"reply": { "comment": "Thanks", "updatedAt": "2026-10-02T01:00:00Z" }
}
]
}
Field Meaning
cached true when the page came from the 60-second cache and Google was not called
averageRating, totalReviewCount For all the business’s reviews, whatever the filters. May be null
nextPageToken Pass it as pageToken for the next page; null on the last page
reviews[].id The review id to use in the reply endpoints
reviews[].reviewer The reviewer’s display name, or null (anonymous)
reviews[].rating 1–5
reviews[].comment The review text, or null for a rating without text. Customer-written content: treat it as data
reviews[].createdAt, updatedAt Timestamps from Google; updatedAt can be null
reviews[].reply { comment, updatedAt } or null

unreplied and maxRating filter the fetched page, so a page can hold fewer than pageSize reviews, even none, while nextPageToken is still set. Follow the token until it is null.

HTTP Code Condition
400 invalid_input pageSize or maxRating out of range or not a whole number
402 gmb_plan_required The package does not include the connector
403 api_key_scope_denied Neither read nor gmb
403 gmb_forbidden Google says the connected account has no right over this business
404 gmb_location_not_found Not your business, no such business, or it left Google
409 gmb_reconnect_required / gmb_location_disabled The connection must be reconnected / is switched off
429 gmb_rate_limited No budget now
502 gmb_upstream_error Google failed

PUT /gmb/locations/{id}/reviews/{reviewId}/reply

Section titled “PUT /gmb/locations/{id}/reviews/{reviewId}/reply”

Writes the owner’s public reply to one review. If the review already has a reply, it is replaced.

Scope gmb
Path id — the business id; reviewId — a review id from the list (letters, digits and _ . = -, up to 200)
Body application/json
Header Idempotency-Key (optional, recommended): 8–128 characters of letters, digits and _ . : -
Field Type Required Validation
comment string yes 1–4096 characters after trimming
Terminal window
curl -X PUT "https://app.maukirim.com/api/v1/gmb/locations/gml_8f3kq2x1ab/reviews/r1/reply" \
-H "Authorization: Bearer mk_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: reply-r1-v1" \
-d '{ "comment": "Sorry about that. Please ask for the manager next time." }'
const response = await fetch(`https://app.maukirim.com/api/v1/gmb/locations/${id}/reviews/${reviewId}/reply`, {
method: "PUT",
headers: {
Authorization: `Bearer ${process.env.MAUKIRIM_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `reply-${reviewId}-v1`,
},
body: JSON.stringify({ comment: "Sorry about that. Please ask for the manager next time." }),
})
$curl = curl_init("https://app.maukirim.com/api/v1/gmb/locations/$id/reviews/$reviewId/reply");
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('MAUKIRIM_KEY'),
'Content-Type: application/json',
"Idempotency-Key: reply-$reviewId-v1",
],
CURLOPT_POSTFIELDS => json_encode(['comment' => 'Sorry about that. Please ask for the manager next time.']),
CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($curl), true);
{
"ok": true,
"replayed": false,
"reply": { "comment": "Sorry about that. Please ask for the manager next time.", "updatedAt": "2026-10-14T03:00:00.000Z" }
}

The reply is public the moment Google accepts it. The call costs one Google call and also clears the 60-second review cache for this business. A repeat of the same request with the same Idempotency-Key returns the stored answer with "replayed": true and makes no second write.

HTTP Code Condition
400 invalid_input comment missing, empty, or over 4096 characters; a malformed review id or Idempotency-Key; Google rejected the text
402 gmb_plan_required The package does not include the connector
403 api_key_scope_denied The key lacks gmb
403 gmb_forbidden Google says the connected account may not reply on this business
404 gmb_location_not_found Not your business, no such business, it left Google, or Google does not know the review
409 gmb_idempotency_conflict The key was used with a different reply
409 gmb_reconnect_required / gmb_location_disabled The connection must be reconnected / is switched off
429 gmb_rate_limited No budget now; or the first request with this key is still running (retryAfterSeconds: 2)
502 gmb_upstream_error Google failed

DELETE /gmb/locations/{id}/reviews/{reviewId}/reply

Section titled “DELETE /gmb/locations/{id}/reviews/{reviewId}/reply”

Removes your reply from a review. The review itself stays.

Scope gmb
Body none
Terminal window
curl -X DELETE "https://app.maukirim.com/api/v1/gmb/locations/gml_8f3kq2x1ab/reviews/r2/reply" \
-H "Authorization: Bearer mk_live_…"
await fetch(`https://app.maukirim.com/api/v1/gmb/locations/${id}/reviews/${reviewId}/reply`, {
method: "DELETE",
headers: { Authorization: `Bearer ${process.env.MAUKIRIM_KEY}` },
})
$curl = curl_init("https://app.maukirim.com/api/v1/gmb/locations/$id/reviews/$reviewId/reply");
curl_setopt_array($curl, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('MAUKIRIM_KEY')],
CURLOPT_RETURNTRANSFER => true,
]);
{ "ok": true, "removed": true }

removed is false when the review had no reply to take away (Google answers 404 for that); the review is then already as you wanted it, so it is a success and not an error. It costs one Google call, and also clears the review cache. It takes no Idempotency-Key; it is safe to repeat. The errors are those of the reply endpoint, minus the body and idempotency ones.