React Native Card SDK

Tokenize a card in React Native apps via a hosted page.

The React Native Card SDK lets you add and tokenize a card inside your mobile app. The cardholder types the card data on an Autra-hosted page rendered in a WebView — the card number never touches your app or your servers. You receive an opaque slugStoredCard reference to charge the card later.

npm package: @autra-io/react-native-card · Apache-2.0

When to use

ScenarioRecommended approach
Save a card inside a React Native appUse this SDK (<AutraCardForm />)
Charge a previously saved cardServer API POST /v1/acquiring/payments with tokenData
Server-to-server tokenization (no front)Use the API directly (POST /v1/acquiring/tokenize-card)
Checkout / payment link on a websiteUse the Checkout Embed SDK

Requirements

DependencyVersion
React>= 18.0.0
React Native>= 0.72.0
react-native-webview>= 13.0.0 (required peer dependency)

react-native-webview is a peer dependency — install it in your app; the SDK does not bundle it. Expo: works with development builds / expo prebuild (native WebView module). Expo Go is not supported.


How it works

Your app (SDK)        Your backend          Autra
──────────────        ────────────          ─────
1. Request a session ─►
2.                    POST /v1/acquiring/
                      card-sessions       ─►  Create hosted session
3.                    hostedCardUrl       ◄─  (short-lived, single-use)
4. <AutraCardForm hostedCardUrl /> ────────►  Loads cards.autra.io in a WebView
5.                                            Cardholder types PAN/CVV here
6.                                            Tokenizes (direct, HTTPS)
7. onSuccess(slugStoredCard) ◄─────────────
8. Send slugStoredCard ─► store for future charges

Card data flows only between the cardholder and the Autra-hosted page — it never transits your app or backend. Your systems only see opaque values: the hostedCardUrl going in, and the slugStoredCard / slugToken references coming out. This helps reduce your PCI DSS scope.


Quick start

Step 1: Install

npm install @autra-io/react-native-card react-native-webview
# iOS (bare React Native): cd ios && pod install
# Expo: npx expo install react-native-webview

Step 2: Create a session on your backend

Card sessions are created server-side with your Autra API access token. Never call this from the app. See Create hosted card session for the full request/response schema (fields, error codes, TTL).

// Your backend. API base: https://api.autra.io
const res = await fetch('https://api.autra.io/v1/acquiring/card-sessions', {
  method: 'POST',
  headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
  // documentId = the MERCHANT's CPF/CNPJ that owns the session (not the cardholder's).
  body: JSON.stringify({ documentId: '<merchant CPF/CNPJ>' }),
});
const { hostedCardUrl } = await res.json();
// hostedCardUrl is short-lived and single-use — mint one per attempt.
🔑

Access token & IP allow-list. Get your API access token from the Autra dashboard. The IP address of the backend that calls this endpoint must be allow-listed for your tenant — otherwise the call returns 403. Both are configured in the Autra dashboard.

Step 3: Render the form in your app

import { useState } from 'react';
import { Button, View } from 'react-native';
import {
  AutraCardForm,
  type AutraCardTokenizedResult,
  type AutraCardError,
} from '@autra-io/react-native-card';

export function AddCardScreen() {
  const [hostedCardUrl, setHostedCardUrl] = useState<string | null>(null);

  async function start() {
    // Ask YOUR backend for a fresh session (Step 2). URLs are single-use.
    const res = await fetch('https://your-backend.example.com/card-sessions', { method: 'POST' });
    const { hostedCardUrl } = await res.json();
    setHostedCardUrl(hostedCardUrl);
  }

  if (!hostedCardUrl) return <Button title="Add card" onPress={start} />;

  return (
    <View style={{ flex: 1 }}>
      <AutraCardForm
        hostedCardUrl={hostedCardUrl}
        onReady={() => {/* hide your spinner */}}
        onSuccess={(result: AutraCardTokenizedResult) => {
          // Send result.slugStoredCard to your backend and store it there.
        }}
        onError={(error: AutraCardError) => {
          if (error.code === 'token_expired' || error.retryable) {
            setHostedCardUrl(null); // sessions are short-lived: create a NEW one and retry
          }
        }}
        style={{ flex: 1 }}
      />
    </View>
  );
}

Props reference

PropTypeRequiredDescription
hostedCardUrlstringYesHosted session URL created by your backend. Must be HTTPS.
onSuccess(result: AutraCardTokenizedResult) => voidYesFires once, on successful tokenization.
onError(error: AutraCardError) => voidYesFires on configuration, session or tokenization errors.
onReady(requestId?: string) => voidNoThe hosted page validated the session and is interactive.
allowedOriginsreadonly string[]NoAllowed HTTPS origins. Defaults to the hostedCardUrl origin.
styleStyleProp<ViewStyle>NoStyle for the underlying WebView.
testIDstringNoTest identifier.

Callback data

onSuccess — AutraCardTokenizedResult

The token references (slugStoredCard, slugToken) are opaque. The remaining fields are non-sensitive display values (brand, BIN/first4, last4, expiry, alias) — the SDK never exposes the full PAN or the CVV.

FieldDescription
slugStoredCardReference your backend uses to charge the card later.
slugTokenSingle-use token reference.
tokenExpirationDateExpiration of the token reference.
brand, first4, last4, expirationMonth, expirationYearDisplay only. first4 is the card's BIN prefix and last4 the final four digits — both PCI-safe.
nicknameOptional card alias ("Apelido") the cardholder typed on the hosted page. Empty/absent if left blank.
requestIdCorrelation id for support.
🏷️

Card nickname ("Apelido"). The hosted page shows an optional Apelido (opcional) field so the cardholder can label the card (e.g. "Cartão da empresa"). Whatever they type comes back as result.nickname — store and display it to help users tell their saved cards apart. It's optional: absent/empty when left blank.

onError — AutraCardError

{ code, message, requestId?, retryable? }. When retryable is true, create a new session and retry. The table below is the complete set of code values.

CodeMeaningWhat to do
configuration_errorInvalid/non-HTTPS hostedCardUrl or empty allowedOriginsFix the integration
token_expiredSession expired or unauthorizedCreate a new session
message_origin_rejectedMessage from an origin outside the allow-listInvestigate
message_invalidMalformed message from the hosted pageRetry with a new session
validation_errorCardholder input rejectedThe hosted page guides the user
tokenization_failedLoad or tokenization failureIf retryable, retry with a new session

Security & PCI

  • Card data (PAN, CVV) is entered only on the Autra-hosted page and sent directly to Autra — it never transits your app or backend, which helps reduce your PCI DSS scope.
  • Your app only handles the opaque hostedCardUrl (in) and the opaque slugStoredCard / slugToken (out).
  • Keep service credentials (clientSecret, strong access tokens) server-side only.
  • The WebView is hardened by default: HTTPS-only, navigation allow-list, no disk cache, no file access, incognito.
📘

Environment & test cards. There is no separate sandbox — validation runs against production (api.autra.io / cards.autra.io). To test tokenization end to end you need approved test card numbers — request them from Autra. Never use real cardholder data in tests.