Zernio
Zernio
PlatformsGoogle Business ProfilePosts & Content TypesEvent & Offer PostsMulti-Location PostingBusiness Profile ManagementServices & Food MenusAnalyticsInboxFields, Media & Limits
Dashboard
llms.txtOpenAPI
OverviewPlatformsAPI ReferenceResources
Google Business Profile

Services & Food Menus

Read and replace the service list of a Google Business Profile location, and the food menus of a restaurant or cafe.


When you finish this page the services a Google Business Profile (googlebusiness) location offers, and the menus of a food business, come from the API. You need a connected Google Business Profile account (accountId) whose location is verified (verification).

Services

GET /v1/accounts/{accountId}/gmb-services returns the services the location offers and PUT replaces the whole list (Services). Google's API has no per-item update, so send every service on each PUT. A service is either structured (a serviceTypeId from Google's catalog) or free-form (a category and a label), with an optional price.

import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data: services } = await zernio.gmbservices.getGoogleBusinessServices({
  path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' }
});

await zernio.gmbservices.updateGoogleBusinessServices({
  path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' },
  body: {
    serviceItems: [
      ...services.services,
      {
        freeFormServiceItem: {
          category: 'categories/gcid:plumber',
          label: { displayName: 'Pipe Repair', description: 'Emergency and scheduled pipe repair' }
        },
        price: { currencyCode: 'USD', units: '150' }
      }
    ]
  }
});

Response (200) of the read:

{
  "success": true,
  "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
  "locationId": "12345678901234567890",
  "services": [
    {
      "freeFormServiceItem": {
        "category": "categories/gcid:plumber",
        "label": { "displayName": "Pipe Repair", "description": "Emergency and scheduled pipe repair" }
      },
      "price": { "currencyCode": "USD", "units": "150" }
    }
  ]
}

Response (200) of the update: success and the services array as Google stored it, which is the list to send back on the next PUT.

Food menus

For locations that support menus (restaurants, cafes), GET /v1/accounts/{accountId}/gmb-food-menus returns the menus and PUT updates them with the full menus array and an updateMask (Food menus). A menu item's attributes take a price with a currency code, dietaryRestriction (VEGETARIAN, VEGAN, GLUTEN_FREE), allergen (DAIRY, GLUTEN, SHELLFISH, ...), spiciness, servesNumPeople, preparationMethods and mediaKeys for item photos. Give an item options when it comes in variants: each entry carries its own labels and attributes, so a size can set its own price.

const { data: menus } = await zernio.gmbfoodmenus.getGoogleBusinessFoodMenus({
  path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' }
});

await zernio.gmbfoodmenus.updateGoogleBusinessFoodMenus({
  path: { accountId: '66b2e19d8c3f5a7e9d0b1c2d' },
  body: {
    menus: [{
      labels: [{ displayName: 'Lunch Menu', languageCode: 'en' }],
      sections: [{
        labels: [{ displayName: 'Appetizers' }],
        items: [{
          labels: [{ displayName: 'Caesar Salad', description: 'Romaine, parmesan, croutons' }],
          attributes: {
            price: { currencyCode: 'USD', units: '12' },
            dietaryRestriction: ['VEGETARIAN']
          }
        }]
      }]
    }],
    updateMask: 'menus'
  }
});

console.log(menus.menus);

Response (200) of the read:

{
  "success": true,
  "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
  "locationId": "12345678901234567890",
  "name": "accounts/123456789/locations/12345678901234567890/foodMenus",
  "menus": [
    {
      "labels": [{ "displayName": "Lunch Menu", "languageCode": "en" }],
      "sections": [
        {
          "labels": [{ "displayName": "Appetizers" }],
          "items": [
            {
              "labels": [{ "displayName": "Caesar Salad", "description": "Romaine, parmesan, croutons" }],
              "attributes": {
                "price": { "currencyCode": "USD", "units": "12" },
                "dietaryRestriction": ["VEGETARIAN"]
              }
            }
          ]
        }
      ]
    }
  ]
}

Response (200) of the update: the same body, with menus as Google stored it.

If it fails

Both endpoints proxy Google, so a 400 on PUT /gmb-services means Google rejected the serviceItems list and its own message comes back in the envelope:

{
  "error": "Request contains an invalid argument.",
  "code": "gbp_bad_request"
}

Read the location's categories with Location details, and send a freeFormServiceItem when Google's catalog has no serviceTypeId for what the business offers. On the food-menu calls a 400 means the account is not a Google Business Profile account or has no location selected; menus themselves exist only on locations Google gives menu support to. A 403 on either surface means the Google login has no permission on this location, and a 401 with code token_invalid means Google revoked the token, so reconnect the account. Error handling covers the envelope.

Related

  • Services and Food menus: the full schemas.
  • Business Profile Management: verification, hours, photos, attributes and action links.
  • Multi-Location Posting: the locationId these endpoints accept.
Was this page helpful?

Business Profile Management

Read and update a Google Business Profile listing through the API, with verification, hours, photos, attributes and action links.

Analytics

Read daily performance metrics and the search keywords that triggered impressions for a Google Business Profile location.

On this page

ServicesFood menusIf it failsRelated