Google — exchange OAuth code for access token
Overview
Exchanges a Google OAuth code for an access token, stores it (google_access_tokens), and then branches: with connect_google=1 + company_id_hash it links the token to that company and syncs its GBP locations (dispatching DuplicateGMBDebugger). With source=app it returns the token plus fetched account/location data; otherwise it returns only the stored token id + token. Requires the business.manage scope to have been granted at consent. Records gbp_connection_events.
Prerequisites
- Either a bearer token in the
Authorizationheader, or the invitehashthis endpoint accepts in place of one. - Values for the required query parameter
code— see the table below.
Base URL
| Environment | URL |
|---|---|
| Production | https://production-api.shoutaboutus.com |
| Development | https://development-api.shoutaboutus.com |
Endpoint
GET /api/v1/google/access-token
Authentication
-
A bearer token is optional here. Send one to act as a signed-in user, or supply the documented
hashinstead. -
Use a bearer token (api guard).
-
OR use the public connect-page pair (
connect_google=1+company_id_hash). -
OR use an invite
hash. -
No token is needed for the latter two.
Rate limit
- 30 requests/min per IP (public).
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Required | Google OAuth authorization code. |
connect_google | integer (0,1) | Optional | 1 → link token to company + sync GBP locations. |
company_id_hash | string | Optional | Required when connect_google=1. Hashid of the target company. |
source | string (app,web) | Optional | app returns account+location data; picks the redirect URI. |
hash | string | Optional | Invite hash encoding [store_id, 15]; grants access without a token. |
How it works
- 200 with the token payload (web/app) or the synced location list (
connect_google=1). 400 for an invalid company hash. Note: missingbusiness.managescope, absent access token, and Google token-endpoint errors are surfaced viaerrorResponse(HTTP 500) with an explanatory message.
Response
200 OK (web flow) · 200
200{
"data": {
"google_access_token_id": 42,
"google_access_token": "<google-access-token>",
"account_data": []
}
}200 OK (connect_google=1, locations synced) · 200
200{
"data": [
{
"name": "Demo Store",
"url": "https://maps.google.com/?cid=1234567890"
}
]
}400 Invalid company · 400
400{
"message": "Bad Request",
"status": "error",
"errors": "Invalid request!"
}500 Scope not granted · 500
500{
"message": "You still need to grant us access to your Google Business Profile. Please be sure the check boxes are all selected.",
"status": "error",
"errors": []
}Errors
| Status | Meaning |
|---|---|
400 | Invalid company |
401 | The bearer token is missing, expired or invalid |
422 | The request failed validation — the response names the fields |
500 | Scope not granted |
Example request
curl --request GET \
--url "https://production-api.shoutaboutus.com/api/v1/google/access-token?code=<google_oauth_code>&source=web" \
--header 'Authorization: Bearer <bearer-token>' \
--header 'Accept: application/json'Updated 9 days ago
