Skip to main content
Solved

Promotional entitlement with custom expiration not extending correctly on renewal

  • February 17, 2026
  • 3 replies
  • 49 views

Forum|alt.badge.img+3

Hi,

I’m implementing team subscriptions where an admin has a normal auto-renewing subscription, and team members receive a promotional entitlement that expires at the same time as the admin’s current period.

On renewal, I try to extend the members’ entitlement by calling the V1 “grant promotional entitlement” endpoint again with a new end_time_ms.
 

const url = `https://api.revenuecat.com/v1/subscribers/${encodeURIComponent(appUserId)}/entitlements/${encodeURIComponent(entitlementId)}/promotional`;
const response = await fetch(
url,
{
method: 'POST',
headers: {
Authorization: `Bearer ${revenueCatApiKey.value()}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(
{
end_time_ms: endsAtMs,
}
),
}
);


Response:

{
insertId: "699397e5000ee469665d0539"
jsonPayload: {
appUserId: "okolifiqPsTzY10TRV9yA627o3w2"
endsAtMs: 1771281961210
entitlementId: "Team Pro Access"
expiresAt: "2026-02-16T22:46:01.210Z"
message: "rc:grant_entitlement_success"
responseBody: {
request_date: "2026-02-16T22:19:17Z"
request_date_ms: 1771280357932
subscriber: {
entitlements: {
Team Pro Access: {
expires_date: "2026-02-16T21:46:01Z"
product_identifier: "rc_promo_Team Pro Access_custom"
purchase_date: "2026-02-16T21:19:05Z"
}
}
first_seen: "2026-02-12T20:10:28Z"
last_seen: "2026-02-13T20:12:45Z"
non_subscriptions: {
0
}
original_app_user_id: "okolifiqPsTzY10TRV9yA627o3w2"
other_purchases: {
0
}
subscriptions: {
rc_promo_Team Pro Access_custom: {
expires_date: "2026-02-16T21:46:01Z"
is_sandbox: false
original_purchase_date: "2026-02-16T21:19:05Z"
period_type: "normal"
price: {
2
}
purchase_date: "2026-02-16T21:19:05Z"
store: "promotional"
store_transaction_id: "1bbdbf1ab911a470fca79c2876ad6d64"
}
}
}
status: 201
}

 

  • The API returns 201.

  • However, the entitlement expiration sometimes remains at the previous value.

  • After the old expiration passes, the member loses access.

  • This seems more frequent when the new expiration is close to the current one (tested only sandbox).

Questions:

  1. Is it officially supported to “extend” an already active promotional entitlement by calling the grant endpoint again with a later end_time_ms?

  2. Are there timing limitations when the new expiration is close to the existing expiration?

  3. Is the recommended approach for team subscriptions instead to grant lifetime promo entitlements and only revoke on admin subscription loss?

I want to confirm whether syncing member entitlements to each renewal via end_time_ms is a supported production-safe pattern, or if this is expected behavior.

Thanks.

Best answer by erik-macinnis

Hello!

Yes, your approach should work, as long as you’re extending the promotional entitlement to a time that’s more than two hours beyond the current expiration.

If the new end_time_ms falls within two hours of the existing expiration, the system won’t update the entitlement’s expiry, even though the API returns a 201 response. That’s likely why you’re seeing the expiration remain unchanged in some cases.

So as long as you ensure the new expiration is sufficiently in the future (outside that two-hour window), extending on renewal should work as expected.

Let me know if you have any other questions.

All the best,
Erik - Developer Support Engineer

3 replies

erik-macinnis
RevenueCat Staff
Forum|alt.badge.img+1
  • RevenueCat Staff
  • February 18, 2026

Hi there,

Thanks for reaching out.

Is it possible that this is only happening when the new end_time_ms is less than two hours later than the current expiration? It looks like we do not update the expiration date if the new end_time_ms is within two hours of the existing expiration.

Looking at the request for the app user ID you shared, okolifiqPsTzY10TRV9yA627o3w2, the new end_time_ms falls within that two hour window.

Let me know if that matches what you are seeing. Happy to look further if not!

Cheers,
Erik - Developer Support Engineer


Forum|alt.badge.img+3
  • Author
  • New Member
  • February 19, 2026



Hi Erik, thanks for your response.
Yes, that is the case. My current flow is:

Listen for webhook [INITIAL_PURCHASE, RENEWAL]
When this is detected, update the expiration for all team members. 

According to this doc, RENEWAL is triggered less than one hour before the end of the billing period. Does that mean my approach mentioned before will not work? I used this article, where it was mentioned it is possible to update the expiration. Another approach is to grant lifetime entitlement and listen for EXPIRATION.

Could you please guide me with the suggested approach from you? 

Thank you again.
 


erik-macinnis
RevenueCat Staff
Forum|alt.badge.img+1
  • RevenueCat Staff
  • Answer
  • February 21, 2026

Hello!

Yes, your approach should work, as long as you’re extending the promotional entitlement to a time that’s more than two hours beyond the current expiration.

If the new end_time_ms falls within two hours of the existing expiration, the system won’t update the entitlement’s expiry, even though the API returns a 201 response. That’s likely why you’re seeing the expiration remain unchanged in some cases.

So as long as you ensure the new expiration is sufficiently in the future (outside that two-hour window), extending on renewal should work as expected.

Let me know if you have any other questions.

All the best,
Erik - Developer Support Engineer