Google Business verification
A business must be verified before Google shows many of its changes publicly. These endpoints let you drive Google’s verification from the API. They are served by Google’s Verifications API, a separate Google API from the ones that list and edit businesses. Who manages the listing is on the managers page. Every call is one metered Google call and needs a package that includes the connector.
These APIs may need enabling and approval. If the Verifications API is not enabled or approved for the Google project MauKirim runs under, these calls answer
503 gmb_api_unavailable. That is an operator-side problem. Google also limits how often a business may be verified, and which methods it offers varies by business; we do not restate Google’s rules, so rely on the options endpoint.
A new business starts unverified
Section titled “A new business starts unverified”A business you create through the API (or an
assistant) is not verified: its verificationState reads unverified, and Google does not apply many public
changes to it until it is. The flow from nothing to a live listing is:
POST /gmb/connections/{id}/locations(usevalidateOnlyfirst) — returns the new business’sid.POST …/verifications/options— which methods Google offers for this address (a postcard to the address is the usual one; others appear when Google can confirm the business another way).POST …/verifications/startwith one of them.POST …/verifications/{verificationId}/completewith the code the business receives. A postcard takes days, so keep the verification id and come back.- Add photos and posts.
The usual order
Section titled “The usual order”GET …/verifications— is it already verified or pending?POST …/verifications/options— which methods does Google offer now?POST …/verifications/startwith one of those methods.- When the person at the business receives the code,
POST …/verifications/{verificationId}/complete.
The verification objects are passed through in Google’s own shape.
GET /gmb/locations/{id}/verifications
Section titled “GET /gmb/locations/{id}/verifications”| Scope | read or gmb |
curl https://app.maukirim.com/api/v1/gmb/locations/gml_8f3kq2x1ab/verifications -H "Authorization: Bearer mk_live_…"{ "ok": true, "verifications": [ { "name": "locations/123/verifications/v1", "method": "EMAIL", "state": "PENDING", "createTime": "2026-10-14T03:00:00Z" } ]}state is Google’s (PENDING, COMPLETED, FAILED). The id to use in step 4 is the last segment of name.
POST /gmb/locations/{id}/verifications/options
Section titled “POST /gmb/locations/{id}/verifications/options”Asks Google which verification methods are available for this business right now. It changes nothing at
Google, but it is a POST, so it needs the gmb scope.
| Scope | gmb |
| Body | Optional { "languageCode": "en" } (default en) |
{ "ok": true, "options": [ { "verificationMethod": "EMAIL", "emailData": { "domain": "example.com", "user": "owner" } }, { "verificationMethod": "SMS", "phoneNumber": "+62 21 5550 100" } ]}POST /gmb/locations/{id}/verifications/start
Section titled “POST /gmb/locations/{id}/verifications/start”Starts a verification. Google sends a code or a postcard to the business, so call it only with a method the options endpoint offered, and tell whoever will receive it.
| Scope | gmb |
| Header | Idempotency-Key (optional, recommended): 8–128 characters of letters, digits and _ . : - |
| Field | Required | Rule |
|---|---|---|
method |
yes | ADDRESS (postcard), EMAIL, PHONE_CALL, SMS, AUTO or VETTED_PARTNER |
languageCode |
no | Up to 16 characters; default en |
emailAddress |
for EMAIL |
A valid email address, up to 254 characters |
phoneNumber |
for SMS and PHONE_CALL |
Up to 32 characters |
mailerContact |
no | For ADDRESS: the contact name on the postcard, up to 100 characters |
curl -X POST https://app.maukirim.com/api/v1/gmb/locations/gml_8f3kq2x1ab/verifications/start \ -H "Authorization: Bearer mk_live_…" -H "Content-Type: application/json" \ -H "Idempotency-Key: verify-gml_8f3kq2x1ab-email-1" \ -d '{ "method": "EMAIL", "emailAddress": "owner@example.com" }'const response = await fetch(`https://app.maukirim.com/api/v1/gmb/locations/${id}/verifications/start`, { method: "POST", headers: { Authorization: `Bearer ${process.env.MAUKIRIM_KEY}`, "Content-Type": "application/json", "Idempotency-Key": `verify-${id}-email-1`, }, body: JSON.stringify({ method: "EMAIL", emailAddress: "owner@example.com" }),})const { verification } = await response.json()$curl = curl_init("https://app.maukirim.com/api/v1/gmb/locations/$id/verifications/start");curl_setopt_array($curl, [ CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('MAUKIRIM_KEY'), 'Content-Type: application/json', "Idempotency-Key: verify-$id-email-1", ], CURLOPT_POSTFIELDS => json_encode(['method' => 'EMAIL', 'emailAddress' => 'owner@example.com']), CURLOPT_RETURNTRANSFER => true,]);$verification = json_decode(curl_exec($curl), true)['verification'];{ "ok": true, "replayed": false, "verification": { "name": "locations/123/verifications/v2", "method": "EMAIL", "state": "PENDING" }}The same key with the same body is "replayed": true and starts no second verification (so no second
email or postcard); a different body under the same key is 409 gmb_idempotency_conflict. The response is 200.
POST /gmb/locations/{id}/verifications/{verificationId}/complete
Section titled “POST /gmb/locations/{id}/verifications/{verificationId}/complete”Enters the code the business received.
| Scope | gmb |
| Path | verificationId — from the list or the start answer (letters, digits and _ . = -) |
| Body | { "pin": "123456" } — 4–8 digits |
curl -X POST https://app.maukirim.com/api/v1/gmb/locations/gml_8f3kq2x1ab/verifications/v2/complete \ -H "Authorization: Bearer mk_live_…" -H "Content-Type: application/json" \ -d '{ "pin": "123456" }'{ "ok": true, "verification": { "name": "locations/123/verifications/v2", "method": "EMAIL", "state": "COMPLETED" } }A malformed pin is 400 invalid_input before Google is called; a wrong code is refused by Google, which also
answers 400 invalid_input. Google limits the attempts, so do not guess. MauKirim does not log the pin.
Errors
Section titled “Errors”| HTTP | Code | Condition |
|---|---|---|
| 400 | invalid_input |
An unknown method, a missing emailAddress or phoneNumber, an invalid email, a malformed pin or id or key, or Google refused the request (a wrong code, a method not offered) |
| 401 | api_key_invalid / api_key_revoked / api_key_expired |
|
| 402 | gmb_plan_required |
The package does not include the connector |
| 403 | api_key_scope_denied |
Writes (including options) need gmb; reads need read or gmb |
| 403 | gmb_forbidden |
Google says the connected account may not verify this business |
| 404 | gmb_location_not_found |
Not your business, no such business, it left Google, or no such verification |
| 409 | gmb_reconnect_required / gmb_location_disabled / gmb_idempotency_conflict |
See Errors |
| 429 | gmb_rate_limited |
No budget now (Retry-After) |
| 502 | gmb_upstream_error |
Google failed |
| 503 | gmb_api_unavailable |
The Verifications API is not enabled or approved for the deployment’s Google project |