How to Add "Order Online" and "Book" Buttons to Google Business Profile via API

Create, prefer, update, and delete place action links — the Order online, Book, Reserve a table, and Shop buttons on a Google Business Profile listing — programmatically, across one location or hundreds.

The buttons under a listing’s name — “Order online”, “Reserve a table”, “Book online”, “Shop” — are place action links. Each is a typed URL on the location. Google renders the button label from the type and sends the customer to the URL.

place_action_typeButton
FOOD_ORDERINGOrder online (pickup or delivery, unspecified)
FOOD_DELIVERYOrder delivery
FOOD_TAKEOUTOrder pickup
DINING_RESERVATIONReserve a table
APPOINTMENTBook an appointment
ONLINE_APPOINTMENTBook an online appointment
SHOP_ONLINEShop online

Which types a location accepts depends on its category. A hair salon gets APPOINTMENT; a restaurant gets the food and reservation types. A type the location’s category does not support is rejected with 422.

Every request below takes location_id, the placement id from List placements.

Terminal window
curl "https://api.postproxy.dev/api/profiles/prof_abc123/google_business/place_action_links?location_id=accounts/113344/locations/558899" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"placeActionLinks": [
{
"name": "locations/558899/placeActionLinks/12345",
"uri": "https://acme.example/order",
"placeActionType": "FOOD_ORDERING",
"isPreferred": true,
"isEditable": true,
"providerType": "MERCHANT",
"createTime": "2026-09-01T10:00:00Z"
},
{
"name": "locations/558899/placeActionLinks/67890",
"uri": "https://delivery-platform.example/acme-coffee",
"placeActionType": "FOOD_DELIVERY",
"isPreferred": false,
"isEditable": false,
"providerType": "AGGREGATOR_3P"
}
]
}

Two fields decide what you can do with each entry:

  • providerTypeMERCHANT links were created by the business. AGGREGATOR_3P links were pushed by a third-party platform such as a delivery or reservation service that Google integrates with.
  • isEditabletrue only for merchant links. Aggregator links cannot be changed or removed through the API; the business can only outrank them with a preferred link of its own.
Terminal window
curl -X POST "https://api.postproxy.dev/api/profiles/prof_abc123/google_business/create_place_action_link" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location_id": "accounts/113344/locations/558899",
"uri": "https://acme.example/order",
"place_action_type": "FOOD_ORDERING",
"is_preferred": true
}'

The response is the created link with its name, which every later update or delete needs.

When a location has several links of the same type — the business’s own ordering page plus one or more aggregators — Google shows the preferred one first. Only one link per type per location can be preferred. Setting is_preferred: true on your link moves it ahead of the aggregator’s, which is the main reason to manage these links at all: commission-free orders on the business’s own site instead of a marketplace.

Terminal window
curl -X PATCH "https://api.postproxy.dev/api/profiles/prof_abc123/google_business/update_place_action_link" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location_id": "accounts/113344/locations/558899",
"name": "locations/558899/placeActionLinks/12345",
"fields": ["isPreferred"],
"is_preferred": true
}'

Update the URL

fields names what changes; uri, placeActionType, and isPreferred are all patchable:

Terminal window
curl -X PATCH "https://api.postproxy.dev/api/profiles/prof_abc123/google_business/update_place_action_link" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location_id": "accounts/113344/locations/558899",
"name": "locations/558899/placeActionLinks/12345",
"fields": ["uri"],
"uri": "https://order.acme.example/downtown"
}'

Passing a name that belongs to a different location returns 400.

Terminal window
curl -X DELETE "https://api.postproxy.dev/api/profiles/prof_abc123/google_business/delete_place_action_link" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location_id": "accounts/113344/locations/558899",
"name": "locations/558899/placeActionLinks/12345"
}'
{ "success": true }

Point every location at its own ordering page

Chains usually have one ordering URL per location. Read the current links first so the script updates an existing link rather than creating a duplicate:

const BASE = "https://api.postproxy.dev";
const headers = {
Authorization: `Bearer ${process.env.POSTPROXY_API_KEY}`,
"Content-Type": "application/json",
};
const qs = (o) => new URLSearchParams(o).toString();
const { data: locations } = await fetch(`${BASE}/api/profiles/${PROFILE}/placements`, { headers })
.then((r) => r.json());
for (const loc of locations) {
const uri = orderingUrlFor(loc.id); // e.g. from your own DB, keyed by location
const { placeActionLinks = [] } = await fetch(
`${BASE}/api/profiles/${PROFILE}/google_business/place_action_links?${qs({ location_id: loc.id })}`,
{ headers }
).then((r) => r.json());
const mine = placeActionLinks.find(
(l) => l.placeActionType === "FOOD_ORDERING" && l.providerType === "MERCHANT"
);
if (mine) {
await fetch(`${BASE}/api/profiles/${PROFILE}/google_business/update_place_action_link`, {
method: "PATCH",
headers,
body: JSON.stringify({ location_id: loc.id, name: mine.name, fields: ["uri", "isPreferred"], uri, is_preferred: true }),
});
} else {
await fetch(`${BASE}/api/profiles/${PROFILE}/google_business/create_place_action_link`, {
method: "POST",
headers,
body: JSON.stringify({ location_id: loc.id, uri, place_action_type: "FOOD_ORDERING", is_preferred: true }),
});
}
}

Errors

StatusCause
400location_id, uri, place_action_type, or name missing; a fields entry with no value; a name from another location
404The profile cannot see that location_id
422The type is not allowed for the location’s category, or the link is not editable (aggregator-owned)

Full parameter tables are on the Google Business API reference. The menu link and appointment link shown in the “From the business” section are attributes (url_menu, url_appointment), not action links.

Ready to get started?

Start with our free plan and scale as your needs grow. No credit card required.