> 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/api-and-references/appstore.md).

# Appstore

The Pullbay App Store API provides programmatic access to iOS app metadata, search, similar-app recommendations, reviews, and developer catalogs from the Apple App Store. Integrate App Store data into your applications, dashboards, and analytics pipelines without scraping or manual lookups.

**Base URL:** `https://dashboard.pullbay.com/api`

## Overview

The App Store service lets you:

* Look up a single app by its numeric App ID or its Bundle ID
* Search the App Store by keyword
* Find apps similar to a given app
* Fetch reviews for an app, sorted by recency or helpfulness
* List every app published by a given developer

All endpoints are read-only `GET` requests against public App Store data — you don't need to own or register an app of your own.

## Common Use Cases

**Competitor Analysis** — Pull a competitor's app metadata and reviews to track positioning, version cadence, and rating trends over time.

**Sentiment Monitoring** — Collect reviews on a schedule and feed the `title`/`text` fields into your own sentiment-analysis or alerting pipeline.

**Market Research** — Use Search Apps and Get Similar Apps together to map out a category and see how apps cluster around features and audiences.

**Product Development** — Mine review text for recurring feature requests and complaints to help prioritize a roadmap.

**Developer Portfolio Tracking** — Use Get Developer Apps to see everything a given publisher has shipped, useful for due diligence or competitive landscape work.

## Endpoints

| Endpoint                  | Description                             | Pagination          |
| ------------------------- | --------------------------------------- | ------------------- |
| `GET /appstore/apps`      | Get a single app by App ID or Bundle ID | —                   |
| `GET /appstore/search`    | Search apps by term                     | `page` / `maxItems` |
| `GET /appstore/similar`   | Get apps similar to a given app         | —                   |
| `GET /appstore/reviews`   | Get reviews for an app                  | `page` / `maxItems` |
| `GET /appstore/developer` | Get all apps published by a developer   | —                   |

***

### Get App

Returns a single application. Provide exactly one of `appId` or `bundleId`.

**Request**

```bash
GET /appstore/apps
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type   | Required                  | Default | Description                                                                                       |
| ---------- | ------ | ------------------------- | ------- | ------------------------------------------------------------------------------------------------- |
| `appId`    | string | One of `appId`/`bundleId` | —       | Numeric App Store ID, 8–12 digits (e.g. `389801252`)                                              |
| `bundleId` | string | One of `appId`/`bundleId` | —       | Bundle identifier, up to 255 characters (e.g. `com.burbn.instagram`)                              |
| `country`  | string | No                        | —       | 2-letter storefront code. Not restricted to a fixed list — any 2-letter code is accepted.         |
| `lang`     | string | No                        | —       | Language code for localized text, 2–3 letters with an optional region subtag (e.g. `en`, `en-us`) |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/appstore/apps" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d appId=389801252 \
  -d country=us
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "id": 389801252,
      "appId": "com.burbn.instagram",
      "title": "Instagram",
      "url": "https://apps.apple.com/us/app/instagram/id389801252?uo=4",
      "description": "Little moments lead to big friendships. Share yours on Instagram.",
      "icon": "https://is1-ssl.mzstatic.com/.../512x512bb.jpg",
      "genres": ["Photo & Video", "Social Networking"],
      "genreIds": ["6008", "6005"],
      "primaryGenre": "Photo & Video",
      "primaryGenreId": 6008,
      "contentRating": "12+",
      "languages": ["EN", "FR", "DE", "JA", "ES"],
      "size": "563586048",
      "requiredOsVersion": "16.3",
      "released": "2010-10-06T08:12:41Z",
      "updated": "2026-04-20T17:48:35Z",
      "releaseNotes": "Performance optimizations and stability improvements.",
      "version": "426.0.0",
      "price": 0,
      "currency": "USD",
      "free": true,
      "developerId": 389801255,
      "developer": "Instagram, Inc.",
      "developerUrl": "https://apps.apple.com/us/developer/instagram-inc/id389801255?uo=4",
      "developerWebsite": "http://instagram.com/",
      "score": 4.69066,
      "reviews": 28962365,
      "currentVersionScore": 4.69066,
      "currentVersionReviews": 28962365,
      "screenshots": ["https://is1-ssl.mzstatic.com/.../392x696bb.jpg"],
      "ipadScreenshots": [],
      "appletvScreenshots": [],
      "supportedDevices": ["iPhone5s-iPhone5s", "iPadAir-iPadAir", "iPhone16Pro-iPhone16Pro"]
    }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                                         |
| ------------------------ | ------ | ------------------------------------------------------------------- |
| `data`                   | array  | Array containing a single [Application object](#application-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                                    |

**Credit cost:** charged dynamically per request; the exact amount is always returned in `pricing.creditsCharged`. There is no published flat rate — read the figure from the response.

***

### Search Apps

Search the App Store for apps matching a term.

**Request**

```bash
GET /appstore/search
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type    | Required | Default | Description                                                       |
| ---------- | ------- | -------- | ------- | ----------------------------------------------------------------- |
| `term`     | string  | Yes      | —       | Search term, 1–255 characters                                     |
| `country`  | string  | No       | —       | 2-letter storefront code                                          |
| `lang`     | string  | No       | —       | Language code for localized text                                  |
| `page`     | integer | No       | —       | Page number, 1–5. Mutually exclusive with `maxItems`              |
| `maxItems` | integer | No       | —       | One-shot bulk pull, 1–200 results. Mutually exclusive with `page` |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/appstore/search" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d term="photo editor" \
  -d country=us \
  -d page=1
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    { "id": 389801252, "appId": "com.burbn.instagram", "title": "Instagram", "...": "..." }
  ],
  "pagination": { "page": 1, "hasNextPage": true, "cursor": null, "offset": null },
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                                     | Type              | Description                                         |
| ----------------------------------------- | ----------------- | --------------------------------------------------- |
| `data`                                    | array             | Array of [Application objects](#application-object) |
| `pagination.page`                         | integer, nullable | Current page number (only set when using `page`)    |
| `pagination.hasNextPage`                  | boolean, nullable | Whether another page is available                   |
| `pagination.cursor` / `pagination.offset` | string, nullable  | Unused by this endpoint — always `null` here        |
| `pricing.creditsCharged`                  | number            | Credits charged for this request                    |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No flat per-page or per-result rate is published — read the figure from each response.

***

### Get Similar Apps

Returns apps similar to a given app. Provide exactly one of `appId` or `bundleId`.

**Request**

```bash
GET /appstore/similar
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type   | Required                  | Default | Description                       |
| ---------- | ------ | ------------------------- | ------- | --------------------------------- |
| `appId`    | string | One of `appId`/`bundleId` | —       | Numeric App Store ID, 8–12 digits |
| `bundleId` | string | One of `appId`/`bundleId` | —       | Bundle identifier                 |
| `country`  | string | No                        | —       | 2-letter storefront code          |
| `lang`     | string | No                        | —       | Language code for localized text  |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/appstore/similar" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d bundleId=com.burbn.instagram
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    { "id": 454638411, "appId": "com.toyopagroup.picaboo", "title": "Snapchat", "...": "..." }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                         |
| ------------------------ | ------ | --------------------------------------------------- |
| `data`                   | array  | Array of [Application objects](#application-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                    |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`.

***

### Get Reviews

Returns reviews for one app. Provide exactly one of `appId` or `bundleId`.

**Request**

```bash
GET /appstore/reviews
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter  | Type    | Required                  | Default | Description                                                       |
| ---------- | ------- | ------------------------- | ------- | ----------------------------------------------------------------- |
| `appId`    | string  | One of `appId`/`bundleId` | —       | Numeric App Store ID, 8–12 digits                                 |
| `bundleId` | string  | One of `appId`/`bundleId` | —       | Bundle identifier                                                 |
| `country`  | string  | No                        | —       | 2-letter storefront code                                          |
| `sort`     | string  | No                        | —       | `recent` or `helpful`                                             |
| `page`     | integer | No                        | —       | Page number, 1–10. Mutually exclusive with `maxItems`             |
| `maxItems` | integer | No                        | —       | One-shot bulk pull, 1–500 results. Mutually exclusive with `page` |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/appstore/reviews" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d appId=389801252 \
  -d country=us \
  -d sort=recent \
  -d page=1
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    {
      "id": "13997548250",
      "date": "2026-04-25T19:57:33-07:00",
      "userName": "Catie0012",
      "userUrl": "https://itunes.apple.com/us/reviews/id1632846422",
      "version": "426.0.0",
      "score": 5,
      "title": "How I love your app",
      "text": "Una experiencia inigualable",
      "url": "https://itunes.apple.com/us/review?id=389801252&type=Purple%20Software",
      "country": "US"
    }
  ],
  "pagination": { "page": 1, "hasNextPage": true, "cursor": null, "offset": null },
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type              | Description                                      |
| ------------------------ | ----------------- | ------------------------------------------------ |
| `data`                   | array             | Array of [Review objects](#review-object)        |
| `pagination.page`        | integer, nullable | Current page number (only set when using `page`) |
| `pagination.hasNextPage` | boolean, nullable | Whether another page is available                |
| `pricing.creditsCharged` | number            | Credits charged for this request                 |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`. No flat per-page or per-review rate is published.

***

### Get Developer Apps

Returns the list of apps published by a single developer.

**Request**

```bash
GET /appstore/developer
Authorization: Bearer YOUR_API_KEY
```

**Parameters**

| Parameter     | Type   | Required | Default | Description                       |
| ------------- | ------ | -------- | ------- | --------------------------------- |
| `developerId` | string | Yes      | —       | Numeric developer ID, 8–12 digits |
| `country`     | string | No       | —       | 2-letter storefront code          |

**Example**

```bash
curl -G "https://dashboard.pullbay.com/api/appstore/developer" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d developerId=389801255
```

**Response**

```json
{
  "status": 200,
  "message": "OK",
  "success": true,
  "data": [
    { "id": 389801252, "appId": "com.burbn.instagram", "title": "Instagram", "...": "..." }
  ],
  "pricing": { "creditsCharged": 1 }
}
```

**Response Schema**

| Field                    | Type   | Description                                         |
| ------------------------ | ------ | --------------------------------------------------- |
| `data`                   | array  | Array of [Application objects](#application-object) |
| `pricing.creditsCharged` | number | Credits charged for this request                    |

**Credit cost:** dynamic, returned in `pricing.creditsCharged`.

***

## Errors

All non-2xx responses share the same envelope:

```json
{
  "status": 400,
  "message": "Bad request",
  "success": false,
  "error": { "code": "BAD_REQUEST" }
}
```

| Status | Meaning                                                                           |
| ------ | --------------------------------------------------------------------------------- |
| `400`  | Bad request — missing/invalid parameters, or both `appId` and `bundleId` supplied |
| `402`  | Insufficient credits                                                              |
| `404`  | App, developer, or review set not found                                           |

## Object Schema

### Application object

| Field                                                    | Type                      | Description                                     |
| -------------------------------------------------------- | ------------------------- | ----------------------------------------------- |
| `id`                                                     | integer                   | Numeric App Store ID                            |
| `appId`                                                  | string                    | Bundle identifier                               |
| `title`                                                  | string                    | App name                                        |
| `url`                                                    | string                    | App Store listing URL                           |
| `description`                                            | string                    | App description                                 |
| `icon`                                                   | string                    | Icon image URL                                  |
| `genres` / `genreIds`                                    | array                     | Genre names and IDs                             |
| `primaryGenre` / `primaryGenreId`                        | string / integer          | Primary genre name and ID                       |
| `contentRating`                                          | string                    | Age rating (e.g. `12+`)                         |
| `languages`                                              | array                     | Supported language codes                        |
| `size`                                                   | string                    | App size in bytes                               |
| `requiredOsVersion`                                      | string                    | Minimum iOS version                             |
| `released` / `updated`                                   | string (date-time)        | Initial release and last update timestamps      |
| `releaseNotes`                                           | string                    | "What's New" text for the current version       |
| `version`                                                | string                    | Current version number                          |
| `price` / `currency` / `free`                            | number / string / boolean | Pricing info                                    |
| `developerId` / `developer`                              | integer / string          | Developer ID and name                           |
| `developerUrl` / `developerWebsite`                      | string                    | Developer's App Store page and external site    |
| `score` / `reviews`                                      | number / integer          | All-time rating and review count                |
| `currentVersionScore` / `currentVersionReviews`          | number / integer          | Rating and review count for the current version |
| `screenshots` / `ipadScreenshots` / `appletvScreenshots` | array                     | Screenshot URLs per device class                |
| `supportedDevices`                                       | array                     | Compatible device identifiers                   |

### Review object

| Field      | Type               | Description                                 |
| ---------- | ------------------ | ------------------------------------------- |
| `id`       | string             | Review ID                                   |
| `date`     | string (date-time) | When the review was posted                  |
| `userName` | string             | Reviewer's display name                     |
| `userUrl`  | string             | Link to the reviewer's profile              |
| `version`  | string             | App version the review was left for         |
| `score`    | integer            | Rating, 1–5                                 |
| `title`    | string             | Review title                                |
| `text`     | string             | Review body                                 |
| `url`      | string             | Permalink to the review                     |
| `country`  | string             | Storefront country the review was posted on |

Note: the Review object does not include a helpful-vote count or "verified purchase" flag — only the fields listed above are returned.

## Finding App IDs and Bundle IDs

* **App ID**: the numeric ID in an App Store URL, e.g. `https://apps.apple.com/us/app/instagram/id389801252` → `389801252`.
* **Bundle ID**: the package identifier shown on a developer's site or in App Store Connect, e.g. `com.burbn.instagram`.
* Either ID resolves the same app — use whichever you already have on hand. Don't pass both in the same request.

## Country and Language Codes

* `country` accepts any 2-letter code (the schema only constrains it to exactly 2 characters) — it isn't validated against a fixed allow-list in the spec, so pass a standard ISO 3166-1 alpha-2 storefront code (`us`, `gb`, `jp`, `de`, ...).
* `lang` accepts a 2–3 letter language code, optionally with a region subtag (`en`, `en-us`, `pt-br`) — also not restricted to a fixed list.
* Neither parameter has a documented default in the API spec. If you omit them, behavior is determined by the underlying App Store lookup rather than a guaranteed Pullbay default — pass both explicitly if you need a predictable storefront/locale.

## Python Example: Paginating Through Reviews

This example fetches reviews for an app a page at a time, stopping when `pagination.hasNextPage` is `false` or the page cap (10) is reached:

```python
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://dashboard.pullbay.com/api"

def get_all_reviews(app_id, country="us", max_pages=10):
    all_reviews = []
    page = 1
    while page <= max_pages:
        resp = requests.get(
            f"{BASE_URL}/appstore/reviews",
            headers={"Authorization": f"Bearer {API_KEY}"},
            params={"appId": app_id, "country": country, "sort": "recent", "page": page},
        )
        resp.raise_for_status()
        body = resp.json()
        all_reviews.extend(body["data"])
        if not body.get("pagination", {}).get("hasNextPage"):
            break
        page += 1
    return all_reviews

reviews = get_all_reviews(389801252)
print(f"Fetched {len(reviews)} reviews")
```

Each request is billed independently, with the charged amount reported in that response's `pricing.creditsCharged` — there's no separate "fetch everything in one call" endpoint, so a multi-page pull like this makes one request per page.

## FAQ

<details>

<summary>How do I find an app's ID?</summary>

Visit the app's page on the Apple App Store. Look at the URL — it contains `/id` followed by a number. That number is the `appId`. For example, `https://apps.apple.com/us/app/instagram/id389801252` → `389801252`.

</details>

<details>

<summary>What countries are supported?</summary>

Any 2-letter storefront code is accepted by the API — it isn't restricted to a published list of supported countries.

</details>

<details>

<summary>How many reviews can I fetch in one call?</summary>

Up to 500 with `maxItems`, or up to 10 pages via `page` (page size isn't fixed by the spec). `page` and `maxItems` are mutually exclusive — use one or the other per request.

</details>

<details>

<summary>Can I filter reviews by star rating?</summary>

The API only supports sorting (`recent` or `helpful`), not server-side filtering by rating. Fetch the reviews you need and filter client-side on the `score` field.

</details>

<details>

<summary>What's the credit cost per request?</summary>

It's dynamic — every response includes `pricing.creditsCharged` with the exact amount for that call. There's no fixed published rate per endpoint or per result.

</details>

<details>

<summary>Can I export reviews to CSV?</summary>

The API returns JSON. Convert it to CSV with your language's tooling (e.g. Python's `csv` module) or load it directly into a BI tool.

</details>


---

# 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/api-and-references/appstore.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.
