Setup·6 min read

How to create an App Store Connect API key to read and reply to reviews

Step by step: create an App Store Connect API key with the Customer Support role, find the Issuer ID and Key ID, test it, and reply to customer reviews through the API.

The App Store Connect API lets your tools read your app’s customer reviews and post replies, without logging in to App Store Connect every time. You need an API key for it: three pieces of information that together prove a request comes from your team.

This guide shows how to create one with the least access needed for reviews, keep it safe, and check that it works.

What you need

  • An Apple Developer account with apps in App Store Connect, and the Account Holder or an Admin role. Other roles can’t create team keys.
  • About five minutes.

Create the key

  1. Open the API keys page

    Sign in to App Store Connect, open Users and Access, then the Integrations tab, and choose App Store Connect API → Team Keys.
  2. Request access (first time only)

    If you’ve never used the API, Apple asks the Account Holder to request access and accept the terms. It’s usually granted right away.
  3. Generate a key with the Customer Support role

    Click + (Generate API Key), give it a name you’ll recognize (for example “Reviews”), and choose the Customer Support access. It can read reviews and answer them, and nothing else: no builds, no pricing, no sales data.
  4. Download the private key (only once!)

    Click Download API Key to get a file named like AuthKey_2X9R4HXF34.p8. Apple lets you download it only once. Save it in your password manager.
  5. Copy the Issuer ID and the Key ID

    The Issuer ID (a long ID with dashes) is shown above the list of keys, the same for your whole team. The Key ID (10 letters and numbers) is in the key’s row.

Check that it works

Every API request carries a short-lived token (a JWT) signed with your private key. It uses the ES256 algorithm, your Key ID in the header, your Issuer ID as the issuer, appstoreconnect-v1 as the audience, and expires within 20 minutes. Here’s a minimal Node.js example using the jose library:

import { importPKCS8, SignJWT } from "jose";
import { readFileSync } from "node:fs";

const privateKey = await importPKCS8(readFileSync("AuthKey_2X9R4HXF34.p8", "utf8"), "ES256");
const token = await new SignJWT({})
  .setProtectedHeader({ alg: "ES256", kid: "2X9R4HXF34", typ: "JWT" }) // Key ID
  .setIssuer("57246542-96fe-1a63-e053-0824d011072a")                 // Issuer ID
  .setIssuedAt()
  .setExpirationTime("15m")                                           // Apple allows at most 20 minutes
  .setAudience("appstoreconnect-v1")
  .sign(privateKey);

// Newest reviews of one app (use the numeric Apple ID, not the bundle ID)
const res = await fetch(
  "https://api.appstoreconnect.apple.com/v1/apps/1234567890/customerReviews?sort=-createdDate&limit=50",
  { headers: { Authorization: `Bearer ${token}` } },
);
console.log(await res.json());

The app ID in the URL is the app’s numeric Apple ID (App Store Connect → your app → App Information), not the bundle ID. Each review in the result has a rating, title, body, the reviewer’s nickname, the date and the country (territory).

Reply to a review

To answer, send a POST with the review’s ID. Posting again for the same review replaces your previous reply. A reply can be up to about 5,970 characters.

POST https://api.appstoreconnect.apple.com/v1/customerReviewResponses
{
  "data": {
    "type": "customerReviewResponses",
    "attributes": { "responseBody": "Thanks for the report! It's fixed in version 2.4." },
    "relationships": {
      "review": { "data": { "type": "customerReviews", "id": "REVIEW_ID" } }
    }
  }
}

New replies first appear with the state PENDING_PUBLISH: Apple checks them before they’re shown on the App Store, which usually takes up to a day. The reviewer is notified when the reply is published.

Common errors

ErrorWhat it means
401 NOT_AUTHORIZEDWrong Issuer ID or Key ID, a revoked key, an expired token (over 20 minutes), or your computer’s clock is off.
403 FORBIDDENThe key’s role can’t do this. For reviews, use Customer Support, App Manager or Admin.
404 NOT_FOUNDYou used the bundle ID instead of the numeric Apple ID, or the app belongs to another team.
409 CONFLICTThe reply was rejected, for example because it’s empty.

Keep the key safe

  • Treat the .p8 file like a password: never commit it to Git, never paste it in chat or email.
  • Use a separate key per tool, so you can revoke one without breaking the others.
  • If a key might have leaked, revoke it immediately in Users and Access → Integrations.