# Verify a location

Check whether a Google Business Profile location is verified, see which methods Google offers, start a verification and submit the code.

Google only fully trusts a listing once the business proves it is real. Until then reviews do not come through, many edits do not publish and some listing data is missing. Google calls a verified, published listing "Voice of Merchant". This page shows how to check that state and run a verification from your own product, so a new client never has to leave it to finish setup.

## Check the state

[`GET /v1/accounts/{accountId}/gmb-verifications`](https://pozy.ai/docs/api/getGoogleBusinessVerifications) returns the location's Voice of Merchant state and its verification history.

```bash cURL
curl https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications \
  -H "Authorization: Bearer $POZY_API_KEY"
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications", {
  headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);

if (!data.voiceOfMerchantState.hasVoiceOfMerchant) {
  console.log("Not verified. Pending:", data.voiceOfMerchantState.verify?.hasPendingVerification);
}
```
```python Python
import os
import requests

H = {"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"}
state = requests.get(
    "https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications",
    headers=H, timeout=30,
).json()
print(state["voiceOfMerchantState"])
```

```json
{
  "success": true,
  "accountId": "6713b0e5d1f4c69a2b8e3f75",
  "locationId": "4821930576104832190",
  "voiceOfMerchantState": {
    "hasVoiceOfMerchant": false,
    "hasBusinessAuthority": true,
    "verify": { "hasPendingVerification": false }
  },
  "verifications": [
    { "name": "locations/4821930576104832190/verifications/7Q2093841176", "method": "SMS", "state": "FAILED", "createTime": "2026-10-20T15:02:00Z" }
  ]
}
```

| Field | Meaning |
| --- | --- |
| `hasVoiceOfMerchant` | `true` when the listing is verified and live on Google. You are done. |
| `verify.hasPendingVerification` | When not verified: `true` if a verification is already in progress (waiting for a code), `false` if none has been started or the last one failed |
| `verifications[].state` | `PENDING`, `COMPLETED` or `FAILED` for each attempt |

A verified location also needs to be matched to a published Maps place before reviews appear. That shows up as a non-null `placeId` in [location details](https://pozy.ai/docs/google-business/locations).

## Run a verification

### See which methods Google offers

[`POST .../gmb-verifications/options`](https://pozy.ai/docs/api/fetchGoogleBusinessVerificationOptions) with a `languageCode` lists the methods available for this location. Nothing is sent to the business yet.

```bash cURL
curl -X POST https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications/options \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "languageCode": "pt-PT" }'
```

```json
{
  "success": true,
  "options": [
    { "verificationMethod": "SMS", "phoneNumber": "+351210000123" },
    { "verificationMethod": "PHONE_CALL", "phoneNumber": "+351210000123" },
    { "verificationMethod": "ADDRESS" }
  ]
}
```

A business that serves customers at their address and has no storefront (a service-area business) must also send `context` with its service address, or Google returns `400`.

### Start one

[`POST .../gmb-verifications`](https://pozy.ai/docs/api/startGoogleBusinessVerification) with the chosen `method` and the matching detail.

> **This contacts the business:**
> 
> Starting a verification is a real-world action. Google mails a postcard, calls, or sends a text or email to the business right away. Confirm with the owner before you call it.

| `method` | Send | What Google does |
| --- | --- | --- |
| `SMS` | `phoneNumber` from the options | Texts a code |
| `PHONE_CALL` | `phoneNumber` from the options | Calls and reads a code |
| `EMAIL` | `emailAddress` | Emails a code |
| `ADDRESS` | `mailerContact` (the name on the postcard) | Mails a postcard with a code. This can take days. |
| `AUTO` | Nothing | Verifies at once when Google allows it |
| `VETTED_PARTNER` | Nothing | Used by Google's approved partners |

```bash cURL
curl -X POST https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "method": "SMS", "languageCode": "pt-PT", "phoneNumber": "+351210000123" }'
```

The response returns the new `verification` with `state: "PENDING"`. The last segment of `verification.name` is the `verificationId`.

### Submit the code

When the business has the code, send it to [`POST .../gmb-verifications/{verificationId}/complete`](https://pozy.ai/docs/api/completeGoogleBusinessVerification) as `pin`.

```bash cURL
curl -X POST https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications/7Q2093841177/complete \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "pin": "482913" }'
```
```ts Node
const res = await fetch("https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications/7Q2093841177/complete", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.POZY_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ pin: "482913" }),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);

console.log(data.verification.state); // "COMPLETED" or "FAILED"
```
```python Python
resp = requests.post(
    "https://api.pozy.ai/v1/accounts/6713b0e5d1f4c69a2b8e3f75/gmb-verifications/7Q2093841177/complete",
    headers=H, json={"pin": "482913"}, timeout=30,
)
print(resp.json()["verification"]["state"])
```

`COMPLETED` means Google accepted the code. `FAILED` means it did not; start a new verification to try again.

## Build it into onboarding

A simple flow for new locations:

1. After the account connects, read the verification state.
2. If `hasVoiceOfMerchant` is `true`, continue.
3. If a verification is pending, ask the owner for the code they received and submit it.
4. Otherwise fetch the options, let the owner pick one, start it, and ask for the code.

Postcards can take days to arrive, so let the owner close your app and come back to step 3 later.

## Common errors

| Error | Cause | Fix |
| --- | --- | --- |
| `400` on options | Missing `languageCode`, or a service-area business without `context` | Add the missing field |
| `400` on complete | Wrong code, or the verification is no longer `PENDING` | Check the code, or start a new verification |
| `403` | The Google login cannot manage this location | Reconnect with an owner or manager |
| `401` `token_invalid` | Google revoked the sign-in | Reconnect the account |

## Endpoints

| Endpoint | What it does |
| --- | --- |
| [`GET /v1/accounts/{accountId}/gmb-verifications`](https://pozy.ai/docs/api/getGoogleBusinessVerifications) | Get verification state |
| [`POST /v1/accounts/{accountId}/gmb-verifications`](https://pozy.ai/docs/api/startGoogleBusinessVerification) | Start a verification |
| [`POST /v1/accounts/{accountId}/gmb-verifications/options`](https://pozy.ai/docs/api/fetchGoogleBusinessVerificationOptions) | Fetch verification options |
| [`POST /v1/accounts/{accountId}/gmb-verifications/{verificationId}/complete`](https://pozy.ai/docs/api/completeGoogleBusinessVerification) | Complete a verification |
