# Quick Start Guide (/in-store/getting-started/quick_start_guide)









<div className="bg-background relative h-auto w-full overflow-hidden rounded-lg border mt-8">
  <FlickeringGrid className="absolute inset-0 z-0 size-full" squareSize="4" gridGap="6" maxOpacity="0.1" flickerChance="0.1" height="800" width="2000" />

  <SdkLifecycleDiagram />
</div>

The Accept SDK runs inside your app and handles payments on the device: it captures the card or Tap to Pay, encrypts the data, and keeps card handling out of your code so you stay outside PCI scope. Your backend authenticates each SDK session against the Tapaya API, onboards merchants, and triggers KYB. Tapaya runs the KYB checks and settles funds to the merchant.

## Choose Your Integration Path [#choose-your-integration-path]

There are two ways to take card payments with Tap to Pay. Both hand the actual card interaction off to the
**Tapaya Terminal** plugin app on the same device. They differ in how much of that handoff your app manages:

<Cards>
  <VisualCard title="Accept SDK (recommended)" visual="<Layers />" href="#set-up-your-integrator-account" description="Embed the SDK in your Android app and get the result in callbacks. This guide covers this path." />

  <VisualCard title="Tapaya Terminal only" visual="<SquareTerminal />" href="/in-store/integration/card_terminal#integrate-without-the-sdk" description="No SDK: open Tapaya Terminal with an intent or deeplink and poll the payment status." />
</Cards>

## Set Up Your Integrator Account [#set-up-your-integrator-account]

Before writing any code, set up the account your backend will authenticate against:

1. **Sign up** at [platform.tapaya.com/register](https://platform.tapaya.com/register). This is self-serve: no invite is required.
2. **Log in**, then create or join your organization; you'll be prompted for this automatically right after registering.
3. **Generate your Server Secret Token** from the [API Keys page](https://platform.tapaya.com/api-keys/): your backend uses this to call the Tapaya Platform API (see [Platform API authentication](/platform-api#authentication)).

<Callout title="Not the same as merchant onboarding" type="info">
  This is account setup for **you**, the integrator. Your **merchants** are onboarded separately, either through
  the SDK, the Tapaya Platform UI, your own UI, or an invite link. See [Merchant
  Onboarding](/merchants/onboarding) for details. `POST /merchant/auth/register` only creates the merchant
  shell; hosted invite onboarding starts with `POST /integrator/merchant/send-registration-invite`.
</Callout>

The rest of this guide covers adding the SDK to your project, authenticating a session, and running your first transaction.

<section id="setup-section">
  <div className="fd-steps [&_h3]:fd-step">
    ### Add Dependency [#add-dependency]

    On Android the SDK is published to [Maven Central](https://central.sonatype.com/artifact/com.tapaya/accept); set `acceptVersion` to its latest release. On React Native it installs from npm with
    `npx expo install @tapayadot/accept-react-native` and is wired up by its config plugin.

    <CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="kotlin">
          Android (Kotlin)
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="typescript">
          React Native (TypeScript)
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="kotlin">
        ```kotlin title="build.gradle.kts"
        dependencies {
            // [!code ++:1]
            implementation("com.tapaya:accept:$acceptVersion")
        }
        ```
      </CodeBlockTab>

      <CodeBlockTab value="typescript">
        ```json title="app.json"
        {
          "expo": {
            "plugins": ["@tapayadot/accept-react-native"]
          }
        }
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    Sync the project (Android) or run `npx expo prebuild --clean` (React Native), then initialize and
    authenticate in your application code.

    <CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="kotlin">
          Android (Kotlin)
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="typescript">
          React Native (TypeScript)
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="kotlin">
        ```kotlin title="MyApplication.kt"
        // Step 1: Initialize (once, in Application.onCreate)
        Accept.initialize(this) // sandbox by default; pass isProduction = true to go live
        ```
      </CodeBlockTab>

      <CodeBlockTab value="typescript">
        ```typescript title="App.tsx"
        import Accept from '@tapayadot/accept-react-native';

        // Step 1: Initialize (once, at app startup)
        Accept.initialize(); // sandbox by default; pass { isProduction: true } to go live
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    Authenticate a merchant session with a token obtained from your backend.
    `authenticate` is a `suspend` function and throws an `AcceptException` on failure.

    <CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="kotlin">
          Android (Kotlin)
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="typescript">
          React Native (TypeScript)
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="kotlin">
        ```kotlin
        // Step 2: Authenticate (suspend; call from a coroutine)
        try {
            val sdkToken = myBackend.login() // token from POST /merchant/auth/login
            Accept.auth.authenticate(sdkToken)
            // Accept.state now emits SdkState.Authenticated
        } catch (e: AcceptException) {
            // handle authentication failure
        }
        ```
      </CodeBlockTab>

      <CodeBlockTab value="typescript">
        ```typescript
        // Step 2: Authenticate
        try {
            const sdkToken = await myBackend.login(); // token from POST /merchant/auth/login
            await Accept.auth.authenticate(sdkToken);
            // Accept.state is now 'authenticated'
        } catch (error) {
            // handle authentication failure
        }
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    ### Onboard the Merchant [#onboard-the-merchant]

    Before any transactions are allowed, the merchant must finish KYB onboarding. Onboarding is **no longer
    driven by the Accept SDK**. Complete it through the Tapaya Platform UI, your own UI against the Tapaya
    API, or an invite link. See [Merchant Onboarding](/merchants/onboarding) for all methods.

    <Callout title="Sandbox Auto-Approval" type="info">
      In the sandbox environment, merchants are automatically approved right after onboarding, so you don't have to wait for payment processor review.
    </Callout>

    ### Verify Merchant Readiness [#verify-merchant-readiness]

    Ensure the merchant has finished onboarding and is approved to accept payments.

    <CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="kotlin">
          Android (Kotlin)
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="typescript">
          React Native (TypeScript)
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="kotlin">
        ```kotlin
        val ready = when (val status = Accept.merchant.onboardingStatus()) {
            OnboardingStatus.ReadyForPayments -> true
            is OnboardingStatus.RequiresAction -> false // status.state describes what's blocking
        }
        ```
      </CodeBlockTab>

      <CodeBlockTab value="typescript">
        ```typescript
        const status = await Accept.merchant.onboardingStatus();
        // status.state describes what's blocking when it requires action
        const ready = status.type === 'readyForPayments';
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    The merchant is ready only after the payment processor has approved it. If some information is missing,
    the onboarding must be repeated. In some cases, the payment processor might block the merchant completely, such as when selling prohibited goods.

    ### Install & Activate Terminal [#install--activate-terminal]

    <Callout title="Plugin App Required" type="warn">
      Card payments require the **Tapaya Accept** plugin to be installed on the device.
      Use `Accept.plugin.isInstalled()` to check, and `Accept.plugin.install()` to open the store
      listing if it is missing.
    </Callout>

    The Tapaya Accept plugin is required for card payments. Check if it is installed, then activate
    the terminal, or open the Play Store listing to install it.

    <div className="bg-background relative h-auto w-full overflow-hidden rounded-lg border px-10">
            <img alt="Plugin" src="__img0" />
    </div>

    <CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="kotlin">
          Android (Kotlin)
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="typescript">
          React Native (TypeScript)
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="kotlin">
        ```kotlin
        if (Accept.plugin.isInstalled()) {
            // suspend; returns ActivateTerminalResult (Success / Canceled / Failed)
            Accept.plugin.activateTerminal()
        } else {
            Accept.plugin.install() // opens the store listing
        }
        ```
      </CodeBlockTab>

      <CodeBlockTab value="typescript">
        ```typescript
        if (Accept.plugin.isInstalled()) {
            // returns ActivateTerminalResult: { type: 'success' | 'canceled' | 'failed' }
            await Accept.plugin.activateTerminal();
        } else {
            await Accept.plugin.install(); // opens the store listing
        }
        ```
      </CodeBlockTab>
    </CodeBlockTabs>

    ### Create Payment Transaction [#create-payment-transaction]

    To execute a transaction, call `Accept.payments.pay()` with the amount (in the currency's minor unit)
    and an ISO 4217 currency code. It returns a `Flow<PaymentEvent>`; collect it to observe progress and
    the terminal outcome. `pay()` never throws: failures arrive as `PaymentEvent.CreationFailed`.

    The quick start needs only `amount` and `currency`. For every optional parameter, such as a fixed tip, receipt
    overrides, or metadata, see [Create a payment](../integration/card_terminal#create-a-payment).

    <div className="bg-background relative h-auto w-full overflow-hidden rounded-lg border px-10">
            <img alt="Payment" src="__img1" />
    </div>

    <CodeBlockTabs defaultValue="kotlin" groupId="accept-language">
      <CodeBlockTabsList>
        <CodeBlockTabsTrigger value="kotlin">
          Android (Kotlin)
        </CodeBlockTabsTrigger>

        <CodeBlockTabsTrigger value="typescript">
          React Native (TypeScript)
        </CodeBlockTabsTrigger>
      </CodeBlockTabsList>

      <CodeBlockTab value="kotlin">
        ```kotlin
        Accept.payments.pay(amount = 15000, currency = "CZK") // 150.00 Kč
            .collect { event ->
                when (event) {
                    PaymentEvent.Creating -> Log.d("pay", "creating")
                    is PaymentEvent.Created -> Log.d("pay", "created ${event.paymentToken}")
                    PaymentEvent.Launched -> Log.d("pay", "launched")
                    is PaymentEvent.Result -> Log.d("pay", event.payResult.toString())
                    is PaymentEvent.CreationFailed -> Log.e("pay", event.cause.toString())
                }
            }
        ```
      </CodeBlockTab>

      <CodeBlockTab value="typescript">
        ```typescript
        // payAsync() reduces the event stream to its outcome; use pay() to render progress
        const result = await Accept.payments.payAsync({
            amount: 15000,
            currency: 'CZK', // 150.00 Kč
        });

        if (result.type === 'success') {
            console.log(result.paymentToken, result.receiptUrl);
        }
        ```
      </CodeBlockTab>
    </CodeBlockTabs>
  </div>
</section>
