Skip to content

Latest commit

 

History

History
377 lines (292 loc) · 10.2 KB

File metadata and controls

377 lines (292 loc) · 10.2 KB

Surmado Python SDK

CI PyPI version Python 3.8+

Official Python client for Surmado's AI visibility testing and SEO reports.

One-time reports. No subscriptions. API-first.

Installation

pip install surmado

Quick Start

from surmado import Surmado

client = Surmado()  # uses SURMADO_API_KEY env var

# Run an AI Visibility Test
report = client.signal(
    url="https://example.com",
    brand_name="Example Brand",
    email="you@example.com",
    industry="E-commerce",
    location="United States",
    persona="Small business owners looking for affordable solutions",
    pain_points="Finding reliable vendors, managing costs",
    brand_details="Affordable solutions for growing businesses",
    direct_competitors="Competitor A, Competitor B"
)

print(f"Report queued: {report['report_id']}")

# Wait for completion (or use webhooks)
completed = client.wait_for_report(report["report_id"])
print(f"PDF ready: {completed['download_url']}")
print("(Save for Surmado Solutions) Report Token: ", completed['token'])

See examples/ for runnable scripts.

Repository Structure

/client          ← SDK client code (surmado package)
/examples        ← Runnable usage examples
/integrations    ← Integration guides (Zapier, Make, n8n, Webhooks)
README.md        ← You are here
Directory Contents
client/ Python package source (surmado/), unit tests
examples/ Quick start script, ready to run with your API key
integrations/ Step-by-step guides for Zapier, Make, n8n, and webhook setup

API Surface

Products

Method Description Credits
client.signal(...) AI Visibility report — tests your brand across 7 AI platforms 1
client.scan(...) Site Audit — comprehensive SEO analysis 1
client.solutions(...) Strategy — multi-AI strategic recommendations from 6 agents 1
client.bundle(...) Full Analysis — all 3 reports in one call 3

Signal — AI Visibility Testing

result = client.signal(
    url="https://acme.com",
    brand_name="Acme Corp",                              # max 100 chars
    email="you@acme.com",
    industry="B2B SaaS",                                 # max 200 chars
    location="United States",                            # max 200 chars
    persona="CTOs at mid-market companies",              # max 800 chars
    pain_points="Integration challenges, lack of visibility",  # max 1000 chars
    brand_details="Modern, dev-focused tooling",         # max 1200 chars
    direct_competitors="Asana, Monday.com",              # max 500 chars
)

Scan — SEO Auditing

result = client.scan(
    url="https://acme.com",
    brand_name="Acme Corp",
    email="you@acme.com",
    competitor_urls=["https://competitor1.com", "https://competitor2.com"]
)

Solutions — Strategic Advisory

Mode 1: With Signal Token (recommended)

signal_result = client.signal(...)
solutions_result = client.solutions(
    email="you@acme.com",
    signal_token=signal_result["token"]
)

Mode 2: Standalone

result = client.solutions(
    email="you@acme.com",
    brand_name="Acme Corp",
    business_story="We're a B2B SaaS company in project management...",
    decision="Should we expand to enterprise market?",
    success="$10M ARR in 18 months",
    timeline="Q2 2025",
    scale_indicator="$2M ARR, 20 employees"
)

Mode 3: With Financial Analysis

result = client.solutions(
    email="you@acme.com",
    signal_token=signal_result["token"],
    include_financial=True,
    financial_context="Growing but need to optimize costs",
    monthly_revenue="$50K",
    monthly_costs="$40K",
    cash_available="$200K"
)

Bundle — Full Analysis

result = client.bundle(
    brand_slug="acme_corp",
    email="you@acme.com"
)
# Creates Scan + Signal + Solutions in one call (3 credits)

Rerun Methods

Once you've set up a brand with personas in the Surmado dashboard, run reports with minimal code:

# Signal: 3 fields instead of 10+
result = client.signal_rerun(
    brand_slug="acme_corp",
    persona_slug="cto-enterprise",
    email="you@acme.com"
)

# Scan: 2 fields
result = client.scan_rerun(
    brand_slug="acme_corp",
    email="you@acme.com"
)

Perfect for Zapier/Make/n8n workflows, scheduled monitoring, and dashboard integrations. See integrations/ for setup guides.

Brand Management

# List all brands
brands = client.list_brands()

# Create a brand (fails if already exists)
brand = client.create_brand(
    brand_name="Acme Corp",
    website="https://acme.com",
    industry="B2B SaaS"
)

# Create or get existing brand (never fails with conflict)
brand = client.ensure_brand(
    brand_name="Acme Corp",
    website="https://acme.com"
)

Async Reports & Polling

All reports process asynchronously (~15 minutes). Two ways to get results:

Polling

report = client.signal(...)

# Block until complete (default 20 min timeout)
completed = client.wait_for_report(report["report_id"], timeout_minutes=20)
print(completed["download_url"])

Webhooks

report = client.signal(
    ...,
    webhook_url="https://your-server.com/webhook"
)
# Your webhook receives POST with full report data when complete

See integrations/webhooks.md for payload format and handler examples.

Report Data

Access raw report data (metrics, analysis) as JSON:

# Full data
data = client.get_report_data("rpt_abc123")

# Specific fields only
data = client.get_report_data("rpt_abc123", fields=["status", "insights"])

Handling Errors

from surmado import (
    Surmado,
    AuthenticationError,
    InsufficientCreditsError,
    NotFoundError,
    ValidationError,
    RateLimitError,
    SurmadoError
)

client = Surmado()

try:
    result = client.signal(...)
except AuthenticationError:
    print("Invalid or missing API key")
except InsufficientCreditsError as e:
    print(f"Not enough credits: {e.response}")
except RateLimitError:
    print("Too many requests - back off and retry")
except NotFoundError:
    print("Brand or report not found")
except ValidationError as e:
    print(f"Invalid request params: {e}")
except SurmadoError as e:
    print(f"API error: {e.status_code} - {e}")

Error Status Mapping

Status Code Exception
400 ValidationError
401 AuthenticationError
402 InsufficientCreditsError
404 NotFoundError
422 ValidationError
429 RateLimitError
>=500 SurmadoError

All exceptions inherit from SurmadoError and include status_code and response attributes.

Test Your Key

result = client.test_auth()
print(f"Authenticated as: {result.get('org_id')}")

Timeouts

Default request timeout is 30 seconds. Configure per-client:

client = Surmado(timeout=60)

For wait_for_report, the polling timeout is separate:

completed = client.wait_for_report(report_id, timeout_minutes=30)

Response Format

Report creation returns HTTP 202 Accepted:

{
    "report_id": "rpt_abc123def456",
    "token": "tok_xyz789abc123",  # Save for Solutions Mode 1
    "org_id": "org_xyz789",
    "product": "signal",
    "status": "queued",
    "brand_slug": "example_brand",
    "brand_name": "Example Brand",
    "credits_used": 1,
    "created_at": "2025-01-15T10:30:00Z"
}

Completed reports include download URLs (expire in 15 minutes):

{
    "status": "completed",
    "download_url": "https://storage.googleapis.com/...",      # PDF
    "pptx_download_url": "https://storage.googleapis.com/...", # PPTX
}

Webhook Payload

See integrations/webhooks.md for the full webhook payload reference, including field tables for Signal and Scan summary data.

Field Length Limits

Field Max Length
brand_name 100 chars
industry 200 chars
location 200 chars
persona 800 chars
pain_points 1000 chars
brand_details 1200 chars
direct_competitors 500 chars
indirect_competitors 500 chars
keywords 500 chars
product 1000 chars
business_story 2000 chars
decision 1500 chars
success 1000 chars
timeline 200 chars
scale_indicator 100 chars

Pricing

All reports are $50 each. No subscriptions.

Product Price Credits
Signal $50 1
Scan $50 1
Solutions $50 1

Versioning

This package follows SemVer. To check your installed version:

import surmado
print(surmado.__version__)

Links

License

MIT