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:

Python
# These are equivalent
client.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
ArgumentTypeDescription
namestrBusiness name, 2-150 characters. Required.
descriptionstrBusiness description, minimum 200 characters. Publishers use it as the primary listing copy. Required.
sub_category_idintPrimary subcategory ID. Use client.subcategories() for valid IDs. Required.
country_isostrTwo-letter country ISO code. Use client.countries() for supported countries. Required.
citystrCity. Required for countries with city-level addressing; omit only for service-area businesses with hide_address=True.
streetstrStreet address.
state_isostrState or region ISO code.
postal_codestrPostal or ZIP code.
phonestrPrimary phone number, validated for the country.
websitestrBusiness website URL.
store_idstrYour unique store code; must be unique across the account.
hide_addressboolHide the street address (service-area businesses).
business_hourslist[dict]Weekly hours, e.g. [{"day": "MONDAY", "slots": [...]}].
folder_idslist[str]Folder IDs to place the location in.
service_areadictService-area config: {businessType, regionCode, placeInfos}.
place_action_linkslist[dict]Google action links, e.g. [{"placeActionType": "APPOINTMENT", "uri": "https://...", "isPreferred": True}].
enabled_site_idslist[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_fieldsdictExtra 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.

Python
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
Python
# First page of 25
page = client.locations.list(first=25)
for loc in page:
print(loc.name, loc.city)
 
# Next page manually
if page.has_more:
page2 = page.next_page()
 
# Auto-paginate all locations
for 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
Python
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]
Python
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]
Python
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
Python
# Search all fields
page = client.locations.search("downtown dental", first=10)
 
# Restrict to name only
page = 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).

Python
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
Python
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
Python
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
Python
client.locations.cancel_archive(
[16808],
selection_type="manual",
changed_by="admin@example.com",
)

See also

  • Posts: publish announcements, events, and offers
  • Listings: check sync status per location
  • Reviews: list and respond to reviews
  • Analytics: Google, Bing, Facebook profile analytics