Bug: IAP pricing API returns inconsistent results

The App Store Connect API returns inconsistent results for IAP pricing.

https://api.appstoreconnect.apple.com/v1/inAppPurchasePriceSchedules/:iapId/manualPrices?include=inAppPurchasePricePoint&filter[territory]=USA

I expect to see at least two inAppPurchasePrices objects, one with startDate: null, representing the current, active price, and at least one with a non-null startDate.

Many IAPs I query don't include an inAppPurchasePrices object that has startDate: null, forcing me to sort through the return objects for the latest startDate (excluding those in the future).

Other IAPs I query return only one inAppPurchasePrices object, and that object has startDate: null.

Worst of all, sometimes the startDate: null object points to the wrong price point!

To repro

Run this Node program I wrote using https://www.npmjs.com/package/node-app-store-connect-api

const { fetchJson } = await api({ issuerId: "***", apiKey: "***" });

const iaps = await fetchJson('apps/1302297731/inAppPurchasesV2?limit=200');

const output = {
    noLatest: [],
    noNull: [],
    nullMismatchesLatest: [],
    ok: [],
}

await Promise.all(iaps.map(async (iap) => {
    const { data: inAppPurchasePrices, included } = await fetchJson(`inAppPurchasePriceSchedules/${iap.id}/manualPrices?include=inAppPurchasePricePoint&filter[territory]=USA`,
        { inclusions: 'tree' });
    const latestStartPrice = inAppPurchasePrices.filter(price => price.attributes.startDate && new Date(price.attributes.startDate).getTime() < Date.now())
        .sort((a, b) => b.attributes.startDate.localeCompare(a.attributes.startDate))[0];
    const nullStartPrice = inAppPurchasePrices.filter(price => !price.attributes.startDate)[0];
    if (!latestStartPrice) {
        output.noLatest.push(iap.id);
    }
    if (!nullStartPrice) {
        output.noNull.push(iap.id);
    }
    if (latestStartPrice && nullStartPrice) {
        const latestStartPricePoint = included.inAppPurchasePricePoints[latestStartPrice.relationships.inAppPurchasePricePoint.data.id];
        const nullStartPricePoint = included.inAppPurchasePricePoints[nullStartPrice.relationships.inAppPurchasePricePoint.data.id];
        if (latestStartPricePoint !== nullStartPricePoint) {
            output.nullMismatchesLatest.push(iap.id);
        } else {
            output.ok.push(iap.id);
        }
    }
}));

console.log(JSON.stringify(output, null, 2));

Expected

All IAPs should appear in the ok array, having a startDate: null price that matches the current latest price with a non-null startDate.

Actual

{
  "noLatest": [
    "1497954161",
    "1441701978",
    "1435841888",
    "1456629092",
    "1381567394",
    "1478155596",
    "1420181684",
    "1546010700",
    "1307073664",
    "1435842259",
    "1447528634",
    "1456628326",
    "1355941688",
    "1355943062",
    "1389691983",
    "1364108501",
    "1614866807",
    "1412920025",
    "1412927608",
    "1377458307",
    "1635603476",
    "1614867647",
    "1402141384",
    "1355943058",
    "1522960459",
    "1438261088",
    "1355943066",
    "1473496366",
    "1435186057",
    "1364106150",
    "1443695443",
    "1473495651",
    "1624284308",
    "1412923459",
    "1532797948",
    "1467986798",
    "1364102273",
    "1480297027",
    "1391358524",
    "1606438471",
    "1497951341",
    "1364106702",
    "1332191975",
    "1480298417",
    "1454531393",
    "1634234785",
    "1496622145",
    "1355942300",
    "1607908448",
    "1412924898",
    "1452845547",
    "1412922765",
    "1614901335",
    "1412928940",
    "1601726945",
    "1579373942",
    "1635602874",
    "1496621119",
    "1402775284",
    "1555535989",
    "1481266301",
    "1402141505",
    "1467986077",
    "1526194764",
    "1584208741",
    "1364106824",
    "1522959003",
    "1364107650",
    "1450343495",
    "1419335516",
    "1473494688",
    "1361358209",
    "1440133234",
    "1449545225",
    "1529667540",
    "1635603182",
    "1412928190",
    "1355943775",
    "1441701155",
    "1514835714",
    "1634325161",
    "1412923835"
  ],
  "noNull": [
    "1402141378",
    "1402141617",
    "1402141630",
    "1402141433",
    "1402141611",
    "1402141281",
    "1402141605",
    "1402141608",
    "1402141440",
    "1402141273",
    "1402141370",
    "1402141442",
    "1402141439",
    "1402141437",
    "1402141276",
    "1402141389",
    "1402141504",
    "1402141502",
    "1402141501",
    "1402141607",
    "1402141615",
    "1402141613",
    "1402141435",
    "1402141619",
    "1402141510",
    "1402141429",
    "1402141494",
    "1402141279",
    "1402141622",
    "1402141623",
    "1402141375",
    "1402141610",
    "1402141606",
    "1402142202",
    "1402141508",
    "1402141609",
    "1402141424",
    "1402141503",
    "1402141441",
    "1402141509",
    "1402141280",
    "1402141430",
    "1402141496",
    "1402141616",
    "1402141292",
    "1402141295",
    "1402141275",
    "1402141612",
    "1402141298",
    "1402141385",
    "1402141282",
    "1402141272",
    "1402141602",
    "1402141423",
    "1402141625",
    "1402141629",
    "1402141271",
    "1402141387",
    "1402141601",
    "1402141386",
    "1402141428",
    "1402141421",
    "1402141495",
    "1402141294",
    "1402141438",
    "1402140691",
    "1402141390",
    "1402142201",
    "1402141627",
    "1402141620",
    "1402141614",
    "1402141604",
    "1402141434",
    "1402141296",
    "1402141383",
    "1402141278",
    "1402141626",
    "1402141621"
  ],
  "nullMismatchesLatest": [
    "1559613404",
    "1480951433",
    "1593896143",
    "1624290126",
    "1402141388",
    "1497950653",
    "1611780428",
    "1478784036",
    "1575588963",
    "1607162006",
    "1611045747",
    "1575589112",
    "1569461289",
    "1619138153",
    "1583793186",
    "1601722583",
    "1539790918",
    "1487867489",
    "1402141618",
    "1506977067",
    "1588425188",
    "1632448119",
    "1619138571",
    "1497954915",
    "1611045866",
    "1593060899",
    "1601719729",
    "1482341662",
    "1512806464",
    "1532073035",
    "1530425266",
    "1617098896",
    "1611046073",
    "1633118569",
    "1497959781",
    "1412920918",
    "1624064036",
    "1497951222",
    "1617100668",
    "1578378729",
    "1536619711",
    "1569460808",
    "1632483553",
    "1478782797",
    "1482341459",
    "1543962463",
    "1606792538",
    "1402141426",
    "1588968070",
    "1493021281",
    "1564178247",
    "1624276610",
    "1562385331",
    "1585716972",
    "1517480296",
    "1402141422",
    "1482781115"
  ],
  "ok": [
    "1402141274",
    "1391871240",
    "1402141293",
    "1364108521",
    "1469870296",
    "1461673391",
    "1443694803",
    "1402141425",
    "1481265446",
    "1402141443",
    "1412917867",
    "1384042585",
    "1562888619",
    "1412920920",
    "1402141507",
    "1402141506",
    "1402141452",
    "1364107061",
    "1447036664",
    "1364107609"
  ]
}

I filed this in Feedback Assistant as FB10941060.

Bug: IAP pricing API returns inconsistent results
 
 
Q