@tagadapay/headless-sdk
v1.4.0
Published
Headless SDK for using TagadaPay as a checkout, offers, and CRM backend from any external website
Readme
@tagadapay/headless-sdk
Use TagadaPay as a headless checkout and CRM backend from any website — React, Vue, vanilla JS, or plain HTML. Zero runtime dependencies in core.
Install
npm install @tagadapay/headless-sdk
# Optional: for card tokenization
npm install @tagadapay/core-jsQuick Start (Vanilla JS)
import { createHeadlessClient } from '@tagadapay/headless-sdk';
const tagada = createHeadlessClient({
storeId: 'store_abc123',
environment: 'production',
});
// Load checkout session
const session = await tagada.checkout.loadSession(checkoutToken, sessionToken);
// Set customer info (stored in memory, sent with address)
await tagada.checkout.updateCustomer(session.id, {
email: '[email protected]',
firstName: 'John',
lastName: 'Doe',
});
// Set address — customer fields are included automatically
await tagada.checkout.updateAddress(session.id, {
shippingAddress: { line1: '10 Rue de la Paix', city: 'Paris', postalCode: '75002', country: 'FR' },
});
// Tokenize card + pay with automatic 3DS / redirect handling
const { tagadaToken } = await tagada.payment.tokenizeCard({
cardNumber: '4242424242424242',
expiryDate: '12/28',
cvc: '123',
});
const result = await tagada.payment.processPayment({
checkoutSessionId: session.id,
tagadaToken,
});
if (result.status === 'succeeded') {
console.log('Payment succeeded!', result.order);
} else if (result.status === 'requires_redirect') {
// SDK handles this automatically in React; in vanilla JS, redirect manually:
window.location.href = result.redirectUrl;
} else if (result.status === 'failed') {
console.error(result.error);
}Quick Start (React)
import { TagadaHeadlessProvider, useCheckout, usePayment } from '@tagadapay/headless-sdk/react';
function App() {
return (
<TagadaHeadlessProvider storeId="store_abc123" environment="production">
<CheckoutPage />
</TagadaHeadlessProvider>
);
}
function CheckoutPage() {
const { session, updateCustomer, updateAddress } = useCheckout(checkoutToken, sessionToken);
const { processPayment, isProcessing, tokenizeCard } = usePayment({
onPaymentSuccess: (result) => router.push('/thank-you'),
onPaymentFailed: (result) => alert(result.error),
});
const handlePay = async () => {
// Customer + address (single atomic API call under the hood)
await updateCustomer({ email, firstName, lastName });
await updateAddress({ shippingAddress: { line1, city, postalCode, country } });
// Tokenize + pay — 3DS redirects and polling are handled automatically
const { tagadaToken } = await tokenizeCard({ cardNumber, expiryDate, cvc });
await processPayment({ checkoutSessionId: session.id, tagadaToken });
// onPaymentSuccess / onPaymentFailed callbacks fire automatically
};
return <button onClick={handlePay} disabled={isProcessing}>Pay Now</button>;
}Payment Flow
processPayment() handles the full payment lifecycle automatically:
- Tokenize → creates a payment instrument from the card
- Pay → submits payment to the processor
- 3DS / Redirect → if the bank requires authentication, the SDK redirects the user and resumes automatically on return
- Poll → waits for async processing to complete
- Result → returns a typed
ProcessPaymentResult
The return type is a discriminated union:
| Status | Meaning |
|--------|---------|
| succeeded | Payment confirmed. Show success screen. |
| requires_redirect | User must visit a URL (3DS, bank auth). Auto-handled in React. |
| failed | Payment declined or errored. result.error has details. |
| pending | Still processing (rare — polling timed out). |
Address Handling
The SDK handles both shipped and digital products:
// Shipped product — billing defaults to shipping
await tagada.checkout.updateAddress(sessionId, {
shippingAddress: { line1: '...', city: '...', country: 'FR' },
});
// Digital product — billing only, no shipping needed
await tagada.checkout.updateAddress(sessionId, {
billingAddress: { country: 'FR' },
});
// Separate billing and shipping
await tagada.checkout.updateAddress(sessionId, {
shippingAddress: { line1: '...', city: '...', country: 'FR' },
billingAddress: { line1: '...', city: '...', country: 'DE' },
});
// Or use the combined method
await tagada.checkout.updateCustomerAndAddress(sessionId, {
customer: { email: '[email protected]', firstName: 'John', lastName: 'Doe' },
shippingAddress: { line1: '...', city: '...', country: 'FR' },
});Modules
| Module | What it does |
|--------|-------------|
| tagada.checkout | Session management — load, update cart, promo codes, shipping |
| tagada.payment | Full payment lifecycle — APMs, tokenize, 3DS, pay, poll, express checkout |
| tagada.offers | Upsells & order bumps — preview, pay, post-purchase accept/decline |
| tagada.customer | CRM data — profile, orders, subscriptions |
| tagada.catalog | Product browsing — list products, variants, prices |
CDN Usage
<script src="https://cdn.jsdelivr.net/npm/@tagadapay/headless-sdk/dist/tagada-headless.min.js"></script>
<script>
const tagada = TagadaHeadless.create({ storeId: 'store_abc123' });
</script>Example
A complete React checkout app is available as a live demo and open-source reference:
- Live demo: headless-react-eta.vercel.app
- Source code: github.com/TagadaPay/examples/tree/main/headless-react
Architecture
- Zero dependencies in core — native
fetch, no axios - Tree-shakeable ESM — unused modules are eliminated by bundlers
- Framework-agnostic core + thin React hooks layer
- TypeScript first — full type coverage, JSDoc on every method
- Optional
@tagadapay/core-jspeer — only needed for client-side card tokenization - Automatic 3DS — handles redirects, iframe challenges, and polling out of the box
Package Exports
| Import path | What you get |
|------------|--------------|
| @tagadapay/headless-sdk | Core client + all modules |
| @tagadapay/headless-sdk/react | React hooks + provider |
License
MIT
