{"id":10510,"library":"app-store-server-api","title":"Apple App Store Server API Client","description":"This package provides a robust Node.js client for the Apple App Store Server API, simplifying interactions with Apple's services for in-app purchases and subscriptions. Currently stable at version 0.17.3, it receives frequent updates, often aligning with new releases and features of the underlying App Store Server API. Key features include automatic management of authentication tokens, comprehensive support for App Store Server Notifications V2, typed responses for enhanced developer experience, and helpers for decoding JWS (JSON Web Signature) items with built-in certificate validation against Apple's Certificate Authority. It distinguishes itself by abstracting away much of the complexity of the Apple API, including handling of transaction history, subscription status, and order lookup endpoints, while providing type-safe parameters for filtering and sorting.","status":"active","version":"0.17.3","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/agisboye/app-store-server-api","tags":["javascript","app","store","server","api","apple","in-app","purchase","iap","typescript"],"install":[{"cmd":"npm install app-store-server-api","lang":"bash","label":"npm"},{"cmd":"yarn add app-store-server-api","lang":"bash","label":"yarn"},{"cmd":"pnpm add app-store-server-api","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"While CommonJS `require` can still work in some setups, native ESM `import` is the recommended and standard approach, especially after TypeScript target was switched to ES6 in v0.17.0.","wrong":"const AppStoreServerAPI = require('app-store-server-api').AppStoreServerAPI","symbol":"AppStoreServerAPI","correct":"import { AppStoreServerAPI } from 'app-store-server-api'"},{"note":"The `Environment` enum is a named export. Ensure correct casing and named import syntax.","wrong":"import { ENVIRONMENT } from 'app-store-server-api'","symbol":"Environment","correct":"import { Environment } from 'app-store-server-api'"},{"note":"Decoding helpers like `decodeTransaction`, `decodeRenewalInfo`, and `decodeTransactions` are named exports from the main package entry point.","wrong":"import decodeTransaction from 'app-store-server-api/decodeTransaction'","symbol":"decodeTransaction","correct":"import { decodeTransaction } from 'app-store-server-api'"},{"note":"A typo was fixed in v0.14.1, renaming `isdecodedNotificationSummaryPayload` to `isDecodedNotificationSummaryPayload`. Ensure you use the corrected name.","wrong":"import { isdecodedNotificationSummaryPayload } from 'app-store-server-api'","symbol":"isDecodedNotificationSummaryPayload","correct":"import { isDecodedNotificationSummaryPayload } from 'app-store-server-api'"}],"quickstart":{"code":"import { AppStoreServerAPI, Environment, ProductTypeParameter, SortParameter } from 'app-store-server-api';\n\n// Ensure these are loaded from secure environment variables in a production setup\nconst KEY = process.env.APPLE_PRIVATE_KEY ?? \n`-----BEGIN PRIVATE KEY-----\nMHcCAQEEIPWH5lyoG7Wbzv71ntF6jNvFwwJLKYmPWN/KBD4qJfMcoAoGCCqGSM49\nAwEHoUQDQgAEMOlUa/hmyAPU/RUBds6xzDO8QNrTFhFwzm8E4wxDnSAx8R9WOMnD\ncVGdtnbLFIdLk8g4S7oAfV/gGILKuc+Vqw==\n-----END PRIVATE KEY-----`;\nconst KEY_ID = process.env.APPLE_KEY_ID ?? \"ABCD123456\";\nconst ISSUER_ID = process.env.APPLE_ISSUER_ID ?? \"91fa5999-7b54-4363-a2a8-265363fa6cbe\";\nconst APP_BUNDLE_ID = process.env.APPLE_APP_BUNDLE_ID ?? \"com.yourcompany.app\";\n\nconst api = new AppStoreServerAPI(\n  KEY, KEY_ID, ISSUER_ID, APP_BUNDLE_ID, Environment.Sandbox // Use Environment.Production for live apps\n);\n\nasync function getRecentPurchases(originalTransactionId: string) {\n  try {\n    const response = await api.getTransactionHistory(originalTransactionId, {\n      productType: ProductTypeParameter.AutoRenewable,\n      sort: SortParameter.Descending,\n      limit: 20 // Fetch up to 20 transactions\n    });\n\n    // Decoding verifies the signature and provides typed access to transaction data.\n    const transactions = await api.decodeTransactions(response.signedTransactions);\n\n    console.log(`Found ${transactions.length} transactions for ${originalTransactionId}:`);\n    for (const transaction of transactions) {\n      console.log(`  Transaction ID: ${transaction.transactionId}, Product ID: ${transaction.productId}, Purchase Date: ${new Date(transaction.purchaseDate).toISOString()}`);\n      // Further processing with transaction data...\n    }\n\n    if (response.hasMore) {\n      console.log('More transactions available. Consider fetching with response.revision for next page.');\n    }\n  } catch (error) {\n    console.error('Error fetching transaction history:', error);\n  }\n}\n\n// Example usage (replace with a real originalTransactionId from your system)\n// In a real application, you'd get this from your database or client.\nconst exampleOriginalTransactionId = \"123456789012345\"; \ngetRecentPurchases(exampleOriginalTransactionId);\n","lang":"typescript","description":"This quickstart demonstrates how to initialize the App Store Server API client and fetch a user's recent auto-renewable transaction history, including decoding and verifying the signed transaction data. It highlights the use of environment variables for sensitive API credentials."},"warnings":[{"fix":"Upgrade your Node.js runtime to version 18.12.0 or later.","message":"As of `v0.16.0`, the library requires Node.js version 18.12.0 or newer. Users running older Node.js runtimes must upgrade their environment to avoid compatibility issues.","severity":"breaking","affected_versions":">=0.16.0"},{"fix":"Review your project's TypeScript configuration and build pipeline to ensure compatibility with ES6 target output.","message":"In `v0.17.0`, the TypeScript compilation target was changed to ES6. This may impact projects with specific `tsconfig.json` configurations or build processes that rely on an older TypeScript output target.","severity":"breaking","affected_versions":">=0.17.0"},{"fix":"To reveal the Issuer ID, you must first create an API key for the *App Store Connect API* (not the App Store Server API). After creation, the Issuer ID will become visible in the App Store Connect portal under 'Users and Access' -> 'Integrations' -> 'In-App Purchase'.","message":"Apple's official documentation for obtaining the Issuer ID in App Store Connect is currently incorrect. Developers often struggle to find it.","severity":"gotcha","affected_versions":"all"},{"fix":"Update your code to use the correctly cased function name: `isDecodedNotificationSummaryPayload`.","message":"A typo in a notification helper function, `isdecodedNotificationSummaryPayload`, was fixed in `v0.14.1`. The correct name is `isDecodedNotificationSummaryPayload`.","severity":"gotcha","affected_versions":">=0.14.1"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Upgrade `app-store-server-api` to version `0.17.1` or newer, which includes handling for the 202 status code.","cause":"Older versions of the client did not explicitly handle HTTP 202 (Accepted) as a successful response for certain API calls, leading to errors.","error":"Error: Unexpected status code: 202 Accepted"},{"fix":"Ensure your project is configured for ES modules (e.g., by setting `\"type\": \"module\"` in `package.json` or using `.mjs` file extension) and use `import` statements. Alternatively, if sticking to CommonJS, explicitly use `require()` syntax with `.cjs` file extension or configure `tsconfig.json` for CommonJS output.","cause":"Attempting to use ES module `import` syntax in a CommonJS context or `require()` in an ES module context, especially prevalent after the v0.17.0 TypeScript target change to ES6.","error":"SyntaxError: Cannot use import statement outside a module or ReferenceError: require is not defined"},{"fix":"Double-check your API Key, Key ID, Issuer ID, and App Bundle ID for accuracy. Ensure the private key is correctly formatted and the JWT generation logic is sound. Verify that the JWT is not expired and is signed with the correct algorithm (ES256).","cause":"The JWT (JSON Web Token) used for authentication is invalid, expired, or the credentials (Key ID, Issuer ID, Bundle ID, Private Key) are incorrect.","error":"Error: API request failed with status 401: NOT_AUTHORIZED"}],"ecosystem":"npm"}