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.
What place action links are
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_type | Button |
|---|---|
FOOD_ORDERING | Order online (pickup or delivery, unspecified) |
FOOD_DELIVERY | Order delivery |
FOOD_TAKEOUT | Order pickup |
DINING_RESERVATION | Reserve a table |
APPOINTMENT | Book an appointment |
ONLINE_APPOINTMENT | Book an online appointment |
SHOP_ONLINE | Shop 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.
List the links on a location
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:
providerType—MERCHANTlinks were created by the business.AGGREGATOR_3Plinks were pushed by a third-party platform such as a delivery or reservation service that Google integrates with.isEditable—trueonly 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.
Create a link
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.
Make your own link the preferred one
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.
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:
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.
Delete a link
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
| Status | Cause |
|---|---|
400 | location_id, uri, place_action_type, or name missing; a fields entry with no value; a name from another location |
404 | The profile cannot see that location_id |
422 | The 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.