Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT
By the end of this guide, your backend will authorize premium features by reading custom_claims.subscription from the attestation JWT — with subscription state flowing in automatically from Apple and/or Stripe, shared across a whole family, and no API key anywhere.
Apple: In App Store Connect, set your App Store Server Notifications v2 production (and sandbox) URL to https://api.grantiva.io/webhooks/apple/app-store-notifications.
Stripe: Add a webhook endpoint in your Stripe dashboard pointing at the per-org path returned by GET /api/v1/org/entitlement-config (stripeWebhookPath), subscribed to checkout.session.completed and customer.subscription.* events. Use that endpoint’s signing secret as signingSecret in step 1.
Create one stable UUID string per family/household in your system. The same value goes to three places:
let familyId = household.grantivaSubjectId // a stable UUID string you persist// a) Tell Grantiva on every member's device (SDK 2.1.0+)grantiva.setSubjectId(familyId)// b) Attach it to Apple purchaseslet result = try await product.purchase(options: [ .appAccountToken(UUID(uuidString: familyId)!)])
Call setSubjectId before validateAttestation() (or any time — the id rides the next attest/refresh). Call clearSubjectId() if the device leaves the household; omitting the id on refresh keeps the existing link.
Apple requires appAccountToken to be a UUID, so the sharing-unit id must be a UUID string.
const claims = await verifyGrantivaJWT(token); // RS256 against Grantiva's JWKSconst sub = claims.custom_claims?.subscription;if (sub?.is_active && sub.environment === "production") { grantAccess(sub.tier); // "plus", etc. — your tier strings} else { grantAccess("free"); // absent claim ⇒ free}
That’s it. When someone in the family subscribes, cancels, or is refunded, Apple/Stripe notify Grantiva, and every family device’s next JWT carries the updated claim.
JWTs refresh within an hour on their own. If you cache authorization state, subscribe to the subscription.changed / subscription.expired / subscription.refundedwebhooks and evict your cache for the delivered subject_id. Treat the webhook as a nudge — the JWT remains the source of truth.
Sandbox purchases flow through with "environment": "sandbox" in the claim. Keep the check from step 4 (environment === "production") in production backends, and relax it in staging.
Claiming purchases made before you had a sharing-unit id
Purchases made before you started sending a sharing-unit id carry no appAccountToken, so webhook ingestion can’t attach them. Have the app present the transaction instead:
for await result in Transaction.currentEntitlements { guard case .verified(let transaction) = result else { continue } // POST { subjectId, signedTransaction } to // https://api.grantiva.io/api/v1/entitlements/apple/claim-transaction try await claimTransaction(subjectId: familyId, jws: result.jwsRepresentation)}
The same call handles “restore purchases” onto a different account or family. See Subscription Claims.
If a claim doesn’t appear, read GET /api/v1/org/entitlement-ingest-events — it lists processed events and every drop Grantiva could attribute to your organization, with the reason.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Grantiva","colors":{"primary":"#0D9373","light":"#14B8A6","dark":"#0F766E"},"logo":{"light":"https://mintcdn.com/grantiva/28yUEStsNJ7W6bTh/logo/light.svg?fit=max\u0026auto=format\u0026n=28yUEStsNJ7W6bTh\u0026q=85\u0026s=eae01fca557fac8bace0e6013fba687e","dark":"https://mintcdn.com/grantiva/28yUEStsNJ7W6bTh/logo/dark.svg?fit=max\u0026auto=format\u0026n=28yUEStsNJ7W6bTh\u0026q=85\u0026s=eff9cf4b2d0249e169d9097ff2cd8ce2"},"favicon":"https://mintcdn.com/grantiva/5pA1C2NemWT_0-V1/favicon.ico?fit=max\u0026auto=format\u0026n=5pA1C2NemWT_0-V1\u0026q=85\u0026s=6179ff3876d340dbbbc59f55625081e6","navbar":{"links":[{"href":"mailto:support@grantiva.io","label":"Support"}],"primary":{"type":"button","label":"Get Started","href":"https://grantiva.io/get-started"}},"footer":{"socials":{"github":"https://github.com/grantiva"}},"contextual":{"options":["copy","view","claude","cursor"],"display":"header"},"styling":{"latex":false},"navigation":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/grantiva"},{"anchor":"Dashboard","icon":"chart-line","href":"https://grantiva.io/dashboard"},{"anchor":"Status","icon":"signal","href":"https://grantiva-services.instatus.com"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"grantiva","hasAudioNarration":false,"actualSubdomain":"grantiva","customDomains":["docs.grantiva.io"],"gitSource":{"type":"github","owner":"grantiva","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":false,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6aa172c396b31dab3ab9d3ea","collectionId":"7b2bedaf-285e-4a6a-b269-61d6da31b886","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6aa172c396b31dab3ab9d3ea"},"feedback":{"thumbs":true,"edits":true,"issues":true},"entitlements":{},"buildId":"6aa172c396b31dab3ab9d3ea","clientVersion":"0.0.4044","searchFilterCounts":[{"language":"default","tag":"Documentation","count":47},{"language":"default","tag":"API Reference","count":46},{"language":"default","tag":"CLI","count":13},{"language":"default","tag":"SDKs","count":9},{"language":"default","tag":"Concepts","count":8},{"language":"default","tag":"Dashboard","count":8},{"language":"default","tag":"Getting Started","count":8},{"language":"default","tag":"Console","count":7},{"language":"default","tag":"Feature Flags","count":6},{"language":"default","tag":"Organization","count":6}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"quickstart-subscription-claims","slug":"/quickstart-subscription-claims","pageMetadata":{"title":"Subscription Claims Quick Start","description":"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT","href":"/quickstart-subscription-claims"},"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: \"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT\"\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`,li:`li`,p:`p`,pre:`pre`,span:`span`,strong:`strong`,ul:`ul`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsxs(_components.p,{children:[`By the end of this guide, your backend will authorize premium features by reading `,_jsx(_components.code,{children:`custom_claims.subscription`}),` from the attestation JWT — with subscription state flowing in automatically from Apple and/or Stripe, shared across a whole family, and no API key anywhere.`]}),`\n`,_jsx(Heading,{level:`2`,id:`prerequisites`,children:`Prerequisites`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[`Grantiva SDK `,_jsx(_components.strong,{children:`2.1.0+`}),` installed and attestation working (`,_jsx(_components.a,{href:`/quickstart`,children:`Quick Start`}),`)`]}),`\n`,_jsxs(_components.li,{children:[`The `,_jsx(_components.strong,{children:`Admin`}),` role in your Grantiva organization — entitlement ingestion itself is available on every plan`]}),`\n`,_jsx(_components.li,{children:`An Apple app with In-App Purchases and/or a Stripe account selling subscriptions`}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`1-map-your-products-to-tiers`,children:`1. Map your products to tiers`}),`\n`,_jsxs(_components.p,{children:[`Configure ingestion once via `,_jsx(_components.code,{children:`PUT /api/v1/org/entitlement-config`}),` (dashboard session, admin role):`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`16`,language:`json`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`json`,children:_jsxs(_components.code,{language:`json`,numberOfLines:`16`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`{`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"enabled\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`true`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"apple\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"bundleId\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"com.example.app\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"products\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"com.example.plus.monthly\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"tier\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"plus\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"interval\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"monthly\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"com.example.plus.annual\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"tier\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"plus\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"interval\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"annual\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"stripe\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"signingSecret\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"whsec_...\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"prices\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:` \"price_1AbCdE\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: { `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"tier\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"plus\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#116329`,\"--shiki-dark\":`#9CDCFE`},children:`\"interval\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"monthly\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`tier`}),` values are yours — Grantiva passes them through to the claim verbatim. See the `,_jsx(_components.a,{href:`/api-reference/entitlements/config`,children:`config API reference`}),` for details.`]}),`\n`,_jsx(Heading,{level:`2`,id:`2-point-apple-and-stripe-at-grantiva`,children:`2. Point Apple and Stripe at Grantiva`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Apple`}),`: In App Store Connect, set your `,_jsx(_components.strong,{children:`App Store Server Notifications v2`}),` production (and sandbox) URL to `,_jsx(_components.code,{children:`https://api.grantiva.io/webhooks/apple/app-store-notifications`}),`.`]}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.strong,{children:`Stripe`}),`: Add a webhook endpoint in your Stripe dashboard pointing at the per-org path returned by `,_jsx(_components.code,{children:`GET /api/v1/org/entitlement-config`}),` (`,_jsx(_components.code,{children:`stripeWebhookPath`}),`), subscribed to `,_jsx(_components.code,{children:`checkout.session.completed`}),` and `,_jsx(_components.code,{children:`customer.subscription.*`}),` events. Use that endpoint’s signing secret as `,_jsx(_components.code,{children:`signingSecret`}),` in step 1.`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`3-mint-a-sharing-unit-id-and-use-it-everywhere`,children:`3. Mint a sharing-unit id and use it everywhere`}),`\n`,_jsxs(_components.p,{children:[`Create one stable `,_jsx(_components.strong,{children:`UUID string`}),` per family/household in your system. The same value goes to three places:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`9`,language:`swift`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`swift`,children:_jsxs(_components.code,{language:`swift`,numberOfLines:`9`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` familyId `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` household.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`grantivaSubjectId`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // a stable UUID string you persist`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// a) Tell Grantiva on every member's device (SDK 2.1.0+)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`grantiva.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`setSubjectId`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(familyId)`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// b) Attach it to Apple purchases`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` try`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` product.`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`purchase`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`options`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`appAccountToken`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`UUID`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`uuidString`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: familyId)`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`!`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`])`})}),`\n`]})})}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`8`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// c) Attach it to Stripe Checkout (web payers)`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` session`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` stripe`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`checkout`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`sessions`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:`create`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`({`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` mode:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"subscription\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` client_reference_id:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` familyId`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`,`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` line_items:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [{ `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`price:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"price_1AbCdE\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`quantity:`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#B5CEA8`},children:` 1`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }],`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` metadata:`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`grantiva_price_id:`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"price_1AbCdE\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` },`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // ...`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`});`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`Call `,_jsx(_components.code,{children:`setSubjectId`}),` before `,_jsx(_components.code,{children:`validateAttestation()`}),` (or any time — the id rides the next attest/refresh). Call `,_jsx(_components.code,{children:`clearSubjectId()`}),` if the device leaves the household; omitting the id on refresh keeps the existing link.`]}),`\n`,_jsxs(Warning,{children:[`Apple requires `,_jsx(_components.code,{children:`appAccountToken`}),` to be a UUID, so the sharing-unit id must be a UUID string.`]}),`\n`,_jsx(Heading,{level:`2`,id:`4-gate-features-on-your-backend`,children:`4. Gate features on your backend`}),`\n`,_jsxs(_components.p,{children:[`Verify the JWT as usual (`,_jsx(_components.a,{href:`/backend-verification`,children:`Backend JWT Verification`}),`) and read the claim:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`8`,language:`javascript`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`javascript`,children:_jsxs(_components.code,{language:`javascript`,numberOfLines:`8`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` claims`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` verifyGrantivaJWT`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`token`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// RS256 against Grantiva's JWKS`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`const`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4FC1FF`},children:` sub`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` =`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` claims`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`custom_claims`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`?.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`subscription`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`;`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` (`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`sub`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`?.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`is_active`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` \u0026\u0026`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:` sub`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`environment`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:` ===`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:` \"production\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`) {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` grantAccess`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`sub`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`tier`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// \"plus\", etc. — your tier strings`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`} `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`else`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` grantAccess`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"free\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`); `}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:`// absent claim ⇒ free`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsx(_components.p,{children:`That’s it. When someone in the family subscribes, cancels, or is refunded, Apple/Stripe notify Grantiva, and every family device’s next JWT carries the updated claim.`}),`\n`,_jsx(Heading,{level:`2`,id:`5-optional-instant-invalidation`,children:`5. Optional: instant invalidation`}),`\n`,_jsxs(_components.p,{children:[`JWTs refresh within an hour on their own. If you cache authorization state, subscribe to the `,_jsx(_components.code,{children:`subscription.changed`}),` / `,_jsx(_components.code,{children:`subscription.expired`}),` / `,_jsx(_components.code,{children:`subscription.refunded`}),` `,_jsx(_components.a,{href:`/concepts/webhooks#subscription-events`,children:`webhooks`}),` and evict your cache for the delivered `,_jsx(_components.code,{children:`subject_id`}),`. Treat the webhook as a nudge — the JWT remains the source of truth.`]}),`\n`,_jsx(Heading,{level:`2`,id:`sandbox-testing`,children:`Sandbox testing`}),`\n`,_jsxs(_components.p,{children:[`Sandbox purchases flow through with `,_jsx(_components.code,{children:`\"environment\": \"sandbox\"`}),` in the claim. Keep the check from step 4 (`,_jsx(_components.code,{children:`environment === \"production\"`}),`) in production backends, and relax it in staging.`]}),`\n`,_jsx(Heading,{level:`2`,id:`claiming-purchases-made-before-you-had-a-sharing-unit-id`,children:`Claiming purchases made before you had a sharing-unit id`}),`\n`,_jsxs(_components.p,{children:[`Purchases made before you started sending a sharing-unit id carry no `,_jsx(_components.code,{children:`appAccountToken`}),`, so webhook ingestion can’t attach them. Have the app present the transaction instead:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`swift`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`swift`,children:_jsxs(_components.code,{language:`swift`,numberOfLines:`6`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` Transaction.currentEntitlements {`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` guard`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` case`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` .`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`verified`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`let`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` transaction) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` result `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`else`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` { `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`continue`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` }`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // POST { subjectId, signedTransaction } to`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` // https://api.grantiva.io/api/v1/entitlements/apple/claim-transaction`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` try`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` await`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` claimTransaction`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`subjectId`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: familyId, `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:`jws`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: result.`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`jwsRepresentation`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`}`})}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[`The same call handles “restore purchases” onto a different account or family. See `,_jsx(_components.a,{href:`/concepts/subscription-claims#claiming-a-past-purchase`,children:`Subscription Claims`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`troubleshooting`,children:`Troubleshooting`}),`\n`,_jsxs(_components.p,{children:[`If a claim doesn’t appear, read `,_jsx(_components.code,{children:`GET /api/v1/org/entitlement-ingest-events`}),` — it lists processed events and every drop Grantiva could attribute to your organization, with the reason.`]}),`\n`,_jsx(Heading,{level:`2`,id:`next-steps`,children:`Next steps`}),`\n`,_jsxs(_components.ul,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/concepts/subscription-claims`,children:`Subscription Claims concepts`}),` — claim shape, multi-entitlement resolution, reserved key rules`]}),`\n`,_jsx(_components.li,{children:_jsx(_components.a,{href:`/api-reference/entitlements/config`,children:`Entitlement config API`})}),`\n`,_jsxs(_components.li,{children:[_jsx(_components.a,{href:`/api-reference/entitlements/apple-notifications`,children:`Apple notifications endpoint`}),` · `,_jsx(_components.a,{href:`/api-reference/entitlements/stripe-webhook`,children:`Stripe webhook endpoint`})]}),`\n`]})]})}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":{"config":{},"pageMetadata":{"title":"Subscription Claims Quick Start","description":"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT","href":"/quickstart-subscription-claims"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Prerequisites","slug":"prerequisites","depth":2,"children":[]},{"title":"1. Map your products to tiers","slug":"1-map-your-products-to-tiers","depth":2,"children":[]},{"title":"2. Point Apple and Stripe at Grantiva","slug":"2-point-apple-and-stripe-at-grantiva","depth":2,"children":[]},{"title":"3. Mint a sharing-unit id and use it everywhere","slug":"3-mint-a-sharing-unit-id-and-use-it-everywhere","depth":2,"children":[]},{"title":"4. Gate features on your backend","slug":"4-gate-features-on-your-backend","depth":2,"children":[]},{"title":"5. Optional: instant invalidation","slug":"5-optional-instant-invalidation","depth":2,"children":[]},{"title":"Sandbox testing","slug":"sandbox-testing","depth":2,"children":[]},{"title":"Claiming purchases made before you had a sharing-unit id","slug":"claiming-purchases-made-before-you-had-a-sharing-unit-id","depth":2,"children":[]},{"title":"Troubleshooting","slug":"troubleshooting","depth":2,"children":[]},{"title":"Next steps","slug":"next-steps","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"grantiva","siteName":"Grantiva","title":"Subscription Claims Quick Start - Grantiva","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-02T17:06:37.357Z","originalFileLocation":"quickstart-subscription-claims.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=\"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT\">\u003cmeta data-mint-head name=\"application-name\" content=\"Grantiva\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_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/grantiva/mV1kXh7vilTKFaGS/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Subscription Claims Quick Start - Grantiva\">\u003cmeta data-mint-head property=\"og:description\" content=\"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Grantiva\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.grantiva.io/quickstart-subscription-claims\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://grantiva.mintlify.app/_mintlify/api/og/v2?division=Getting+Started\u0026amp;title=Subscription+Claims+Quick+Start\u0026amp;description=Gate+backend+features+on+Apple+IAP+or+Stripe+subscription+state+using+only+the+attestation+JWT\u0026amp;theme=ba1821250ed20c14294f1caa\u0026amp;signature=0000a7eca0f4db389c856684f2cef8751480e9ccd2fdbc6146a394b806bfad63\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Subscription Claims Quick Start - Grantiva\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://grantiva.mintlify.app/_mintlify/api/og/v2?division=Getting+Started\u0026amp;title=Subscription+Claims+Quick+Start\u0026amp;description=Gate+backend+features+on+Apple+IAP+or+Stripe+subscription+state+using+only+the+attestation+JWT\u0026amp;theme=ba1821250ed20c14294f1caa\u0026amp;signature=0000a7eca0f4db389c856684f2cef8751480e9ccd2fdbc6146a394b806bfad63\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/grantiva/mV1kXh7vilTKFaGS/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Grantiva\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0D9373\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.grantiva.io/quickstart-subscription-claims\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/quickstart-subscription-claims.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.grantiva.io/#organization\",\"name\":\"Grantiva\",\"url\":\"https://docs.grantiva.io\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/grantiva/28yUEStsNJ7W6bTh/logo/light.svg?fit=max\u0026auto=format\u0026n=28yUEStsNJ7W6bTh\u0026q=85\u0026s=eae01fca557fac8bace0e6013fba687e\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.grantiva.io#website\",\"name\":\"Grantiva\",\"url\":\"https://docs.grantiva.io\",\"publisher\":{\"@id\":\"https://docs.grantiva.io/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.grantiva.io/quickstart-subscription-claims#webpage\",\"url\":\"https://docs.grantiva.io/quickstart-subscription-claims\",\"name\":\"Subscription Claims Quick Start\",\"description\":\"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT\",\"dateModified\":\"2026-09-02T17:06:37.357Z\",\"isPartOf\":{\"@id\":\"https://docs.grantiva.io#website\"},\"breadcrumb\":{\"@id\":\"https://docs.grantiva.io/quickstart-subscription-claims#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.grantiva.io/quickstart-subscription-claims#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Getting Started\",\"item\":\"https://docs.grantiva.io/index\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Subscription Claims Quick Start\",\"item\":\"https://docs.grantiva.io/quickstart-subscription-claims\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.grantiva.io/quickstart-subscription-claims#article\",\"headline\":\"Subscription Claims Quick Start\",\"name\":\"Subscription Claims Quick Start\",\"description\":\"Gate backend features on Apple IAP or Stripe subscription state using only the attestation JWT\",\"url\":\"https://docs.grantiva.io/quickstart-subscription-claims\",\"mainEntityOfPage\":{\"@id\":\"https://docs.grantiva.io/quickstart-subscription-claims#webpage\"},\"dateModified\":\"2026-09-02T17:06:37.357Z\",\"publisher\":{\"@id\":\"https://docs.grantiva.io/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.grantiva.io#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Grantiva\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Grantiva","nav":{"global":{"anchors":[{"anchor":"GitHub","icon":"github","href":"https://github.com/grantiva"},{"anchor":"Dashboard","icon":"chart-line","href":"https://grantiva.io/dashboard"},{"anchor":"Status","icon":"signal","href":"https://grantiva-services.instatus.com"}]},"tabs":[{"tab":"Documentation","groups":[{"group":"Getting Started","pages":[{"title":"Introduction","href":""},{"title":"Quick Start","href":"/quickstart"},{"title":"Simulator Setup","href":"/simulator-setup"},{"title":"Feedback Quick Start","href":"/quickstart-feedback"},{"title":"Feature Flags Quick Start","href":"/quickstart-flags"},{"title":"VRT Quick Start","href":"/quickstart-vrt"},{"title":"Webhooks Quick Start","description":"Receive real-time notifications for device attestation events","href":"/quickstart-webhooks"},{"title":"Subscription Claims Quick Start","href":"/quickstart-subscription-claims"}]},{"group":"SDKs","pages":[{"title":"Installation","description":"Add the Grantiva SDK to your iOS or macOS project","href":"/sdk/installation"},{"title":"Attestation","href":"/sdk/attestation"},{"title":"Testing Your Integration","href":"/sdk/testing"},{"title":"User Identity","href":"/sdk/user-identity"},{"title":"Feedback","href":"/sdk/feedback"},{"title":"Feature Flags","href":"/sdk/feature-flags"},{"title":"Error Handling","href":"/sdk/error-handling"},{"title":"GrantivaUI","href":"/sdk/grantiva-ui"},{"title":"Android SDK","href":"/sdk/android"}]},{"group":"CLI","pages":[{"title":"Installation","href":"/cli/installation"},{"title":"Configuration","href":"/cli/configuration"},{"title":"Commands","href":"/cli/commands"},{"title":"Simulator management","href":"/cli/simulators"},{"group":"Console","pages":[{"title":"Console commands","href":"/cli/console"},{"title":"Console: feature flags","href":"/cli/console-flags"},{"title":"Console: apps, claims, and devices","href":"/cli/console-apps"},{"title":"Console: analytics","href":"/cli/console-analytics"},{"title":"Console: VRT review and release notes","href":"/cli/console-vrt"},{"title":"Console: feedback and support","href":"/cli/console-feedback"},{"title":"Console: organization","href":"/cli/console-org"}]},{"title":"MCP Server","href":"/cli/mcp"},{"title":"CI integration","href":"/cli/ci-integration"}]},{"group":"Concepts","pages":[{"title":"Device Attestation","href":"/concepts/attestation"},{"title":"Risk Scoring","href":"/concepts/risk-scoring"},{"title":"JWT Claims","href":"/concepts/jwt-claims"},{"title":"Custom Claims","href":"/concepts/custom-claims"},{"title":"Subscription Claims","href":"/concepts/subscription-claims"},{"title":"Webhooks","href":"/concepts/webhooks"},{"title":"Security","href":"/concepts/security"},{"title":"Visual Regression Testing","href":"/concepts/vrt"}]},{"group":"Push","pages":[{"title":"Push Notifications","href":"/push/overview"}]},{"group":"Dashboard","pages":[{"title":"Dashboard Overview","href":"/dashboard/overview"},{"title":"Attestation analytics","href":"/dashboard/analytics"},{"title":"Devices","href":"/dashboard/devices"},{"title":"Feature flags in the dashboard","href":"/dashboard/feature-flags"},{"title":"Feedback and support","href":"/dashboard/feedback"},{"title":"Billing \u0026 Plans","href":"/dashboard/billing"},{"title":"Team Management","href":"/dashboard/team-management"},{"title":"Settings, keys, and audit log","href":"/dashboard/settings"}]}]},{"tab":"API Reference","pages":[{"title":"API Reference","href":"/api-reference/introduction"}]}]},"basePath":"","title":"Subscription Claims Quick Start - Grantiva","buildId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","deploymentId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","dynamics":[],"chunks":[]}