Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mavera.io/llms.txt

Use this file to discover all available pages before exploring further.

Scenario

You need a quick sentiment read on a specific business — is the trend positive or negative? Yelp’s API returns up to 3 review excerpts per business (full reviews require scraping, which violates ToS). You pull these excerpts and send them to Mavera Chat for rapid sentiment classification. It’s a fast signal — not deep analysis — useful for screening competitors or monitoring your own listings. Flow: Yelp GET /businesses/{id}/reviews → Up to 3 excerpts → Mavera POST /responses → Quick sentiment classification

Architecture

Code

import os, requests, json
from openai import OpenAI

YELP = os.environ["YELP_API_KEY"]
MV = os.environ["MAVERA_API_KEY"]
YELP_H = {"Authorization": f"Bearer {YELP}"}

# 1. Get business details + reviews
BUSINESS_IDS = [
    "houndstooth-coffee-austin",
    "fleet-coffee-austin",
    "merit-coffee-austin",
]

mavera = OpenAI(api_key=MV, base_url="https://app.mavera.io/api/v1")

results = []
for biz_id in BUSINESS_IDS:
    # Business details
    biz = requests.get(f"https://api.yelp.com/v3/businesses/{biz_id}",
        headers=YELP_H).json()
    name = biz.get("name", biz_id)
    rating = biz.get("rating", 0)
    review_count = biz.get("review_count", 0)

    # Review excerpts (max 3)
    revs = requests.get(f"https://api.yelp.com/v3/businesses/{biz_id}/reviews",
        headers=YELP_H).json().get("reviews", [])

    excerpt_block = "\n".join(
        f"[{r.get('rating',0)}/5] {r.get('text','')[:300]}"
        for r in revs
    )

    # 2. Quick sentiment via Mavera Chat
    response = mavera.responses.create(model="mavera-1",
        input=[{"role": "user", "content": f"""Quick sentiment analysis for {name} ({rating}/5, {review_count} reviews).

Review excerpts:
{excerpt_block}

Return JSON: {{
  "sentiment": "positive|negative|mixed",
  "confidence": 0-1,
  "key_themes": ["theme1", "theme2"],
  "one_line_summary": "..."
}}"""}],
        extra_body={"response_format": {"type": "json_object"}})

    parsed = json.loads(response.output[0].content[0].text)
    results.append({"name": name, "rating": rating, "reviews": review_count, **parsed})
    print(f"{name}: {parsed.get('sentiment','')} ({parsed.get('confidence',0):.0%}) — {parsed.get('one_line_summary','')}")

# 3. Summary
print(f"\n=== Sentiment Summary ({len(results)} businesses) ===")
for r in results:
    emoji = {"positive": "↑", "negative": "↓", "mixed": "→"}.get(r.get("sentiment", ""), "?")
    print(f"  {emoji} {r['name']}: {r['rating']}/5, {r.get('sentiment','?')}, themes: {', '.join(r.get('key_themes', []))}")

Example Output

{
  "businesses_analyzed": 3,
  "results": [
    {
      "name": "Houndstooth Coffee",
      "rating": 4.5,
      "sentiment": "positive",
      "confidence": 0.92,
      "key_themes": ["espresso quality", "minimalist design", "knowledgeable staff"],
      "one_line_summary": "Consistently praised for exceptional espresso and curated ambiance."
    },
    {
      "name": "Fleet Coffee",
      "rating": 4.0,
      "sentiment": "mixed",
      "confidence": 0.71,
      "key_themes": ["outdoor seating", "food truck partnerships", "parking challenges"],
      "one_line_summary": "Loved for the outdoor vibe, dinged for limited parking and inconsistent hours."
    },
    {
      "name": "Merit Coffee",
      "rating": 4.5,
      "sentiment": "positive",
      "confidence": 0.88,
      "key_themes": ["single-origin beans", "pour-over quality", "friendly baristas"],
      "one_line_summary": "Strong loyal following for pour-over enthusiasts; consistently high marks."
    }
  ]
}

Error Handling

Yelp’s API returns a maximum of 3 review excerpts per business. This is a ToS limitation — do not scrape for more. Use the excerpts as a directional signal only.
Yelp uses URL-slug-style IDs (e.g., houndstooth-coffee-austin). Find them via business search or from Yelp page URLs.
With only 3 excerpts, confidence should be interpreted loosely. Flag any result with confidence below 0.6 as “insufficient data.”