# Get ASO workstation

Read the stored ASO workstation for one tracked app.

## Endpoint: GET /v1/aso/apps/{appId}

- Method: `GET`
- Path: `/v1/aso/apps/{appId}`
- Authentication: Bearer API credential or OAuth access token
- Required scope: `context:read`
- MCP tool: `aso`
- MCP action: `get`

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `appId` | path | uuid | yes | Tracked ASO app id. |

## 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

Read the stored workstation. Difficulty and demand are directional indicators, not search volume or advertising data.

```
curl --get 'https://api.peekpanda.com/v1/aso/apps/11111111-1111-4111-8111-111111111111' \
  --header "Authorization: Bearer $PEEKPANDA_TOKEN" \
  --header 'x-genviral-tenancy: personal'
```

## MCP request

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

```
{
  "name": "aso",
  "arguments": {
    "request": {
      "action": "get",
      "params": {
        "appId": "<appId>"
      }
    }
  }
}

```

## Response

The response includes the tracked app, its saved keywords, observed positions, rivals, ideas, insights and refresh state for the US English storefront. Every keyword row is one saved keyword with its `trackedKeywordId` and `source`; rankings for searches the app has not saved are listed by keyword discovery, not here. `demand` is Apple's weekly search popularity for the phrase (1 to 100, with Apple's 1 to 5 tier). Where Apple reports nothing for a US phrase, `popularityEstimate` carries PeekPanda's own estimate: a tier (`very_low`, `low`, `medium` or `high`), never a number on Apple's scale, with `estimatedAt` and the `modelTrainedAt` of the weekly model behind it. The two never appear together: when `demand` is set, `popularityEstimate` is null. Neither is a search count.

```
{
  "app": {
    "storeId": "0000000000",
    "name": "Example Calorie Tracker",
    "iconUrl": null,
    "developerName": "Example Labs",
    "primaryGenre": "Health & Fitness",
    "rating": 4.7,
    "ratingCount": 12450,
    "inCatalogue": true,
    "id": "11111111-1111-4111-8111-111111111111",
    "kind": "apple",
    "role": "mine",
    "createdAt": "2026-09-06T00:00:00.000Z",
    "lastRefreshedAt": "2026-09-06T00:00:00.000Z",
    "keywordCount": 1
  },
  "refresh": {
    "state": "fresh",
    "lastRefreshedAt": "2026-09-06T00:00:00.000Z",
    "nextAllowedAt": "2026-09-06T01:00:00.000Z",
    "staleQueryCount": 0,
    "activeJobId": null,
    "budget": {
      "userRefreshesToday": 1,
      "userDailyLimit": 40
    }
  },
  "profile": {
    "positionKind": "observed_search_api_position",
    "storeId": "0000000000",
    "coverage": {
      "queriesMatched": 0,
      "country": "us",
      "language": "en_us",
      "source": "itunes_search",
      "latestObservedAt": null,
      "observationCount": 0
    },
    "summary": {
      "top3": 0,
      "top10": 0,
      "top50": 0,
      "bestPosition": null,
      "medianPosition": null
    },
    "keywords": [],
    "rivals": [],
    "keywordIdeas": [],
    "insights": [
      {
        "kind": "coverage_gap",
        "title": "Not in the collected query set yet",
        "detail": "This app did not appear in any collected App Store search. That says nothing about its real rankings.",
        "keywords": [],
        "catalogueStoreId": null
      }
    ]
  },
  "keywords": [
    {
      "query": "calorie tracker",
      "position": 4,
      "trackedKeywordId": "22222222-2222-4222-8222-222222222222",
      "source": "manual",
      "note": null,
      "tags": [
        {
          "id": "55555555-5555-4555-8555-555555555555",
          "name": "Potential",
          "color": "#0f9d58",
          "createdAt": "2026-09-06T00:00:00.000Z",
          "updatedAt": "2026-09-06T00:00:00.000Z"
        }
      ],
      "observedAt": "2026-09-06T00:00:00.000Z",
      "isStale": false,
      "resultCount": 1,
      "apps": [
        {
          "storeId": "0000000000",
          "position": 4,
          "name": "Example Calorie Tracker",
          "isSubject": true,
          "inCatalogue": true
        }
      ],
      "history": [
        {
          "observedAt": "2026-09-06T00:00:00.000Z",
          "position": 4
        }
      ],
      "difficulty": {
        "score": 40
      },
      "demand": {
        "score": 90,
        "tier": 5,
        "country": "us",
        "periodStart": "2026-08-30",
        "periodEnd": "2026-09-05",
        "observedAt": "2026-09-06T00:00:00.000Z"
      },
      "popularityEstimate": null
    },
    {
      "query": "calorie tracker for keto",
      "position": null,
      "trackedKeywordId": "66666666-6666-4666-8666-666666666666",
      "source": "manual",
      "note": null,
      "tags": [],
      "observedAt": "2026-09-06T00:00:00.000Z",
      "isStale": false,
      "resultCount": 0,
      "apps": [],
      "history": [],
      "difficulty": null,
      "demand": null,
      "popularityEstimate": {
        "tier": "medium",
        "method": "peekpanda_popularity_estimate",
        "country": "us",
        "estimatedAt": "2026-09-06T00:00:00.000Z",
        "modelTrainedAt": "2026-09-05T00:30:00.000Z"
      }
    }
  ],
  "tags": [
    {
      "id": "55555555-5555-4555-8555-555555555555",
      "name": "Potential",
      "color": "#0f9d58",
      "createdAt": "2026-09-06T00:00:00.000Z",
      "updatedAt": "2026-09-06T00:00:00.000Z"
    }
  ],
  "trackedCompetitors": []
}

```

## Source

Dated public App Store search results and suggestion observations for the US English storefront. Positions are observed result order. Difficulty and demand are directional indicators, not search volume or advertising data.

## Refresh

This read returns stored observations. Use the related refresh command when newer evidence is needed.
