Appearance
Tokenizer
Tokenizer is a JavaScript library that injects a secure, hosted payment form into your website via an iframe. When a customer enters their card or bank account details, the information goes directly to our PCI-compliant servers—never touching your website—and you receive a token in return.
This token can then be used in place of the actual payment details for any API call, keeping your website out of PCI scope while giving you full control over the payment flow.

Simple Example
A complete, working payment form in a single HTML file:
html
<!DOCTYPE html>
<html>
<head>
<title>Checkout</title>
<script src="https://sandbox.gosparrowone.com/tokenizer/tokenizer.js"></script>
</head>
<body>
<h1>Checkout</h1>
<div id="payment-form"></div>
<button onclick="tokenizer.submit()">Pay</button>
<script>
var tokenizer = new Tokenizer({
url: 'https://sandbox.gosparrowone.com',
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: function(resp) {
if (resp.status === 'success') {
// Send token to your server to complete payment
// Token is valid for 2 minutes
console.log('Token:', resp.token)
}
}
})
</script>
</body>
</html>That's it. The iframe renders a secure card form, and when the customer clicks "Pay", you receive a token to send to your server.
Why Use Tokenizer?
| Without Tokenizer | With Tokenizer |
|---|---|
| Card numbers pass through your server | Card numbers go directly to the gateway |
| Your site is in PCI scope (SAQ D) | Your site stays out of PCI scope (SAQ A) |
| You must secure and audit your entire infrastructure | Security burden shifts to the gateway |
| Complex compliance requirements | Simplified compliance |
How It Works
Step-by-Step
- Page loads — Your checkout page includes the Tokenizer script
- Iframe appears — Tokenizer creates a secure iframe (hosted by us, not you)
- Customer types card info — Card data goes into the iframe, never your code
- You call
submit()— Iframe sends card data directly to our servers - You get a token — We return a token (good for 2 min) to your callback
- Your server charges it — Use the token in your API call instead of the card number
Token Expiration
Tokens expire after 2 minutes. Complete your API call right away.
Data Flow
| Data | Where It Goes |
|---|---|
| Card number, CVV, expiration | Directly to the gateway via iframe (never touches your server) |
| Token | Returned to your JavaScript callback, then sent to your server |
| Name, address, email, phone | Passed through to your callback (not tokenized, not sent to gateway until you make an API call) |
Steps
1. Add Script
Load the Tokenizer JavaScript library in your HTML <head> or bottom of the body. This script provides the Tokenizer class that creates the secure payment form.
html
<head>
<script src="https://sandbox.gosparrowone.com/tokenizer/tokenizer.js"></script>
</head>2. Add Element
Add a container element where the payment form will render, plus a button to trigger submission. The container can be any element with an ID or class selector.
html
<!-- Tokenizer injects the secure iframe in here -->
<div id="payment-form"></div>
<!-- Your submit button triggers tokenization -->
<button onclick="tokenizer.submit()">Pay Now</button>3. Initialize
Create a new Tokenizer instance with your configuration. The minimum required options are apikey, container, and a submission callback.
javascript
var tokenizer = new Tokenizer({
// Your public API key (from Control Panel → Settings → API Keys)
apikey: 'pub_XXXXXXXXXXXXXX',
// CSS selector where the iframe will be injected
container: '#payment-form',
// Callback when tokenizer.submit() completes
submission: (resp) => {
// Token generated successfully
if (resp.status === 'success') {
console.log('Token:', resp.token)
sendTokenToServer(resp.token)
}
// Form validation failed (empty or invalid fields)
else if (resp.status === 'validation') {
console.log('Invalid fields:', resp.invalid)
}
// Error occurred (network, invalid API key, etc.)
else {
console.log('Error:', resp.msg)
}
}
})4. Use Token
Once your frontend receives the token, send it to your backend server. Your server then makes the actual API call using your secret key (never expose this in frontend code).
Frontend: Send token to your server
javascript
function sendTokenToServer(token) {
fetch('/api/charge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: token,
amount: 1999 // $19.99 in cents
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.href = '/thank-you'
}
})
}Backend: Process the transaction
Your server receives the token and calls the gateway API with your secret key:
json
{
"type": "sale",
"amount": 1999,
"payment_method": {
"token": "the-token-from-tokenizer"
}
}See Transaction Processing for complete API documentation.
Public vs Secret Keys
- Public key (
pub_XXXX) — Used in Tokenizer on your frontend. Safe to expose in browser code. - Secret key — Used for server-side API calls. Never expose in frontend code.
Token Expiration
Tokens expire after 2 minutes. Complete your API call immediately after receiving the token.
Default Output

Configuration
Local Dev
When developing locally, set the url option to point to the API:
javascript
var tokenizer = new Tokenizer({
url: 'https://sandbox.gosparrowone.com', // Required for localhost
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: (resp) => { console.log(resp) }
})API Key URL Restrictions
If your public API key has URL restrictions, add both your website URL and the url you set in Tokenizer to the allowed list. The iframe makes requests from the configured URL.
Payments
Tokenizer supports credit/debit cards and ACH. By default, only card is enabled.
javascript
var tokenizer = new Tokenizer({
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: (resp) => { console.log(resp) },
settings: {
payment: {
types: ['card', 'ach'], // Enable both card and ACH
card: {
requireCVV: true, // Require CVV entry
strict_mode: false, // Set true for 19-digit cards
mask_number: true // Mask card number as user types
},
ach: {
sec_code: 'web', // Default SEC code: web, ccd, ppd, tel
showSecCode: false, // Show SEC code dropdown to user
verifyAccountRouting: true // Validate routing numbers
}
}
}
})Extra Fields
Tokenizer can collect billing, shipping, and user information alongside payment details. This data is not tokenized—it's passed through to your callback for you to use in API calls.
javascript
var tokenizer = new Tokenizer({
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: (resp) => {
console.log(resp.token) // Tokenized payment data
console.log(resp.user) // Name, email, phone (if enabled)
console.log(resp.billing) // Billing address (if enabled)
console.log(resp.shipping) // Shipping address (if enabled)
},
settings: {
user: {
showName: true,
showEmail: true,
showPhone: true,
showTitle: true,
showInline: true
},
billing: {
show: true,
showTitle: true
},
shipping: {
show: true,
showTitle: true
}
}
})Fees
Automatically calculate surcharges or service fees based on the payment type and processor:
javascript
var tokenizer = new Tokenizer({
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
amount: 2500, // Base amount in cents ($25.00)
settings: {
payment: {
calculateFees: true,
processorId: 'optional-processor-id' // Uses default if not specified
}
},
validCard: (card) => {
// Called when a valid card is entered
console.log('Service Fee:', card.ServiceFee)
console.log('Surcharge:', card.Surcharge)
console.log('Disclosure:', card.Disclosure) // Text to show cardholder
},
submission: (resp) => { console.log(resp) }
})Callbacks
| Callback | When It Fires | Use Case |
|---|---|---|
submission | After submit() completes | Handle token, errors, or validation failures |
onLoad | Iframe finished loading | Show loading spinner until ready |
onPaymentChange | User switches between card/ACH | Update UI or fee display |
validCard | Valid card number entered | Display card type, check surchargeability, show fees |
achOnChange | ACH account type or SEC code changes | Update UI based on ACH selection |
magStripeSwipe | Card swipe detected | Handle card reader input |
Submission
javascript
submission: (resp) => {
switch(resp.status) {
case 'success':
// Token generated successfully
sendToServer(resp.token)
break
case 'validation':
// Form validation failed - show errors to user
resp.invalid.forEach(field => {
console.log('Invalid field:', field)
})
break
case 'error':
// Server error occurred
console.log('Error:', resp.msg)
break
}
}Valid Card
javascript
validCard: (card) => {
console.log(card.isValid) // true if passes Luhn check
console.log(card.bin) // BIN data (card type, issuer, etc.)
// If calculateFees is enabled:
console.log(card.RequestedAmount) // Base transaction amount
console.log(card.ServiceFee) // Service fee to add
console.log(card.Surcharge) // Surcharge amount
console.log(card.PaymentAdjustment) // { value, type }
console.log(card.Disclosure) // Surcharge disclosure text
// Check if card is surchargeable in a specific state
var canSurcharge = tokenizer.isSurchargeable('IL', card.bin)
}Methods
| Method | Description |
|---|---|
tokenizer.submit() | Submit the form and generate a token |
tokenizer.submit('5.00') | Submit with amount (required for 3DS/Paay) |
tokenizer.setError('cvv') | Highlight a field as invalid |
tokenizer.setExpDate('12/25') | Programmatically set expiration date |
tokenizer.isSurchargeable(state, bin) | Check if card can be surcharged |
Styling
Pass CSS styles to customize the iframe's appearance:
javascript
var tokenizer = new Tokenizer({
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: (resp) => { console.log(resp) },
settings: {
styles: {
body: {
color: '#333333'
},
input: {
'border-radius': '4px',
'border': '1px solid #cccccc',
'padding': '10px',
'font-size': '16px'
},
'input:focus': {
'border-color': '#0066cc',
'outline': 'none'
},
'.payment .cvv input': {
'width': '80px'
}
}
}
})Inspecting Elements
Use your browser's developer tools to inspect the iframe and identify CSS selectors for styling specific elements.
Examples
Default

Dark Mode

Purple

Advanced
3DS (Paay)
If 3DS is enabled on your account, Tokenizer handles authentication automatically:
javascript
var tokenizer = new Tokenizer({
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: (resp) => {
console.log(resp.paay) // 3DS authentication results
},
settings: {
paay: {
sandbox: false, // Use sandbox for testing
forceDisabled: false, // Set true to skip 3DS
rejectChallenges: [] // Statuses to reject
}
}
})
// Amount is required for 3DS (otherwise runs as Non-Payment Authentication)
tokenizer.submit('25.00')Card Readers
Tokenizer automatically detects card swipe input when the card number field is focused. The magStripeSwipe callback fires when a swipe is detected.
SPAs
For single page applications, Tokenizer outputs as UMD. Import it in your main file:
javascript
import './tokenizer.js'
// Now available globally
new Tokenizer({
apikey: 'pub_XXXXXXXXXXXXXX',
container: '#payment-form',
submission: (resp) => { console.log(resp) }
})Examples
Sale
See Transaction Processing for more details.
Add to Vault
Integrations
Konnektive
When using Tokenizer with Konnektive CRM, submit the token in the formCardNonce field to their Order Import API.
Troubleshooting
| Issue | Solution |
|---|---|
| Iframe not loading | Verify the container element exists before initializing Tokenizer |
| Token request fails on localhost | Set the url option to your API endpoint |
| API key error | Ensure you're using a public key (pub_XXXX), not your secret key |
| Token expired | Tokens last 2 minutes—complete your API call immediately after receiving it |
| Styles not applying | Inspect the iframe to find correct CSS selectors |
| URL restriction error | Add both your site URL and the Tokenizer url to your API key's allowed URLs |