Your first sandbox purchase
This guide ends when a purchase made from your app shows up as an active entitlement in the dashboard and from a server-side call. Nothing is “done” until both are true.
Prerequisites
Section titled “Prerequisites”- An Orca account and an app in the dashboard (
Organization → App). - One store connected in sandbox/test mode. Pick the one you can test fastest:
- Apple: a sandbox tester in App Store Connect and an app you can run on a device or simulator. See Apple App Store integration.
- Google Play: an internal test track and a license tester. See Google Play integration.
- Stripe: test mode and the test card
4242 4242 4242 4242. See Stripe integration.
- Your public API key (client) and private API key (server) from the dashboard.
1. Create one entitlement and link one product
Section titled “1. Create one entitlement and link one product”In the dashboard, create an entitlement (for example pro_tier) and link the store’s product to it. Until a product is linked for the store you are testing, queryProducts() returns nothing for it. See Entitlements & Products.
Working looks like: the entitlement shows a linked product for your store.
2. Configure the client SDK in sandbox
Section titled “2. Configure the client SDK in sandbox”Swift:
Orca.configure(configuration: OrcaConfiguration( publicKey: "your_public_key", environment: .sandbox))try await Orca.identify(customerEmail: "tester@example.com")Kotlin (in Application.onCreate()):
Orca.configure(this, OrcaConfiguration( publicKey = "your_public_key", environment = OrcaEnvironment.SANDBOX, customerEmail = null,))For Kotlin, call Orca.identify("tester@example.com") from a coroutine after login and before purchasing.
Flutter:
final orca = Orca(publicKey: 'YOUR_ORCA_PUBLIC_KEY', environment: OrcaEnvironment.sandbox);await orca.identify('tester@example.com');Web:
const orca = new OrcaClient('public_api_key', 'sandbox')await orca.identify('tester@example.com')Working looks like: no notConfigured errors, and the email you passed is the one you will look up later.
3. Query products
Section titled “3. Query products”let products = try await Orca.queryProducts()final products = await orca.queryProducts(ExternalStore.stripe); // argument ignored on mobileconst products = await orca.queryProducts('stripe')Working looks like: at least one product with a formattedPrice. If the list is empty, the product is not linked to the entitlement for this store, or the store credentials in the dashboard are wrong.
Make the purchase
Section titled “Make the purchase”final entitlements = await orca.listEntitlements();await orca.purchase( entitlements.first, externalStore: ExternalStore.stripe, redirectUrl: 'https://yourapp.com/success', failureRedirectUrl: 'https://yourapp.com/failure',);const entitlements = await orca.listEntitlements()const chosen = entitlements.find((e) => e.id === 'pro_tier')if (!chosen) throw new Error('Create and link the pro_tier entitlement first.')
await orca.purchase({ store: 'stripe', entitlement: chosen, redirectUrl: 'https://yourapp.com/checkout/success', failureRedirectUrl: 'https://yourapp.com/checkout/failure',})Register the listener below before calling purchase() above. Purchases confirm asynchronously, so react to the event instead of assuming purchase() returning means success:
orca.purchaseEvents.listen((event) { switch (event.event) { case PurchaseEventType.success: // refresh entitlements case PurchaseEventType.canceled: // nothing to do case PurchaseEventType.failed: // show an error case PurchaseEventType.error: // something went wrong on Orca's side }});Working looks like: a success event (or, on web, a redirect to your success URL), and the sandbox purchase appearing in the store’s own console (App Store Connect sandbox, Play Console orders, Stripe test payments).
5. Confirm from the client
Section titled “5. Confirm from the client”final active = await orca.getActiveEntitlements();final isPro = active.any((e) => e.entitlementId == 'pro_tier');6. Confirm from your server
Section titled “6. Confirm from your server”This is the step people skip. Do not skip it.
const server = new OrcaServerClient(process.env.ORCA_API_KEY!) // private keyconst active = await server.getActiveEntitlements('tester@example.com', 'sandbox')console.log(active.some((e) => e.entitlement_id === 'pro_tier')) // trueWorking looks like: true, using the same email you passed to identify().
Common errors
Section titled “Common errors”| Symptom | Usual cause | Fix |
|---|---|---|
queryProducts() returns [] |
Product not linked to the entitlement for this store, or store integration incomplete | Check the entitlement’s products tab and the store integration page |
| Purchase succeeds in the store but the server sees no entitlement | Different email on client and server, or you are reading prod while you bought in sandbox |
Use one email; pass the same environment |
OrcaError.notConfigured (Swift) |
configure not called before other calls |
Call it in App init or AppDelegate |
| Web checkout never redirects back | redirectUrl not reachable or not HTTPS |
Use a real HTTPS URL, even in development (a tunnel works) |
Nothing happens after purchase() on Flutter |
You are not listening to purchaseEvents |
Subscribe before calling purchase() |