# Get competitor case file

Read one competitor app’s whole overview in one request.

## Endpoint: GET /v1/competitors/{platform}/{storeId}/case-file

- Method: `GET`
- Path: `/v1/competitors/{platform}/{storeId}/case-file`
- Authentication: Bearer API credential or OAuth access token
- Required scope: `context:read`
- MCP tool: `get_app`
- MCP action: `case_file`

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `platform` | path | ios | yes | The preview supports iOS only. |
| `storeId` | path | numeric string | yes | Apple App Store identifier. |
| `country` | query | two-letter storefront code | no | Chart storefront; defaults to us. |
| `categoryId` | query | all or App Store genre id | no | Chart category; defaults to all. |
| `chartType` | query | free, paid or grossing | no | Chart for the standing. When omitted, a priced app reads the paid chart and a free app the free chart. |

## Known errors

- 400 invalid_request for an invalid filter, identity or limit.
- 401 authentication_required for a missing or invalid credential.
- 402 subscription_required when access is not entitled.
- 403 authorization_required for a missing scope or unavailable preview access.
- 403 workspace_not_accessible when x-genviral-tenancy names a workspace the credential cannot reach.
- 404 not_found when the record is outside the accessible catalogue.
- 429 rate_limited; honor Retry-After when present.
- 429 daily_call_limit; the plan's daily API and MCP calls are used until 00:00 UTC.

## Request

Identify the listing and, optionally, the chart the standing is read from.

```
curl --get 'https://api.peekpanda.com/v1/competitors/ios/0000000000/case-file' \
  --header "Authorization: Bearer $PEEKPANDA_TOKEN" \
  --header 'x-genviral-tenancy: personal' \
  --data-urlencode 'country=us'
```

## MCP request

Call get_app with action case_file. Path fields go in params, filters in query, and a write body in body.

```
{
  "name": "get_app",
  "arguments": {
    "request": {
      "action": "case_file",
      "params": {
        "platform": "<platform>",
        "storeId": "<storeId>"
      }
    }
  }
}

```

## Response

listing.currentFacts holds the name, rating, rating count and price to show, each with its provenance (observed from an App Store storefront, or the catalogue snapshot) and its own asOf date; the top-level listing fields keep the dated snapshot. paid is ready, updating (a rebuild is pending and nothing is stored yet), none (no paid evidence, with the reason) or unavailable (its read failed). A ready summary is read at request time over the last 7 days and 12 weeks, and its attribution splits the ads by basis. startedLast7Days counts ads that started on the reading day or the six UTC days before it; recentDays lays out those same seven days one by one, newest first, with quiet days as zero: newAds is how many ads started that day and liveAds how many of those are still live, and the seven newAds add up to startedLast7Days. weeklyStarts counts new ads per Monday week, oldest first, ending with the reading day’s own partial week. latestAds (newest first) and longestRunningAds (live ads with a start date, earliest start first, empty when none) use the Search paid ads item shape with short-lived media URLs. aso, estimates and rankStanding are null outside iOS; grossing is null when the chart is already grossing. listingHistory.storefronts lists every App Store storefront with an earlier iPhone screenshot set, the most recently changed first; each carries its currentScreenshotUrls and its earlier sets, most recently replaced first, with up to 12 earlier sets across all storefronts. PeekPanda keeps a set when a store lookup returns different iPhone screenshots: replacedAt is the lookup that first saw the new set and lastSeenAt the last lookup that still saw this one, so the developer changed the page between them. History starts at the first change PeekPanda saw. viewer is yours alone. See Section states for sections whose read failed.

```
{
  "listing": {
    "platform": "ios",
    "storeId": "0000000000",
    "appName": "Example Calorie Tracker",
    "category": "Health & Fitness",
    "developerId": "example-developer",
    "price": 0,
    "adSupported": null,
    "inAppPurchases": true,
    "totalRatings": 12450,
    "rating": 4.7,
    "installs": {
      "kind": "ratings_proxy",
      "value": 622500
    },
    "releaseDate": "2024-05-01",
    "storeUpdatedAt": "2026-09-06",
    "sourceUpdatedAt": "2026-09-06",
    "descriptionUpdatedAt": null,
    "description": null,
    "shortDescription": null,
    "source": "itunes",
    "snapshotDate": "2026-03-01",
    "currentFacts": {
      "appName": {
        "provenance": "observed",
        "value": "Example Calorie Tracker",
        "asOf": "2026-09-06T00:00:00.000Z",
        "country": "us"
      },
      "rating": {
        "provenance": "observed",
        "value": 4.8,
        "asOf": "2026-09-06T00:00:00.000Z",
        "country": "us"
      },
      "totalRatings": {
        "provenance": "observed",
        "value": 13210,
        "asOf": "2026-09-06T00:00:00.000Z",
        "country": "us"
      },
      "price": {
        "provenance": "snapshot",
        "value": 0,
        "asOf": "2026-09-06"
      }
    }
  },
  "paid": {
    "kind": "ready",
    "summary": {
      "totalAds": 14,
      "liveAds": 6,
      "startedLast7Days": 2,
      "recentDays": [
        {
          "day": "2026-09-06",
          "newAds": 0,
          "liveAds": 0
        },
        {
          "day": "2026-09-05",
          "newAds": 0,
          "liveAds": 0
        },
        {
          "day": "2026-09-04",
          "newAds": 1,
          "liveAds": 1
        },
        {
          "day": "2026-09-03",
          "newAds": 0,
          "liveAds": 0
        },
        {
          "day": "2026-09-02",
          "newAds": 0,
          "liveAds": 0
        },
        {
          "day": "2026-09-01",
          "newAds": 1,
          "liveAds": 0
        },
        {
          "day": "2026-08-31",
          "newAds": 0,
          "liveAds": 0
        }
      ],
      "medianRunDays": 41,
      "longestRunDays": 188,
      "liveBeyond60Days": 2,
      "longevity": [
        {
          "band": "0-6",
          "count": 1
        },
        {
          "band": "7-14",
          "count": 1
        },
        {
          "band": "15-30",
          "count": 1
        },
        {
          "band": "31-60",
          "count": 1
        },
        {
          "band": "61-90",
          "count": 1
        },
        {
          "band": "90+",
          "count": 1
        }
      ],
      "weeklyStarts": [
        {
          "weekStart": "2026-06-15",
          "newAds": 1
        },
        {
          "weekStart": "2026-06-22",
          "newAds": 1
        },
        {
          "weekStart": "2026-06-29",
          "newAds": 1
        },
        {
          "weekStart": "2026-07-06",
          "newAds": 1
        },
        {
          "weekStart": "2026-07-13",
          "newAds": 1
        },
        {
          "weekStart": "2026-07-20",
          "newAds": 1
        },
        {
          "weekStart": "2026-07-27",
          "newAds": 1
        },
        {
          "weekStart": "2026-08-03",
          "newAds": 1
        },
        {
          "weekStart": "2026-08-10",
          "newAds": 1
        },
        {
          "weekStart": "2026-08-17",
          "newAds": 1
        },
        {
          "weekStart": "2026-08-24",
          "newAds": 1
        },
        {
          "weekStart": "2026-08-31",
          "newAds": 2
        }
      ],
      "formats": {
        "video": 9,
        "image": 5,
        "carousel": 0,
        "dynamic": 0,
        "unknown": 0
      },
      "destinations": {
        "appStore": 12,
        "playStore": 0,
        "web": 2,
        "unknown": 0
      },
      "topCta": "Install now",
      "advertiserCount": 1,
      "attribution": {
        "appStoreLink": {
          "total": 12,
          "live": 5
        },
        "sellerDomain": {
          "total": 2,
          "live": 1
        },
        "operator": {
          "total": 0,
          "live": 0
        }
      }
    },
    "advertisers": [
      {
        "advertiserId": "33333333-3333-4333-8333-333333333333",
        "externalId": "example-page",
        "name": "Example Calorie Tracker",
        "totalAds": 14,
        "liveAds": 6
      }
    ],
    "latestAds": [],
    "longestRunningAds": [],
    "builtAt": "2026-09-06T00:00:00.000Z",
    "updating": null
  },
  "aso": {
    "positionKind": "observed_search_api_position",
    "storeId": "0000000000",
    "country": "us",
    "language": "en_us",
    "source": "itunes_search",
    "queriesMatched": 1,
    "summary": {
      "top3": 0,
      "top10": 1,
      "top50": 1,
      "bestPosition": {
        "query": "calorie tracker",
        "position": 4
      },
      "medianPosition": 4
    },
    "bestPositions": [
      {
        "query": "calorie tracker",
        "position": 4,
        "popularity": 63
      }
    ]
  },
  "estimates": {
    "data": []
  },
  "rankStanding": {
    "country": "us",
    "categoryId": "all",
    "chartType": "free",
    "chart": {
      "chartType": "free",
      "latest": {
        "day": "2026-09-06",
        "rank": 18
      },
      "previous": {
        "day": "2026-09-05",
        "rank": 21
      }
    },
    "grossing": null,
    "storefronts": [
      {
        "country": "us",
        "day": "2026-09-06",
        "rank": 18
      },
      {
        "country": "gb",
        "day": "2026-09-06",
        "rank": 33
      }
    ]
  },
  "listingHistory": {
    "storefronts": [
      {
        "country": "us",
        "currentScreenshotUrls": [
          "https://is1-ssl.mzstatic.com/image/thumb/example-now/392x696bb.jpg"
        ],
        "versions": [
          {
            "replacedAt": "2026-08-14T09:30:00.000Z",
            "lastSeenAt": "2026-08-13T09:30:00.000Z",
            "version": "4.1.3",
            "screenshotUrls": [
              "https://is1-ssl.mzstatic.com/image/thumb/example-old/392x696bb.jpg"
            ]
          }
        ]
      }
    ]
  },
  "organic": {
    "matchedCount": 1,
    "candidateLimitReached": false,
    "latest": [
      {
        "sourceId": "organic-post-example",
        "productName": "Example Calorie Tracker",
        "caption": "A stored organic clip",
        "link": "https://www.tiktok.com/@example/video/1",
        "datePublished": "2026-09-06",
        "match": {
          "status": "suggested",
          "evidence": "store_url",
          "score": 1
        }
      }
    ]
  },
  "viewer": {
    "canGenerateIntelligence": true,
    "requests": {
      "data": [
        {
          "id": "11111111-1111-4111-8111-111111111111",
          "kind": "aso",
          "status": "requested",
          "requestedAt": "2026-09-06T00:00:00.000Z"
        }
      ]
    }
  }
}

```

## Source

The stored per-app paid signal (an ad belongs to the app its own verified App Store link names, or to the app whose proven advertiser page ran it), current US App Store search observations, PeekPanda estimates, stored Apple chart snapshots and the public organic corpus. Missing evidence is null or none, never zero.

## Refresh

This read returns stored observations and does not start collection.

## How paid ads reach an app

Every paid count covers all of the app’s ads, and paid.summary.attribution splits total and live ads by basis. appStoreLink: the ad itself links to the app on the App Store. sellerDomain: the ad ran on the app’s own advertiser page, matched by the website its App Store listing publishes and the page name, and lands on that website. operator: the page was confirmed by PeekPanda review. The three add up to totalAds and liveAds. An ad belongs to one app at most: an ad that links another app counts for that app. A name alone never attributes a page.

## Why paid can be none

paid.kind none says why PeekPanda shows no paid counts, read from stored collection state. reason is not_searched (PeekPanda has not looked for the app’s advertiser yet), searching (a search runs now), no_proven_advertiser (the latest search proved no advertiser page; lastSearchedAt says when), collecting (the app’s page is proven and its ads are on the way), advertiser_has_no_ads (the proven page’s latest walk found no Meta ads) or advertiser_under_review (the page is held back pending review). advertiser names the proven page, or is null. none never means the app does not advertise.

```
{
  "kind": "none",
  "reason": "advertiser_has_no_ads",
  "lastSearchedAt": "2026-09-06T00:00:00.000Z",
  "advertiser": {
    "externalId": "100000000000001",
    "name": "Example Calorie Tracker"
  }
}

```

## Section states

Each section says why it holds no evidence. null means the section does not apply to this listing: aso, estimates, rankStanding and listingHistory are null outside iOS. none means PeekPanda holds no paid evidence for the app, with the reason. unavailable means the section could not be read for this request. It says nothing about the evidence itself, so retry later instead of reading it as empty. paid, aso, estimates, rankStanding, listingHistory, organic and viewer.requests can each be unavailable while the rest of the case file still answers; the listing is the only part whose failure fails the request. The example shows a case file whose paid, estimates, organic and request reads failed.

```
{
  "listing": {
    "platform": "ios",
    "storeId": "0000000000",
    "appName": "Example Calorie Tracker",
    "category": "Health & Fitness",
    "developerId": "example-developer",
    "price": 0,
    "adSupported": null,
    "inAppPurchases": true,
    "totalRatings": 12450,
    "rating": 4.7,
    "installs": {
      "kind": "ratings_proxy",
      "value": 622500
    },
    "releaseDate": "2024-05-01",
    "storeUpdatedAt": "2026-09-06",
    "sourceUpdatedAt": "2026-09-06",
    "descriptionUpdatedAt": null,
    "description": null,
    "shortDescription": null,
    "source": "itunes",
    "snapshotDate": "2026-03-01",
    "currentFacts": {
      "appName": {
        "provenance": "observed",
        "value": "Example Calorie Tracker",
        "asOf": "2026-09-06T00:00:00.000Z",
        "country": "us"
      },
      "rating": {
        "provenance": "observed",
        "value": 4.8,
        "asOf": "2026-09-06T00:00:00.000Z",
        "country": "us"
      },
      "totalRatings": {
        "provenance": "observed",
        "value": 13210,
        "asOf": "2026-09-06T00:00:00.000Z",
        "country": "us"
      },
      "price": {
        "provenance": "snapshot",
        "value": 0,
        "asOf": "2026-09-06"
      }
    }
  },
  "paid": {
    "kind": "unavailable"
  },
  "aso": {
    "positionKind": "observed_search_api_position",
    "storeId": "0000000000",
    "country": "us",
    "language": "en_us",
    "source": "itunes_search",
    "queriesMatched": 1,
    "summary": {
      "top3": 0,
      "top10": 1,
      "top50": 1,
      "bestPosition": {
        "query": "calorie tracker",
        "position": 4
      },
      "medianPosition": 4
    },
    "bestPositions": [
      {
        "query": "calorie tracker",
        "position": 4,
        "popularity": 63
      }
    ]
  },
  "estimates": {
    "kind": "unavailable"
  },
  "rankStanding": {
    "country": "us",
    "categoryId": "all",
    "chartType": "free",
    "chart": {
      "chartType": "free",
      "latest": {
        "day": "2026-09-06",
        "rank": 18
      },
      "previous": {
        "day": "2026-09-05",
        "rank": 21
      }
    },
    "grossing": null,
    "storefronts": [
      {
        "country": "us",
        "day": "2026-09-06",
        "rank": 18
      },
      {
        "country": "gb",
        "day": "2026-09-06",
        "rank": 33
      }
    ]
  },
  "listingHistory": {
    "storefronts": [
      {
        "country": "us",
        "currentScreenshotUrls": [
          "https://is1-ssl.mzstatic.com/image/thumb/example-now/392x696bb.jpg"
        ],
        "versions": [
          {
            "replacedAt": "2026-08-14T09:30:00.000Z",
            "lastSeenAt": "2026-08-13T09:30:00.000Z",
            "version": "4.1.3",
            "screenshotUrls": [
              "https://is1-ssl.mzstatic.com/image/thumb/example-old/392x696bb.jpg"
            ]
          }
        ]
      }
    ]
  },
  "organic": {
    "kind": "unavailable"
  },
  "viewer": {
    "canGenerateIntelligence": true,
    "requests": {
      "kind": "unavailable"
    }
  }
}

```
