Real Time Update

Real-time updates

RTUs are primarily intended for updates that you can't foresee, such as emergency closures, or metadata that changes periodically (such as ETAs). If your change does not need to be reflected immediately, you can use batch feed ingestion instead. Real-time updates are processed in no more than five minutes.

Google Cloud Platform setup

  1. Setup a GCP project. A GCP project is needed to access the RTU API.
    • Grant editor access food-support@google.com
    • Inform your Google POC of the GCP project number.Your GCP project must be associated with your Actions Center account in order for real-time updates to work.
    • Enable Maps Booking API:
      • In GCP go to APIs & Services > Library.
      • Search for “Google Maps Booking API”.
        Locate Google Maps Booking APIs
      • Find the Sandbox instance (“Google Maps Booking API (Dev)”) and click Enable
      • Find the Production instance (“Google Maps Booking API”) and click Enable
        Enable Google Maps Booking API
      • Create a service account with an editor role to your GCP project. For more details, see Service account setup.
      • Make sure you upload batch feeds to the environment in which you are working on real-time updates.
      • For API authentication we recommend installing the Google Client library in the language of your choice. Use “https://www.googleapis.com/auth/mapsbooking” as the OAuth scope. The code samples included below use these libraries. Otherwise, you'll need to handle token exchanges manually as described in Using OAuth 2.0 to Access Google APIs.

Service account setup

You need a service account to make authenticated HTTPS requests to Google APIs, such as the real-time updates API.

To set up a service account, do the following:

  1. Access the Google Cloud Platform console.
  2. Your account on the Actions Center also has a Google Cloud project associated with it. Select that project, if it's not already selected.
  3. Click Service Accounts in the left menu.
  4. Click Create Service Account.
  5. Enter a name for the service account and click Create.
  6. For Select a role, choose Project > Editor.
  7. Click Continue.
  8. Optional: Add users to grant them access to the service account and click Done.
  9. Click more > Create key for the service account you just created.
  10. Select JSON as the format and click Create.
  11. After your new public/private key pair is generated, download it to your machine.

Working with the API

The Real-time updates API supports two types of operations: Update and Delete. Adding new entities via the real-time update API is not supported. Real-time updates can be batched if you include multiple updates in a single API request. You can batch up to 1,000 updates in a single API call. We recommend utilizing a trigger-based approach to send updates via RTU (i.e. upon a data change in your system trigger a real-time update to Google) rather than a frequency-based approach (i.e. every X minutes scan your system for changes) if possible.

The real-time updates API operates in both sandbox and production environments. Sandbox environment is used to test the API requests and the production environment to update the content visible to Ordering End-to-End users.

  • Sandbox - partnerdev-mapsbooking.googleapis.com
  • Production - mapsbooking.googleapis.com

Endpoints

The real-time updates API exposes two endpoints to handle the incoming requests for inventory updates:

  • UPDATE - /v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchPush
  • DELETE - /v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchDelete

The parameter PARTNER_ID can be found in the Actions Center on the Account and users page, as shown on the screenshot below.

Partner ID on Partner Portal

Taking 10000001 as the value of PARTNER_ID as an example from the screenshot above, the complete URLs for sending API requests in sandbox and production will look like in the examples below.

Sandbox update

https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchPush

Sandbox DELETE

https://partnerdev-mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchDelete

Production update

https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchPush

Production DELETE

https://mapsbooking.googleapis.com/v1alpha/inventory/partners/10000001/feeds/google.food_service/record:batchDelete

Updating entities

To update entities in your inventory, use the update endpoint in an HTTP POST request. Each POST request must include the 10000001 parameter along with a JSON payload containing the entity you wish to update.

Note: Ensure your daily data feeds also contain any changes submitted through the real-time updates API. Otherwise, your data may be out of date or stale.

Update request payload

The request body is a JSON object with a list of records. Each record corresponds to an entity being updated. It consists of the proto_record field and the generation_timestamp indicating the time of the entity update:

  {
    "records": [
      {
        "proto_record":"ServiceData PROTO",
        "generation_timestamp":"UPDATE_TIMESTAMP"
      }
    ]
  }
  • ServiceData PROTO: The proto or JSON translation of the ServiceData entity you are updating.
  • UPDATE_TIMESTAMP: Make sure to include the timestamp of when the entity was generated in your backend systems. If this field is not included, it will be set to the time when Google receives the request. When updating an entity through a batchPush request, the generation_timestamp field is used for entity versioning. See the expected format of time values in the relational inventory schema.
  • The payload body must not exceed 5 MB in size.
  • Strip whitespaces to reduce size.
  • There can be up to 1,000 updates in a batchPush request.

Examples

Update an ETA

Suppose you urgently need to update the ETA of a delivery service from 30-60 to 60-90 minutes. Your update must contain the JSON for the entire Service entity.

Consider a service entity that looks as the follows:

{
	"service": {
		"service_id": "service/entity002",
		"service_type": "DELIVERY",
		"parent_entity_id": "entity002",
		"lead_time": {
			"min_lead_time_duration": "600s",
			"max_lead_time_duration": "1800s"
		},
		"action_link_id": "delivery_link/entity002"
	}
}

Your real-time update by HTTP POST are as follows (request bodies are pretty printed for readability):

POST v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [{
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "service" : {
        "service_id" : "23456/delivery",
        "service_type" : "DELIVERY",
        "parent_entity_id" : "23456",
        "disabled" : "false",
        "action_link_id": "delivery_link/entity002",
        "lead_time" : {
          "min_lead_time_duration" : {
            "seconds": "3600"
          },
          "max_lead_time_duration" : {
            "seconds": "5400"
          }
        }
      }
    },
    "generation_timestamp": "2023-09-13T17:11:10.750Z"
  }]
}

Update multiple entities

To update multiple restaurant entities in a single API call, include multiple records in the proto_record field of the request body.

POST v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchPush
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [{
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "service" : {
        "service_id" : "23456/delivery",
        "service_type" : "DELIVERY",
        "parent_entity_id" : "23456",
        "disabled" : "false",
        "action_link_id": "delivery_link/entity002",
        "lead_time" : {
          "min_lead_time_duration" : {
            "seconds": "1800"
          },
          "max_lead_time_duration" : {
            "seconds": "3600"
          }
        }
      }
    },
    "generation_timestamp": "2023-09-13T17:11:10.750Z"
  },
  {
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "fee" : {
        "fee_id" : "12345/delivery_fee",
        "fee_type" : "DELIVERY",
        "fixed_amount" : {
          "currency_code" : "USD",
          "units" : "10",
          "nanos" : "0"
        },
        "service_ids": ["service/entity002"]
      }
    },
    "generation_timestamp" : "2023-09-13T17:11:10.750Z"
  }]
}

Delete entities

To delete entities from your inventory, use the DELETE endpoint in an HTTP POST request. Each POST request must include the PARTNER_ID parameter along with the JSON payload which contains the identifier of the entity you want to delete.

Note: Ensure your daily data feeds also contain any changes submitted through the real-time update API. Otherwise, the daily batch ingestion will overwrite your real-time changes.

POST v1alpha/inventory/partners/PARTNER_ID/feeds/google.food_service/record:batchDelete
Host: mapsbooking.googleapis.com
Content-Type: application/json
{
  "records": [{
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "service" : {
        "service_id" : "23456/delivery"
      }
    },
    "delete_time": "2023-09-13T17:11:10.750Z"
  },
  {
    "proto_record": {
      "@type": "type.googleapis.com/food.ordering.service.v1.ServiceData",
      "fee" : {
        "fee_id" : "12345/delivery_fee"
     }
  },
  "delete_time" : "2023-09-13T17:11:10.750Z"
  }]
}

Adding entities

Do not use real-time updates to add new entities as this may result in data inconsistencies. Instead, use batch feeds.

Validation & API response codes

There are two type of validations performed on the real-time update API calls:

  • Request-level - These validations check that the payload follows the schema and every proto_record contains an id and type fields. These checks are synchronous and the results are returned in the API response body. A response code 200 and an empty JSON body {} means these validations passed and the entities in that request were queued for processing. A non-200 response code means that one or more of these validations failed and the entire request is rejected (including all entities in the payload). For example, if a proto_record is missing a @type, the following error response is returned:
  {
      "error": {
        "code": 400,
    "message": "Record:{...}",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.DebugInfo",
        "detail": "[ORIGINAL ERROR] generic::invalid_argument: Failed to parse one or more rtu records. Record:... The entity type could not be extracted from the entity value." 
      }
    ]
  }
  • Entity-level: Each entity (proto_record) in the payload is validated against the schema. Issues encountered at this phase of validation are not reported in the API response. They are only reported in the RTU Reporting dashboard of the Actions Center.

Note: A 200 response code does not mean that all entities were successfully ingested.

API quotas

Real-time API updates have a quota of 1,500 requests every 60 seconds, or 25 requests per second on average. When a quota is exceeded, Google responds with the following error message:

{
  "error": {
    "code": 429,
    "message": "Insufficient tokens for quota ...",
    "status": "RESOURCE_EXHAUSTED",
    "details": [...]
  }
}

To handle this, retry the call again at exponentially larger intervals until it succeeds. If you regularly exhaust the quota, consider to include more entities in one API request. You can include up to 1,000 entities in one API call.

Processing times real-time updates

An entity updated through a real-time update is processed in 5 minutes.