Python SDK for the Synup API
Project description
Synup SDK
Build local presence automations in minutes — review auto-responders, listings monitors, reputation dashboards, bulk onboarding tools, and more.
Installation
pip install synup
Quick start: auto-reply to reviews in 10 lines
import synup
client = synup.Synup() # reads SYNUP_API_KEY from env
# Auto-reply to all 4-5 star reviews that haven't been answered
results = client.workflows.auto_reply_to_reviews(
16808,
template="Thanks for the {rating}-star review! We appreciate your support.",
min_rating=4,
)
print(f"Replied to {len(results)} reviews")
Quick start: listings health audit in 3 lines
import synup
client = synup.Synup()
audit = client.workflows.listings_health_audit(16808)
print(f"Health score: {audit.health_score}%")
print(f"Synced: {audit.synced_count}, Issues: {audit.issue_count}")
print(f"Duplicates found: {len(audit.duplicates)}")
Configuration
import synup
# Minimal — reads SYNUP_API_KEY env var
client = synup.Synup()
# Explicit key
client = synup.Synup(api_key="your-api-key")
# With custom config
client = synup.Synup(
api_key="your-api-key",
timeout=300.0, # request timeout in seconds (default: 240)
max_retries=3, # auto-retry on 429/5xx (default: 2)
)
Locations
# List with pagination
page = client.locations.list(first=10)
for loc in page:
print(loc.name, loc.city, loc.stateIso)
# Next page
if page.has_more:
next_page = page.next_page()
# Auto-paginate all
for loc in client.locations.list(first=100).auto_paging_iter():
print(loc.name)
# Retrieve single location
location = client.locations.retrieve(16808)
print(location.name)
# Search
page = client.locations.search("cafe", first=20)
# By IDs, store codes, folder, or tags
locations = client.locations.list_by_ids([16808, 16749])
locations = client.locations.list_by_store_codes(["STORE01", "STORE02"])
locations = client.locations.list_by_folder(folder_name="franchise")
page = client.locations.list_by_tags(["vip", "recent"], first=20)
# Create
result = client.locations.create({
"name": "Acme Inc",
"storeId": "ACME01",
"street": "123 Main St",
"city": "New York",
"stateIso": "NY",
"postalCode": "10001",
"countryIso": "US",
"phone": "5551234567",
})
print(result.success, result.errors)
# Update, archive, activate
client.locations.update({"id": 16808, "phone": "5559876543"})
client.locations.archive([16808])
client.locations.activate([16808])
Reviews
# List reviews with filters
page = client.reviews.list(16808, first=20, rating_filters=[1, 2])
for review in page:
print(review.content, review.rating)
# Auto-paginate all reviews
for review in client.reviews.list(16808, first=50).auto_paging_iter():
print(review.content)
# Respond to a review
client.reviews.respond(interaction_id="uuid-here", content="Thank you!")
# Edit or archive a response
client.reviews.edit_response(review_id="...", response_id="...", content="Updated reply")
client.reviews.archive_response(response_id="...")
# Review analytics
overview = client.reviews.analytics.overview(16808, start_date="2024-01-01")
timeline = client.reviews.analytics.timeline(16808)
sites = client.reviews.analytics.sites_stats(16808)
# Review phrases
phrases = client.reviews.phrases(["TG9jYXRpb246MTY4MDg="], start_date="2024-01-01")
Listings
# Premium, voice, AI, and additional listings
premium = client.listings.premium(16808)
voice = client.listings.voice(16808)
ai = client.listings.ai(16808)
additional = client.listings.additional(16808)
# Duplicates
dupes = client.listings.duplicates(16808)
client.listings.mark_duplicate(16808, ["listing-item-id"])
client.listings.mark_not_duplicate(16808, ["listing-item-id"])
# Connect/disconnect
client.listings.connect(16808, "listing-id", "account-id")
client.listings.disconnect(16808, "GOOGLE")
Analytics
google = client.analytics.google(16808, from_date="2024-01-01")
bing = client.analytics.bing(16808)
facebook = client.analytics.facebook(16808)
# Rankings
timeline = client.analytics.rankings_timeline(
[16808], "2024-01-01", "2024-03-31", ["Google"]
)
histogram = client.analytics.rankings_histogram(
[16808], "2024-01-01", "2024-03-31", ["Google"]
)
Keywords
keywords = client.keywords.list(16808)
performance = client.keywords.performance(16808, from_date="2024-01-01")
created = client.keywords.add(16808, ["plumber", "plumbing near me"])
client.keywords.archive("keyword-id")
Campaigns
campaigns = client.campaigns.list(16808)
result = client.campaigns.create(
16808,
name="Holiday Feedback",
customers=[{"name": "John", "email": "john@example.com"}],
screening=False,
)
client.campaigns.add_customers("campaign-id", [{"name": "Jane", "email": "jane@example.com"}])
Folders
folders = client.folders.list()
tree = client.folders.tree()
client.folders.create("franchise", parent_folder_name="all_franchise")
client.folders.rename("Old Name", "New Name")
client.folders.add_locations("franchise", [16808, 16749])
client.folders.remove_locations([16808])
client.folders.delete("folder-name")
Users
users = client.users.list()
roles = client.users.roles()
result = client.users.create(email="jane@example.com", role_id="...", first_name="Jane")
client.users.update("user-id", first_name="Jane Updated")
client.users.add_locations("user-id", [16808])
client.users.remove_locations("user-id", [16808])
Tags
tags = client.tags.list()
client.tags.add(16808, "vip")
client.tags.remove(16808, "old-tag")
Photos
photos = client.photos.list(16808)
client.photos.add(16808, [{"photo": "https://example.com/img.jpg", "type": "ADDITIONAL"}])
client.photos.remove(16808, ["photo-id"])
client.photos.star(16808, ["media-id"], starred=True)
Connected accounts
accounts = client.connected_accounts.list()
url = client.connected_accounts.connect_google("https://ok.com", "https://err.com")
client.connected_accounts.disconnect_google("account-id")
# OAuth for single location
url = client.connected_accounts.oauth_url(16808, "GOOGLE", "https://ok.com", "https://err.com")
client.connected_accounts.oauth_disconnect(16808, "FACEBOOK")
Grid reports
result = client.grid_reports.create(
location_id=16808,
keywords=["italian restaurant"],
business_name="Chianti",
business_street="No 12, 5th Block",
business_city="Bengaluru",
business_state="Karnataka",
business_country="India",
latitude=12.935216,
longitude=77.619961,
distance=20,
distance_unit="km",
grid_size=3,
)
report = client.grid_reports.retrieve("report-id")
reports = client.grid_reports.list(16808, page_size=20, page=1)
Automations
result = client.automations.temporary_close(
name="Holiday closure",
start_date="2025-12-24",
start_time="18:00:00",
end_date="2025-12-26",
location_id=16808,
)
Account-level
sites = client.plan_sites()
countries = client.countries()
subs = client.subscriptions()
Workflows — pre-built automations
High-level functions that combine multiple API calls into real product features.
# Auto-reply to positive reviews
results = client.workflows.auto_reply_to_reviews(
16808,
template="Thanks for the {rating}-star review!",
min_rating=4,
dry_run=True, # preview without sending
)
# Onboard a location with folder, tags, and keywords in one call
result = client.workflows.onboard_location(
name="Acme Coffee",
street="123 Main St",
city="New York",
state="NY",
postal_code="10001",
country="US",
phone="5551234567",
folder_name="NYC Stores",
tags=["new", "coffee"],
keywords=["coffee shop near me"],
)
# Bulk onboard from CSV
results = client.workflows.bulk_onboard_locations("locations.csv", folder_name="Imported")
# Weekly reputation report
report = client.workflows.weekly_reputation_report(16808)
print(report.review_summary, report.analytics, report.listings_health)
# Listings health audit
audit = client.workflows.listings_health_audit(16808)
print(f"Score: {audit.health_score}%, Issues: {audit.issue_count}")
Error handling
import synup
client = synup.Synup()
try:
client.locations.list()
except synup.AuthenticationError:
print("Invalid API key")
except synup.RateLimitError as e:
print(f"Rate limited — retry after {e.retry_after}s")
except synup.NotFoundError:
print("Resource not found")
except synup.ValidationError as e:
print(f"Bad request: {e.response_body}")
except synup.APIError as e:
print(f"API error {e.status_code}: {e.response_body}")
except synup.APIConnectionError:
print("Network error — could not reach API")
Version
Current version: 0.4.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
synup-0.4.0.tar.gz
(31.8 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
synup-0.4.0-py3-none-any.whl
(31.3 kB
view details)
File details
Details for the file synup-0.4.0.tar.gz.
File metadata
- Download URL: synup-0.4.0.tar.gz
- Upload date:
- Size: 31.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d7cd995c583fc6f24c891fa3850ea229a82f34bc0755abd9466cce3449bc63a
|
|
| MD5 |
a114f309118ac955c585188a5a3b87ce
|
|
| BLAKE2b-256 |
8d22a6b347c0251c044c5cec098eef0ab89b34a71dd26862a46b720f82e73a2c
|
File details
Details for the file synup-0.4.0-py3-none-any.whl.
File metadata
- Download URL: synup-0.4.0-py3-none-any.whl
- Upload date:
- Size: 31.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78182ec02e664b5e9eb035c0f5240717cda7169ce5788218373a8b49ff3df46f
|
|
| MD5 |
929a0989cafe74dfc3d5059f46d9d545
|
|
| BLAKE2b-256 |
cd14a1532cf810c5fd043099582a503cc942fdcb9249c382cf97026d7db6b4c1
|