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
| Scenario | Recommended approach |
|---|---|
| Save a card inside a React Native app | Use this SDK (<AutraCardForm />) |
| Charge a previously saved card | Server 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 website | Use the Checkout Embed SDK |
Requirements
| Dependency | Version |
|---|---|
| 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-webviewStep 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
| Prop | Type | Required | Description |
|---|---|---|---|
hostedCardUrl | string | Yes | Hosted session URL created by your backend. Must be HTTPS. |
onSuccess | (result: AutraCardTokenizedResult) => void | Yes | Fires once, on successful tokenization. |
onError | (error: AutraCardError) => void | Yes | Fires on configuration, session or tokenization errors. |
onReady | (requestId?: string) => void | No | The hosted page validated the session and is interactive. |
allowedOrigins | readonly string[] | No | Allowed HTTPS origins. Defaults to the hostedCardUrl origin. |
style | StyleProp<ViewStyle> | No | Style for the underlying WebView. |
testID | string | No | Test identifier. |
Callback data
onSuccess — AutraCardTokenizedResult
AutraCardTokenizedResultThe 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.
| Field | Description |
|---|---|
slugStoredCard | Reference your backend uses to charge the card later. |
slugToken | Single-use token reference. |
tokenExpirationDate | Expiration of the token reference. |
brand, first4, last4, expirationMonth, expirationYear | Display only. first4 is the card's BIN prefix and last4 the final four digits — both PCI-safe. |
nickname | Optional card alias ("Apelido") the cardholder typed on the hosted page. Empty/absent if left blank. |
requestId | Correlation 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
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.
| Code | Meaning | What to do |
|---|---|---|
configuration_error | Invalid/non-HTTPS hostedCardUrl or empty allowedOrigins | Fix the integration |
token_expired | Session expired or unauthorized | Create a new session |
message_origin_rejected | Message from an origin outside the allow-list | Investigate |
message_invalid | Malformed message from the hosted page | Retry with a new session |
validation_error | Cardholder input rejected | The hosted page guides the user |
tokenization_failed | Load or tokenization failure | If 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 opaqueslugStoredCard/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.
