---
title: "What does the App Store notification OFFER_REDEEMED mean?"
description: "OFFER_REDEEMED means a customer with an active subscription redeemed an offer. Subtype UPGRADE applies now, DOWNGRADE at the next renewal, and no subtype is an offer on the same plan."
url: https://revenuedot.app/docs/notifications/apple-offer-redeemed
---

# What does the App Store notification OFFER_REDEEMED mean?

The App Store notification OFFER_REDEEMED means a customer with an active subscription redeemed a promotional offer or an offer code.

## Quick facts

| | |
|---|---|
| Notification | `notificationType` `OFFER_REDEEMED` |
| Where | App Store Server Notifications v2 (`responseBodyV2DecodedPayload`) |
| Sent by | The App Store server, to your notification URL |
| What Apple says | A customer with an active subscription redeemed a subscription offer. UPGRADE applies at once, DOWNGRADE at the next renewal date, and no subtype means an offer on the current subscription. |

## What triggers it

- The customer redeemed a promotional offer or offer code while subscribed. First-time and returning subscribers redeeming an offer arrive as `SUBSCRIBED`, and offers on consumables or non-consumables as `ONE_TIME_CHARGE`.
- Subtype `UPGRADE`: the offer upgraded the plan, effective immediately. `DOWNGRADE`: the plan changes at the next renewal.
- Apple says to check `offerType` in the transaction to see what kind of offer it was.

## What your server should do

1. Verify the `signedPayload` with Apple's App Store Server Library (`SignedDataVerifier.verifyAndDecodeNotification`) before you act on anything in it.
2. Read `offerType` and `offerIdentifier` from the signed transaction and record which offer was used.
3. Update the entitlement for an `UPGRADE`; schedule it for a `DOWNGRADE`.
4. Mark the customer as having used the offer, so you do not show it again.
5. Answer HTTP 200 (any code from 200 to 206) once you have stored the notification. Apple retries other answers five times, at 1, 12, 24, 48 and 72 hours after the previous attempt, so make your handler safe to run twice (the payload carries a `notificationUUID`).

## Example

```javascript
// Run on the decoded payload, after you verified Apple's signature.
const notification = {"notificationType":"OFFER_REDEEMED","data":{"environment":"Sandbox","bundleId":"com.example.app"}};

function decide(n) {
  if (n.notificationType !== "OFFER_REDEEMED") return "ignore";
  const when = { UPGRADE: "now", DOWNGRADE: "at the next renewal" }[n.subtype] ?? "on the current plan";
  return "record the offer, apply it " + when;
}

console.log(decide(notification));
```

*Run-checked: `npm run check:snippets` runs this snippet with Node and compares its output with `record the offer` (checked 2026-10-03).*

## How RevenueDot handles it

RevenueDot verifies Apple's signature, checks the bundle ID, stores the notification and answers 200. A purchase RevenueDot has not seen is applied only when the app's **Track new purchases from server-to-server notifications** setting is on. The signed transaction carries the offer, and RevenueDot stores its identifier as the period's offer, which webhooks send as `offer_code`. The period type follows the offer (a free offer is `TRIAL`, a paid introductory or offer code period is `INTRO`, a paid promotional or win-back period is `NORMAL`). A plan change gives the same `PRODUCT_CHANGE` rules as `DID_CHANGE_RENEWAL_PREF`.

## Related

- [What does the App Store notification DID_CHANGE_RENEWAL_PREF mean?](https://revenuedot.app/docs/notifications/apple-did-change-renewal-pref.md)
- [What does the App Store notification SUBSCRIBED mean?](https://revenuedot.app/docs/notifications/apple-subscribed.md)
- [What does the App Store notification ONE_TIME_CHARGE mean?](https://revenuedot.app/docs/notifications/apple-one-time-charge.md)
- [Which webhook events does RevenueDot send?](https://revenuedot.app/docs/api/webhook-events.md)
- [Set up App Store notifications in RevenueDot](https://revenuedot.app/docs/guides/app-store.md)

## Source

- [Apple: notificationType](https://developer.apple.com/documentation/appstoreservernotifications/notificationtype)
- [Apple: Responding to App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications/responding-to-app-store-server-notifications)
- [Apple: app-store-server-library-node (SignedDataVerifier)](https://github.com/apple/app-store-server-library-node)
- [RevenueDot server: stores/apple/notifications.ts (how the notification is applied)](https://github.com/revenuedot/revenuedot/blob/main/apps/server/src/stores/apple/notifications.ts)
- [RevenueDot server: stores/apple/map.ts (how the transaction becomes a stored purchase)](https://github.com/revenuedot/revenuedot/blob/main/apps/server/src/stores/apple/map.ts)
- [RevenueDot core: events.ts (how a change becomes a webhook event)](https://github.com/revenuedot/revenuedot/blob/main/packages/core/src/events.ts)

Checked: 2026-10-03
