# Connect to a reader

Connect your application to a Stripe Terminal reader.

> If you haven’t chosen a reader yet, compare the available [Terminal readers](https://docs.stripe.com/terminal/payments/setup-reader.md) and choose one that best suits your needs.

# Smart Readers


Smart readers run Stripe reader software to communicate directly with Stripe over the internet. Connecting your app to a smart reader requires three steps:

1. [Register a reader](https://docs.stripe.com/terminal/payments/connect-reader.md#register-reader) to your Stripe account.
2. [Discover readers](https://docs.stripe.com/terminal/payments/connect-reader.md#discover-readers) with the SDK.
3. [Connect to a reader](https://docs.stripe.com/terminal/payments/connect-reader.md#connect-reader) with the SDK.

## Register a reader [Server-side]

Before you can connect your application to a smart reader, you must register the reader to your account.

#### Dashboard

### Register in the Dashboard

You can add your reader directly in the [Dashboard](https://dashboard.stripe.com/test/terminal).

#### Register by registration code

1. In the [Readers](https://dashboard.stripe.com/terminal/readers) page, click **Register reader**.
2. If you have a [smart reader](https://docs.stripe.com/terminal/smart-readers.md), enter the key sequence `0-7-1-3-9` to display a unique registration code. If you have a BBPOS WisePOS E or Stripe Reader S700/S710, go to the [reader settings](https://docs.stripe.com/terminal/payments/setup-reader/bbpos-wisepos-e.md#settings) and tap **Generate pairing code**.
3. Enter the registration code then click **Next**.
4. Optionally, choose a name for the reader.
5. If you already created a Location, select the reader’s new Location. Otherwise, create a Location by clicking **+ Add new**.
6. Click **Register** to finish registering your reader.

#### Register by serial number

1. In the [Readers](https://dashboard.stripe.com/terminal/readers) page, click **Register reader**.
2. Find the serial number on the device and enter the serial number. To register multiple devices at once, you can enter multiple serial numbers separated by commas.
3. Optionally, choose a name for the reader.
4. If you already created a Location, select the reader’s new Location. Otherwise, create a Location by clicking **+ Add new**.
5. Click **Register** to finish registering your reader.

#### Register by hardware order

1. In the [Hardware orders](https://dashboard.stripe.com/terminal/hardware_orders) page, find an order with a status of either “shipped” or “delivered.” Click the overflow menu (⋯) at the end of the row, then click **Register**.
2. On the **Register Readers** page, select one or more readers from the hardware order to register, then click **Register**.
3. Optionally, choose a name for the reader. If you selected multiple readers, the name serves as a prefix and we name the readers sequentially (for example, for a given input of “Test reader”, we name the readers “Test reader 1”, “Test reader 2”, and so on).
4. If you already created a Location, select the reader’s new Location. Otherwise, create a Location by clicking **+ Add new**.
5. Click **Register** to finish registering your readers.

#### API

For larger deployments, enable users in the field to receive and set up new readers on their own. In your app, build a flow to [register](https://docs.stripe.com/api/terminal/readers/create.md) a reader with the Stripe API.

1. If you have a [smart reader](https://docs.stripe.com/terminal/smart-readers.md), enter the key sequence `0-7-1-3-9` to display a unique registration code. If you have a BBPOS WisePOS E or Stripe Reader S700/S710, go to the [reader settings](https://docs.stripe.com/terminal/payments/setup-reader/bbpos-wisepos-e.md#settings) and tap **Generate pairing code**.
2. The user enters the code in your application.
3. Your application sends the code to Stripe:

```curl
curl https://api.stripe.com/v1/terminal/readers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -d registration_code={{READER_REGISTRATION_CODE}} \
  --data-urlencode "label=Alice's reader" \
  -d "location={{TERMINALLOCATION_ID}}"
```

To confirm that you’ve registered a reader correctly, list all the readers you’ve registered at that location:

#### curl

```bash
curl https://api.stripe.com/v1/terminal/readers \
  -u <<YOUR_SECRET_KEY>>:
```

## Discover readers [Client-side]

- [discoverReaders (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#discoverReaders)

After registering the reader to your account, search for previously registered readers to connect to your point-of-sale application with `discoverReaders`, setting `discoveryMethod` to `internet`.

You can scope your discovery using the `location` you registered the reader to in the previous step.

```js
export default function DiscoverScreen() {
  const { discoverReaders, discoveredReaders } =
    useStripeTerminal({
      onUpdateDiscoveredReaders: (readers) => {
        // After the SDK discovers a reader, your app can connect to it.
      },
    });

  useEffect(() => {
    const fetchReaders = async () => {
      const { error } = await discoverReaders({
        discoveryMethod: 'internet',
      });
    }

    fetchReaders();
  }, [discoverReaders]);

  return <View />;
}
```

## Connect to a reader [Client-side]

> In version `0.0.1-beta.29` of the React Native SDK, you can use the [easyConnect](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#easyconnect) method to combine reader discovery and connection into a single API call for a simpler integration experience.

To connect your point-of-sale application to a reader, call `connectReader` with the selected reader.

To prevent connection failures, make sure you always pass a reader object from the most recent discovery results. Don’t cache or reuse reader objects from a previous discovery session.

```js
const { reader, error } = await connectReader({
  discoveryMethod: 'internet',
  reader,
});

if (error) {
  console.log('connectReader error:', error);
  return;
}

console.log('Reader connected successfully', reader);
```

- [connectReader (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/interfaces/StripeTerminalSdkType.html#connectreader-1)

### Multiple connections

Only one instance of the Stripe Terminal SDK can connect to a reader at a given time. By default, when you call `connectReader` from another application, the incoming connection replaces the existing SDK-to-reader connection, and the previously connected SDK disconnects from the reader. The `connectReader` method takes a configuration object with a `failIfInUse` property, whose default value is `false`. When your application sets `failIfInUse` to true, the `connectReader` call has an alternate behavior where the incoming connection fails when the reader is in the middle of a `collectPaymentMethod` or `confirmPaymentIntent` call initiated by another SDK. If the reader is connected to another SDK but is idle (displaying the splash screen before `collectPaymentMethod` is called), setting `failIfInUse` has no change to the connection behavior, and the incoming connection request can always break the existing SDK-to-reader connection.

```js
const { reader: connectedReader, error } = await connectReader({
  discoveryMethod: 'internet',
  reader,
  failIfInUse: true,
});
```

|                                                                                   | failIfInUse is false (default)                                                                                                                                                                                         | failIfInUse is true                                                                                                                                                                                                    |
| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connectInternetReader` called from a new SDK when the reader is idle.            | The existing SDK-to-reader connection breaks, and the new SDK connects to the reader. The next command from the previously-connected SDK fails with a reader error, and that app’s `onDidDisconnect` method is called. | The existing SDK-to-reader connection breaks, and the new SDK connects to the reader. The next command from the previously-connected SDK fails with a reader error, and that app’s `onDidDisconnect` method is called. |
| `connectInternetReader` called from a new SDK when the reader is mid-transaction. | The existing SDK-to-reader connection breaks, and the new SDK connects to the reader. The next command from the previously-connected SDK fails with a reader error, and that app’s `onDidDisconnect` method is called. | The incoming connection fails with a reader error. The existing SDK-to-reader connection doesn’t break and the command in progress continues.                                                                          |

For the least-disruptive connection experience in multi-reader environments, we recommend setting `failIfInUse` to `true` on your application’s initial connection attempt. Then, allow your users to retry the connection with `failIfInUse` set to `false` if the connection fails the first time.

With this setup, one of your users can’t accidentally interrupt a transaction by inadvertently connecting to an in-use reader, but can still connect if needed.

### Handle disconnects 

- [UserCallbacks (React Native)](https://stripe.dev/stripe-terminal-react-native/api-reference/index.html#UserCallbacks)

Your app must implement the `onDidDisconnect` callback to handle when a reader disconnects. When you implement this callback, display a UI that notifies your user of the disconnected reader. You can call `discoverReaders` to scan for readers and initiate reconnection.

Your app can attempt to automatically reconnect to the disconnected reader or display a UI that prompts your user to reconnect to a different reader.

The reader can disconnect from your app if it loses connection to the network. To simulate an unexpected disconnect, power off the reader.

```js
const terminal = useStripeTerminal({
  onDidDisconnect: (result) => {
    // Consider displaying a UI to notify the user and start rediscovering readers
  },
});
```

### Automatic reconnection

Stripe Terminal doesn’t automatically reconnect to a reader when your application starts. Instead, you can build a reconnection flow by storing reader IDs and attempting to connect to a known reader on startup.

Display some UI during the discovery and connection process to indicate that an automatic reconnection is taking place.


## Next steps

You’ve connected your application to the reader. Next, [collect your first Stripe Terminal payment](https://docs.stripe.com/terminal/payments/collect-card-payment.md).

The BBPOS and Chipper™ name and logo are trademarks or registered trademarks of BBPOS Limited in the United States or other countries. The Verifone® name and logo are either trademarks or registered trademarks of Verifone in the United States and/or other countries. Use of the trademarks doesn’t imply any endorsement by BBPOS or Verifone.
