IndiSell Docs Dashboard →
Checkout

Mobile apps (SDK)

Open the IndiSell checkout inside your mobile app with a WebView. Your backend mints a session; the app opens the returned URL and detects success.

IndiSell checkout runs in a WebView inside your mobile app — the same OTP-verified, server-priced checkout your web shoppers get. There's no heavy native SDK to link: your backend creates a checkout session, your app opens the returned URL, and you detect completion from the WebView's navigation.

ℹ️
Mobile checkout is enabled per store. If you don't see your SDK secret under Settings → Integrations → Mobile app, ask support to switch it on.

How it works

Your backend POST /session IndiSell returns checkout URL App WebView opens URL ✓ redirect = done
Session on the backend (secret stays server-side) → WebView opens the URL → your redirect URL signals success.

Step 1 — Create a session (your backend)

Call this from your server, not the app — the SDK secret must never ship in an app binary.

curl -X POST https://cart.indisell.io/api/checkout/session \
  -H "Authorization: Bearer sk_indisell_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "key": "mk_YOUR_PUBLIC_KEY",
    "items": [ { "variantId": 47274160193667, "quantity": 1 } ],
    "redirectUrl": "myapp://checkout/done"
  }'

Response:

{ "url": "https://cart.indisell.io/m/eyJ...sig", "sessionId": "eyJ...", "expiresIn": 7200 }
FieldRequiredNotes
keyyesYour public key (mk_…) from Settings → Integrations → Mobile app
itemsyesArray of { variantId, quantity } — Shopify numeric variant ids
redirectUrlyesWhere checkout sends the shopper on success. An https:// URL or your app scheme (myapp://…). On success IndiSell appends ?status=success&order=<number>

The Authorization header is your SDK secret (sk_indisell_…), also on that settings page.

⚠️
Keep the SDK secret on your server. Anyone with it can create checkout sessions for your store. The public key is safe to ship; the secret is not.

Step 2 — Open the URL in a WebView

Point a WebView at the url you got back, and watch its navigation for your redirectUrl. When you see it, the order is placed — close the WebView.

React Native

import { WebView } from 'react-native-webview';

function Checkout({ url, onDone }) {
  return (
    <WebView
      source={{ uri: url }}
      javaScriptEnabled
      onShouldStartLoadWithRequest={(req) => {
        if (req.url.startsWith('myapp://checkout/done')) {
          onDone(new URL(req.url).searchParams.get('order'));
          return false; // don't actually navigate to the app scheme
        }
        return true;
      }}
    />
  );
}

Flutter

WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setNavigationDelegate(NavigationDelegate(
    onNavigationRequest: (nav) {
      if (nav.url.startsWith('myapp://checkout/done')) {
        final order = Uri.parse(nav.url).queryParameters['order'];
        onDone(order);
        return NavigationDecision.prevent;
      }
      return NavigationDecision.navigate;
    },
  ))
  ..loadRequest(Uri.parse(url));

iOS (Swift, WKWebView)

func webView(_ webView: WKWebView,
             decidePolicyFor navigationAction: WKNavigationAction,
             decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    if let u = navigationAction.request.url, u.absoluteString.hasPrefix("myapp://checkout/done") {
        let order = URLComponents(url: u, resolvingAgainstBaseURL: false)?
            .queryItems?.first(where: { $0.name == "order" })?.value
        onDone(order)
        decisionHandler(.cancel)
        return
    }
    decisionHandler(.allow)
}

Android (Kotlin, WebView)

webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient() {
  override fun shouldOverrideUrlLoading(v: WebView, req: WebResourceRequest): Boolean {
    val u = req.url.toString()
    if (u.startsWith("myapp://checkout/done")) {
      onDone(req.url.getQueryParameter("order"))
      return true // handled — don't load the app scheme
    }
    return false
  }
}
webView.loadUrl(url)

Step 3 — Handle completion

On success the checkout redirects to your redirectUrl with ?status=success&order=<number>. Catch that in the navigation handler (above), close the WebView, and show your own confirmation screen. The order is already created in Shopify and visible in your IndiSell dashboard.

If the shopper closes the WebView before finishing, no order is created — just dismiss it.

Security model

  • Server-priced — every price, discount and COD decision is recomputed server-side at checkout, so a tampered cart can't change what's charged.
  • Signed sessions — the checkout URL is HMAC-signed and expires in 2 hours; it can't be forged or edited.
  • Secret stays server-side — sessions are minted with your SDK secret from your backend, never from the app.
  • Validated redirects — only https:// and app-scheme URLs are accepted, so the redirect can't be turned into a script or open redirect.

A note for Shopify mobile apps

If your app is built on your Shopify store (e.g. a headless or Shopify Mobile-Buy-SDK app), the flow is identical: build the items array from the Shopify cart the shopper assembled, create a session on your backend, and open the URL. IndiSell handles OTP, address, payment and order creation — you get the shopper back with a completed order.