Quickstart

Connect to listingsAPI, list your locations, create one in a single call, and respond to a review.

1. Set your API key

Get your key from API Keys → New key in the listingsAPI developer dashboard. The SDK reads it from the LISTINGSAPI_KEY environment variable automatically.

bash
export LISTINGSAPI_KEY="your-api-key"

2. List your locations

quickstart.py
import listingsapi
 
client = listingsapi.ListingsAPI()
 
page = client.locations.list(first=5)
for loc in page:
print(loc.name, "--", loc.city, loc.stateIso)
 
print(f"\nShowing {len(page)} locations, has_more={page.has_more}")
bash
python quickstart.py

Expected output:

bash
Acme Dental Downtown -- New York NY
Acme Dental Midtown -- New York NY
Acme Dental Brooklyn -- Brooklyn NY
 
Showing 3 locations, has_more=False

To walk every page automatically, use client.locations.list(first=100).auto_paging_iter(); it follows cursor pages so you never manage cursors by hand.

3. Create a location in one call

locations.add() takes every mandatory field as a keyword argument and validates them client-side (name length, 200-character description minimum, category, country, city) before any network call, so a bad payload fails fast with a clear ValidationError.

Python
import listingsapi
 
client = listingsapi.ListingsAPI()
 
result = client.locations.add(
name="Acme Dental Uptown",
description=(
"Acme Dental Uptown is a family-owned dental practice on the Upper "
"West Side of New York offering preventive care, cosmetic dentistry, "
"orthodontics, and emergency appointments. Our board-certified team "
"combines modern equipment with a gentle, patient-first approach."
),
sub_category_id=1432,
country_iso="US",
city="New York",
street="482 Columbus Ave",
state_iso="NY",
postal_code="10024",
phone="6443859313",
)
 
print(result.location.id)
print(result.location.name)

Publishers use the description as the primary listing copy, which is why the API requires at least 200 characters. Get valid sub_category_id values from client.subcategories().

The new ID comes back as a base64 string like TG9jYXRpb246MTY4MDg=. Numeric and base64 IDs are interchangeable everywhere the SDK takes a location ID, so client.locations.retrieve(16808) and client.locations.retrieve("TG9jYXRpb246MTY4MDg=") fetch the same location.

4. Respond to a review

List reviews for a location, then reply using the review's interactionId:

Python
import listingsapi
 
client = listingsapi.ListingsAPI()
 
reviews = client.reviews.list(16808, first=10, rating_filters=[4, 5])
for review in reviews:
print(review.rating, "-", review.get("content"))
 
review = reviews[0]
client.reviews.respond(
interaction_id=review.interactionId,
content="Thank you for the kind review! We look forward to seeing you again soon.",
)

If the platform rejects the reply, the SDK raises ValidationError even when the HTTP status is 200; you never check success flags yourself.

5. Handle errors

Python
import listingsapi
 
try:
client = listingsapi.ListingsAPI(api_key="bad-key")
client.locations.list()
except listingsapi.AuthenticationError as e:
print("Invalid key:", e.code)

Invalid keys come back either as HTTP 401 or as an HTTP 200 body carrying the platform code SY90005; the SDK raises AuthenticationError for both. See Error handling for the full exception hierarchy.

Next steps