GMB AI Cloud API

Read clients, posting-plan usage, reviews and performance, and create AI-generated Google Business Profile posts from your own website or app. JSON over HTTPS.

Base URL: https://gmb.hoverbusinessservices.in/api/v1Download Postman collectionPostman environment

Authentication

Create a key in Dashboard → API & developers (requires a plan with API access). The key is shown once - store it server-side only. Send it in the Authorization header (or X-API-Key).

curl https://gmb.hoverbusinessservices.in/api/v1/me \
  -H "Authorization: Bearer gmbk_xxxxxxxxxx_your-secret"

Keys can be renamed, disabled, regenerated (old value stops immediately), revoked, given an expiry date and limited to scopes. Never put a key in browser or mobile code.

Rate limits

  • Per key: 60 requests/minute (admins can raise it per key).
  • Per workspace: 300 requests/minute across all keys.
  • POST /posts: 10 requests/minute per key.

Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix seconds). A 429 includes Retry-After. Posting is additionally capped by each client's posting plan (weekly and total).

Responses & errors

Success: { "data": …, "request_id": "…" }. Error:

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded (key). Retry after the reset time."
  },
  "request_id": "7c1e2d…"
}

Error codes

400VALIDATION_ERRORA parameter is missing or invalid.
401INVALID_API_KEYMissing, malformed, revoked or unknown key. Also KEY_DISABLED / KEY_EXPIRED.
403INSUFFICIENT_SCOPEThe key lacks the scope this endpoint needs. PLAN_NO_API when the plan has no API access.
404NOT_FOUNDThe record doesn't exist in your workspace.
422WEEKLY_LIMITPosting plan cap hit. Also TOTAL_LIMIT, PLAN_EXPIRED, OUTSIDE_PLAN, NOT_A_POSTING_DAY, NO_POSTING_PLAN.
429RATE_LIMITEDToo many requests. Wait until X-RateLimit-Reset (see Retry-After).
503MAINTENANCEPlatform maintenance. Retry later. API_DISABLED when the API is switched off.

Scopes

Available scopes

clients:readscopeList clients and their posting plans
posts:readscopeRead posts and their status
posts:writescopeCreate posts (counts against the posting plan)
reviews:readscopeRead Google reviews
reports:readscopeRead performance data

Webhooks

Outgoing webhooks are configured by the platform admin. Each request is a JSON POST signed with X-Signature: sha256=<HMAC of body>. Until your workspace has webhooks, poll GET /posts/{id}.

Account

Who am I

GET/api/v1/me

Returns the workspace and key the request is authenticated with. Use it to verify a key.

curl "https://gmb.hoverbusinessservices.in/api/v1/me" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "workspace": {
      "id": 3,
      "name": "Hover Media",
      "status": "ACTIVE",
      "plan": "Agency"
    },
    "key": {
      "id": 7,
      "name": "Website",
      "prefix": "gmbk_1a2b3c4d5e",
      "scopes": [
        "clients:read",
        "posts:read"
      ],
      "expires_at": null
    }
  },
  "request_id": "0b6f…"
}

Clients

List clients

GET/api/v1/clientsscope: clients:read

Query parameters

pageintegerPage number, default 1
limitinteger1-100, default 20
searchstringFilter by business name or city
curl "https://gmb.hoverbusinessservices.in/api/v1/clients" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "items": [
      {
        "id": 14,
        "business_name": "Smile Dental",
        "category": "Dentist",
        "city": "Ghaziabad",
        "website": "https://smiledental.in",
        "phone": "+91…",
        "active": true,
        "gmb_status": "GOOGLE_CONNECTED",
        "created_at": "2026-08-01T09:00:00.000Z"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1
  }
}

Clients

Get client

GET/api/v1/clients/{id}scope: clients:read

Client details with its posting plan usage.

curl "https://gmb.hoverbusinessservices.in/api/v1/clients/14" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "id": 14,
    "business_name": "Smile Dental",
    "posting_plan": {
      "state": "ACTIVE",
      "total_posts": 24,
      "used": 14,
      "remaining": 10
    }
  }
}

Clients

Posting plan usage

GET/api/v1/clients/{id}/posting-planscope: clients:read

Plan window, weekly limit and usage. Counted = scheduled + pending + processing + published (rejected/failed free the slot).

curl "https://gmb.hoverbusinessservices.in/api/v1/clients/14/posting-plan" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "state": "ACTIVE",
    "start_date": "2026-09-01",
    "end_date": "2026-10-31",
    "duration_months": 2,
    "posts_per_week": 3,
    "posting_days": [
      1,
      3,
      5
    ],
    "total_posts": 24,
    "used": 14,
    "remaining": 10,
    "breakdown": {
      "published": 12,
      "scheduled": 0,
      "pending": 2,
      "processing": 0
    },
    "this_week": {
      "index": 4,
      "start": "2026-09-22",
      "end": "2026-09-28",
      "limit": 3,
      "used": 2,
      "remaining": 1
    }
  }
}

Posts

List posts

GET/api/v1/postsscope: posts:read

Query parameters

client_idintegerOnly this client
statusstringPENDING, READY_FOR_REVIEW, NEEDS_REVIEW, APPROVED, REJECTED, PUBLISHED, FAILED
pageinteger
limitinteger1-100
curl "https://gmb.hoverbusinessservices.in/api/v1/posts" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "items": [
      {
        "id": 812,
        "client_id": 14,
        "status": "READY_FOR_REVIEW",
        "post_type": "Service",
        "topic": "Root canal - what to expect",
        "title": "Root canal treatment in Indirapuram: what to expect",
        "description": "Worried about a root canal? …",
        "cta": "Book a visit",
        "image_url": "https://cdn.example.com/p/812.jpg",
        "qa_score": 88,
        "scheduled_date": "2026-10-02",
        "published_at": null,
        "created_at": "2026-09-25T10:20:11.000Z",
        "source": "api"
      }
    ],
    "page": 1,
    "limit": 20,
    "total": 1
  }
}

Posts

Create post

POST/api/v1/postsscope: posts:write

Creates a post slot and (by default) starts AI generation in the background. Enforces the client's posting plan: weekly cap, total cap, plan window, posting days and expiry - exactly like the dashboard. Poll GET /posts/{id} until status is READY_FOR_REVIEW. Limited to 10 requests/min per key.

Body (JSON)

client_idintegerrequired
topicstringoptional - AI picks one if empty
post_typestringService, Offer, Educational, Local, Seasonal, … (default Service)
scheduled_dateYYYY-MM-DDdefault today
generatebooleandefault true
curl -X POST "https://gmb.hoverbusinessservices.in/api/v1/posts" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"client_id":14,"topic":"Root canal - what to expect","post_type":"Service","scheduled_date":"2026-10-02"}'

Response 201

{
  "data": {
    "id": 812,
    "client_id": 14,
    "status": "PENDING",
    "post_type": "Service",
    "topic": "Root canal - what to expect",
    "title": null,
    "description": "Worried about a root canal? …",
    "cta": "Book a visit",
    "image_url": "https://cdn.example.com/p/812.jpg",
    "qa_score": 88,
    "scheduled_date": "2026-10-02",
    "published_at": null,
    "created_at": "2026-09-25T10:20:11.000Z",
    "source": "api",
    "generation": "started"
  }
}

Error 422

{
  "error": {
    "code": "WEEKLY_LIMIT",
    "message": "Weekly limit reached: 3 posts per week (week of 2026-09-29 - 2026-10-05).",
    "details": {
      "limit": 3,
      "weekStart": "2026-09-29",
      "weekEnd": "2026-10-05"
    }
  },
  "request_id": "a1c2…"
}

Posts

Get post

GET/api/v1/posts/{id}scope: posts:read

curl "https://gmb.hoverbusinessservices.in/api/v1/posts/14" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "id": 812,
    "client_id": 14,
    "status": "READY_FOR_REVIEW",
    "post_type": "Service",
    "topic": "Root canal - what to expect",
    "title": "Root canal treatment in Indirapuram: what to expect",
    "description": "Worried about a root canal? …",
    "cta": "Book a visit",
    "image_url": "https://cdn.example.com/p/812.jpg",
    "qa_score": 88,
    "scheduled_date": "2026-10-02",
    "published_at": null,
    "created_at": "2026-09-25T10:20:11.000Z",
    "source": "api"
  }
}

Reviews

List reviews

GET/api/v1/clients/{id}/reviewsscope: reviews:read

curl "https://gmb.hoverbusinessservices.in/api/v1/clients/14/reviews" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "average_rating": 4.6,
    "total": 212,
    "items": [
      {
        "id": "AbFvOq…",
        "author": "Rahul",
        "rating": 5,
        "comment": "Great service",
        "created_at": "2026-09-20T08:00:00Z",
        "reply": null
      }
    ]
  }
}

Reports

Performance

GET/api/v1/clients/{id}/performancescope: reports:read

Query parameters

daysinteger7-365, default 30
curl "https://gmb.hoverbusinessservices.in/api/v1/clients/14/performance" \
  -H "Authorization: Bearer $API_KEY"

Response 200

{
  "data": {
    "days": 30,
    "is_sample_data": false,
    "totals": {
      "views": 4210,
      "website_clicks": 180,
      "calls": 96,
      "directions": 140
    },
    "series": [
      {
        "date": "2026-09-01",
        "views": 120,
        "search_views": 80,
        "maps_views": 40,
        "website_clicks": 6,
        "calls": 3,
        "directions": 4
      }
    ]
  }
}

Example integration (Node.js)

const API = "https://gmb.hoverbusinessservices.in/api/v1";
const headers = { Authorization: `Bearer ${process.env.GMB_API_KEY}`, "Content-Type": "application/json" };

// 1. check plan capacity
const plan = await (await fetch(`${API}/clients/14/posting-plan`, { headers })).json();
if (plan.data.this_week.remaining > 0) {
  // 2. create a post - AI generates it in the background
  const res = await fetch(`${API}/posts`, { method: "POST", headers, body: JSON.stringify({ client_id: 14, topic: "Monsoon AC service" }) });
  const { data, error } = await res.json();
  if (error) console.error(error.code, error.message);
  else console.log("post", data.id, data.status);
}

Questions? Open a support ticket.