Rate Limits
GMBapi enforces multiple, independent quota layers. A single request may be subject to more than one limit at the same time. When any limit is exceeded the API responds with 429 Too Many Requests.
| Mechanism | Limit | Window | Scope |
|---|
| General limit | 100 requests | 1 minute | All authenticated routes, per account or organization |
| Local Schema limit | 30 requests | 1 minute | GET /local-schema/automated/:token |
| Citations quota | 50 requests | 1 hour | POST /citations/activate and POST /citations/disable |
| Location edit quota | 200 requests | 1 hour | PATCH /location/update |
Rate-limited responses (429) include the following headers so clients can back off intelligently:
| Header | Description |
|---|
X-RateLimit-Limit | Maximum number of requests allowed in the current window. |
X-RateLimit-Remaining | Number of requests remaining in the current window. |
X-RateLimit-Reset | UNIX timestamp (seconds) at which the current window resets. |
Retry-After | Number of seconds to wait before retrying the request. |
When you receive a 429, prefer honoring the Retry-After header over implementing your own delay. Each quota layer (global, location updates, citations, token routes) is tracked independently.
HTTP Status Codes
| Status | Name | Description |
|---|
| 200 | OK | Request succeeded. Some routes return { "success": false, ... } in the body for soft errors without changing the status code. |
| 302 | Found | OAuth callback redirect. On error, redirects with a ?error=<message> query parameter. |
| 400 | Bad Request | Invalid or missing request parameters, failed DTO validation, or business rule violations (e.g. duplicate service items, exceeding max per_page, invalid cursor, missing required IDs). |
| 401 | Unauthorized | Missing or invalid Bearer token, expired token, token not in database, account suspended (TRIAL_PAUSED, TRIAL_ENDED, SUBSCRIPTION_ENDED), or token not authorized for the requested endpoint. |
| 403 | Forbidden | Insufficient token authorization level (e.g. an account-level token on an org-level endpoint), or Citations API disabled for the billing account. |
| 404 | Not Found | Requested resource does not exist — organization, account, business profile, location, review data, update document, or OAuth state. |
| 409 | Conflict | Resource already in the target state (e.g. citations already ACTIVE), a conflicting update is already in progress, or a unique identifier (id, reference_id) already exists. |
| 429 | Too Many Requests | API quota exceeded. Includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After headers. Three separate quota layers apply — see Rate Limits. |
| 500 | Internal Server Error | Unexpected server-side failure — infrastructure errors, misconfigured environment variables, unhandled exceptions, or upstream service failures (Google, Firebase, Redis). |
Machine-Readable Error Codes
For most non-200 responses, the GMBapi API returns a JSON body containing a code field with a stable, machine-readable identifier. Use the code (rather than parsing the human-readable message) to drive client-side logic.
{
"success": false,
"code": "ALREADY_ACTIVE",
"message": "Citations are already active for this location"
}
| Code | Status | Description | |
|---|
ALREADY_ACTIVE | 409 | Citations are already active for this location. | |
NOT_ACTIVE | 409 | Citations are not active — cannot disable. | |
IN_PROGRESS | 409 | A citations operation is already in progress for this location. | |
QUOTA_REACHED | 429 | Hourly quota exceeded (citations or location updates). | |
MISSING_LOCATION_FIELDS | 400 | Required location fields are missing — the response includes a missing_fields array. | |
New error codes may be added over time. Treat unknown codes defensively and always fall back to the HTTP status code for generic handling.