Skip to content

Errors

Every failure has the same shape, and it never contains a provider’s prose or your data:

{ "ok": false, "code": "api_key_scope_denied" }

code is the machine-readable part; the message is written to MauKirim’s log and never returned, so you can log a response body without worrying that it carries a phone number.

HTTP code Condition
401 api_key_invalid No Authorization header, not Bearer <token>, or no key matches
401 api_key_revoked The key was revoked
401 api_key_expired The key’s expiry has passed
403 api_key_scope_denied The key lacks the scope this route requires
403 forbidden The key is fine but the account is missing or not active
404 rental_not_found The device is not rented by this account — also returned for a device that does not exist
HTTP code Condition
400 invalid_input Missing or malformed field; wrong Content-Type (three routes require application/json); body larger than 8 KB; missing Idempotency-Key; template scalar or item-list variables that do not match the reviewed placeholders
409 batch_idempotency_conflict The Idempotency-Key was already used with a different request
413 batch_too_large Text over 4096 characters, caption over 1024, or an Idempotency-Key over 128
429 rate_limited Too many OTP sends for the same number — see below. (Google Business: also too many connect sessions in an hour)
HTTP code Condition
402 insufficient_credits Credit balance is below the cost of this message
409 device_not_connected No MauKirim sending number is ready right now
503 worker_offline The dispatch worker has no fresh heartbeat — transient, retry
409 batch_idempotency_conflict See above: same key, different request
404 gateway_not_found The device’s gateway no longer exists
409 gateway_disabled The device’s gateway is switched off by an operator
410 media_unavailable The media id is unknown, owned by another account, expired (7 days), or no bucket is configured
404 device_not_found The device id is unknown to this deployment
409 rental_device_not_ready The device is reachable but too stale to accept the operation
400 invalid_input Image not JPEG/PNG, empty, over 5 MiB, or its bytes do not match the declared type
HTTP code Condition
404 webhook_not_configured Rotation or deletion on a device with no destination
400 invalid_input Destination URL missing, not https, carrying credentials/query/fragment, an IP literal or localhost; unknown event name

The connector’s codes. All of them keep the standard envelope; gmb_rate_limited alone carries one more field.

HTTP code Condition
402 gmb_plan_required The account’s package does not include the Google Business connector (Growth and above do). Upgrade, or ask an operator to add it
404 gmb_location_not_found The business does not exist, is not on this account, or has left Google (removed_upstream). Identical for all three — the API never confirms that a business id is real
404 gmb_connection_not_found The connection does not exist or is not this account’s
429 gmb_rate_limited No Google budget right now: the shared pool of 300 queries a minute, this account’s own share, or a short pause after Google itself answered 429. Carries Retry-After and retryAfterSeconds
409 gmb_reconnect_required Google no longer accepts the saved permission (revoked, expired or password changed). The account owner must reconnect in the dashboard
403 gmb_forbidden Google refused: the connected Google account is probably not an Owner or Manager of that business, or the permission was narrowed
503 gmb_api_unavailable Google refused the request because a Business Profile API is not enabled or not approved for the MauKirim deployment’s Google project: the core API (then everything fails, including the first sync) or one feature’s own API (insights, verification, place action links, lodging). Not an account problem; MauKirim support fixes it
409 gmb_location_disabled The business or its connection is switched off: by an operator, because the connection was disconnected, or by you (disabledBy: user: every business found on connect or sync starts off until you turn it on). From the activation endpoint it also means MauKirim support switched the business off, and it cannot be turned on there
409 gmb_location_limit The package’s allowance of active businesses is full, so no more can be turned on or created (10 on Growth, 50 on Business, 200 on Scale, 1,000 on Platform); businesses that are switched off do not count. Turning businesses on is atomic: when it would not fit nothing changes. A create is refused with this before anything exists on Google
409 gmb_idempotency_conflict An Idempotency-Key was reused with a different edit, reply, upload, invitation or new business
413 gmb_file_too_large A photo upload is over 5 MB. Refused from Content-Length before the body is read, and nothing is sent to Google
415 gmb_unsupported_media A photo upload is not a JPEG or PNG. The file’s bytes decide, not its name or declared type. Convert it and send it again
400 gmb_authorization_failed The Google consent round trip failed — denied, expired, or no refresh permission granted. Shown in the dashboard, and as the error of a failed connect session
400 gmb_redirect_not_allowed The redirectUrl of a connect session, or a return address being registered, is not an https address (http only on localhost), has credentials, a fragment (or, when registering, a query), is not absolute or is too long — or it is not inside one of the account’s registered return addresses. Nothing is created
404 gmb_session_not_found No connect session with that id, or it is not this account’s (identical for both); on the public connect page, an unknown link
410 gmb_session_expired A connect link’s 30 minutes ran out. Create a new session. Shown on the public connect page; the API reports an expired session as pending past its expiresAt
409 gmb_session_state The connect session is not in a state that step allows: it was already completed, cancelled or failed. Shown on the public connect page
409 gmb_redirect_exists That return address is already registered
502 gmb_upstream_error Google answered with an error or something MauKirim cannot interpret. Retry later
503 gmb_unconfigured The connector is not configured on this deployment (no Google client or credential key)
400 invalid_input Also: a field that cannot be changed, a value outside its limit (title 100, description 750, reply 4096 characters; a post’s 1,500-character summary, https-only links and photo URLs, a CALL button with a URL; a metric, date range or month; an attribute name; a path outside the Google door’s allow-list), a bad status, limit, pageSize, maxRating, externalId or date, and a request Google itself rejected as invalid
404 not_found Also: a Google Business job that is not this account’s, and a return address that is not this account’s
429 rate_limited Also: more than 120 connect sessions created in an hour. Carries Retry-After and retryAfterSeconds

A gmb_rate_limited response looks like this:

HTTP/1.1 429 Too Many Requests
Retry-After: 7
{ "ok": false, "code": "gmb_rate_limited", "retryAfterSeconds": 7 }

See Google Business rate limits for what to do about it.

HTTP code Condition
404 not_found A referenced record does not exist for this account
500 server_error Unexpected — record it and contact support with the time and the request

Rate limits, and their absence from responses

Section titled “Rate limits, and their absence from responses”

No /api/v1 response sets an X-RateLimit-* header. Retry-After appears only on the Google Business endpoints: a 429 gmb_rate_limited and the 429 rate_limited of creating a connect session. Both come with retryAfterSeconds in the body. The other limit reachable from this API is OTP issuing, which sets no header:

Limit Value Keyed by
OTP issue 5 per hour Your account and the destination phone number together

POST /otp/verify has no rate limit of its own; it is bounded by the challenge’s 5-attempt budget instead (see Send and verify an OTP). Sign-in, signup and password-reset limits exist but belong to the dashboard’s session endpoints, not this API.

Because counts are never returned, treat an OTP 429 as “back off and try later” rather than parsing a number out of a header. A Google Business 429 tells you how long: wait Retry-After seconds. A verification flow that retries on 429 with a short delay is usually fine; one that loops immediately is not.

Situation Safe to retry?
503 worker_offline, 502/timeouts Yes — the request very likely did nothing. Retry with the same Idempotency-Key.
402 insufficient_credits Not until the balance is topped up
409 batch_idempotency_conflict No — you reused a key with a different body. Use a new key for a genuinely new request.
429 rate_limited Later, not immediately
429 gmb_rate_limited Yes, after Retry-After seconds, with the same Idempotency-Key on a write
429 rate_limited on creating a connect session Yes, after Retry-After seconds; reuse a still-pending session instead of creating many
410 gmb_session_expired, 409 gmb_session_state No: create a new connect session
502 gmb_upstream_error Yes, with backoff and the same Idempotency-Key
409 gmb_reconnect_required Not until the account owner reconnects in the dashboard
500 server_error Yes, once, with the same key — then report it