Developers
Documentation API
The GMB Club API lets you publish and schedule posts on your social networks via Zapier, Make, or your own scripts. It also lets you retrieve generated articles.
Key concepts
The v2 API uses GMB Club's hierarchical Sphere / Bubble architecture.
| Concept | Description | Example |
|---|---|---|
| Sphere | Brand / Company / Franchisor | "Auto Sud" |
| Bubble | Location / Point of sale | "Auto Sud Marseille" |
| Resources | Accounts connected to the bubble | Facebook, Instagram, GMB |
Important
Authentication
The API uses API keys for authentication. A key can have two scopes: it covers either a single location (bubble key) or all the brand's locations (sphere key). A bubble key sees only its own location's data; a sphere key sees data for all locations — the ideal option for a multi-location website: a single key, a single integration. Call GET /api/v2/me first to find out which scope you have: the « bulle » field is filled in for a bubble key and is null for a sphere key.
Key scope: bubble or sphere
A single scope rule, valid across the whole API:
- A key covers one location (bubble key) or the entire brand (sphere key). It defines what is allowed, never what is targeted.
- Any route that acts on a target accepts a target parameter:
bulle_idfor a location,fiche_idfor a Google listing. Always in the same place: URL parameter for reads, body field for writes. - Without the parameter: a bubble key targets its location; a sphere key gets a
400that names the missing parameter. Never an arbitrary choice. - List routes without a parameter return the whole brand, and each item carries its
bulle_id. - A target outside the key's scope returns
403; a nonexistent target,404.
Possible responses (backend messages, in French):
| Code | Response (detail) |
|---|---|
403 | Cet établissement n'appartient pas à votre périmètre. |
403 | Cette fiche GMB n'appartient pas à votre périmètre. |
404 | Établissement introuvable : <identifiant> |
404 | Aucune fiche GMB associée à cette clé API. |
400 | Cette clé API couvre plusieurs établissements. Précisez `bulle_id` (liste : GET /api/v2/bulles). |
400 | Cette clé API couvre plusieurs fiches Google. Précisez `fiche_id` (liste : GET /api/v2/me). |
Get an API key
- Sign in to GMB Club
- Select your bubble in the header
- Settings → API keys → New key
- Choose the scope: "This location" or "Whole brand"
- Configure permissions and copy the key
A "Whole brand" key covers every location, including those created later: it's the right choice for a single website that serves several locations — one secret to manage, and nothing to do when a new location opens.
Important
Key format
gmb_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxUsage
curl -H "X-API-Key: gmb_live_xxxx..." \
-H "Content-Type: application/json" \
https://app.gmb-club.com/api/v2/meJSON only
Base URL
https://app.gmb-club.com/api/v2Endpoints
/api/v2/healthChecks that the API is operational. No authentication required.
{
"status": "ok",
"api_version": "2.0",
"timestamp": "2026-07-27T18:00:00.000000Z"
}Key identity
/api/v2/meAuthreadReturns info about the API key, bubble, sphere and connected resources. Call this endpoint first.
{
"api_version": "2.0",
"bulle": { "id": "abc-123", "name": "Auto Sud Marseille", "city": "Marseille" },
"sphere": { "id": "xyz-789", "name": "Auto Sud", "slug": "auto-sud" },
"permissions": ["read", "schedule", "publish"],
"rate_limits": { "per_minute": 60, "per_day": 1000 },
"connected_platforms": ["facebook", "instagram", "gmb", "linkedin"],
"gmb_fiches": [{
"id": "accounts/115473832376124235338/locations/12517715818229047311",
"name": "Auto Sud - Marseille Centre",
"address": "12 rue de la Paix, 13001, Marseille",
"service_area": false
}]
}Sphere key
bulle field is null and the gmb_fiches array lists all the brand's listings.Social connections
/api/v2/connectionsAuthreadReturns social network connection details for this bubble.
[
{ "platform": "facebook", "connected": true, "name": "Auto Sud Marseille", "bulle_id": "abc-123", "expires_at": "2025-12-15T10:00:00", "needs_reconnect": false },
{ "platform": "instagram", "connected": true, "name": "autosud_marseille", "bulle_id": "abc-456", "expires_at": "2025-12-15T10:00:00", "needs_reconnect": false }
]| Parameter | Type | Default |
|---|---|---|
bulle_id | string | Restrict to one location. Default: the key's location, or every location of the brand. |
With a sphere key, bulle_id indicates which location each Facebook page or Instagram account belongs to.
Platform limits
/api/v2/platforms/limitsAuthreadReturns character and media limits for each platform.
{
"character_limits": { "<plateforme>": "<int>" },
"image_limits": {
"<plateforme>": { "max_size_mb": "<int>", "carousel_min": "<int?>", "carousel_max": "<int?>" }
},
"video_limits": {
"<plateforme>": { "max_size_mb": "<int>", "max_duration_sec": "<int?>" }
}
}Shape, not frozen values
Create a post
/api/v2/postsAuthscheduleCreates a new scheduled post or publishes immediately.
Common errors
Sphere key: bulle_id required
bulle_id is now required on POST /posts. Previously the call succeeded by picking a default location, which could publish to the wrong Google listing. Existing integrations that use a sphere key must add this field.Body (JSON)
{
"content": "Discover our new arrivals! 🚗 #automobile",
"platforms": ["facebook", "instagram", "gmb"],
"image_url": "https://example.com/images/promo.jpg",
"scheduled_at": "2025-12-01T10:00:00+01:00",
"gmb_fiche_id": "gmb-fiche-123-456"
}Parameters
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | Post text (1-5000 chars) |
platforms | array | Yes | Array: facebook, instagram, gmb, linkedin, pinterest, tiktok, snapchat, youtube. The platform must be connected on the location, otherwise HTTP 400 « Plateforme non connectée ». |
image_url | string | No | Single image URL |
image_urls | array | No | JSON URL array for carousel (2-10) |
video_url | string | No | Video URL |
scheduled_at | string | No | ISO 8601 date/time (default: +1h) |
gmb_fiche_id | string | No | GMB listing ID (see /me) |
publish_now | boolean | No | If true, publish immediately |
bulle_id | string | Sphere key | Required with a sphere key: the targeted location. Inferred automatically with a bubble key. |
content or text
Response:
{
"id": 42,
"content": "Discover our new arrivals! 🚗 #automobile",
"platforms": ["facebook", "instagram", "gmb"],
"status": "scheduled",
"image_url": "https://example.com/images/promo.jpg",
"scheduled_gmb": "2025-12-01T10:00:00+01:00",
"created_at": "2025-11-29T18:00:00Z",
"updated_at": "2025-11-29T18:00:00Z",
"warnings": []
}List posts
/api/v2/postsAuthreadReturns bubble posts with pagination.
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | - | pending, published, error |
limit | integer | 50 | 1-100 |
offset | integer | 0 | Pagination offset |
bulle_id | string | - | Restrict to one location. Default: the key's location, or every location of the brand. |
Bare array
[
{
"id": 42,
"bulle_id": "abc-123",
"content": "Discover our new arrivals! 🚗",
"platforms": ["facebook", "gmb"],
"status": "published",
"image_url": "https://example.com/images/promo.jpg",
"image_urls": null,
"video_url": null,
"scheduled_instagram": null,
"scheduled_facebook": "2025-12-01T10:00:00+01:00",
"scheduled_gmb": "2025-12-01T10:00:00+01:00",
"scheduled_linkedin": null,
"scheduled_pinterest": null,
"scheduled_tiktok": null,
"scheduled_snapchat": null,
"scheduled_youtube": null,
"published_instagram": null,
"published_facebook": "2025-12-01T10:00:05+01:00",
"published_gmb": "2025-12-01T10:00:05+01:00",
"published_linkedin": null,
"published_pinterest": null,
"published_tiktok": null,
"published_snapchat": null,
"published_youtube": null,
"error_instagram": null,
"error_facebook": null,
"error_gmb": null,
"error_linkedin": null,
"error_pinterest": null,
"error_tiktok": null,
"error_snapchat": null,
"error_youtube": null,
"platform_refs": { "facebook": "...", "gmb": "..." },
"created_at": "2025-11-29T18:00:00Z",
"updated_at": "2025-12-01T10:00:05Z",
"warnings": []
}
]Full response, field by field
scheduled_ / published_ / error_ trio per platform: the scheduled date, the actual publication date, and the error message, if any. A platform not involved in a given post has its three fields set to null. platform_refs holds the references of the publications on each platform once published; warnings, the non-blocking warnings./api/v2/posts/{post_id}AuthreadRetrieves a post by its identifier. Returns the same object as an element of GET /api/v2/posts.
/api/v2/posts/{post_id}AuthscheduleUpdates a pending post (status: pending only).
Partial update
Body (JSON)
{
"content": "Updated text!",
"scheduled_at": "2025-12-02T14:00:00+01:00"
}/api/v2/posts/{post_id}AuthdeleteDeletes a pending or errored post.
/api/v2/posts/{post_id}/publishAuthpublishForces immediate publication of a scheduled post.
Simplified social publishing
Three endpoints designed for Make, n8n and Zapier integrations: publish, check the quota, track the status. They all require a bubble key (see « Key scope »).
List articles
/api/v2/articlesAuthreadReturns generated articles for this bubble. Ideal for custom site integration.
Site without your website (major CMS supported)
{
"articles": [{
"id": 12,
"title": "5 tips for maintaining your car",
"excerpt": "Expert tips to extend your vehicle's life.",
"content_html": "<h2>Introduction</h2><p>Regular maintenance...</p>",
"featured_image_url": "https://storage.example.com/images/article-12.jpg",
"meta_title": "5 car maintenance tips | Auto Sud Marseille",
"meta_description": "Our experts share their best car maintenance tips.",
"target_keyword": "car maintenance Marseille",
"status": "published",
"published_at": "2026-03-10T14:00:00Z",
"created_at": "2026-03-08T09:00:00Z",
"updated_at": "2026-03-12T08:30:00Z",
"slug": "5-conseils-pour-entretenir-sa-voiture",
"bulle_id": "abc-123",
"bulle_name": "Auto Sud Marseille"
}],
"total": 24, "limit": 10, "offset": 0
}Multi-location website
bulle_id indicates which page to publish each one on. bulle_id is null if the article is attached only to the brand, with no location. The full location mapping is obtained via GET /api/v2/bulles.Parameters
| Parameter | Type | Default |
|---|---|---|
status | string | published · draft · all |
updated_since | string | ISO 8601 — articles modified since this date (filters on updated_at, sorted oldest to newest). |
bulle_id | string | Restrict to one location. Default: the key's location, or every location of the brand. |
Stay in sync
Detect a correction. since filters on the publication date: an article published a month ago and then corrected this morning won't show up. To catch corrections, use updated_since, which filters on updated_at. Results are then sorted oldest to newest, which lets you resume a sync exactly where it stopped by keeping the last value received.
Build your URLs from the slug, never from the title. The slug is locked at first publication and is never recomputed, even if the title is corrected afterward. Deriving the URL from the title would expose your pages to an address change after indexing.
Detect a removal. An unpublished article no longer appears under status=published. With status=all, it comes back to you with its actual status ("draft"), an explicit signal. A deleted article, on the other hand, disappears entirely: treat the list you receive as the source of truth — whatever is no longer in it is no longer online.
/api/v2/articles/{article_id}AuthreadRetrieves full article content by ID.
{
"id": 12,
"title": "5 conseils pour entretenir sa voiture",
"excerpt": "Nos conseils d'expert.",
"content_html": "<h2>Introduction</h2><p>...</p>",
"featured_image_url": "https://storage.example.com/images/article-12.jpg",
"meta_title": "5 conseils entretien | Auto Sud",
"meta_description": "Nos experts partagent leurs conseils.",
"target_keyword": "entretien voiture marseille",
"status": "published",
"published_at": "2026-03-10T14:00:00Z",
"created_at": "2026-03-08T09:00:00Z",
"updated_at": "2026-03-12T08:30:00Z",
"slug": "5-conseils-pour-entretenir-sa-voiture",
"bulle_id": "abc-123",
"bulle_name": "Auto Sud Marseille"
}Confirm article rendering
/api/v2/articles/{article_id}/confirmAuthreadPingback sent by your script after rendering a fetched article. It has two effects: 1. it lets GMB Club know which articles are actually live on your site, as opposed to merely exposed by the API; 2. by sending `rendered_url`, it feeds the internal linking of your articles — the more useful effect day to day. Optional but recommended.
When to call it
Optional JSON body. The `rendered_url` field (string, max 2048 chars, must start with http:// or https://) is the public URL of the page where your script has just rendered the article. It is the only address of your site that GMB Club knows: it lets your future articles cite earlier ones with a link that points to the right place. Without it, no internal linking is possible on your site — we never guess a URL, and an invented link would be a dead link. Technically optional, but strongly recommended.
// Après avoir affiché l'article dans le DOM
fetch(`https://app.gmb-club.com/api/v2/articles/${article.id}/confirm`, {
method: "POST",
headers: {
"X-API-Key": "gmb_live_xxxx...",
"Content-Type": "application/json"
},
body: JSON.stringify({ rendered_url: location.href })
});CORS tip
$ch = curl_init("https://app.gmb-club.com/api/v2/articles/{$id}/confirm");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
"rendered_url" => "https://monsite.fr/blog/article-{$id}"
]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"X-API-Key: gmb_live_xxxx...",
"Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);await fetch(`https://app.gmb-club.com/api/v2/articles/${id}/confirm`, {
method: "POST",
headers: {
"X-API-Key": process.env.GMB_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ rendered_url: `https://monsite.fr/blog/article-${id}` }),
});import requests
requests.post(
f"https://app.gmb-club.com/api/v2/articles/{id}/confirm",
headers={"X-API-Key": "gmb_live_xxxx...", "Content-Type": "application/json"},
json={"rendered_url": f"https://monsite.fr/blog/article-{id}"},
)curl -X POST \
-H "X-API-Key: gmb_live_xxxx..." \
-H "Content-Type: application/json" \
-d '{"rendered_url": "https://monsite.fr/blog/123"}' \
https://app.gmb-club.com/api/v2/articles/42/confirm200 response on successful confirmation:
{
"article_id": 42,
"confirmed_at": "2026-05-25T14:30:00Z",
"confirmation_source": "pingback"
}Internal linking of your articles
Cross-cutting conventions
Three mechanisms recur across most v2 endpoints. Understanding them once saves a lot of errors.
Risk-free preview: dry_run
Default listing: optional fiche_id
Long operations: 202 response
Workspace
Key's sphere
/api/v2/spheresAuthreadReturns the sphere (brand) attached to the API key: name, slug, default tone and language.
[
{
"id": "xyz-789",
"name": "Auto Sud",
"slug": "auto-sud",
"default_language": "fr",
"default_tone": "professionnel",
"created_at": "2026-01-15T09:00:00Z"
}
]Sphere's locations
/api/v2/bullesAuthreadLists the bubbles (locations) of the sphere, with their city and the number of attached Google listings.
[
{ "id": "abc-123", "name": "Auto Sud Marseille", "city": "Marseille", "tone": "professionnel", "language": "fr", "sphere_id": "xyz-789", "created_at": "2026-01-20T11:00:00Z" },
{ "id": "abc-456", "name": "Auto Sud Aix", "city": "Aix-en-Provence", "tone": "professionnel", "language": "fr", "sphere_id": "xyz-789", "created_at": "2026-01-20T11:05:00Z" }
]Location details
/api/v2/bulles/{bulle_id}AuthreadReturns a bubble's details: effective tone and language (inherited from the sphere if unset), number of Google listings, connected networks.
{
"id": "abc-123",
"name": "Auto Sud Marseille",
"city": "Marseille",
"tone": "professionnel",
"language": "fr",
"sphere_id": "xyz-789",
"created_at": "2026-01-20T11:00:00Z",
"effective_tone": "professionnel",
"effective_language": "fr",
"gmb_fiches_count": 2
}Google reviews
List reviews
/api/v2/reviewsAuthreadReturns the listing's Google reviews, paginated and filterable (rating, reply status, keyword, dates), sortable by date or rating.
Parameters
| Parameter | Type | Default |
|---|---|---|
min_stars | integer | 1-5 · 1 |
max_stars | integer | 1-5 · 5 |
status | string | responded · drafts · unresponded |
keyword | string | - |
date_from | string | ISO 8601 |
date_to | string | ISO 8601 |
sort_by | string | date_desc |
fiche_id | string | Default listing: optional fiche_id |
limit | integer | 1-100 · 25 |
page | integer | 1 |
{
"fiche": { "id": "gmb-fiche-123", "name": "Auto Sud - Marseille Centre", "address": "12 rue de la Paix, Marseille", "place_id": "ChIJ...", "average_rating": 4.6, "total_reviews": 128 },
"reviews": [{
"review_id": "rev-abc",
"customer_name": "Julie A.",
"rating": 5,
"text": "Service impeccable, je recommande !",
"review_timestamp": "2026-07-01T09:12:00Z",
"response_text": null,
"reply_date": null,
"responded": false,
"author_photo": "https://lh3.googleusercontent.com/..."
}],
"average_rating": 4.6,
"total_reviews": 128,
"filtered_count": 1,
"status_counts": { "all": 128, "responded": 90, "drafts": 12, "unresponded": 26 },
"page": 1,
"total_pages": 3
}Reviews summary
/api/v2/reviews/summaryAuthreadReturns the average rating, total number of reviews and their breakdown by status (responded, drafts, unresponded).
{
"fiche": { "id": "gmb-fiche-123", "name": "Auto Sud - Marseille Centre" },
"average_rating": 4.6,
"total_reviews": 128,
"status_counts": { "all": 128, "responded": 90, "drafts": 12, "unresponded": 26 }
}Review acquisition
Acquisition stats
/api/v2/acquisition/statsAuthreadReturns review-request statistics over 30 days: number sent, by channel (SMS, email) and by status.
{
"fiche_id": "gmb-fiche-123",
"total_requests": 84,
"by_channel": { "sms": 50, "email": 34 },
"by_status": {},
"last_30_days": 84
}Send review requests
/api/v2/acquisition/review-requestsAuthpublishSends review requests by SMS and/or email to a list of contacts. Subject to monthly quotas. 202 response with a batch_id; supports dry_run.
Body (JSON)
{
"contacts": [
{ "customer_name": "Julie A.", "channel": "sms", "customer_phone": "+33612345678" },
{ "customer_name": "Marc D.", "channel": "email", "customer_email": "[email protected]", "custom_message": "Merci pour votre visite !" }
],
"dry_run": false
}contacts[]
Response:
{
"queued": true,
"queued_count": 2,
"batch_id": "batch-abc-123",
"contacts": [
{ "customer_name": "Julie A.", "channel": "sms", "contact": "+33612345678" },
{ "customer_name": "Marc D.", "channel": "email", "contact": "[email protected]" }
],
"fiche_name": "Auto Sud - Marseille Centre"
}Google listing
Google Business metrics
/api/v2/gmb/metricsAuthreadReturns the Google listing's KPIs over a period: views, searches, calls, website clicks, direction requests.
| Parameter | Type | Default |
|---|---|---|
period_days | integer | 1-90 · 30 |
fiche_id | string | Default listing: optional fiche_id |
{
"fiche_id": "gmb-fiche-123",
"fiche_name": "Auto Sud - Marseille Centre",
"period_days": 30,
"kpis": {
"views_total": 5420,
"views_search": 3110,
"views_maps": 2310,
"calls": 87,
"website": 214,
"directions": 156,
"messages": 12,
"bookings": 4
},
"timeseries": [
{ "label": "2026-06-01", "vues": 180, "interactions": 22 }
],
"breakdown": {}
}Optimization score
/api/v2/gmb/optimizerAuthreadReturns the listing's latest optimization score (0 to 100), cached. Fast read, no new audit.
{
"kind": "gmb",
"fiche_id": "gmb-fiche-123",
"fiche_name": "Auto Sud - Marseille Centre",
"display_name": "Auto Sud - Marseille Centre",
"score": 82,
"breakdown": {},
"scored_at": "2026-07-05T08:00:00Z"
}Run a full audit
/api/v2/gmb/optimizer/auditAuthpublishRuns a full audit of the listing (Google data + AI analysis) and returns a detailed score with improvement suggestions. Costly operation: supports dry_run.
{
"kind": "gmb",
"fiche_id": "gmb-fiche-123",
"fiche_name": "Auto Sud - Marseille Centre",
"score": 82,
"breakdown": {},
"suggestions": [
{ "field": "description", "reason": "Trop courte", "suggested_value": "..." },
{ "field": "hours", "reason": "Horaires du dimanche manquants" }
],
"review_count": 128,
"avg_rating": 4.6,
"analyzed_at": "2026-07-05T08:00:00Z"
}Apply changes
/api/v2/gmb/optimizer/applyAuthpublishApplies a list of {field, value} changes to the Google listing (real write to Google). Costly operation: supports dry_run.
Body (JSON)
{
"changes": [
{ "field": "description", "value": "Garage automobile à Marseille..." }
],
"dry_run": true
}Response (dry_run):
{
"dry_run": true,
"fiche_id": "gmb-fiche-123",
"fiche_name": "Auto Sud - Marseille Centre",
"changes": [ { "field": "description", "value": "Garage automobile à Marseille..." } ],
"fields": ["description"]
}Local Pack visibility score
/api/v2/visibility/scanAuthreadReturns the listing's latest visibility scan in the Google Local Pack: score and average position around the location.
{
"fiche_id": "gmb-fiche-123",
"snapshot_id": "snap-789",
"visibility_score": 74,
"scanned_at": "2026-07-04T10:00:00Z"
}If no scan is available, the response takes the following form — not the flat form with visibility_score:
{ "fiche_id": "gmb-fiche-123", "snapshot": null }SEO & keywords
SEO data
/api/v2/seo/dataAuthreadReturns the listing's latest full SEO snapshot. The kind parameter selects the content: snapshot (positions, traffic, health) or competitors (identified competitors).
| Parameter | Type | Default |
|---|---|---|
kind | string | snapshot · competitors · (défaut : snapshot) |
bulle_id | string | Required with a sphere key (the targeted location). Optional with a bubble key. |
Response:
With data (the normal case), the response is flat:
{
"kind": "snapshot",
"snapshot_id": 42,
"bulle_id": "abc-123",
"created_at": "2026-03-10T04:00:00Z",
"website_url": "https://auto-sud-marseille.fr",
"has_ai_analysis": true,
"ranked_keywords": {},
"competitors": {},
"onpage": {},
"pagespeed": {},
"ai_analysis": {}
}Conditional content blocks
ranked_keywords, competitors, onpage, pagespeed, ai_analysis — are absent from the response when the scan didn't produce them: they aren't null, they simply aren't there. Test for their presence before reading them.When no scan has run yet for this location:
{ "kind": "snapshot", "snapshot": null, "bulle_id": "abc-123" }With kind=competitors:
{
"kind": "competitors",
"bulle_id": "abc-123",
"competitors": [],
"snapshot_date": "2026-03-10T04:00:00Z"
}Without a scan: competitors is [] and snapshot_date is absent.
Tracked keywords
/api/v2/seo/tracked-keywordsAuthreadLists the keywords tracked for the listing, with their current position, change (delta) and search volume.
bulle_id — Required with a sphere key (the targeted location). Optional with a bubble key.
[
{
"id": 12,
"keyword": "garage marseille",
"last_position": 4,
"previous_position": 6,
"delta": 2,
"last_search_volume": 1300,
"last_url": "https://autosud.fr/",
"last_checked_at": "2026-07-05T06:00:00Z",
"created_at": "2026-05-01T09:00:00Z",
"history": [ { "checked_at": "2026-07-05T06:00:00Z", "position": 4 } ]
}
]Add a keyword to tracking
/api/v2/seo/tracked-keywordsAuthpublishAdds a keyword to the listing's rank tracking.
Body (JSON)
{ "keyword": "garage marseille centre" }bulle_id — Required with a sphere key: the targeted location. Inferred automatically with a bubble key.
Response:
{
"id": 34,
"keyword": "garage marseille centre",
"last_position": null,
"previous_position": null,
"delta": null,
"last_search_volume": null,
"last_url": null,
"last_checked_at": null,
"created_at": "2026-07-20T10:00:00Z",
"history": []
}Search Console data
/api/v2/seo/search-consoleAuthreadReturns live Google Search Console data (impressions, clicks, position) by the requested dimensions, filters and dates.
| Parameter | Type | Default |
|---|---|---|
dimensions | array | query · page · date · country · device |
days | integer | 1-365 |
start_date | string | ISO 8601 |
end_date | string | ISO 8601 |
row_limit | integer | - |
query_contains | string | - |
query_equals | string | - |
page_contains | string | - |
page_equals | string | - |
country | string | - |
device | string | - |
search_type | string | - |
bulle_id | string | Required with a sphere key (the targeted location). Optional with a bubble key. |
Response:
{
"bulle_id": "abc-123",
"site_url": "https://autosud.fr/",
"start_date": "2026-06-01",
"end_date": "2026-06-30",
"dimensions": ["query"],
"search_type": "web",
"row_count": 1,
"rows": [ { "keys": ["garage marseille"], "clicks": 42, "impressions": 800, "ctr": 0.0525, "position": 4.2 } ]
}Run an SEO scan
/api/v2/seo/scanAuthpublishRuns a full SEO scan of the listing. Subject to a monthly quota (429 if exceeded). Costly operation: supports dry_run.
Body (JSON)
{ "dry_run": false }bulle_id — Required with a sphere key: the targeted location. Inferred automatically with a bubble key.
429
Response:
{
"ran": true,
"kind": "full",
"bulle_id": "abc-123",
"scanned_at": "2026-07-20T10:00:00Z",
"quota_used": 3,
"quota_limit": 10
}Look up a keyword
/api/v2/seo/keyword-lookupAuthpublishAnalyzes a keyword on demand: search volume, difficulty, related keywords. Costly operation: supports dry_run.
Body (JSON)
{ "keyword": "vidange voiture marseille", "dry_run": false }bulle_id — Required with a sphere key: the targeted location. Inferred automatically with a bubble key.
Response:
{
"kind": "keyword-lookup",
"keyword": "vidange voiture marseille",
"result": {}
}SEO articles (create & publish)
Create articles
/api/v2/articlesAuthpublishCreates one or more articles for connected sites (WordPress, Wix). AI writing runs in the background. Subject to a quota. 201 response.
Body (JSON)
{
"title": "Comment entretenir sa voiture en été",
"target_keyword": "entretien voiture été",
"site_ids": [12, 34],
"wix_site_ids": [7],
"ai_word_count_target": 1500,
"generate_content": true,
"generate_image": false,
"tone": "professional",
"language": "fr",
"meta_title": "Entretien voiture été | Auto Sud",
"meta_description": "Nos conseils d'expert pour préparer l'été.",
"excerpt": "Préparez votre véhicule pour l'été."
}Parameters
| Field | Type | Required |
|---|---|---|
title | string (min 3) | Yes |
target_keyword | string (min 2) | Yes |
site_id · site_ids | integer · integer[] | No |
wix_site_id · wix_site_ids | integer · integer[] | No |
ai_word_count_target | integer · 1500 | No |
generate_content | boolean · true | No |
generate_image | boolean · false | No |
tone | string · professional | No |
language | string · fr | No |
featured_image_url · meta_title · meta_description · excerpt | string | No |
bulle_id | string | Sphere key |
201 Created
Response:
{
"created": [ { "id": 42, "title": "Comment entretenir sa voiture en été", "site_id": 12 } ],
"skipped": [ { "wix_site_id": 7, "reason": "already_exists" } ],
"count": 1,
"generating": true
}Without a CMS (custom-built site)
bulle_id instead of a CMS site (site_ids / wix_site_ids), the article is created and attached to the location, without a CMS. This is the mode for custom-built sites (Next.js, Astro, in-house theme): the article is then served by GET /api/v2/articles, which your site consumes itself.{
"title": "5 conseils pour entretenir sa voiture",
"target_keyword": "entretien voiture marseille",
"bulle_id": "abc-123"
}The response then carries kind = api in created[], with site_id set to null:
{
"created": [ { "id": 43, "kind": "api", "site_id": null } ],
"count": 1,
"generating": true
}Update an article
/api/v2/articles/{article_id}AuthpublishPartially updates an article (only the provided fields change). Returns 409 if the article is already published online.
Body (JSON)
{
"title": "Nouveau titre",
"content_html": "<h2>...</h2>",
"excerpt": "...",
"meta_title": "...",
"meta_description": "...",
"target_keyword": "...",
"featured_image_url": "https://..."
}Partial update
Response:
{ "article_id": 42, "updated_fields": ["title", "meta_description"], "status": "draft" }Publish or schedule an article
/api/v2/articles/{article_id}/publishAuthpublishPublishes an article immediately, or schedules it if scheduled_at (future ISO date) is provided. Costly operation: supports dry_run.
Body (JSON)
{
"scheduled_at": "2026-07-15T09:00:00+02:00",
"dry_run": false
}Response:
{
"scheduled": true,
"article_id": 42,
"title": "Comment entretenir sa voiture en été",
"scheduled_at": "2026-07-15T09:00:00+02:00"
}QR codes
List QR codes
/api/v2/qr-codesAuthreadReturns the bubble's tracked QR codes, with scan count and redirect type (gate).
[
{
"id": 1,
"bulle_id": "abc-123",
"name": "Avis Auto Sud",
"target": "Page Google Reviews",
"scan_count": 342,
"last_scanned_at": "2026-07-18T15:00:00Z",
"is_active": true,
"gate_enabled": true,
"gate_threshold": 4,
"created_at": "2026-04-01T10:00:00Z"
}
]bulle_id — Restrict to one location. Default: the key's location, or every location of the brand.
Create a QR code
/api/v2/qr-codesAuthpublishCreates a tracked QR code pointing to a target URL, with an optional color and logo.
Body (JSON)
{
"target_url": "https://g.page/r/xxxx/review",
"name": "Avis Auto Sud",
"color_hex": "#000000",
"with_logo": true
}bulle_id — Optional: without it, a sphere key creates a QR code at the brand level (valid).
Response:
{
"id": 1,
"name": "Avis Auto Sud",
"target_url": "https://g.page/r/xxxx/review",
"short_url": "https://gmb.link/xxxx",
"png_url": "https://app.gmb-club.com/static/qr/xxxx.png",
"color_hex": "#000000",
"with_logo": true,
"scan_count": 0,
"created_at": "2026-07-20T10:00:00Z"
}Sites & reports
Connected sites
/api/v2/sitesAuthreadLists the sites connected to the bubble. Filterable by platform (wordpress, wix, shopify, prestashop).
| Parameter | Type | Default |
|---|---|---|
platform | string | wordpress · wix |
bulle_id | string | Restrict to one location. Default: the key's location, or every location of the brand. |
[
{
"platform": "wordpress",
"id": 1,
"site_url": "https://autosud.fr",
"site_name": "Auto Sud",
"sphere_id": "xyz-789",
"bulle_id": "abc-123",
"is_shared": false,
"has_api_key": true,
"wp_version": "6.5",
"plugin_version": "1.4.0",
"theme_name": "GeneratePress"
},
{
"platform": "wix",
"id": 2,
"site_url": "https://autosud-aix.wixsite.com",
"site_name": "Auto Sud Aix",
"sphere_id": "xyz-789",
"bulle_id": "abc-456",
"is_shared": false,
"has_token": true
}
]List reports
/api/v2/reportsAuthreadReturns already generated reports, with PDF and CSV download URLs.
| Parameter | Type | Default |
|---|---|---|
type | string | fiche · (défaut : fiche) |
limit | integer | 1-100 · 20 |
bulle_id | string | Restrict to one location. Default: the key's location, or every location of the brand. |
[
{
"fiche_name": "Auto Sud - Marseille Centre",
"report_name": "Rapport juin 2026",
"period": "2026-06",
"generated_at": "2026-07-01T08:00:00Z",
"pdf_url": "https://app.gmb-club.com/static/reports/rep-1.pdf",
"csv_url": "https://app.gmb-club.com/static/reports/rep-1.csv"
}
]Generate a report
/api/v2/reportsAuthpublishGenerates a PDF report. type = fiche for one location, or combine with at least two fiche_ids. Asynchronous processing (~1 to 2 min): 202 response, result retrievable via GET /v2/reports.
Body (JSON)
{
"type": "combine",
"fiche_ids": ["gmb-fiche-123", "gmb-fiche-456"],
"date_start": "2026-06-01",
"date_end": "2026-06-30",
"report_name": "Rapport juin 2026",
"dry_run": false
}date_start and date_end required
202 Accepted
Response:
{ "generated": true, "type": "combine", "report_id": "rep-1", "fiches_count": 2 }Images
Upload an image
/api/v2/images/uploadAuthpublishSends an image (image_base64 OR url, never both). JPEG, PNG, WebP, GIF formats, 8 MB maximum. Returns an image_url reusable in posts and articles.
Body (JSON)
{ "url": "https://example.com/photo.jpg" }
// ou : { "image_base64": "data:image/png;base64,iVBORw0..." }Response:
{
"uploaded": true,
"image_url": "https://app.gmb-club.com/static/uploads/mcp/xxxx.webp",
"size_bytes": 84213,
"format": "webp"
}Generate an image with AI
/api/v2/images/generateAuthpublishGenerates an image with AI from a prompt. align_with_brand (on by default) applies the brand's identity. Returns an image_url.
Body (JSON)
{
"prompt": "Un mécanicien souriant dans un garage moderne et lumineux",
"align_with_brand": true
}bulle_id — Required with a sphere key when align_with_brand is true (the location whose brand guidelines are aligned).
Response:
{
"generated": true,
"image_url": "https://app.gmb-club.com/static/uploads/mcp/xxxx.webp",
"brand_aligned": true
}Permissions
Each API key has configurable permissions:
readRead posts, articles, connections and info
scheduleCreate and modify scheduled posts
publishPublish immediately
deleteDelete posts
Rate Limiting
Each API key has configurable request limits:
| Limit | Default value |
|---|---|
| Per minute | 60 |
| Per day | 1000 |
Error codes
| Code | Description |
|---|---|
200 | Success |
201 | Resource created |
202 | Long operations: 202 response |
400 | Invalid request (check Content-Type and JSON format) |
401 | Missing or invalid API key |
403 | Insufficient permission |
404 | Resource not found |
409 | State conflict (e.g. article already published) |
410 | Resource gone at the provider (e.g. review removed from Google) |
422 | Invalid data |
429 | Rate limit exceeded |
500 | Server error |
502 | External service failed (Google, DataForSEO) |
503 | Service not configured or unavailable |
Code examples
import requests
API_KEY = "gmb_live_xxxx..."
BASE_URL = "https://app.gmb-club.com/api/v2"
headers = { "X-API-Key": API_KEY, "Content-Type": "application/json" }
# 1. Get key info
me = requests.get(f"{BASE_URL}/me", headers=headers).json()
print(f"Sphere: {me['sphere']['name']}")
print(f"Bubble: {me['bulle']['name']}")
# 2. Create a post
response = requests.post(f"{BASE_URL}/posts", headers=headers, json={
"content": "Post from Python!",
"platforms": ["facebook", "instagram"],
"scheduled_at": "2025-12-01T10:00:00+01:00"
})
print(response.json())
# 3. Get published articles
articles = requests.get(f"{BASE_URL}/articles", headers=headers,
params={"status": "published", "limit": 10}).json()
for article in articles['articles']:
print(f"#{article['id']}: {article['title']}")Make · n8n · Zapier
Make.com & n8n modules
dry_run
Make.com setup
Use the HTTP → Make a request module.
Critical parameter
Zapier setup
Use the Webhooks by Zapier → Custom Request action.
Security
| Measure | Description |
|---|---|
| Hashed keys | Stored as SHA256 hash, never in plain text |
| HTTPS required | All requests must use HTTPS |
| Bubble isolation | Each key only accesses its bubble's data |
| Optional expiration | Keys can have an expiration date |
| Revocation | Keys can be revoked at any time |
| Rate limiting | Abuse protection via Redis |

/api/v2/social/publishAuthpublishPublishes or schedules a post on one or more platforms.
Body (JSON)
platformstextimage_urlimage_urlsvideo_urlscheduled_atbulle_idplatforms: facebook, instagram, linkedin, pinterest, tiktok, snapchat, youtube, gmb.text: 1 to 63206 characters.image_urlfor a single image,image_urlsfor a carousel.scheduled_at(ISO 8601) absent = immediate publication.Response:
statusispublishing(immediate publication) orscheduled(scheduled).