Skip to content

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.

  • 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:
  • Your public API key (client) and private API key (server) from the dashboard.
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.

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.

let products = try await Orca.queryProducts()
final products = await orca.queryProducts(ExternalStore.stripe); // argument ignored on mobile
const 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.

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).

final active = await orca.getActiveEntitlements();
final isPro = active.any((e) => e.entitlementId == 'pro_tier');

This is the step people skip. Do not skip it.

const server = new OrcaServerClient(process.env.ORCA_API_KEY!) // private key
const active = await server.getActiveEntitlements('tester@example.com', 'sandbox')
console.log(active.some((e) => e.entitlement_id === 'pro_tier')) // true

Working looks like: true, using the same email you passed to identify().

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()