AppSkyline for developers

Drive your app store rank tracking from your own code: a REST API with scoped keys and per-key rate limits over the apps and search terms you track across the iOS App Store, Google Play and the Microsoft Store, plus signed webhooks when something changes.

API keys

Get a key and authenticate

The AppSkyline REST API lets your own backend work with what the dashboard shows: the apps your organization tracks, the search terms tracked for each of them across the iOS App Store, Google Play and the Microsoft Store, and the store engagement rows behind the stats pages.

Open the AppSkyline dashboard and create an API key under API keys. The secret is shown once, when the key is created, and never again — store it somewhere safe. A key belongs to a single organization, so the organization is implied by the key and never has to be sent.

Authenticate every request with HTTP Basic auth carrying only the key secret, base64-encoded, in the Authorization header.

# The Authorization header is HTTP Basic auth carrying only the key secret,
# with no username and no colon.
Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)

Every endpoint lives under https://api.appskyline.com. Requests made with a key are rate limited per key; going over the limit returns 429.

Quick start

Your first three calls

List your tracked apps, start tracking a new search term for one of them, then read the terms tracked for that app.

# List the apps your organization tracks
curl https://api.appskyline.com/api/apps \
  -H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"

# Track a new search term for one of them. country is a two-letter ISO code and
# language a two-letter ISO code; the pair is the storefront the term is
# ranked in.
curl -X POST https://api.appskyline.com/api/keywords \
  -H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)" \
  -H "Content-Type: application/json" \
  -d '{
    "appId": "APP_ID",
    "searchTerms": "dental practice software",
    "country": "us",
    "language": "en"
  }'

# Read back the terms tracked for that app
curl "https://api.appskyline.com/api/keywords?appId=APP_ID&limit=50" \
  -H "Authorization: Basic $(printf %s YOUR_API_KEY_SECRET | base64)"

Browse the full API reference — every endpoint with its parameters, request body, responses and required scope.

Claude connector

Use AppSkyline from Claude

Connect AppSkyline to Claude to ask about the apps your organization tracks, the search terms you monitor and their current store rankings. The connector uses your AppSkyline account, so Claude can only access the organization you authorize.

In Claude, open Settings, choose Connectors, then add a custom connector with the URL below. Claude sends you to AppSkyline to sign in and approve access. After connecting, ask a natural-language question such as “What is our current rank for restaurant POS on the iOS App Store in the United States?”

# In Claude: Settings > Connectors > Add custom connector
# Connector URL
https://mcp.appskyline.com/mcp

# Then sign in to your AppSkyline account when Claude asks you to connect.
# Example prompt: "Show the current App Store rank for one of my apps."

The connector has separate read and write tools. Claude identifies changes before performing them, while rank lookups can render a compact inline result with the app, store, country, keyword and current position.

You need an AppSkyline account with access to at least one tracked app. To remove access later, disconnect AppSkyline in Claude or revoke the connection from your AppSkyline account.

Scopes

Least privilege by default

Each key carries a list of scopes, so an integration that only needs to read your rankings never gets the ability to change what is tracked. New keys start read-only; widen them explicitly in the dashboard. A request whose key is missing the scope an endpoint requires is refused with 403.

  • apps:readList the apps of your organization and read one by id.
  • apps:writeCreate and update apps.
  • keywords:readList tracked search terms and read one by id.
  • keywords:writeCreate, update and delete tracked search terms.
  • stats:readRead store engagement rows for your apps.

Webhooks

Signed webhooks

Add a webhook subscription to your organization and AppSkyline POSTs the events you picked to your server as they happen.

  • app.createdAn app was added to tracking.
  • app.updatedAn app was edited.
  • keyword.createdA search term started being tracked for an app.
  • keyword.updatedA tracked search term was edited.
  • keyword.deletedA tracked search term was removed.
POST https://your-server.com/appskyline-webhook
X-Appskyline-Event: keyword.created
X-Appskyline-Signature: t=1719000000,v1=<hmac-sha256 hex>
Content-Type: application/json

{
  "event": "keyword.created",
  "timestamp": 1719000000,
  "data": { "...": "..." }
}

Verify the signature

Every delivery carries an X-Appskyline-Signature header of the form t=timestamp,v1=signature, where the signature is an HMAC-SHA256 of timestamp.body keyed by the subscription secret shown to you once when the subscription was created. Recompute it over the raw body and compare before trusting the payload.

import crypto from 'node:crypto'

// body must be the RAW request body, byte for byte
function verify(header, body, secret) {
  const [t, v1] = (header || '').split(',').map(part => part.split('=')[1])
  if (!t || !v1) return false

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${t}.${body}`)
    .digest('hex')

  // timingSafeEqual throws on a length mismatch, so a malformed signature
  // has to be rejected before the comparison rather than by it.
  if (v1.length !== expected.length) return false

  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
}

Delivery is one best-effort attempt with a five second timeout and no retries, so respond 2xx quickly and do the work asynchronously. An endpoint that fails twenty times in a row is disabled automatically and has to be re-enabled in the dashboard.

Start building