Decision · SHOT mobile · Apple resubmit
Three ways to keep B2B grant codes after Apple 3.1.1
The situation
Apple rejected v1.0.155 under 3.1.1 because SHOT lets users redeem
membership codes in-app to unlock paid features. The B2B model — clubs
sign real-world contracts, SHOT mints codes, clubs distribute them — is
non-negotiable. What are the actual options, and which one preserves
the contract economics?
Rejection guideline
3.1.1 — in-app promo codes unlock paid features outside Apple's billing
B2C path today
Apple IAP, Google IAP, Stripe web — kept as-is
B2B path today
Club signs contract → SHOT mints code → club distributes → member redeems
What Apple really wants
No iOS UI that grants paid access outside their billing — not "kill your codes"
Apple-sanctioned — zero 3.1.1 risk
150k codes per app per quarter (hard cap)
Apple takes 0% on 100%-off redemptions
Code format is Apple-generated 16-char alphanumeric — ugly to share
Native iOS redemption UX
One code = one user. No multi-use "CLUB-XYZ-2026" model
No web detour for iOS users
Tied to a subscription IAP — renewal semantics, not durable grants
Works without any code on your backend
iOS-only. Android + web users need a different path anyway
—
Designed for marketing promos, not B2B contracts. No bulk-revoke for churned partner
Apple risk: zero
B2B fit: poor
Cap: 150k/quarter
Cross-platform: iOS only
Code lifecycle: Apple-owned
Already built — schema, admin UI, RPC, redemption logic all exist
User makes one web trip to redeem
Multi-use codes match B2B reality (1 code, N seats)
No iOS-native "enter code" UX
SHOT controls full lifecycle — mint, revoke, extend, audit
Codes are SHOT-format strings, not Apple-blessed
Same flow works on web / iOS / Android — one truth source
—
B2B economics intact: bill club out-of-band, no Apple cut
—
Fix ships as a one-PR iOS-surface gate (1 day)
—
Apple risk: zero
B2B fit: strong
Cap: none
Cross-platform: web + iOS + Android
Code lifecycle: SHOT-owned
Apple-sanctioned enterprise channel
Wrong shape — VPP is for "company buys app for employees", not "club hands free passes to members"
Volume discount on bulk purchases
Club must pay Apple via Business Manager — kills your "bill outside Apple" B2B economics
Centralized seat management for the buyer
Apple still takes their cut on the bulk purchase
Apple owns invoicing for the buyer
Members may need Business-Manager-enrolled Apple IDs (or accept friction)
—
iOS-only. Android/web users still need a different B2B path
—
Heavy onboarding: DUNS, Business Manager enrollment, VPP agreement, payment instrument per club
Apple risk: zero
B2B fit: enterprise-shaped
Cap: none
Cross-platform: iOS only
Setup cost: high (weeks)
Dimension
01 · Apple Offer Codes
02 · Web-only redemption
03 · VPP
Solves Apple 3.1.1
Yes
Yes
Yes
Keep B2B contract economics(bill club outside Apple)
Partial — Apple controls codes but no rev cut on free
Yes — full control, no Apple involvement
No — Apple owns the transaction
Multi-use bulk codes(one CLUB-XYZ for 50 members)
No — one code per user
Yes — max_redemptions=N
No — one license per member
Cross-platform parity(web / iOS / Android)
iOS only
All three
iOS only (+ Android via separate VPP-equivalent)
Code lifecycle control(extend, revoke, audit)
Apple-mediated
SHOT-owned, in your DB
Apple Business Manager
Quarterly issuance cap
150,000
Unlimited
Unlimited
Eng cost to ship
~1 week (offer code IAP, RC mapping, UI)
~1 day (iOS gate + /redeem route)
Weeks (DUNS, Business Manager, payment routing)
Fits "UN grant / charity partnership" use case
Awkward — feels like marketing promo
Native — durable, club-named codes
No — VPP is enterprise procurement
Recommendation
Ship Approach 02 — web-only redemption . The membership-code
infrastructure already exists: membership_codes table, admin UI,
redemption RPC, RC webhook integration. Apple's rejection is about the iOS
UI surface , not the codes themselves. Hide the redeem and guest-pass
buttons on isNativePlatform, extract /redeem into
a standalone web route, and the rejection is gone in one PR.
Why not Offer Codes for B2B grants:
One code = one user. Your model is one club code = many member redemptions.
Apple sized them for marketing campaigns (150k/quarter cap, single-use semantics).
Lifecycle is Apple's — you can't revoke a churned club partner from your dashboard.
iOS-only. You'd still need a parallel system for Android and web users.
Tied to a subscription IAP — long-term grant semantics are awkward.
Why not VPP: It's an enterprise procurement channel — clubs would
have to pay Apple directly through Apple Business Manager, killing the "we bill the
club outside Apple" contract economics that make grants viable.
Where Offer Codes do shine: Keep them in your back pocket for
consumer promos that genuinely need an Apple-native flow — "50% off the first
month" growth experiments, App Store Connect press codes, holiday discounts. Wrong
tool for B2B partnerships, right tool for individual promotional discounts.
Concrete next step: One PR gating PaywallOptions.tsx:360
on !isNativePlatform, plus a standalone /redeem route. Notes
to Reviewer: "Membership codes redeemed on shotclubhouse.com/redeem; iOS app reads
entitlement from server, no in-app code redemption."