> For the complete documentation index, see [llms.txt](https://docs.pullbay.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pullbay.com/documentation/pullbay-for-teams/pullbay-for-mobile-agencies.md).

# Pullbay for Mobile Agencies

Mobile agencies manage dozens—sometimes hundreds—of client apps across their portfolio. Keeping track of how each app is performing in the app store is a manual nightmare: scrolling through app store pages, manually counting reviews, manually checking ratings, manually compiling reports for each client. Pullbay's App Store Reviews API lets agencies automate this entire workflow, deliver professional review health reports to clients, and scale monitoring across their entire portfolio without per-seat costs or manual busywork.

## The Agency Challenge: Scale Without Overhead

A typical mobile agency faces this scenario:

* You manage 30 client apps across iOS and Android
* Each client wants a monthly report on app store health
* Each client is asking different questions: "Are we getting good reviews?" "Is our rating improving?" "How do we compare to competitors?"
* Your team is spending 10–15 hours per month manually pulling data and compiling reports

Pullbay solves this by letting you fetch review data for all 30 apps with a few API calls, then generate consistent, professional reports for each client.

## Why Agencies Need Review Monitoring

### Tracking Client App Health

App store reviews are a key health metric for your clients' apps, just like active users or retention. When you publish an app or release a major update, the first signal of success (or failure) is the app store review rating. A sudden drop in rating after a release means something broke. A spike in negative reviews means customer success is declining.

**Early warning system for problems:**

* Release ships on Monday
* By Wednesday, you pull reviews and see average rating dropped 0.5 stars
* You immediately alert the client: "We need to investigate"
* Client fixes the issue and ships a hotfix
* Rating recovers by Friday
* Client prevents a major churn event

Without automated monitoring, you might not catch this until your client calls you upset about poor reviews.

### Competitive Intelligence for Clients

Clients often want to understand how they stack up against competitors. "Is our app rated higher or lower than our competitor?" "Do their reviews mention features we lack?" Pullbay lets you pull competitor data and give clients monthly competitive benchmarks.

### Client Reporting and Retention

Clients love data. A monthly review health report (rating trend, review volume, competitive benchmark, top themes) demonstrates value and keeps clients engaged. It also gives you a reason to have monthly check-in calls—"Let's review your app's performance this month."

## Setting Up Multi-App Monitoring for Agencies

### Organizing Client Apps

Start by storing your client app IDs in a structured format. This makes it easy to scale:

```python
# clients.json - Store this in your system
clients = {
    "Acme Corp": {
        "app_id": "com.acme.app",
        "ios_id": "1234567890",
        "competitors": ["com.competitor1.app", "com.competitor2.app"],
        "contact_email": "pm@acme.com"
    },
    "Widget Inc": {
        "app_id": "com.widget.app",
        "ios_id": "0987654321",
        "competitors": ["com.competitor3.app"],
        "contact_email": "product@widget.com"
    },
    # ... 28 more clients
}
```

### Fetching Reviews for All Clients

Write a simple script that loops through all clients and fetches their reviews:

```python
import requests
import json
from datetime import datetime

api_url = "https://api.pullbay.com/v1/app-store/reviews"
headers = {"Authorization": "Bearer YOUR_API_KEY"}

def fetch_client_reviews(app_id, limit=200):
    """Fetch reviews for a single app."""
    params = {"app_id": app_id, "limit": limit}
    response = requests.get(api_url, headers=headers, params=params)

    if response.status_code == 200:
        return response.json()["reviews"]
    else:
        print(f"Error fetching reviews for {app_id}: {response.status_code}")
        return []

def generate_client_summary(client_name, app_id, reviews):
    """Generate a summary for a single client app."""
    if not reviews:
        return None

    ratings = [r["rating"] for r in reviews]
    avg_rating = sum(ratings) / len(ratings)

    summary = {
        "client": client_name,
        "app_id": app_id,
        "timestamp": datetime.now().isoformat(),
        "metrics": {
            "avg_rating": round(avg_rating, 2),
            "total_reviews": len(reviews),
            "5_star_count": len([r for r in reviews if r["rating"] == 5]),
            "4_star_count": len([r for r in reviews if r["rating"] == 4]),
            "3_star_count": len([r for r in reviews if r["rating"] == 3]),
            "2_star_count": len([r for r in reviews if r["rating"] == 2]),
            "1_star_count": len([r for r in reviews if r["rating"] == 1]),
            "5_star_percentage": round(len([r for r in reviews if r["rating"] == 5]) / len(reviews) * 100, 1),
        }
    }

    return summary

# Load clients and generate summaries
clients = {
    "Acme Corp": "com.acme.app",
    "Widget Inc": "com.widget.app",
    # ... all other clients
}

all_summaries = []

for client_name, app_id in clients.items():
    reviews = fetch_client_reviews(app_id)
    summary = generate_client_summary(client_name, app_id, reviews)

    if summary:
        all_summaries.append(summary)
        print(f"✓ {client_name}: {summary['metrics']['avg_rating']} stars ({summary['metrics']['total_reviews']} reviews)")

# Save summaries to a JSON file or database
with open("client_summaries.json", "w") as f:
    json.dump(all_summaries, f, indent=2)

print(f"\nGenerated summaries for {len(all_summaries)} clients")
```

This script fetches reviews for all your clients in one run, consumes credits efficiently, and generates consistent metrics for each client.

## Generating Weekly Client Digests

Create a professional weekly or monthly report for each client. Here's a template:

```python
def generate_client_report(client_name, app_id, competitors_dict=None):
    """
    Generate a comprehensive weekly report for a client.
    """
    api_url = "https://api.pullbay.com/v1/app-store/reviews"
    headers = {"Authorization": "Bearer YOUR_API_KEY"}

    # Fetch client app reviews
    params = {"app_id": app_id, "limit": 300}
    response = requests.get(api_url, headers=headers, params=params)
    client_reviews = response.json()["reviews"]

    client_ratings = [r["rating"] for r in client_reviews]
    client_avg_rating = sum(client_ratings) / len(client_ratings)

    report = {
        "client": client_name,
        "week": datetime.now().strftime("%Y-W%W"),
        "app_health": {
            "avg_rating": round(client_avg_rating, 2),
            "total_reviews": len(client_reviews),
            "5_star_percentage": round(len([r for r in client_reviews if r["rating"] == 5]) / len(client_reviews) * 100, 1),
            "1_star_count": len([r for r in client_reviews if r["rating"] == 1]),
            "trend": "improving" if client_avg_rating > 4.0 else "stable" if client_avg_rating > 3.7 else "declining"
        },
        "top_5_star_themes": extract_themes(client_reviews, rating=5),
        "top_1_star_themes": extract_themes(client_reviews, rating=1),
    }

    # Add competitive comparison if available
    if competitors_dict:
        report["competitive_analysis"] = {}
        for comp_name, comp_id in competitors_dict.items():
            comp_response = requests.get(api_url, headers=headers, params={"app_id": comp_id, "limit": 300})
            comp_reviews = comp_response.json()["reviews"]
            comp_ratings = [r["rating"] for r in comp_reviews]
            comp_avg = sum(comp_ratings) / len(comp_ratings)

            report["competitive_analysis"][comp_name] = {
                "avg_rating": round(comp_avg, 2),
                "vs_client": round(client_avg_rating - comp_avg, 2)
            }

    return report

# Generate report for one client
report = generate_client_report(
    "Acme Corp",
    "com.acme.app",
    competitors_dict={"Competitor A": "com.competitor1.app"}
)

print(json.dumps(report, indent=2))
```

**Sample report output:**

```json
{
  "client": "Acme Corp",
  "week": "2026-W15",
  "app_health": {
    "avg_rating": 4.3,
    "total_reviews": 156,
    "5_star_percentage": 62.8,
    "1_star_count": 8,
    "trend": "improving"
  },
  "competitive_analysis": {
    "Competitor A": {
      "avg_rating": 3.9,
      "vs_client": 0.4
    }
  }
}
```

## Identifying Review Themes Automatically

Extract top themes from 1-star and 5-star reviews to identify what's working and what's broken:

```python
def extract_themes(reviews, rating=5, top_keywords=None):
    """
    Extract common themes from reviews with a specific rating.
    Returns most-mentioned keywords.
    """
    if top_keywords is None:
        top_keywords = {
            "performance": ["slow", "lag", "fast", "smooth", "crash", "freeze"],
            "usability": ["easy", "intuitive", "complicated", "confusing", "hard"],
            "features": ["feature", "missing", "request", "support", "doesn't"],
            "support": ["support", "help", "response", "customer service"],
            "price": ["price", "expensive", "cost", "affordable", "value"],
            "reliability": ["reliable", "stable", "bugs", "glitch", "broken"],
        }

    matching_reviews = [r for r in reviews if r["rating"] == rating]
    text = " ".join([r["content"].lower() for r in matching_reviews])

    theme_counts = {}
    for theme, keywords in top_keywords.items():
        count = sum(text.count(keyword) for keyword in keywords)
        if count > 0:
            theme_counts[theme] = count

    return dict(sorted(theme_counts.items(), key=lambda x: x[1], reverse=True))

# Example usage
five_star_themes = extract_themes(reviews, rating=5)
one_star_themes = extract_themes(reviews, rating=1)

print("Top themes in 5-star reviews:", five_star_themes)
print("Top themes in 1-star reviews:", one_star_themes)
```

Output:

```
Top themes in 5-star reviews: {'features': 15, 'ease': 12, 'performance': 8}
Top themes in 1-star reviews: {'performance': 22, 'features': 8, 'support': 5}
```

Your client can immediately see: "Users love our features and ease of use, but performance is our biggest pain point."

## Automating Weekly Digests to Clients

Schedule your monitoring script to run weekly, generate reports for all clients, and email each client their report:

```python
import json
from datetime import datetime

def send_client_report_email(client_email, report_data):
    """
    Format and send a client report via email.
    (Uses your preferred email service: SendGrid, AWS SES, etc.)
    """
    subject = f"Weekly App Store Health Report: {report_data['client']}"

    body = f"""
Hi {report_data['client']},

Here's your app store health report for {report_data['week']}:

OVERALL HEALTH
- Average Rating: {report_data['app_health']['avg_rating']} stars
- Total Reviews: {report_data['app_health']['total_reviews']}
- 5-Star Reviews: {report_data['app_health']['5_star_percentage']}%
- Trend: {report_data['app_health']['trend'].upper()}

TOP THEMES (5-STAR REVIEWS)
{format_themes(report_data['top_5_star_themes'])}

TOP THEMES (1-STAR REVIEWS)
{format_themes(report_data['top_1_star_themes'])}

COMPETITIVE COMPARISON
{format_competitive(report_data.get('competitive_analysis', {}))}

Questions? Reply to this email or schedule a call with your account manager.

Best regards,
Your Agency
    """

    # Send via your email service
    # send_email(to=client_email, subject=subject, body=body)

def format_themes(themes):
    return "\n".join([f"- {theme.title()}: {count} mentions" for theme, count in themes.items()])

def format_competitive(competitive_data):
    if not competitive_data:
        return "Not available this week"
    return "\n".join([f"- {comp}: {metrics['vs_client']:+.1f} vs your rating" for comp, metrics in competitive_data.items()])
```

Each client gets a professional, data-driven report every week. They see their rating trend, what customers love, what they hate, and how they compare to competitors. This adds enormous value and keeps clients engaged.

## Scaling Across Your Portfolio

**Rate limits and credit efficiency:**

* **Free plan** (10 req/min): Works for 1–2 client apps
* **Starter plan** (60 req/min): Monitor 5–10 apps with weekly reports
* **Growth plan** (300 req/min): Monitor 20+ apps with weekly updates
* **Scale plan** (1000+ req/min): Monitor 50+ apps with daily monitoring

Credits are consumed only on successful requests, so you're never paying for failed API calls. No per-seat pricing—whether you have 5 clients or 500, you pay only for the API calls.

**Example: Scaling to 30 clients**

With a Growth plan (300 req/min), you can:

* Pull reviews for 30 client apps: 30 requests
* Pull reviews for 60 competitor apps (2 per client): 60 requests
* Extract themes and generate summaries: 10 requests
* Total: 100 requests per week to monitor 30 clients

That's less than 0.5% of your rate limit. You could run this weekly with room to spare.

## Example Workflow: Complete Monthly Report for a Client

Here's what a real weekly workflow looks like:

{% stepper %}
{% step %}

### Monday morning (automated)

1. Script runs and fetches reviews for all 30 client apps + competitors
2. Generates summary metrics and extracts themes for each client
3. Creates JSON reports and stores them in a database or S3 bucket
   {% endstep %}

{% step %}

### Tuesday morning

1. You review the week's data and flag any anomalies
2. You write brief narrative summaries for each client report
3. System sends personalized emails to each client
   {% endstep %}

{% step %}

### Client receives their report

* Acme Corp sees their rating is 4.3 stars, up 0.1 from last week
* They see that "performance" is mentioned in 22 one-star reviews
* They see they're rated 0.4 stars higher than their nearest competitor
* They understand exactly what they need to focus on
  {% endstep %}

{% step %}

### Client calls you

* "Our performance issues are costing us reviews—we need to prioritize that bug fix"
* "We're beating competitors—let's use that in our marketing"
* You're now a strategic partner, not just a developer shop
  {% endstep %}
  {% endstepper %}

## Get Started: Multi-App Monitoring for Agencies

1. **Sign up for Starter or Growth plan**: Pullbay pricing scales with your portfolio
2. **Store client app IDs**: Create a JSON file or spreadsheet with all your clients' app IDs and competitors
3. **Write your monitoring script**: Use the Python examples above as a template
4. **Schedule weekly runs**: Set up a cron job to run your script every Monday morning
5. **Create an email template**: Generate professional client reports and send them automatically
6. **Review and iterate**: Look for anomalies in the data; use insights to improve client apps
7. **Build a dashboard**: Store reports in a database and create an agency dashboard showing all clients' app health

Pullbay turns manual, time-consuming app store monitoring into a scalable, automated workflow. Your clients get professional reports, you get valuable competitive intelligence, and your team saves 10+ hours per month.

***

*Ready to scale your agency's app monitoring? Get your free API key at Pullbay and start generating client reports today.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pullbay.com/documentation/pullbay-for-teams/pullbay-for-mobile-agencies.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
