Reponse in blank by "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" in spite of passing valid transactionId

Hello, A user subscribed by in-app purchase subscription in the app "Target Leaderboard". We have got the transaction Id and base64 encoded receipt data in response. We can generate the JWT by the In-app purchase key file and key Id. But when we try to fetch all subscriptions by "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" by passing the transaction Id, blank response is returned. Why it is happening?

Also, when we are try to fetch original transaction Id by "https://sandbox.itunes.apple.com/verifyReceipt" by passing the base64 encoded receipt data and SharedSecret, code 21003 is returned. Why it is happening? Please help.

I have fetched the "originalTransactionId" by "https://sandbox.itunes.apple.com/verifyReceipt" API. But even passing the "originalTransactionId" to "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" API, response is also blank. Why it is happening? Please help.

The API is returning: HTTP Status Code: 401 Response: Unauthenticated Request ID: 7R5JMGYTCFTGWHBZYCS5FLJF4Y.0.0.

This is due to invalid JWT. But we are creating the JWT according to the rule of Apple.

So why it is showing 401? Our code is:

$endpoint = "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions/2000000636560504";


$curl = curl_init($endpoint);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $jwt,
    'Content-Type: application/json'
]);

curl_setopt($curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);

$response = curl_exec($curl);

// Check for any cURL errors
if (curl_errno($curl)) {
    echo 'Error:' . curl_error($curl);
} else {
    $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    echo "HTTP Status Code: " . $http_code . PHP_EOL;

    // Check if the response is empty or not
    if (empty($response)) {
        echo "Response is empty, check if the originalTransactionId is valid or the API is returning correct data." . PHP_EOL;
    } else {
        // Output the API response
        echo "Response: " . $response . PHP_EOL;
    }
}

We are creating the JWT with PHP with the subscription Key Id and the .p8 file. Our JWT creation code is below:

$keyId = 'YM6QNH7F68';
$issuerId = 'e931e2dd-242b-46d2-8ee2-263fa7d585b7';
$privateKey = file_get_contents('SubscriptionKey_YM6QNH7F68.p8');

// JWT Header
$header = [
    'alg' => 'ES256',  // Algorithm for signing
    'kid' => $keyId
];

// JWT Payload
$issuedAt = time();
$expirationTime = $issuedAt + (20 * 60); // JWT valid for 20 minutes
$audience = 'appstoreconnect-v1'; // Audience field

$payload = [
    'iss' => $issuerId,        // Issuer ID
    'iat' => $issuedAt,        // Issued at time
    'exp' => $expirationTime,  // Expiration time
    'aud' => $audience,
    "bid" => "com.targetleaderboard"
];

// Function to base64 encode without padding
function base64UrlEncode($data)
{
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

// Encode Header and Payload
$base64UrlHeader = base64UrlEncode(json_encode($header));
$base64UrlPayload = base64UrlEncode(json_encode($payload));

// Create the unsigned token
$unsignedToken = $base64UrlHeader . "." . $base64UrlPayload;

// Load the private key for signing
$privateKeyResource = openssl_pkey_get_private($privateKey);

// Sign the token using the private key and ES256 (ECDSA with P-256 curve and SHA-256)
$signature = '';
openssl_sign($unsignedToken, $signature, $privateKeyResource, OPENSSL_ALGO_SHA256);

// Free the private key from memory
//openssl_free_key($privateKeyResource);

// Encode the signature in base64 URL format
$base64UrlSignature = base64UrlEncode($signature);

// Concatenate the JWT
$jwt = $unsignedToken . "." . $base64UrlSignature;

$jwt = $jwt . PHP_EOL;

But why the "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" API is returning 401 code? Please help!

Hello, I can see that your signature is invalid. I would recommend using a JWT signing library within PHP if possible, or using the App Store Server Library available for Node.js, Python, Java, or Swift

Hi, I’m encountering a similar issue with the App Store Server API.

After successfully completing an auto-renewable subscription purchase in my React Native app, I’m retrieving the transactionId and other details correctly:

{
  "originalTransactionDateIOS": 1732733802000,
  "originalTransactionIdentifierIOS": "2000007891139879",
  "productId": "product.id",
  "transactionDate": 1732748202000,
  "transactionId": "2000007935522994",
  "transactionReceipt": "xxxxxxxxxxxxCwIBAwIBAQ"
}

However, when I send the transactionId to the server and call the https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions endpoint using the App Store Server API, I always receive an empty array in response.

Additionally, while testing using StoreKit Test in Xcode, I consistently get 0 as the transactionId, making it difficult to validate the subscription status and expiry date.

Has anyone else encountered this issue? What could be causing the getTransactionHistory or getTransactionInfo API to return no data?

Any insights would be greatly appreciated!

Reponse in blank by "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions" in spite of passing valid transactionId
 
 
Q