Mobile SDK
Drop the donation flow into your app without shipping a Wishbone secret.
@wishbone/sdk opens the hosted donation flow from inside your app (TypeScript / React Native). The cardholder never leaves your experience, and your binary never contains a Wishbone key.
Trust model
Your API key is a server secret. The SDK calls a tokenProvider that you implement; your backend mints a cardholder-scoped embed token via POST /v1/embed/token and returns it. The SDK opens the flow with that short-lived token.
Bank app ──(1) request flow──▶ Your backend ──(2) POST /v1/embed/token──▶ Wishbone
▲ │ │
│ ◀──────────── embed token ──────────────┘
└──(3) open hosted flow with the short-lived token (this SDK) ──▶ WishboneEmbed tokens are encrypted, carry the cardholder and any pre-selection you set, and expire in 60–900 seconds (default 600).
Install
npm install @wishbone/sdk
# Recommended for the best in-app browser UX (pick one):
npm install expo-web-browser
# or
npm install react-native-inappbrowser-rebornUsage
import { WishboneProvider, useWishbone } from "@wishbone/sdk/react";
function Root() {
return (
<WishboneProvider
environment="production"
tokenProvider={async (params) => {
// Your backend holds the Wishbone API key.
const res = await fetch("https://api.mybank.com/wishbone/embed-token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(params),
});
return res.json(); // { embedToken: "wbt_…" }
}}
>
<App />
</WishboneProvider>
);
}
function DonateButton() {
const { donate, loading } = useWishbone();
return (
<Button
title="Donate points to Tennessee"
disabled={loading}
onPress={async () => {
const result = await donate({
schoolId: "sch_tennessee",
fund: "annual_fund",
amount: 50,
pointsRedeemed: 5000,
returnUrl: "mybank://wishbone/complete",
});
if (result.status === "completed") {
// result.donationId, result.dollarAmount, …
}
}}
/>
);
}Result
donate() resolves with status of completed, pending, failed or cancelled, plus donationId, schoolId, dollarAmount, pointsRedeemed and, on failure, errorCode. Treat it as a UI signal only — the authoritative outcome is the webhook, which arrives even if the app is closed.
The SDK never sees points balances, card data, or your API key — only the pre-selection hints you pass and the embed token your backend mints.