{
  "openapi": "3.0.3",
  "info": {
    "title": "GMB Ranking API",
    "version": "1.0.0",
    "description": "Read-only access to a business's Google Business Profile performance, local rank tracking, reviews and citations, with an API key from Account → Developer API (paid plans). Keys may be limited to one location.",
    "contact": {
      "email": "hello@gmbranking.com",
      "url": "https://developers.gmbranking.com"
    }
  },
  "servers": [
    {
      "url": "https://www.gmbranking.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Who the key belongs to"
    },
    {
      "name": "Businesses",
      "description": "Locations on the account"
    },
    {
      "name": "Performance",
      "description": "Google Business Profile metrics"
    },
    {
      "name": "Rankings",
      "description": "Local rank-grid tracking"
    },
    {
      "name": "Reviews & citations",
      "description": "Reputation data"
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Create one at https://www.gmbranking.com/account/api (Pro and Agency plans). Read-only."
      }
    },
    "schemas": {
      "MetricSeries": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "example": "Profile views"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "One value per entry in the response's `labels` array, oldest first.",
            "example": [
              263,
              296,
              241,
              259,
              273,
              208
            ]
          }
        }
      },
      "Performance": {
        "type": "object",
        "properties": {
          "business": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "google_connected": {
                "type": "boolean"
              }
            }
          },
          "months": {
            "type": "integer",
            "enum": [
              1,
              3,
              6,
              12
            ]
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": [
              "May",
              "Jun",
              "Jul",
              "Aug",
              "Sep",
              "Oct"
            ]
          },
          "metrics": {
            "type": "object",
            "description": "Empty object when the location is not linked to Google; read `error` for why.",
            "properties": {
              "views": {
                "$ref": "#/components/schemas/MetricSeries"
              },
              "calls": {
                "$ref": "#/components/schemas/MetricSeries"
              },
              "website": {
                "$ref": "#/components/schemas/MetricSeries"
              },
              "directions": {
                "$ref": "#/components/schemas/MetricSeries"
              },
              "bookings": {
                "$ref": "#/components/schemas/MetricSeries"
              },
              "messages": {
                "$ref": "#/components/schemas/MetricSeries"
              }
            }
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Business": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "example": 42
          },
          "name": {
            "type": "string",
            "example": "Acme Plumbing"
          },
          "address": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "rating": {
            "type": "number",
            "nullable": true
          },
          "reviews_count": {
            "type": "integer"
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "photo": {
            "type": "string",
            "nullable": true
          },
          "google_connected": {
            "type": "boolean"
          },
          "profile_views_30d": {
            "type": "integer",
            "nullable": true
          },
          "profile_calls_30d": {
            "type": "integer",
            "nullable": true
          },
          "profile_clicks_30d": {
            "type": "integer",
            "nullable": true
          },
          "last_synced_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "example": "plan_required"
          },
          "upgrade_url": {
            "type": "string"
          },
          "docs_url": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "Unauthenticated": {
        "description": "No key, or the key was revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PlanRequired": {
        "description": "Key is valid but the account's plan does not include API access.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "More than 120 requests per minute for this key."
      }
    }
  },
  "paths": {
    "/api/v1/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "The account behind this key",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 1,
                    "name": "Acme Ltd",
                    "email": "you@example.com",
                    "company": "Acme",
                    "plan": "agency",
                    "businesses_count": 25,
                    "created_at": "2026-07-06T13:11:25+00:00"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/api/v1/businesses": {
      "get": {
        "tags": [
          "Businesses"
        ],
        "summary": "Every location on the account",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Business"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          }
        }
      }
    },
    "/api/v1/businesses/{business}": {
      "get": {
        "tags": [
          "Businesses"
        ],
        "summary": "One location in full, plus saved reports",
        "parameters": [
          {
            "name": "business",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          },
          "404": {
            "description": "Not found, or not on this account."
          }
        }
      }
    },
    "/api/v1/businesses/{business}/performance": {
      "get": {
        "tags": [
          "Performance"
        ],
        "summary": "Google Business Profile metrics, month by month",
        "parameters": [
          {
            "name": "business",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "months",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                1,
                3,
                6,
                12
              ],
              "default": 6
            }
          },
          {
            "name": "range",
            "in": "query",
            "description": "Same window as the Performance page buttons. Equivalent to months=1|3|6|12.",
            "schema": {
              "type": "string",
              "enum": [
                "1M",
                "3M",
                "6M",
                "1Y"
              ],
              "default": "6M"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Performance"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          },
          "404": {
            "description": "Not found, or not on this account."
          }
        }
      }
    },
    "/api/v1/businesses/{business}/rankings": {
      "get": {
        "tags": [
          "Rankings"
        ],
        "summary": "Local rank grid — latest scan and history per keyword",
        "parameters": [
          {
            "name": "business",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "include_grid",
            "in": "query",
            "description": "Include every grid point of the latest scan.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          }
        }
      }
    },
    "/api/v1/businesses/{business}/reviews": {
      "get": {
        "tags": [
          "Reviews & citations"
        ],
        "summary": "Stored Google reviews plus external ones",
        "parameters": [
          {
            "name": "business",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          }
        }
      }
    },
    "/api/v1/businesses/{business}/citations": {
      "get": {
        "tags": [
          "Reviews & citations"
        ],
        "summary": "Citation / NAP status per directory",
        "parameters": [
          {
            "name": "business",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "403": {
            "$ref": "#/components/responses/PlanRequired"
          }
        }
      }
    }
  }
}
