How to enable Refund Keeper for the App Store and Google Play
Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.
Refund Keeper is enabled per store. The App Store and Google Play have separate requirements and a handling option each, and that option is what turns a store on, so enabling one leaves the other untouched.Before you start, check the requirements. Setup spans two places: the Refund Keeper section hosts the setup guide that tracks your progress, while the controls themselves live in Settings — the store credentials on each store’s card, and the handling option under Settings → Refund Keeper.
The Refund Keeper section shows a setup guide that tracks each prerequisite and completes items by fact rather than by self-attestation. Two of the items complete themselves once data starts arriving, and you cannot tick them manually.
Store
Item in the guide
How it completes
App Store
Add the App Store Connect API key
When a usable key is stored and Apple accepts it
App Store
Enable App Store Server Notifications V2
Automatically, once a notification from Apple arrives
App Store
Choose your refund handling preference
When you pick an option other than Do not handle
Google Play
Connect a Google Play service account
When an Android app with a service account key is connected
Google Play
Receive Real-time developer notifications
Automatically, once an RTDN message arrives
Google Play
Choose your dispute handling preference
When you pick an option other than Do not handle
The first two items of each store are its connection items, and they are what gates the store: until both are complete, Refund Keeper cannot be turned on for it. The third item is the handling choice itself — the step that turns the store on once its connection is in place, not a precondition for it. The dashboard names the specific missing item instead of failing with a generic error.
The setup guide tracks the App Store and Google Play steps separately; the notification steps complete on their own
The guide’s Enable … in Settings button is not a separate switch — it is a shortcut to that store’s handling option, which is the control that turns the store on. It stays disabled while the store’s connection items are open. When the guide says a store’s steps must be complete before you enable it, it means those connection items: the third item is the enabling itself.
Point App Store Server Notifications V2 at Qonversion
Follow the Apple Server-to-Server Notifications guide. Version 1 notifications are not supported: they do not carry the refund events Refund Keeper needs. This step completes itself once a notification arrives, which can take a few minutes.
2
Add a key for App Store Server API requests
Refund Keeper sends consumption responses through the App Store Server API. Use an In-App Purchase API key, the key Apple documents for this API, or an App Store Connect API key. Upload the .p8 file with its Key ID and Issuer ID in Settings → App Store. Pages written before the menu was reorganised call the same place Project Settings → Stores → Apple App Store.
3
Choose how refund requests are handled
Open Settings → Refund Keeper and pick one of the App Store options: Do not handle, Send usage data and let Apple decide, Ask Apple to decline the refund, or Ask Apple to grant the refund. The option is the switch: anything other than Do not handle turns Refund Keeper on for the App Store. Refund Keeper then starts answering refund requests that arrive from this moment on, and requests Apple already decided are not revisited.
On Google Play, Refund Keeper answers chargeback disputes, not regular Play refunds. See how the Google Play flow works.
1
Connect an Android app with a Google Play service account key
Refund Keeper answers through the Google Play Developer API using the same credentials Qonversion uses to validate purchases. Follow Set up Google Play for Qonversion and make sure the service account has access to the Google Play Developer API.
2
Point Real-time developer notifications at Qonversion
Refund Keeper learns about disputes only from RTDN. Follow Google Real-time Developer Notifications. This step completes itself once the first notification arrives.
3
Choose how chargeback disputes are handled
Open Settings → Refund Keeper and pick one of the Google Play options: Do not handle, Send usage data and let Google decide, Ask Google to decline the dispute, or Ask Google to grant the dispute. As on the App Store, the option is the switch: anything other than Do not handle turns Refund Keeper on for Google Play, and it starts answering disputes that arrive from this moment on, within Google’s 24-hour response window.
Settings → Refund Keeper: one handling option per store, with Do not handle as the off state. Here the App Store is on and set to decline, while Google Play is still off because its RTDN step is not finished — until RTDN arrives, a Google Play answering option cannot be applied
Enabling Google Play requires RTDN to have delivered at least one notification. Until a store’s connection steps are done — the credentials, and a first notification actually received — the dashboard does not let you turn that store on, and the setup guide’s own Enable Google Play in Settings action stays disabled. Choosing the handling option is the step that follows, not a precondition. This is by design: a keeper that is on while notifications are silent loses disputes without any signal.
Refund Keeper answers only events that arrive after the store is on. Nothing is applied retroactively.
The first answers may take a few minutes to appear because the opt-in is cached briefly on the serving path.
Items start appearing in the Refund Keeper table with status Pending. App Store requests show a countdown to Apple’s answer deadline; Google Play disputes appear only once Google has accepted Refund Keeper’s answer, and their Deadline column shows Answered. See Refund Keeper analytics.
Changing the handling option later affects the next event only. Answers already sent cannot be revised.
The dashboard names the missing prerequisite. The usual causes are a missing or rejected App Store key, no App Store notification received yet, no Android app with a service account key, or no RTDN notification received yet.
The notification item never completes
Both notification items complete by fact, so they stay open until a message actually arrives. Re-check the destination configured in App Store Connect or in the Google Play Console, then trigger any purchase event in a sandbox or test environment. For Google Play, confirm the topic you configured matches the one Qonversion shows, and that the subscription attached to it still points at the Qonversion endpoint.
Apple rejected the API key
Refund Keeper requires a key Apple accepts for App Store Server API requests. Replace it with an In-App Purchase API key and confirm the Key ID and Issuer ID match the uploaded .p8 file.
Google Play disputes show no outcome
Google does not return the verdict when the answer is sent. Qonversion detects the outcome afterwards from follow-up notifications and order state, so Saved or Refunded appears later than the answer. Until then the dispute stays Pending. If seven days pass with no refund on the order, the dispute is recorded as Saved, dated at that seven-day mark; the row itself flips about two days later, once late refund data has had time to arrive.
{"docsConfig":{"theme":"aspen","$schema":"https://mintlify.com/docs.json","name":"Qonversion","colors":{"primary":"#7357C2","light":"#AB7DFF","dark":"#7357C2"},"favicon":"https://mintcdn.com/qonversion/i4lAeIKmC47lf8K-/59c36df-small-Avatars_500x500_Black.png?fit=max\u0026auto=format\u0026n=i4lAeIKmC47lf8K-\u0026q=85\u0026s=3f20c2a21d5255fe08a1688d9bfc9efb","api":{"examples":{"languages":["curl","python","javascript","php","ruby","go","java"]}},"appearance":{"default":"system","strict":false},"background":{"color":{"light":"#FFFFFF","dark":"#161617"}},"navbar":{"links":[{"href":"https://qonversion.io","label":"Home"},{"href":"https://dash.qonversion.io","label":"Dashboard"},{"href":"https://status.qonversion.io","label":"Status"}]},"footer":{"socials":{"github":"https://github.com/qonversion","x":"https://x.com/qonversion_io","linkedin":"https://www.linkedin.com/company/qonversion"}},"search":{"prompt":"Search Qonversion docs..."},"seo":{"indexing":"all"},"fonts":{"family":"Inter"},"icons":{"library":"fontawesome"},"styling":{"eyebrows":"section","codeblocks":{"theme":{"light":"github-light-default","dark":"github-dark-default"}},"latex":true},"contextual":{"options":["copy","view","claude","chatgpt"],"display":"header"},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"qonversion","hasAudioNarration":false,"actualSubdomain":"qonversion","customDomains":["documentation.qonversion.io"],"gitSource":{"type":"github","owner":"qonversion","repo":"documentation_mintlify","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ad7846a7a3fec7fec593fbf","collectionId":"99359740-6f49-406b-83a9-621b4655ec87","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ad7846a7a3fec7fec593fbf"},"entitlements":{},"buildId":"6ad7846a7a3fec7fec593fbf","clientVersion":"0.0.3902","searchFilterCounts":[{"language":"default","tag":"API reference","count":157},{"language":"default","tag":"Guides","count":146},{"language":"default","tag":"REST API v4","count":111},{"language":"default","tag":"Get started","count":57},{"language":"default","tag":"SDK migration guides","count":32},{"language":"default","tag":"Integrations","count":31},{"language":"default","tag":"No-Code Builder","count":27},{"language":"default","tag":"Platform resources","count":22},{"language":"default","tag":"Resource guides","count":20},{"language":"default","tag":"Analytics","count":19}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableAskAiSearchBar":true},"hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[],"isAtlas":false,"googleFontsInlined":false},"customCss":[{"filePath":"custom.css","content":".dark,:root,:root[class~=dark]{--qdoc-button:#8161db;--qdoc-button-label:#ffffff}:root{--qdoc-page:#ffffff;--qdoc-chrome:#fafafa;--qdoc-surface:#ffffff;--qdoc-field:#f7f7f9;--qdoc-subtle:#f6f6f6;--qdoc-text:#272727;--qdoc-text-secondary:#6e6e6e;--qdoc-text-tertiary:#595959;--qdoc-border:rgba(51, 51, 51, 0.12);--qdoc-border-strong:rgba(51, 51, 51, 0.28);--qdoc-accent:#7357c2;--qdoc-accent-hover:#664cb0;--qdoc-accent-soft:#f3f0fe;--qdoc-accent-ring:rgba(115, 87, 194, 0.32);--qdoc-positive:#166b37;--qdoc-warning:#7a5f17;--qdoc-negative:#b32b2b;--qdoc-info:#3155c6;--qdoc-p-infra:#70dda5;--qdoc-p-forecast:#00d8ff;--qdoc-p-ads:#ff76d5;--qdoc-p-experiments:#ff8347;--qdoc-p-mcp:#cabaf9;--qdoc-p-label:#14121c;--qdoc-radius-card:12px;--qdoc-radius-control:10px;--qdoc-radius-chip:999px;--qdoc-measure:68ch;--qdoc-ease:cubic-bezier(0.2, 0, 0, 1);--qdoc-fast:120ms;--qdoc-normal:200ms}.dark,:root[class~=dark]{--qdoc-page:#161617;--qdoc-chrome:#161617;--qdoc-surface:#232325;--qdoc-field:#1d1d1f;--qdoc-subtle:rgba(255, 255, 255, 0.06);--qdoc-text:#ffffff;--qdoc-text-secondary:rgba(255, 255, 255, 0.7);--qdoc-text-tertiary:rgba(255, 255, 255, 0.5);--qdoc-border:rgba(255, 255, 255, 0.12);--qdoc-border-strong:rgba(255, 255, 255, 0.28);--qdoc-accent:#ab7dff;--qdoc-accent-hover:#b98fff;--qdoc-accent-soft:rgba(130, 100, 219, 0.18);--qdoc-accent-ring:rgba(171, 125, 255, 0.4);--qdoc-positive:#7adb9b;--qdoc-warning:#f0cd77;--qdoc-negative:#f08a8a;--qdoc-info:#a8c1ff}#content-area h1{font-weight:600;text-wrap:balance;font-size:2.25rem;line-height:1.15;letter-spacing:-.022em}#content-area h2,#content-area h3,#content-area h4,#content-area h5,#content-area h6{font-weight:600;text-wrap:balance;letter-spacing:-.015em}#content-area h2{font-size:1.5rem;line-height:1.22;margin-block:3rem 1rem}#content-area h3{font-size:1.1875rem;line-height:1.3;margin-block:2.25rem .75rem}#content-area li,#content-area p{font-size:1.0625rem;line-height:1.65;color:var(--qdoc-text-secondary)}#content-area .prose>p,#content-area>div>p{max-width:var(--qdoc-measure)}#content-area p{text-wrap:pretty}#content-area h1+p{font-size:1.1875rem;line-height:1.55;color:var(--qdoc-text-secondary)}#content-area code,#content-area table td,#content-area table th{font-variant-numeric:tabular-nums}#content-area a.link,#content-area a:not([class]){color:var(--qdoc-accent);text-decoration-color:var(--qdoc-accent-ring);text-decoration-thickness:from-font;text-underline-position:from-font;text-underline-offset:.12em;text-decoration-skip-ink:auto;transition:color var(--qdoc-fast) var(--qdoc-ease)}#content-area a.link:hover,#content-area a:not([class]):hover{color:var(--qdoc-accent-hover);text-decoration-color:currentColor}#content-area abbr[title]{text-decoration:underline dotted;cursor:help}#content-area .code-group-tab,#content-area [class*=code] [role=tab],#content-area figcaption{color:var(--qdoc-text-secondary)!important;font-size:.75rem;font-weight:500;letter-spacing:.02em}#content-area .code-group-tab[data-state=active],#content-area [class*=code] [role=tab][aria-selected=true]{color:var(--qdoc-text)!important;box-shadow:inset 0 -2px 0 0 var(--qdoc-accent)}#content-area pre{border:1px solid var(--qdoc-border);border-radius:var(--qdoc-radius-card);font-size:.84375rem;line-height:1.6}#content-area :not(pre)>code{background:var(--qdoc-subtle);border:1px solid var(--qdoc-border);border-radius:6px;padding:.1em .35em;font-size:.875em}#content-area button[aria-label*=Copy i]{position:relative}#content-area button[aria-label*=Copy i]::after{content:\"\";position:absolute;inset:50% auto auto 50%;width:44px;height:44px;transform:translate(-50%,-50%)}#content-side-layout a,#navigation-items a{color:var(--qdoc-text-secondary);border-radius:var(--qdoc-radius-control);transition:color var(--qdoc-fast) var(--qdoc-ease),background-color var(--qdoc-fast) var(--qdoc-ease)}#navigation-items a:hover{color:var(--qdoc-text);background:var(--qdoc-subtle)}#navigation-items a[aria-current],#navigation-items a[data-active=true]{background:var(--qdoc-accent-soft);font-weight:500;box-shadow:inset 2px 0 0 0 var(--qdoc-accent)}#content-area table{border-color:var(--qdoc-border)}#content-area thead th{color:var(--qdoc-text);font-size:.8125rem;font-weight:600;letter-spacing:.01em}#content-area tbody td{font-size:.9375rem;line-height:1.5}#content-area tbody tr:hover{background:var(--qdoc-subtle)}#content-area .card{border-radius:var(--qdoc-radius-card);border:1px solid var(--qdoc-border);box-shadow:none;transition:border-color var(--qdoc-fast) var(--qdoc-ease)}@media (hover:hover) and (pointer:fine){#content-area a.card:hover{border-color:var(--qdoc-border-strong)}}#content-area [class*=callout],#content-area blockquote{border-radius:var(--qdoc-radius-card);border-inline-start:3px solid var(--qdoc-border-strong)}#content-area img:not([src*=\"shields.io\"]){border-radius:var(--qdoc-radius-card);outline:1px solid rgba(0,0,0,.1);outline-offset:-1px}.dark #content-area img:not([src*=\"shields.io\"]){outline-color:rgba(255,255,255,.1)}.qdoc-chip{display:inline-block;padding:.15em .7em;border-radius:var(--qdoc-radius-chip);background:var(--qdoc-subtle);color:var(--qdoc-text);font-size:.75rem;font-weight:600;line-height:1.5;white-space:nowrap}.qdoc-chip[data-product]{color:var(--qdoc-p-label)}.qdoc-chip[data-product=infra]{background:var(--qdoc-p-infra)}.qdoc-chip[data-product=forecast]{background:var(--qdoc-p-forecast)}.qdoc-chip[data-product=ads]{background:var(--qdoc-p-ads)}.qdoc-chip[data-product=experiments]{background:var(--qdoc-p-experiments)}.qdoc-chip[data-product=mcp]{background:var(--qdoc-p-mcp)}:root[data-qdoc-product] #content-area h1{padding-inline-start:.75rem;border-inline-start:3px solid var(--qdoc-rail, var(--qdoc-border-strong));margin-inline-start:-.75rem}:root[data-qdoc-product=infra]{--qdoc-rail:var(--qdoc-p-infra)}:root[data-qdoc-product=forecast]{--qdoc-rail:var(--qdoc-p-forecast)}:root[data-qdoc-product=ads]{--qdoc-rail:var(--qdoc-p-ads)}:root[data-qdoc-product=experiments]{--qdoc-rail:var(--qdoc-p-experiments)}:root[data-qdoc-product=mcp]{--qdoc-rail:var(--qdoc-p-mcp)}.qdoc-stage{display:inline-block;font-size:.6875rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--qdoc-text-tertiary)}::selection{background:var(--qdoc-accent-soft);color:var(--qdoc-text)}:root{accent-color:var(--qdoc-accent);caret-color:var(--qdoc-accent)}:where(a, button, [role=\"button\"], summary, input, select, textarea):focus-visible{outline:2px solid transparent;outline-offset:2px;box-shadow:0 0 0 2px var(--qdoc-page),0 0 0 4px var(--qdoc-accent);border-radius:var(--qdoc-radius-control)}@supports selector(::-webkit-scrollbar){#navigation-items::-webkit-scrollbar{width:10px}#navigation-items::-webkit-scrollbar-thumb{background:var(--qdoc-border-strong);border:3px solid transparent;background-clip:content-box;border-radius:999px}}.method-nav-pill>.text-green-700,.method-pill.text-green-700{color:var(--qdoc-positive)!important;background-color:rgba(39,197,90,.12)!important}.method-nav-pill>.text-blue-700,.method-pill.text-blue-700{color:var(--qdoc-accent)!important;background-color:var(--qdoc-accent-soft)!important}.method-nav-pill>.bg-\\[\\#2AB673\\]{background-color:#166b37!important}.method-nav-pill>.bg-\\[\\#3064E3\\]{background-color:#7357c2!important}.dark .method-nav-pill>.bg-\\[\\#2AB673\\]{background-color:#27633f!important}.dark .method-nav-pill>.bg-\\[\\#3064E3\\]{background-color:#8161db!important}@media (max-width:767px){#content-area li,#content-area p{font-size:1rem;line-height:1.6}#content-area h1{font-size:1.75rem}#content-area h2{font-size:1.3125rem;margin-block:2.25rem .75rem}#content-area pre{font-size:.8125rem}#content-area{padding-bottom:max(3rem,env(safe-area-inset-bottom))}}@media (prefers-reduced-motion:reduce){*,::after,::before{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}#navigation-items,#sidebar,header.z-30{background-color:var(--qdoc-page)}.z-30 a[href=\"/\"] img,.z-30 a[href=\"/\"] svg{height:26px;width:auto}.z-30 a[href=\"/\"]{font-size:1.5rem;letter-spacing:-.025em}#navigation-items a{font-size:.9375rem;font-weight:500;color:#4a4a4a;padding-block:.5rem}.dark #navigation-items a{color:rgba(255,255,255,.82)}#navigation-items a[aria-current],#navigation-items a[data-active=true]{color:var(--qdoc-accent)}#navigation-items .sidebar-group-icon{width:16px;height:16px;flex:none;opacity:1;color:var(--qdoc-accent)}#navigation-items .sidebar-group-header{display:flex;align-items:center;gap:.5rem;font-size:.875rem;font-weight:600;letter-spacing:0;color:var(--qdoc-text)}#content-area .card,#content-area [class*=callout],#content-area blockquote,#content-area thead th{background:var(--qdoc-subtle)}#content-area pre{background:var(--qdoc-field)}#content-area .card pre{background:var(--qdoc-page)}#page-context-menu button{background-color:var(--qdoc-subtle)}#page-context-menu button:hover{background-color:var(--qdoc-border)}#content-area .qdoc-products .columns>.card{border-inline-start-width:3px}#content-area .qdoc-products .columns>.card:nth-child(1){border-inline-start-color:var(--qdoc-p-infra)}#content-area .qdoc-products .columns>.card:nth-child(2){border-inline-start-color:var(--qdoc-p-ads)}#content-area .qdoc-products .columns>.card:nth-child(3){border-inline-start-color:var(--qdoc-p-experiments)}#content-area .qdoc-products .columns>.card:nth-child(4){border-inline-start-color:var(--qdoc-p-mcp)}.z-30 .h-14{height:66px!important;padding:15px 16px 5px!important}.z-30 .h-10{height:48px!important}.z-30 .h-14 a[href=\"/\"]{margin-top:-3px!important}"}],"page":{"pagePath":"docs/enable-refund-keeper","slug":"/docs/enable-refund-keeper","pageMetadata":{"title":"How to enable Refund Keeper for the App Store and Google Play","sidebarTitle":"Enable Refund Keeper","description":"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.","href":"/docs/enable-refund-keeper"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,em:`em`,hr:`hr`,li:`li`,p:`p`,strong:`strong`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,..._provideComponents(),...props.components},{Accordion,AccordionGroup,Frame,Heading,Note,OptimizedImage,Step,Steps,Table}=_components;if(!Accordion)_missingMdxReference(`Accordion`,true);if(!AccordionGroup)_missingMdxReference(`AccordionGroup`,true);if(!Frame)_missingMdxReference(`Frame`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Note)_missingMdxReference(`Note`,true);if(!OptimizedImage)_missingMdxReference(`OptimizedImage`,true);if(!Step)_missingMdxReference(`Step`,true);if(!Steps)_missingMdxReference(`Steps`,true);if(!Table)_missingMdxReference(`Table`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`Refund Keeper is enabled `,_jsx(_components.strong,{children:`per store`}),`. The App Store and Google Play have separate requirements and a handling option each, and that option is what turns a store on, so enabling one leaves the other untouched.`]}),`\n`,_jsxs(_components.p,{children:[`Before you start, check the `,_jsx(_components.a,{href:`refund-keeper#what-do-you-need-before-enabling-refund-keeper`,children:`requirements`}),`. Setup spans two places: the `,_jsx(_components.a,{href:`https://dash.qonversion.io/refund-keeper`,children:`Refund Keeper`}),` section hosts the setup guide that tracks your progress, while the controls themselves live in `,_jsx(_components.strong,{children:`Settings`}),` — the store credentials on each store’s card, and the handling option under `,_jsx(_components.strong,{children:`Settings → Refund Keeper`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`what-does-the-setup-guide-check`,children:`What does the setup guide check?`}),`\n`,_jsx(_components.p,{children:`The Refund Keeper section shows a setup guide that tracks each prerequisite and completes items by fact rather than by self-attestation. Two of the items complete themselves once data starts arriving, and you cannot tick them manually.`}),`\n`,_jsxs(Table,{children:[_jsx(_components.thead,{children:_jsxs(_components.tr,{children:[_jsx(_components.th,{children:`Store`}),_jsx(_components.th,{children:`Item in the guide`}),_jsx(_components.th,{children:`How it completes`})]})}),_jsxs(_components.tbody,{children:[_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`App Store`}),_jsx(_components.td,{children:`Add the App Store Connect API key`}),_jsx(_components.td,{children:`When a usable key is stored and Apple accepts it`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`App Store`}),_jsx(_components.td,{children:`Enable App Store Server Notifications V2`}),_jsx(_components.td,{children:`Automatically, once a notification from Apple arrives`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`App Store`}),_jsx(_components.td,{children:`Choose your refund handling preference`}),_jsxs(_components.td,{children:[`When you pick an option other than `,_jsx(_components.strong,{children:`Do not handle`})]})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Google Play`}),_jsx(_components.td,{children:`Connect a Google Play service account`}),_jsx(_components.td,{children:`When an Android app with a service account key is connected`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Google Play`}),_jsx(_components.td,{children:`Receive Real-time developer notifications`}),_jsx(_components.td,{children:`Automatically, once an RTDN message arrives`})]}),_jsxs(_components.tr,{children:[_jsx(_components.td,{children:`Google Play`}),_jsx(_components.td,{children:`Choose your dispute handling preference`}),_jsxs(_components.td,{children:[`When you pick an option other than `,_jsx(_components.strong,{children:`Do not handle`})]})]})]})]}),`\n`,_jsxs(_components.p,{children:[`The first two items of each store are its `,_jsx(_components.strong,{children:`connection`}),` items, and they are what gates the store: until both are complete, Refund Keeper cannot be turned on for it. The third item is the handling choice itself — the step that turns the store on once its connection is in place, not a precondition for it. The dashboard names the specific missing item instead of failing with a generic error.`]}),`\n`,_jsx(Frame,{caption:`The setup guide tracks the App Store and Google Play steps separately; the notification steps complete on their own`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=890e17dcb2fc09bf22b116f759eeff77`,alt:`The Refund Keeper setup guide, with three App Store steps and three Google Play steps tracked separately`,\"data-og-width\":`1456`,width:`1456`,\"data-og-height\":`565`,height:`565`,\"data-path\":`images/docs/refund-keeper-setup-guide.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?w=280\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=0b64893382960e69d348812d9d849584 280w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?w=560\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=04093b9a6e547c065f87086f6e924c50 560w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?w=840\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=a07f37391301e016fa704fef27e734ba 840w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?w=1100\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=f823b6315c2223c4bf44c62063e25d9e 1100w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?w=1650\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=1c04d3770ff91d89f01e935bdf0e8a71 1650w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-setup-guide.png?w=2500\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=c1b46a8bb8e27d54e6ed570dfa49055b 2500w`})}),`\n`,_jsxs(_components.p,{children:[`The guide’s `,_jsx(_components.strong,{children:`Enable … in Settings`}),` button is not a separate switch — it is a shortcut to that store’s handling option, which is the control that turns the store on. It stays disabled while the store’s connection items are open. When the guide says a store’s steps must be complete before you enable it, it means those connection items: the third item is the enabling itself.`]}),`\n`,_jsx(Heading,{level:`2`,id:`how-to-enable-refund-keeper-for-the-app-store`,children:`How to enable Refund Keeper for the App Store`}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Point App Store Server Notifications V2 at Qonversion`,children:_jsxs(_components.p,{children:[`Follow the `,_jsx(_components.a,{href:`ios-s2s-notifications`,children:`Apple Server-to-Server Notifications guide`}),`. Version 1 notifications are not supported: they do not carry the refund events Refund Keeper needs. This step completes itself once a notification arrives, which can take a few minutes.`]})}),_jsx(Step,{title:`Add a key for App Store Server API requests`,children:_jsxs(_components.p,{children:[`Refund Keeper sends consumption responses through the App Store Server API. Use an `,_jsx(_components.a,{href:`in-app-purchase-api-key`,children:`In-App Purchase API key`}),`, the key Apple documents for this API, or an `,_jsx(_components.a,{href:`app-store-connect-api-key`,children:`App Store Connect API key`}),`. Upload the `,_jsx(_components.code,{children:`.p8`}),` file with its Key ID and Issuer ID in `,_jsx(_components.strong,{children:`Settings → App Store`}),`. Pages written before the menu was reorganised call the same place `,_jsx(_components.em,{children:`Project Settings → Stores → Apple App Store`}),`.`]})}),_jsx(Step,{title:`Choose how refund requests are handled`,children:_jsxs(_components.p,{children:[`Open `,_jsx(_components.strong,{children:`Settings → Refund Keeper`}),` and pick one of the App Store options: `,_jsx(_components.strong,{children:`Do not handle`}),`, `,_jsx(_components.strong,{children:`Send usage data and let Apple decide`}),`, `,_jsx(_components.strong,{children:`Ask Apple to decline the refund`}),`, or `,_jsx(_components.strong,{children:`Ask Apple to grant the refund`}),`. The option is the switch: anything other than `,_jsx(_components.strong,{children:`Do not handle`}),` turns Refund Keeper on for the App Store. Refund Keeper then starts answering refund requests that arrive from this moment on, and requests Apple already decided are not revisited.`]})})]}),`\n`,_jsx(Heading,{level:`2`,id:`how-to-enable-refund-keeper-for-google-play`,children:`How to enable Refund Keeper for Google Play`}),`\n`,_jsxs(_components.p,{children:[`On Google Play, Refund Keeper answers `,_jsx(_components.strong,{children:`chargeback disputes`}),`, not regular Play refunds. See `,_jsx(_components.a,{href:`refund-keeper#how-does-refund-keeper-answer-google-play-chargeback-disputes`,children:`how the Google Play flow works`}),`.`]}),`\n`,_jsxs(Steps,{children:[_jsx(Step,{title:`Connect an Android app with a Google Play service account key`,children:_jsxs(_components.p,{children:[`Refund Keeper answers through the Google Play Developer API using the same credentials Qonversion uses to validate purchases. Follow `,_jsx(_components.a,{href:`android-store-setup`,children:`Set up Google Play for Qonversion`}),` and make sure the service account has access to the Google Play Developer API.`]})}),_jsx(Step,{title:`Point Real-time developer notifications at Qonversion`,children:_jsxs(_components.p,{children:[`Refund Keeper learns about disputes only from RTDN. Follow `,_jsx(_components.a,{href:`google-developer-notifications`,children:`Google Real-time Developer Notifications`}),`. This step completes itself once the first notification arrives.`]})}),_jsx(Step,{title:`Choose how chargeback disputes are handled`,children:_jsxs(_components.p,{children:[`Open `,_jsx(_components.strong,{children:`Settings → Refund Keeper`}),` and pick one of the Google Play options: `,_jsx(_components.strong,{children:`Do not handle`}),`, `,_jsx(_components.strong,{children:`Send usage data and let Google decide`}),`, `,_jsx(_components.strong,{children:`Ask Google to decline the dispute`}),`, or `,_jsx(_components.strong,{children:`Ask Google to grant the dispute`}),`. As on the App Store, the option is the switch: anything other than `,_jsx(_components.strong,{children:`Do not handle`}),` turns Refund Keeper on for Google Play, and it starts answering disputes that arrive from this moment on, within Google’s 24-hour response window.`]})})]}),`\n`,_jsx(Frame,{caption:`Settings → Refund Keeper: one handling option per store, with Do not handle as the off state. Here the App Store is on and set to decline, while Google Play is still off because its RTDN step is not finished — until RTDN arrives, a Google Play answering option cannot be applied`,children:_jsx(OptimizedImage,{src:`https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=a9e7d88a1a3966f8443e08202498f19d`,alt:`The Refund Keeper settings page with one handling option per store: the App Store set to Ask Apple to decline the refund, Google Play set to Do not handle`,\"data-og-width\":`1372`,width:`1372`,\"data-og-height\":`345`,height:`345`,\"data-path\":`images/docs/refund-keeper-settings-stores.png`,\"data-optimize\":`true`,\"data-opv\":`3`,srcset:`https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?w=280\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=18d85830a985c332ff267c788f7851fe 280w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?w=560\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=8fcf688fdc53d16ff90b44f9c4738999 560w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?w=840\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=bdc4fc5ebee58fe89a5f04dad725d8a7 840w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?w=1100\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=d2a212927128121b5c6bf995dda35ec8 1100w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?w=1650\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=e43ee29df11d090e6679ffe3e8f4ba4b 1650w, https://mintcdn.com/qonversion/eizAJ0E-bhCHkEw-/images/docs/refund-keeper-settings-stores.png?w=2500\u0026fit=max\u0026auto=format\u0026n=eizAJ0E-bhCHkEw-\u0026q=85\u0026s=a94bcb2fe966fba2e9f86145a264f48f 2500w`})}),`\n`,_jsx(Note,{children:_jsxs(_components.p,{children:[`Enabling Google Play requires RTDN to have delivered at least one notification. Until a store’s `,_jsx(_components.strong,{children:`connection`}),` steps are done — the credentials, and a first notification actually received — the dashboard does not let you turn that store on, and the setup guide’s own `,_jsx(_components.strong,{children:`Enable Google Play in Settings`}),` action stays disabled. Choosing the handling option is the step that follows, not a precondition. This is by design: a keeper that is on while notifications are silent loses disputes without any signal.`]})}),`\n`,_jsx(Heading,{level:`2`,id:`what-happens-right-after-you-enable-a-store`,children:`What happens right after you enable a store?`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsx(_components.li,{children:`Refund Keeper answers only events that arrive after the store is on. Nothing is applied retroactively.`}),`\n`,_jsx(_components.li,{children:`The first answers may take a few minutes to appear because the opt-in is cached briefly on the serving path.`}),`\n`,_jsxs(_components.li,{children:[`Items start appearing in the Refund Keeper table with status `,_jsx(_components.code,{children:`Pending`}),`. App Store requests show a countdown to Apple’s answer deadline; Google Play disputes appear only once Google has accepted Refund Keeper’s answer, and their Deadline column shows `,_jsx(_components.code,{children:`Answered`}),`. See `,_jsx(_components.a,{href:`analytics-overview`,children:`Refund Keeper analytics`}),`.`]}),`\n`,_jsx(_components.li,{children:`Changing the handling option later affects the next event only. Answers already sent cannot be revised.`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`troubleshooting`,children:`Troubleshooting`}),`\n`,_jsxs(AccordionGroup,{children:[_jsx(Accordion,{title:`A store cannot be turned on`,id:`a-store-cannot-be-turned-on`,children:_jsx(_components.p,{children:`The dashboard names the missing prerequisite. The usual causes are a missing or rejected App Store key, no App Store notification received yet, no Android app with a service account key, or no RTDN notification received yet.`})}),_jsx(Accordion,{title:`The notification item never completes`,id:`the-notification-item-never-completes`,children:_jsx(_components.p,{children:`Both notification items complete by fact, so they stay open until a message actually arrives. Re-check the destination configured in App Store Connect or in the Google Play Console, then trigger any purchase event in a sandbox or test environment. For Google Play, confirm the topic you configured matches the one Qonversion shows, and that the subscription attached to it still points at the Qonversion endpoint.`})}),_jsx(Accordion,{title:`Apple rejected the API key`,id:`apple-rejected-the-api-key`,children:_jsxs(_components.p,{children:[`Refund Keeper requires a key Apple accepts for App Store Server API requests. Replace it with an `,_jsx(_components.a,{href:`in-app-purchase-api-key`,children:`In-App Purchase API key`}),` and confirm the Key ID and Issuer ID match the uploaded `,_jsx(_components.code,{children:`.p8`}),` file.`]})}),_jsx(Accordion,{title:`Google Play disputes show no outcome`,id:`google-play-disputes-show-no-outcome`,children:_jsxs(_components.p,{children:[`Google does not return the verdict when the answer is sent. Qonversion detects the outcome afterwards from follow-up notifications and order state, so `,_jsx(_components.code,{children:`Saved`}),` or `,_jsx(_components.code,{children:`Refunded`}),` appears later than the answer. Until then the dispute stays `,_jsx(_components.code,{children:`Pending`}),`. If seven days pass with no refund on the order, the dispute is recorded as `,_jsx(_components.code,{children:`Saved`}),`, dated at that seven-day mark; the row itself flips about two days later, once late refund data has had time to arrive.`]})})]}),`\n`,_jsx(_components.hr,{}),`\n`,_jsx(_components.p,{children:_jsx(_components.a,{href:`refund-keeper`,children:`Refund Keeper`})}),`\n`,_jsx(_components.p,{children:_jsx(_components.a,{href:`analytics-overview`,children:`Refund Keeper Analytics`})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"codeStyling":{"theme":{"light":"github-light-default","dark":"github-dark-default"}},"config":{},"pageMetadata":{"title":"How to enable Refund Keeper for the App Store and Google Play","sidebarTitle":"Enable Refund Keeper","description":"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.","href":"/docs/enable-refund-keeper"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"What does the setup guide check?","slug":"what-does-the-setup-guide-check","depth":2,"children":[]},{"title":"How to enable Refund Keeper for the App Store","slug":"how-to-enable-refund-keeper-for-the-app-store","depth":2,"children":[]},{"title":"How to enable Refund Keeper for Google Play","slug":"how-to-enable-refund-keeper-for-google-play","depth":2,"children":[]},{"title":"What happens right after you enable a store?","slug":"what-happens-right-after-you-enable-a-store","depth":2,"children":[]},{"title":"Troubleshooting","slug":"troubleshooting","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":["/_mintlify/custom/qonversion/a8b6627337592ade/custom.js"],"subdomain":"qonversion","siteName":"Qonversion","title":"How to enable Refund Keeper for the App Store and Google Play - Qonversion","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-20T15:12:17.526Z","originalFileLocation":"docs/enable-refund-keeper.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Qonversion\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"How to enable Refund Keeper for the App Store and Google Play - Qonversion\">\u003cmeta data-mint-head property=\"og:description\" content=\"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Qonversion\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://documentation.qonversion.io/docs/enable-refund-keeper\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"How to enable Refund Keeper for the App Store and Google Play - Qonversion\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/qonversion/Dzad_pULPIRkhK0k/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Qonversion\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#7357C2\">\u003clink data-mint-head rel=\"canonical\" href=\"https://documentation.qonversion.io/docs/enable-refund-keeper\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/docs/enable-refund-keeper.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://documentation.qonversion.io/#organization\",\"name\":\"Qonversion\",\"url\":\"https://documentation.qonversion.io\"},{\"@type\":\"WebSite\",\"@id\":\"https://documentation.qonversion.io#website\",\"name\":\"Qonversion\",\"url\":\"https://documentation.qonversion.io\",\"publisher\":{\"@id\":\"https://documentation.qonversion.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://documentation.qonversion.io/docs/enable-refund-keeper#webpage\",\"url\":\"https://documentation.qonversion.io/docs/enable-refund-keeper\",\"name\":\"How to enable Refund Keeper for the App Store and Google Play\",\"description\":\"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.\",\"dateModified\":\"2026-10-20T15:12:17.526Z\",\"isPartOf\":{\"@id\":\"https://documentation.qonversion.io#website\"},\"breadcrumb\":{\"@id\":\"https://documentation.qonversion.io/docs/enable-refund-keeper#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://documentation.qonversion.io/docs/enable-refund-keeper#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Data and infrastructure\",\"item\":\"https://documentation.qonversion.io/docs/infrastructure\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Refund Keeper\",\"item\":\"https://documentation.qonversion.io/docs/refund-keeper\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How to enable Refund Keeper for the App Store and Google Play\",\"item\":\"https://documentation.qonversion.io/docs/enable-refund-keeper\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://documentation.qonversion.io/docs/enable-refund-keeper#article\",\"headline\":\"How to enable Refund Keeper for the App Store and Google Play\",\"name\":\"How to enable Refund Keeper for the App Store and Google Play\",\"description\":\"Step-by-step setup for Refund Keeper in Qonversion: the setup guide checks, the App Store key and notifications, the Google Play service account and RTDN, and what happens right after you enable each store.\",\"url\":\"https://documentation.qonversion.io/docs/enable-refund-keeper\",\"mainEntityOfPage\":{\"@id\":\"https://documentation.qonversion.io/docs/enable-refund-keeper#webpage\"},\"dateModified\":\"2026-10-20T15:12:17.526Z\",\"publisher\":{\"@id\":\"https://documentation.qonversion.io/#organization\"},\"isPartOf\":{\"@id\":\"https://documentation.qonversion.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Qonversion\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Qonversion","nav":{"global":null,"tabs":[{"tab":"Get started","icon":"rocket","pages":[{"title":"Get started","href":"/docs/qonversion-platform"}]},{"tab":"Guides","icon":"book-open","groups":[{"group":"Apple Ads","icon":"bullseye","pages":[{"title":"Apple Ads in Qonversion: what it does and how to set it up","sidebarTitle":"Overview","href":"/docs/apple-ads"},{"title":"How do I connect Apple Ads to Qonversion?","sidebarTitle":"Connect Apple Ads","href":"/docs/apple-search-ads"},{"title":"How do I collect Apple Ads attribution with the Qonversion SDK?","sidebarTitle":"Collect attribution","href":"/docs/apple-ads-attribution"},{"title":"How do I read the Apple Ads report in Qonversion?","sidebarTitle":"Read the report","href":"/docs/apple-ads-report"},{"title":"Apple Ads report columns and metric definitions","sidebarTitle":"Columns and metrics","href":"/docs/apple-search-ads-analytics"},{"title":"What does the Budget usage column show for Apple Ads campaigns?","sidebarTitle":"Budget usage","href":"/docs/apple-ads-budget-usage"},{"title":"How fresh is Apple Ads data in Qonversion, and how do I fill in spend history?","sidebarTitle":"Data freshness and history","href":"/docs/apple-ads-data-freshness"},{"title":"How do I pause campaigns and change bids and budgets for Apple Ads in Qonversion?","sidebarTitle":"Manage campaigns","href":"/docs/apple-ads-manage-campaigns"},{"title":"How do I use Apple Ads through the Qonversion MCP server?","sidebarTitle":"Apple Ads via MCP","href":"/docs/mcp-apple-ads"},{"title":"Troubleshooting Apple Ads in Qonversion","sidebarTitle":"Troubleshooting","href":"/docs/apple-ads-troubleshooting"}]},{"group":"Remote Configs + A/B Tests","icon":"flask","pages":[{"title":"Remote Configs + A/B Tests","href":"/docs/experiments"},{"group":"Remote Configs","pages":[{"title":"Create Remote Config","href":"/docs/remote-config"},{"title":"How targeting and assignment works","href":"/docs/remote-config-targeting"},{"title":"Launch A/B test from Remote Config","href":"/docs/launch-test-from-remote-config"},{"title":"Migrate Offerings to Remote Configs","href":"/docs/migrate-offerings-to-remote-configs"}]},{"group":"A/B Tests","pages":[{"title":"Paywall experiments","href":"/docs/paywall-experiments"},{"title":"Launch experiments","href":"/docs/launch-experiments"},{"title":"Analyse experiments","href":"/docs/analyse-experiment"},{"title":"Pause experiments","href":"/docs/pause-experiments"},{"title":"Stop experiments","href":"/docs/finish-experiment"},{"title":"Splitting rules","href":"/docs/splitting-rules"}]}]},{"group":"Data and infrastructure","icon":"database","pages":[{"title":"How Qonversion handles subscription infrastructure","href":"/docs/infrastructure"},{"group":"Analytics","pages":[{"title":"Analytics","href":"/docs/analytics"},{"title":"Account Overview","href":"/docs/account-overview"},{"title":"Monitoring","href":"/docs/monitoring"},{"title":"Revenue","href":"/docs/revenue"},{"title":"New users","href":"/docs/users"},{"title":"Trials","href":"/docs/trials"},{"title":"Subscriptions","href":"/docs/subscriptions"},{"title":"Events","href":"/docs/events-analytics"},{"title":"Cohorts","href":"/docs/cohorts"}]},{"group":"Customers","pages":[{"title":"Customers","href":"/docs/customers"},{"title":"Edit Entitlements","href":"/docs/edit-entitlements"},{"title":"Customer Details","href":"/docs/customer-details"}]},{"group":"Raw data export","pages":[{"title":"Raw Data Export","href":"/docs/raw-data-reports"},{"title":"Scheduled Reports","href":"/docs/scheduled-reports"}]},{"group":"Refund Keeper","pages":[{"title":"What is Refund Keeper and how does it work?","sidebarTitle":"Refund Keeper","description":"Refund Keeper answers App Store refund requests and Google Play chargeback disputes automatically, sending the store app usage evidence and your refund preference so fewer unjustified refunds are approved.","href":"/docs/refund-keeper"},{"title":"How to enable Refund Keeper for the App Store and Google Play","sidebarTitle":"Enable Refund Keeper","href":"/docs/enable-refund-keeper"},{"title":"How to read Refund Keeper analytics","sidebarTitle":"Refund Keeper Analytics","description":"What the Refund Keeper section of the Qonversion dashboard shows: the won-back widgets, the activity chart, the refund table with its statuses and answer deadline, and how filtering by Store separates App Store refunds from Google Play chargeback disputes.","href":"/docs/analytics-overview"}]}]},{"group":"Integrations","icon":"plug","pages":[{"title":"Integrations","href":"/docs/integrations-overview"},{"title":"Webhooks","href":"/docs/webhooks"},{"title":"Adjust","href":"/docs/adjust"},{"title":"Amazon S3","href":"/docs/amazon-s3"},{"title":"Amplitude","href":"/docs/amplitude"},{"title":"AppMetrica","href":"/docs/appmetrica"},{"title":"AppsFlyer","href":"/docs/appsflyer"},{"title":"Asapty","href":"/docs/asapty"},{"title":"Branch","href":"/docs/branch"},{"title":"Braze","href":"/docs/braze"},{"title":"CleverTap","href":"/docs/clevertap"},{"title":"Facebook Ads","href":"/docs/facebook"},{"title":"Firebase","href":"/docs/firebase"},{"title":"Google Ads","href":"/docs/google-ads"},{"title":"Google Cloud Storage","href":"/docs/google-cloud-storage"},{"title":"Kochava","href":"/docs/kochava"},{"title":"Mailchimp","href":"/docs/mailchimp"},{"title":"Mixpanel","href":"/docs/mixpanel"},{"title":"OneSignal","href":"/docs/onesignal"},{"title":"PostHog","href":"/docs/posthog"},{"title":"Pushwoosh","href":"/docs/pushwoosh"},{"title":"Segment","href":"/docs/segment"},{"title":"Singular","href":"/docs/singular"},{"title":"Slack","href":"/docs/slack"},{"title":"SplitMetrics Acquire","href":"/docs/splitmetrics"},{"title":"Tenjin","href":"/docs/tenjin"}]},{"group":"Platform resources","icon":"mobile","pages":[{"group":"Apple App Store","pages":[{"title":"Apple App Store","href":"/docs/apple-app-store"},{"title":"App Store Offer Codes","href":"/docs/appstore-offer-codes"},{"title":"App Store Privacy","href":"/docs/app-store-privacy"},{"title":"App Store Promoted Purchases","href":"/docs/app-store-promoted-purchases"},{"title":"App Store Small Business Program","href":"/docs/app-store-small-business-program"},{"title":"Apple Family Sharing","href":"/docs/apple-family-sharing"},{"title":"Apple Promotional Offers","href":"/docs/apple-promotional-offers"},{"title":"Migrate from SwiftyStoreKit","href":"/docs/swiftystorekit-alternative"}]},{"group":"Google Play Store","pages":[{"title":"Google Play Store","sidebarTitle":"Google Play Store","href":"/docs/google-play"},{"title":"Android In-App Products Setup","href":"/docs/android-in-app-products"},{"title":"Android test devices","href":"/docs/android-test-devices"},{"title":"Creating an App in Google Play Console","href":"/docs/app-creation-in-google-play-console"},{"title":"Google Play Data Safety","href":"/docs/google-play-data-safety"},{"title":"License testing","href":"/docs/license-testing"},{"title":"Publish your Android App","href":"/docs/app-publication-in-google-play-console"},{"title":"Upgrade and Downgrade in Google","href":"/docs/google-upgrade-downgrade-or-change-subscription"}]},{"title":"Deferred Purchases","href":"/docs/deferred-purchases"},{"title":"Non-Subscription Purchases","href":"/docs/non-subscription-purchases"},{"title":"Store Product Price Changes","href":"/docs/store-product-price-changes"},{"title":"Upgrade and Downgrade a Subscription","href":"/docs/upgrade-and-downgrade-a-subscription"},{"title":"Sample Apps","href":"/docs/sample-apps"},{"title":"Tutorials","href":"/docs/tutorials"}]},{"group":"No-Code Builder","icon":"paintbrush","pages":[{"title":"Overview","sidebarTitle":"No-Code Builder","href":"/docs/no-codes"},{"group":"Installation","pages":[{"title":"Installation","href":"/docs/installation"},{"title":"Product Setup \u0026 Store Connection","href":"/docs/product-setup-store-connection-1"}]},{"group":"Creating Screens","pages":[{"title":"Creating Screens","href":"/docs/getting-started"},{"group":"Components","pages":[{"title":"Components","href":"/docs/components"},{"title":"Product Blocks","href":"/docs/product-blocks"},{"title":"Social Proof","href":"/docs/social-proof"},{"title":"Carousels","href":"/docs/carousels"},{"title":"CTA Buttons","href":"/docs/cta-buttons"},{"title":"Feature List","href":"/docs/feature-list"},{"title":"Awards","href":"/docs/awards"},{"title":"Lottie Component Source","href":"/docs/no-code-component-lottie-src"}]},{"title":"AI Image Generation","href":"/docs/ai-image-generation"},{"title":"Properties Reference","href":"/docs/properties-reference"},{"title":"Variables","href":"/docs/variables-1"},{"title":"Localization","href":"/docs/ai-localization"},{"title":"Conditional Logic","href":"/docs/conditional-logic"},{"title":"Purchase Loader","href":"/docs/purchase-loader"}]},{"title":"Fallbacks","href":"/docs/fallbacks"},{"title":"Screens Preloading","href":"/docs/screens-preloading"},{"title":"Displaying No-Codes","href":"/docs/displaying-no-codes"},{"title":"Success and Failure Actions","href":"/docs/success-failure-actions"},{"title":"Custom Actions","href":"/docs/custom-actions"},{"title":"Screen Analytics","href":"/docs/no-codes-analytics"},{"title":"Using No-Codes with custom purchases handling","href":"/docs/using-no-codes-with-custom-purchases-handling"},{"group":"Web Funnel","pages":[{"title":"Web Funnel — Sell subscriptions on the web","sidebarTitle":"Web Funnel","href":"/docs/web-funnel"},{"title":"Web Funnel — Redeem web purchases in your app","sidebarTitle":"Web Funnel redemption","href":"/docs/web-funnel-redemption"}]}]},{"group":"SDK migration guides","icon":"arrow-up-right-dots","pages":[{"title":"[Dec 2026] Migration guide. CocoaPods → Swift Package Manager","sidebarTitle":"CocoaPods → SPM (Dec 2026)","href":"/docs/dec-2026-migration-guide-cocoapods-to-spm"},{"title":"Overview","sidebarTitle":"Cordova 7 Migration","href":"/docs/jan-2026-migration-guide-cordova-7"},{"title":"[Jan 2026] Migration guide. Capacitor 1.","href":"/docs/jan-2026-migration-guide-capacitor-1"},{"title":"[Nov 2025] Migration guide. iOS 6.0.0","href":"/docs/nov-2025-migration-guide-ios-600"},{"title":"[Sep 2025] Migration guide. React Native 10.","href":"/docs/sep-2025-migration-guide-react-native-10"},{"title":"[July 2025] Migration guide. Google Play Billing Library 8.","href":"/docs/july-2025-migration-guide-google-play-billing-library-8"},{"group":"[Jul 2024] Google Play Billing Library 7","expanded":false,"pages":[{"title":"[Jul 2024] Migration guide. Google Play Billing Library 7.","href":"/docs/jan-2024-migration-guide-google-play-billing-library-6-copy"},{"title":"Android SDK 7.x to 8.x migration guide","href":"/docs/android-8-migration-guide"},{"title":"Flutter SDK 8.x to 9.x migration guide","href":"/docs/flutter-9-migration-guide"},{"title":"React Native SDK 7.x to 8.x migration guide","href":"/docs/react-native-8-migration-guide"},{"title":"Unity SDK 7.x to 8.x migration guide","href":"/docs/unity-8-migration-guide"},{"title":"Cordova SDK 5.x to 6.x migration guide","href":"/docs/cordova-6-migration-guide"}]},{"group":"[Jan 2024] Google Play Billing Library 6","expanded":false,"pages":[{"title":"[Jan 2024] Migration guide. Google Play Billing Library 6.","href":"/docs/qonversion-sdk-major-version-copy"},{"title":"Android SDK 6.x to 7.x migration guide","href":"/docs/android-7-migration-guide"},{"title":"Flutter SDK 7.x to 8.x migration guide","href":"/docs/flutter-8-migration-guide"},{"title":"React Native SDK 6.x to 7.x migration guide","href":"/docs/react-native-7-migration-guide"},{"title":"Unity SDK 6.x to 7.x migration guide","href":"/docs/unity-7-migration-guide"},{"title":"Cordova SDK 4.x to 5.x migration guide","href":"/docs/cordova-5-migration-guide"}]},{"group":"[Aug 2023] Migration Guide","expanded":false,"pages":[{"title":"[Aug 2023] Migration Guide","href":"/docs/qonversion-sdk-major-version"},{"title":"iOS 5.+ migration guide","href":"/docs/ios-5-migration-guide"},{"title":"Android 6.+ migration guide","href":"/docs/android-6-migration-guide"},{"title":"Flutter 7.+ migration guide","href":"/docs/flutter-7-migration-guide"},{"title":"React Native 6.+ migration guide","href":"/docs/react-native-6-migration-guide"},{"title":"Unity 6.+ migration guide","href":"/docs/unity-6-migration-guide"},{"title":"Cordova 4.+ migration guide","href":"/docs/cordova-4-migration-guide"},{"title":"Web 1.+ migration guide","href":"/docs/web-1-migration-guide"}]},{"group":"[Dec 2022] Migration Guide","expanded":false,"pages":[{"title":"[Dec 2022] Migration Guide","href":"/docs/migrate-to-the-actual-qonversion-sdk-version-december-2022"},{"title":"iOS 3.+ migration guide","href":"/docs/ios-3-migration-guide"},{"title":"Android 4.+ migration guide","href":"/docs/android-4-migration-guide"},{"title":"Flutter 5.+ migration guide","href":"/docs/flutter-5-migration-guide"},{"title":"React Native 4.+ migration guide","href":"/docs/react-native-4-migration-guide"},{"title":"Unity 4.+ migration guide","href":"/docs/unity-4-migration-guide"}]}]}]},{"tab":"For agents","icon":"robot","pages":[{"title":"For agents","href":"/docs/for-agents"}]},{"tab":"API reference","icon":"code","pages":[{"title":"API reference","href":"/reference/v4/overview"}]},{"tab":"Changelog","icon":"clock-rotate-left","pages":[{"title":"Changelog","href":"/changelog"}]}]},"title":"How to enable Refund Keeper for the App Store and Google Play - Qonversion","buildId":"dpl_C3fsfi1EcrBns9Vx91gUSN1X3Hi4","deploymentId":"dpl_C3fsfi1EcrBns9Vx91gUSN1X3Hi4","dynamics":["07c022d89b","a74be98ba7"],"chunks":["Frame-D4lgL6Y4.js","DynamicMarkdown-B-Kaxar8.js","zoom-image-lightbox-Evwtz42K.js","PlusIcon-DYlJbUaT.js","lightbox-handle-r17bVUz3.js"]}