Skip to main content

Python SDK for the Synup API

This project has been archived.

The maintainers of this project have marked this project as archived. No new releases are expected.

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-sdk

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

synup_sdk-0.4.0.tar.gz (31.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

synup_sdk-0.4.0-py3-none-any.whl (31.4 kB view details)

Uploaded Python 3

File details

Details for the file synup_sdk-0.4.0.tar.gz.

File metadata

  • Download URL: synup_sdk-0.4.0.tar.gz
  • Upload date:
  • Size: 31.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.4

File hashes

Hashes for synup_sdk-0.4.0.tar.gz
Algorithm Hash digest
SHA256 206fbdac7678521b19fbd4693d938be3e5be9b56839a3e56a94d244d26eafc6a
MD5 57049b4fa622e1a9ba9ace221d819a6a
BLAKE2b-256 146210c707a17aa3f839893c5040b49719758068cddebb796b40e1821adef606

See more details on using hashes here.

File details

Details for the file synup_sdk-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: synup_sdk-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 31.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.4

File hashes

Hashes for synup_sdk-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 665edee65a7401f586c4f72311c95795256c38e044989cd6ce781da784e3293e
MD5 a25cb0eb846b51714feb7aa23b7fd4bb
BLAKE2b-256 50fe5c43e1a3b1d3a27e3dde019e38d30275f4ae42d899c8048b444096bf663b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page