Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/stripe/stripe-terminal-react-native/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks through a complete end-to-end integration: installing the SDK, wrapping your app, discovering a simulated reader, and collecting a payment.
1

Install the package

Add the SDK to your React Native project using npm or yarn.
npm install @stripe/stripe-terminal-react-native
For iOS, install the native pod:
cd ios && pod install
2

Set up a connection token endpoint

The SDK needs a short-lived connection token from your backend to authenticate with Stripe. Create an endpoint on your server that calls the Stripe API and returns the token secret.Your backend should return a JSON body with a secret field — for example:
{ "secret": "pst_test_..." }
Then write a tokenProvider function in your app that fetches from that endpoint:
const fetchTokenProvider = async (): Promise<string> => {
  const response = await fetch(`${API_URL}/connection_token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
  });
  const { secret } = await response.json();
  return secret;
};
Never expose your Stripe secret key in your React Native app. Always fetch connection tokens from your own backend server.
3

Wrap your app with StripeTerminalProvider

In your root component, wrap your app with StripeTerminalProvider and pass the tokenProvider function. This sets up the context that all SDK hooks and components depend on.
// Root.tsx
import { StripeTerminalProvider } from '@stripe/stripe-terminal-react-native';

function Root() {
  const fetchTokenProvider = async () => {
    const response = await fetch(`${API_URL}/connection_token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
    });
    const { secret } = await response.json();
    return secret;
  };

  return (
    <StripeTerminalProvider
      logLevel="verbose"
      tokenProvider={fetchTokenProvider}
    >
      <App />
    </StripeTerminalProvider>
  );
}
Set logLevel="verbose" during development to see detailed SDK logs. Remove or set to "none" before shipping to production.
4

Initialize the SDK

Call initialize from the useStripeTerminal hook inside a component that is nested within StripeTerminalProvider. This must happen before any other SDK method is called.
// App.tsx
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useStripeTerminal } from '@stripe/stripe-terminal-react-native';

function App() {
  const { initialize } = useStripeTerminal();

  useEffect(() => {
    initialize();
  }, [initialize]);

  return <View />;
}
initialize must be called from a child of StripeTerminalProvider, not from the same component that renders it.
5

Discover readers

Use discoverReaders to search for available readers. During development, set simulated: true to use a built-in simulated reader without any physical hardware.
// PaymentScreen.tsx
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useStripeTerminal } from '@stripe/stripe-terminal-react-native';

export default function PaymentScreen() {
  const { discoverReaders, connectedReader, discoveredReaders } =
    useStripeTerminal({
      onUpdateDiscoveredReaders: (readers) => {
        // readers is the updated list of discovered readers
        console.log('Discovered readers:', readers);
      },
      onDidChangeConnectionStatus: (status) => {
        console.log('Connection status:', status);
      },
    });

  useEffect(() => {
    discoverReaders({
      discoveryMethod: 'bluetoothScan',
      simulated: true,
    });
  }, [discoverReaders]);

  return <View />;
}
6

Connect to a reader

Once readers are discovered, call connectReader with the reader you want to connect to. Pass the locationId of the Stripe Terminal location associated with the reader.
import { useStripeTerminal } from '@stripe/stripe-terminal-react-native';

export default function PaymentScreen() {
  const { discoverReaders, connectReader, discoveredReaders } =
    useStripeTerminal({
      onUpdateDiscoveredReaders: async (readers) => {
        if (readers.length > 0) {
          const { reader, error } = await connectReader({
            discoveryMethod: 'bluetoothScan',
            reader: readers[0],
            locationId: 'tml_your_location_id',
          });

          if (error) {
            console.error('Failed to connect:', error.message);
          } else {
            console.log('Connected to reader:', reader?.id);
          }
        }
      },
    });

  useEffect(() => {
    discoverReaders({
      discoveryMethod: 'bluetoothScan',
      simulated: true,
    });
  }, [discoverReaders]);

  return null;
}
7

Create and collect a payment

With a reader connected, you can collect a payment in three steps:
  1. createPaymentIntent — Create a PaymentIntent for the amount to charge (in the smallest currency unit, e.g. cents).
  2. collectPaymentMethod — Present the reader to the customer to tap, dip, or swipe their card.
  3. confirmPaymentIntent — Submit the payment to Stripe and finalize the charge.
import { useStripeTerminal } from '@stripe/stripe-terminal-react-native';

export default function PaymentScreen() {
  const {
    createPaymentIntent,
    collectPaymentMethod,
    confirmPaymentIntent,
  } = useStripeTerminal();

  const collectPayment = async () => {
    // Step 1: Create the PaymentIntent
    const { paymentIntent, error: createError } = await createPaymentIntent({
      amount: 1000, // $10.00 in cents
      currency: 'usd',
      captureMethod: 'automatic',
    });

    if (createError || !paymentIntent) {
      console.error('Failed to create PaymentIntent:', createError?.message);
      return;
    }

    // Step 2: Collect the payment method from the reader
    const { paymentIntent: collectedIntent, error: collectError } =
      await collectPaymentMethod({
        paymentIntent,
      });

    if (collectError || !collectedIntent) {
      console.error('Failed to collect payment method:', collectError?.message);
      return;
    }

    // Step 3: Confirm the payment
    const { paymentIntent: confirmedIntent, error: confirmError } =
      await confirmPaymentIntent({
        paymentIntent: collectedIntent,
      });

    if (confirmError) {
      console.error('Failed to confirm payment:', confirmError.message);
      return;
    }

    console.log('Payment succeeded:', confirmedIntent?.id);
  };

  return null;
}
When using a simulated reader, no real card is charged. Use simulated: true in discoverReaders during development and switch to a physical reader in production.

Next steps

  • Review Requirements for platform-specific setup including permissions and minimum OS versions.
  • Browse the SDK reference for the full list of available methods and types.

Build docs developers (and LLMs) love