Locations
List, create, update, archive, search, and retrieve locations via client.locations.
All location methods live under client.locations. Install the SDK and
configure your key before using these; see
Installation and Quickstart.
Location IDs
Methods that take a location_id accept either a numeric ID (16808) or its
base64-encoded equivalent ("TG9jYXRpb246MTY4MDg="). The SDK encodes numeric
IDs automatically, so both forms are interchangeable:
# These are equivalentclient.locations.retrieve(16808)client.locations.retrieve("TG9jYXRpb246MTY4MDg=")locations.add
Create a location in one call with every mandatory field as a keyword
argument. This is the recommended way to create locations. The SDK validates
the API's create requirements client-side and raises ValidationError before
any network call, so a bad payload fails fast with a clear message.
client.locations.add(
*,
name: str,
description: str,
sub_category_id: int,
country_iso: str,
city: str | None = None,
street: str | None = None,
state_iso: str | None = None,
postal_code: str | None = None,
phone: str | None = None,
website: str | None = None,
store_id: str | None = None,
hide_address: bool | None = None,
business_hours: list[dict] | None = None,
folder_ids: list[str] | None = None,
service_area: dict | None = None,
place_action_links: list[dict] | None = None,
enabled_site_ids: list[int] | None = None,
additional_fields: dict | None = None,
) -> APIObject
| Argument | Type | Description |
|---|---|---|
name | str | Business name, 2-150 characters. Required. |
description | str | Business description, minimum 200 characters. Publishers use it as the primary listing copy. Required. |
sub_category_id | int | Primary subcategory ID. Use client.subcategories() for valid IDs. Required. |
country_iso | str | Two-letter country ISO code. Use client.countries() for supported countries. Required. |
city | str | City. Required for countries with city-level addressing; omit only for service-area businesses with hide_address=True. |
street | str | Street address. |
state_iso | str | State or region ISO code. |
postal_code | str | Postal or ZIP code. |
phone | str | Primary phone number, validated for the country. |
website | str | Business website URL. |
store_id | str | Your unique store code; must be unique across the account. |
hide_address | bool | Hide the street address (service-area businesses). |
business_hours | list[dict] | Weekly hours, e.g. [{"day": "MONDAY", "slots": [...]}]. |
folder_ids | list[str] | Folder IDs to place the location in. |
service_area | dict | Service-area config: {businessType, regionCode, placeInfos}. |
place_action_links | list[dict] | Google action links, e.g. [{"placeActionType": "APPOINTMENT", "uri": "https://...", "isPreferred": True}]. |
enabled_site_ids | list[int] | Site IDs to publish this location to, when you want a subset of your plan's sites. Use client.plan_sites() for IDs. |
additional_fields | dict | Extra camelCase fields merged into the payload as-is. |
Client-side validation checks: name 2-150 characters, description at
least 200 characters, sub_category_id and country_iso present, and city
present unless hide_address=True.
The return value is the create payload: .location holds the new location.
You never need to check success flags; the SDK raises ValidationError when
the API rejects the payload.
result = client.locations.add( name="Acme Dental", description=( "Acme Dental is a family-owned dental practice offering general, " "cosmetic, and pediatric dentistry in the heart of New York. Our " "team provides cleanings, fillings, crowns, whitening, and same-day " "emergency care in a modern, comfortable office with weekend hours " "and easy online booking for new and returning patients." ), sub_category_id=1432, country_iso="US", city="New York", street="123 Jump Street", state_iso="NY", postal_code="10013", phone="6443859313", website="https://acmedental.example.com", store_id="NYC-001", place_action_links=[ {"placeActionType": "APPOINTMENT", "uri": "https://acmedental.example.com/book", "isPreferred": True}, ], enabled_site_ids=[1, 24, 87],)print("Created:", result.location.id, result.location.name)locations.list
List locations with cursor-based pagination. Returns a SyncPage.
client.locations.list(
*,
first: int | None = None,
after: str | None = None,
before: str | None = None,
last: int | None = None,
) -> SyncPage
# First page of 25page = client.locations.list(first=25)for loc in page: print(loc.name, loc.city) # Next page manuallyif page.has_more: page2 = page.next_page() # Auto-paginate all locationsfor loc in client.locations.list(first=100).auto_paging_iter(): print(loc.name)locations.retrieve
Get a single location by ID. Raises NotFoundError if the ID doesn't exist.
client.locations.retrieve(location_id: str | int) -> APIObject
loc = client.locations.retrieve(16808)print(loc.name, loc.street, loc.city)locations.list_by_ids
Fetch multiple locations by a list of IDs (numeric or base64) in one call.
client.locations.list_by_ids(location_ids: list[str | int]) -> list[APIObject]
locs = client.locations.list_by_ids([16808, 16809, "TG9jYXRpb246MTQwMjQ="])for loc in locs: print(loc.id, loc.name)locations.list_by_store_codes
Fetch locations matching the given store codes.
client.locations.list_by_store_codes(store_codes: list[str]) -> list[APIObject]
locs = client.locations.list_by_store_codes(["SF-001", "NYC-042"])for loc in locs: print(loc.storeId, loc.name)locations.search
Search locations by keyword across name, address, or store ID. Returns a
SyncPage.
client.locations.search(
query: str,
*,
fields: list[str] | None = None,
first: int | None = None,
after: str | None = None,
before: str | None = None,
last: int | None = None,
) -> SyncPage
# Search all fieldspage = client.locations.search("downtown dental", first=10) # Restrict to name onlypage = client.locations.search("Acme Dental", fields=["name"], first=10) for loc in page: print(loc.name, loc.city)locations.create
Create a location from a raw input dict with camelCase field names. Prefer
locations.add for keyword arguments and client-side
validation; use create when you already have a camelCase payload.
client.locations.create(input: dict) -> APIObject
Required by the API: name, description (minimum 200 characters),
subCategoryId, countryIso, and city (for countries with city-level
addressing).
result = client.locations.create({ "name": "Acme Dental Brooklyn", "description": ( "Acme Dental Brooklyn is a family-owned dental practice offering " "general, cosmetic, and pediatric dentistry. Our team provides " "cleanings, fillings, crowns, whitening, and same-day emergency " "care in a modern, comfortable office with weekend hours and easy " "online booking for new and returning patients across Brooklyn." ), "subCategoryId": 1432, "countryIso": "US", "city": "Brooklyn", "street": "88 Court St", "stateIso": "NY", "postalCode": "11201", "phone": "6443859314", "storeId": "NYC-002",})print("Created:", result.location.id)locations.update
Update a location. Pass id plus any fields to change (camelCase). The id
may be numeric or base64; the SDK encodes it automatically.
client.locations.update(input: dict) -> APIObject
result = client.locations.update({ "id": 16808, "phone": "6443859399", "street": "125 Jump Street",})print("Updated:", result.location.id)locations.archive
Archive one or more locations.
client.locations.archive(location_ids: list[str | int]) -> APIObject
result = client.locations.archive([16808, 16809])print(result.to_dict())locations.cancel_archive
Cancel a scheduled archival.
client.locations.cancel_archive(
location_ids: list[str | int],
selection_type: str,
changed_by: str,
) -> APIObject
client.locations.cancel_archive( [16808], selection_type="manual", changed_by="admin@example.com",)