Skip to main content
Solved

Getting 429s on Stripe Server-to-Server Integration

  • April 5, 2026
  • 1 reply
  • 37 views

Forum|alt.badge.img

We are using a hybrid approach for our RevenueCat integration:

  • iOS: We use the react-native-purchases SDK for native In-App Purchases.

  • Mobile Web: We provide an option for users to purchase via Stripe Checkout Links directly in a mobile browser (bypassing the native SDK for these specific transactions).

The Issue

We are consistently seeing Error 7746 ("This fetch token is currently being ingested") on the initial delivery of Stripe webhooks for these web purchases.

Since we are not using the RevenueCat Web SDK to initiate these transactions, we are confused as to why a "fetch token" would already be under ingestion when the webhook arrives.

We're seeing subscriptions sync, but the initial 7746 errors force Stripe to rely on retries, causing a delay in granting entitlements. We're not super concerned with this error, but mainly want to confirm that it is expected.

Integration Details

  • Webhook URL: https://api.revenuecat.com/v1/incoming-webhooks/stripe/app1280305636

  • Configuration: "Track new purchases from server-to-server notifications" is Enabled.

  • User Identification: We pass the app_user_id in the Stripe metadata field.

  • We have setup the RC integration inside stripe.

Questions for Support

  1. Is this expected?

  2. What triggers the ingestion lock? Without a Web SDK call to sync the purchase, what else (besides the webhook itself) would cause RevenueCat to already be ingesting the token?

  3. Is this a race condition between Stripe events? If our webhook is configured for both checkout.session.completed and customer.subscription.created, could RevenueCat be attempting to ingest both simultaneously, triggering the 7746 on the second event?

 

Best answer by hussain

Hi ​@jhideki,

Thanks for the detailed write-up, and your analysis is spot-on.

When a user purchases a subscription via Stripe Checkout, Stripe fires both checkout.session.completed and customer.subscription.created nearly simultaneously. Since you have "Track new purchases from server-to-server notifications" enabled, both events hit our webhook and both attempt to create a receipt for the same subscription. We use a short-lived lock keyed on the Stripe subscription ID to prevent duplicate receipt creation. Hence, whichever event arrives second gets the 7746 / 429. Stripe then retries that webhook, our backend finds the receipt already exists, and processes it as a refresh successfully.

To your questions:

  1. Is this expected? Yes. The 7746 is a concurrency guard working as designed.
  2. What triggers the lock? Not the Web SDK, it's the first of the two simultaneous webhook events acquiring the lock during receipt creation.
  3. Race condition between events? Exactly right. Both events resolve to the same subscription ID, so they contend on the same lock.

The only side effect is a brief delay (seconds) while Stripe retries the second event. No action needed on your side. If you want to reduce the noise, you could configure your Stripe webhook to send only one of the two event types, though having both is perfectly fine.

Hope this helps, let me know if you have any other questions. I’m happy to help.

Best,

Hussain

1 reply

hussain
RevenueCat Staff
Forum|alt.badge.img+6
  • RevenueCat Staff
  • Answer
  • April 7, 2026

Hi ​@jhideki,

Thanks for the detailed write-up, and your analysis is spot-on.

When a user purchases a subscription via Stripe Checkout, Stripe fires both checkout.session.completed and customer.subscription.created nearly simultaneously. Since you have "Track new purchases from server-to-server notifications" enabled, both events hit our webhook and both attempt to create a receipt for the same subscription. We use a short-lived lock keyed on the Stripe subscription ID to prevent duplicate receipt creation. Hence, whichever event arrives second gets the 7746 / 429. Stripe then retries that webhook, our backend finds the receipt already exists, and processes it as a refresh successfully.

To your questions:

  1. Is this expected? Yes. The 7746 is a concurrency guard working as designed.
  2. What triggers the lock? Not the Web SDK, it's the first of the two simultaneous webhook events acquiring the lock during receipt creation.
  3. Race condition between events? Exactly right. Both events resolve to the same subscription ID, so they contend on the same lock.

The only side effect is a brief delay (seconds) while Stripe retries the second event. No action needed on your side. If you want to reduce the noise, you could configure your Stripe webhook to send only one of the two event types, though having both is perfectly fine.

Hope this helps, let me know if you have any other questions. I’m happy to help.

Best,

Hussain