Use this page with AI
Copy this into your coding assistant and add your request.
Read https://openiap.dev/docs/setup/godot and https://openiap.dev/llms.txt. Follow the reading instructions, detailed reference, and linked guides relevant to my task before making changes.
Inspect my existing project and reuse its framework and conventions. Ask me for missing product decisions. Implement the requested behavior and run the applicable checks.
Show the working result, the commands and actual test results, and any remaining limitations. Keep your explanation brief.
My request: [describe what customers should be able to do]Godot Setup
godot-iap is a Godot 4.x plugin for in-app purchases following the OpenIAP Client Protocol. It uses Swift GDExtension for iOS and Kotlin AAR for Android.
Prerequisites#
- Godot 4.3 or higher
- iOS: Xcode 16+ (Swift 6.0+) with iOS 17+ target
- Android: Android SDK with API level 24+
Installation#
Download from Releases (Recommended)#
- Download the latest
godot-iap-{version}.zipfrom GitHub Releases - Extract and copy
addons/godot-iap/to your project'saddons/folder - Enable the plugin in Project > Project Settings > Plugins
The zip includes pre-built binaries for both iOS and Android.
Required Folder Structure#
Copy the whole addons/godot-iap/ folder. Copying only the GDScript files leaves Android without its plugin, and the editor then reports GodotIap singleton not found at runtime.
your-project/
└── addons/
└── godot-iap/
├── android/ <- Android plugin, required for Android
│ ├── GodotIap.gdap <- registers the export checkbox
│ ├── GodotIap.release.aar
│ └── GodotIap.debug.aar
├── bin/ <- iOS plugin, required for iOS
│ ├── godot_iap.gdextension
│ └── ios/
│ ├── GodotIap.framework/
│ └── SwiftGodotRuntime.framework/
├── scripts/
│ └── fix_ios_embed.sh
├── godot_iap.gd
├── godot_iap_plugin.gd
├── types.gd
├── plugin.cfg
├── LICENSE
└── THIRD_PARTY_NOTICES.mdA bin/macos/ folder appears only in releases built with notarized macOS binaries. Everything else above ships in every zip.
Build from Source#
If you need to build from source:
git clone https://github.com/hyodotdev/openiap.git
cd openiap/libraries/godot-iap
# Build for iOS
make ios
# Build for Android
make android
# Copy addons/godot-iap/ to your projectThe checked-in macOS runtime frameworks are Apple Silicon (arm64) only. Custom source builds can override MACOS_ARCHS; make macos requests arm64 x86_64 by default, and generated metadata should only include architectures that the framework binaries actually contain.
iOS Framework Toolchain (Offer Codes)#
The pre-built iOS framework locks in Apple API availability at compile time. One feature depends on this: offer code redemption only returns a verified result when the framework was built with Xcode 27 or later and runs on iOS 27, Mac Catalyst 27, or visionOS 27 or later. Older runtimes still use the non-result system-sheet path even when the framework was built with Xcode 27. A framework built with Xcode 26 also uses that older path, including on Apple 27 devices. The published godot-iap 3.0.0 framework is built with Xcode 27. If you build from source and use offer codes, build with Xcode 27 or later; the runtime requirement remains separate.
macOS: Damaged Framework Warning#
The default release zip does not include macOS runtime frameworks, so most projects can skip this section. It applies only if you build from source with macOS support or use a release or custom zip containing addons/godot-iap/bin/macos. If Godot reports that GodotIap.framework or SwiftGodotRuntime.framework is damaged, clear quarantine and repair the ad-hoc signature:
# Run from your Godot project root after copying addons/godot-iap
xattr -dr com.apple.quarantine addons/godot-iap
codesign --force --deep --sign - --timestamp=none addons/godot-iap/bin/macos/SwiftGodotRuntime.framework
codesign --force --deep --sign - --timestamp=none addons/godot-iap/bin/macos/GodotIap.frameworkPlatform Setup#
Godot Export Presets#
For both iOS and Android, enable the plugin in your export presets:
- Project > Export > Add > iOS (or Android)
- Configure your export settings (Bundle Identifier, Team ID, etc.)
- Enable GodotIap in the Plugins section
On Android the checkbox comes from addons/godot-iap/android/GodotIap.gdap. Godot scans that folder when the project loads, so if the file is missing the Plugins section stays empty and no amount of export configuration will add it.
iOS: Xcode Framework Embedding#
The GodotIap export plugin registers the iOS frameworks during export so they are added to Xcode's Embed Frameworks build phase automatically. Before exporting, make sure GodotIap is enabled in the iOS export preset's Plugins section.
If you exported with an older plugin version, or if Xcode still shows the frameworks as file references instead of framework bundles, run the post-export fixer from your Godot project root:
IOS_EXPORT_DIR=/path/to/ios-export \
./addons/godot-iap/scripts/fix_ios_embed.shThe script finds the exported .xcodeproj, embeds:
GodotIap.frameworkSwiftGodotRuntime.framework
It also converts framework file references to framework bundles and restores any missing framework Info.plist files.
Manual Xcode fallback
- Open the exported
.xcodeprojin Xcode - Select your target > General tab
- Scroll to Frameworks, Libraries, and Embedded Content
- Click + and add:
GodotIap.frameworkSwiftGodotRuntime.framework
- Set both to "Embed & Sign"
The frameworks are located at:
[exported_project]/addons/godot-iap/bin/ios/GodotIap.framework
[exported_project]/addons/godot-iap/bin/ios/SwiftGodotRuntime.frameworkThen confirm the runpath:
- Go to the Build Settings tab
- Search for "Runpath Search Paths" (
LD_RUNPATH_SEARCH_PATHS) - Add
@executable_path/Frameworksif not already present
iOS: Missing Info.plist Fallback#
Due to a Godot export bug, some exports may omit Info.plist files inside embedded frameworks. The fix_ios_embed.sh script above copies the missing files automatically.
If you still need an Xcode build phase fallback:
- Select your target > Build Phases tab
- Click + > New Run Script Phase
- Name it "Copy Framework Info.plist"
- Paste the following script:
# Copy missing Info.plist files for GodotIap frameworks
ADDONS_DIR="${PROJECT_DIR}"
FRAMEWORKS_DIR="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -f "${ADDONS_DIR}/addons/godot-iap/bin/ios/GodotIap.framework/Info.plist" ]; then
cp "${ADDONS_DIR}/addons/godot-iap/bin/ios/GodotIap.framework/Info.plist" \
"${FRAMEWORKS_DIR}/GodotIap.framework/" 2>/dev/null || true
fi
if [ -f "${ADDONS_DIR}/addons/godot-iap/bin/ios/SwiftGodotRuntime.framework/Info.plist" ]; then
cp "${ADDONS_DIR}/addons/godot-iap/bin/ios/SwiftGodotRuntime.framework/Info.plist" \
"${FRAMEWORKS_DIR}/SwiftGodotRuntime.framework/" 2>/dev/null || true
fi- Drag this script phase before the "Embed Frameworks" phase
Prefer the post-export fixer when possible; the build phase is only a fallback for projects that cannot run the script after export.
Scene Setup#
The recommended way to use GodotIap is to add GodotIapWrapper as a child node:
- Open your main scene (or create an autoload scene for IAP management)
- Add a new node: Add Child Node > Node
- Attach the GodotIapWrapper script: Load > addons/godot-iap/godot_iap.gd
- Name it
GodotIapWrapper - Reference it in your script using
@onready var iap = $GodotIapWrapper
Or create the wrapper node programmatically:
extends Node
const Types = preload("res://addons/godot-iap/types.gd")
var iap
func _ready():
# Create wrapper node dynamically
var wrapper = preload("res://addons/godot-iap/godot_iap.gd").new()
wrapper.name = "GodotIapWrapper"
add_child(wrapper)
iap = wrapper
# Now use iap as normal
iap.connected.connect(_on_connected)
iap.init_connection()Verify Installation#
With the GodotIapWrapper node from Scene Setup in place, attach this script to confirm the plugin loads and the store connects:
extends Node
const Types = preload("res://addons/godot-iap/types.gd")
@onready var iap = $GodotIapWrapper
func _ready():
print("Godot IAP is available!")
# Connect signals
iap.connected.connect(_on_connected)
iap.purchase_updated.connect(_on_purchase_updated)
iap.purchase_error.connect(_on_purchase_error)
# Initialize connection
var success = await iap.init_connection()
print("Init result: ", success)
func _on_connected():
print("Store connected!")
func _on_purchase_updated(purchase: Dictionary):
print("Purchase: %s" % purchase.get("product_id", ""))
func _on_purchase_error(error: Dictionary):
print("Error: ", error)Usage#
The typical flow is init_connection → connect the purchase_updated and purchase_error signals → fetch_products → request_purchase → finish_transaction. See the Purchase Guide for the complete flow.
The examples below use the iap reference created in Scene Setup (@onready var iap = $GodotIapWrapper).
GDScript uses snake_case for all function names (init_connection, fetch_products, request_purchase). Return types use Array for lists and Variant for platform-specific single results.
Signal-Based Architecture#
Godot IAP uses signals for purchase events, following Godot's native event pattern:
const Types = preload("res://addons/godot-iap/types.gd")
func _ready():
# Connect signals
iap.purchase_updated.connect(_on_purchase_updated)
iap.purchase_error.connect(_on_purchase_error)
# Initialize
if not await iap.init_connection():
push_error("Store connection failed")
return
func _on_purchase_updated(purchase):
# Validate receipt with your backend or IAPKit, then:
# (second argument: true only for consumable products)
await iap.finish_transaction(purchase, false)
print("Purchased: ", purchase.product_id)
func _on_purchase_error(error):
print("Error: ", error.code, " - ", error.message)Each call here has a full reference — see the purchase_updated and purchase_error signals, init_connection, and finish_transaction for parameters and per-store behavior, and Error Codes for the error.code values.
Fetching Products#
Query store metadata with a ProductRequest; results are platform-typed (ProductAndroid on Android, ProductIOS on iOS):
func _load_products():
var request = Types.ProductRequest.new()
request.skus = ["premium", "coins_100"]
request.type = Types.ProductQueryType.InApp
var products: Array = await iap.fetch_products(request)
for product in products:
# On Android: Types.ProductAndroid
# On iOS: Types.ProductIOS
print(product.id, " - ", product.display_price)See fetch_products for parameters and per-store behavior.
Making a Purchase#
Configure both platforms in a single request — the plugin picks the branch matching the store the game is running on, so one purchase call works everywhere:
func _purchase(sku: String):
var platforms = Types.RequestPurchasePropsByPlatforms.new()
platforms.apple = Types.RequestPurchaseIosProps.new()
platforms.apple.sku = sku
platforms.google = Types.RequestPurchaseAndroidProps.new()
var skus: Array[String] = [sku]
platforms.google.skus = skus
var props = Types.RequestPurchaseProps.in_app(platforms)
# Returns Variant (PurchaseAndroid or PurchaseIOS, or null)
var purchase = await iap.request_purchase(props)See request_purchase for parameters and per-store behavior.
Troubleshooting#
Products not found#
- Ensure all agreements are signed in App Store Connect / Google Play Console
- Verify banking, legal, and tax information is complete and approved
- Check that bundle ID / package name matches exactly
- Products must be in "Ready to Submit" status (Apple) or "Active" (Google)
- Wait 15-30 minutes after creating products before testing
GodotIap singleton not found (Android)#
The GDScript loaded but the Android plugin did not. Check addons/godot-iap/android/ for the .gdap file and both AARs, confirm GodotIap is checked in the Android export preset, and confirm the build used Gradle. Re-extract the release zip over addons/godot-iap/ when a file is missing — see Required Folder Structure.
GodotIap is missing from the export Plugins list#
The GodotIap.gdap file is absent or sits outside addons/godot-iap/android/. Put it back and restart the Godot editor; the plugin list is built when the project loads, not when the export dialog opens.
Android Gradle build fails resolving dependencies#
The .gdap file declares remote dependencies, so the Gradle build resolves them over the network. Read the coordinate the build failed on before assuming the plugin is at fault. The OpenIAP Android library pulls androidx artifacts, which are served by Google's Maven repository rather than Maven Central, so a generated Gradle configuration that lists only Maven Central cannot resolve them. If the repositories are right and resolution still fails, check that the Godot version's bundled Android Gradle Plugin supports the resolved androidx versions, and pin the conflicting dependency in your own Gradle configuration.
App crashes on launch (iOS)#
A crash with Library not loaded: @rpath/GodotIap.framework/GodotIap means the frameworks were not embedded — see iOS: Xcode Framework Embedding and run fix_ios_embed.sh.
GDExtension errors in the desktop editor#
The current release zip ships an iOS-only GDExtension, so on Godot 4.8-dev3 and older the editor on every desktop — Windows, Linux, and macOS alike — logs No GDExtension library found for current OS and architecture each time the project is scanned. The messages stop nothing: Android loads the AAR plugin from addons/godot-iap/android/, and iOS exports still embed and load the frameworks.
The zip's .gdextension declares include_tags = ["ios"] so Godot can skip it silently. Engine support for that filter (godotengine/godot#121575) first shipped in 4.8-dev4; on 4.8-dev3 and older — including 4.3 through 4.7 — the messages cannot be suppressed (godotengine/godot#105615). To silence them while you are not exporting for iOS, rename the file:
mv addons/godot-iap/bin/godot_iap.gdextension \
addons/godot-iap/bin/godot_iap.gdextension.disabledRestore the name before an iOS export, on any machine: Godot discovers and loads the native extension through that file. Skip the rename if your copy carries bin/macos — a source build, or the 3.3.2 and 3.3.3 zips — since a macOS editor loads that library.
Next Steps#
- Purchase Guide — Complete purchase flow with validation and receipt verification
- Subscription Guide — Subscription offers, renewal, and management
- Error Codes — Full error reference and handling strategies
- API Reference — All available APIs with multi-language examples
- Store Setup — support boundaries for alternative stores such as Horizon OS (Meta Quest) and Fire OS / Vega OS (Amazon); godot-iap does not yet ship dedicated flavors for these targets
- GitHub Source