Skip to main content
Version: 2019-05-29 (Current)

Tokens API

Overviewโ€‹

The Tokens API enables you to securely tokenize credit card information without handling sensitive card data on your servers. Tokens are single-use, encrypted references to card data that can be used to create charges.

What are Tokens?โ€‹

Tokens are temporary, single-use representations of credit card information that:

  • Expire after use - Each token can only be used once to create a charge or attach to a customer
  • Protect card data - Your server never handles raw card details
  • Enable PCI compliance - Reduces your PCI compliance scope significantly
  • Validate immediately - Card details are validated during tokenization

Key Featuresโ€‹

Security Firstโ€‹

  • Public key authentication - Use your public key (safe to expose in client-side code)
  • Single-use tokens - Tokens cannot be reused after creating a charge
  • No sensitive data storage - Card data never touches your servers
  • PCI DSS compliant - Meets strictest security standards

Easy Integrationโ€‹

  • Client-side tokenization - Create tokens directly from browser/mobile app
  • Omise.js library - Pre-built JavaScript library for easy integration
  • Mobile SDKs - Native iOS and Android SDKs available
  • Server-to-server - API available for server-side tokenization when needed

Flexibilityโ€‹

  • Works with all card types - Visa, Mastercard, JCB, etc.
  • 3D Secure support - Automatic 3DS handling
  • Card validation - Validates card number, CVV, expiration
  • International support - Process cards from any country

How Tokens Workโ€‹

Standard Flowโ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Client โ”‚ โ”‚ Omise.jsโ”‚ โ”‚ Your โ”‚ โ”‚ Omise โ”‚
โ”‚ Browser โ”‚ โ”‚ Library โ”‚ โ”‚ Server โ”‚ โ”‚ API โ”‚
โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ 1. Enter card โ”‚ โ”‚ โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ 2. Create token โ”‚ โ”‚
โ”‚ โ”‚ (with public key) โ”‚
โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ 3. Return token โ”‚ โ”‚
โ”‚ โ”‚<โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ 4. Send token ID โ”‚ โ”‚ โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ 5. Create charge โ”‚
โ”‚ โ”‚ โ”‚ (with secret key)
โ”‚ โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>โ”‚
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ โ”‚ โ”‚ 6. Charge result โ”‚
โ”‚ โ”‚ โ”‚<โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ โ”‚ โ”‚ โ”‚
โ”‚ 7. Show result โ”‚ โ”‚ โ”‚
โ”‚<โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚
โ”‚ โ”‚ โ”‚ โ”‚

Implementation Stepsโ€‹

  1. Client-side: Collect card details in your payment form
  2. Client-side: Use Omise.js to tokenize card data with your public key
  3. Client-side: Send token ID to your server (safe - it's single-use)
  4. Server-side: Create charge using token ID with your secret key
  5. Server-side: Return payment result to client

Token Lifecycleโ€‹

Statesโ€‹

StateDescriptionCan Create Charge?
ActiveNewly created, unused tokenโœ… Yes
UsedToken used to create charge/customerโŒ No - Error "used_token"
ExpiredToken older than 30 minutesโŒ No - Error "token_expired"

State Transitionsโ€‹

Tokens move through states based on the following triggers:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Active โ”‚ โ† Token created via Omise.js or API
โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜
โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ โ”‚
โ–ผ โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Used โ”‚ โ”‚ Expired โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Transition Triggers:

From StateTo StateTriggerError Code
Active โ†’ UsedToken used in POST /charges or POST /customers/:id/cards-
Active โ†’ Expired30 minutes pass since creationtoken_expired
Used โ†’ sameAttempt to reuse tokenused_token
Expired โ†’ sameAttempt to use expired tokentoken_expired

Examples of State Transitions:

// 1. Create token (Active state)
const token = await omise.tokens.create({
card: {
number: '4242424242424242',
expiration_month: 12,
expiration_year: 2027,
security_code: '123',
name: 'JOHN DOE'
}
});
console.log(token.used); // false (Active)

// 2. Create charge (Active โ†’ Used)
const charge = await omise.charges.create({
amount: 100000,
currency: 'thb',
card: token.id
});
// Token is now marked as Used

// 3. Attempt to reuse (Error: used_token)
try {
await omise.charges.create({
amount: 50000,
currency: 'thb',
card: token.id // Same token
});
} catch (error) {
console.error(error.code); // "used_token"
console.error(error.message); // "token was already used"
}

// 4. Token expires after 30 minutes (Active โ†’ Expired)
// Automatic - no action needed
// If unused for 30+ minutes, token.used === false but API returns token_expired

Expiration Rulesโ€‹

  • Automatic expiration: 30 minutes after creation
  • Single-use: Immediately marked as used after first charge/customer attachment
  • No reuse: Cannot be reused even for same customer
  • Irreversible: Used and expired tokens cannot be reactivated

API Endpointsโ€‹

MethodEndpointDescription
POST/tokensCreate a new token from card data
GET/tokens/:idRetrieve token information

Quick Startโ€‹

<!-- 1. Include Omise.js -->
<script src="https://cdn.omise.co/omise.js"></script>

<script>
// 2. Set your public key
Omise.setPublicKey('pkey_test_YOUR_PUBLIC_KEY');

// 3. Tokenize card
const cardData = {
name: 'JOHN DOE',
number: '4242424242424242',
expiration_month: 12,
expiration_year: 2025,
security_code: '123'
};

Omise.createToken('card', cardData, (statusCode, response) => {
if (statusCode === 200) {
// Success - token created
const tokenId = response.id;

// 4. Send token to your server
fetch('/charge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: tokenId, amount: 100000 })
})
.then(res => res.json())
.then(data => {
console.log('Charge created:', data.id);
})
.catch(err => {
console.error('Charge failed:', err);
alert('Payment processing failed. Please try again.');
});
} else {
// Tokenization failed - handle specific errors
console.error('Tokenization failed:', response);

// Handle common error codes
switch (response.code) {
case 'invalid_card':
alert('Invalid card number. Please check and try again.');
break;
case 'invalid_expiration_date':
alert('Invalid expiration date. Please check and try again.');
break;
case 'invalid_security_code':
alert('Invalid CVV/security code. Please check and try again.');
break;
case 'network_error':
alert('Network error. Please check your connection and try again.');
break;
default:
alert('Payment failed: ' + response.message);
}
}
});
</script>

Server-side Processingโ€‹

// Node.js example
const omise = require('omise')({
secretKey: 'skey_test_YOUR_SECRET_KEY'
});

// Receive token from client
app.post('/charge', async (req, res) => {
const { token, amount } = req.body;

try {
// Create charge with token
const charge = await omise.charges.create({
amount: amount,
currency: 'thb',
card: token // Use token here
});

res.json({ success: true, charge: charge });
} catch (error) {
res.status(400).json({ error: error.message });
}
});

Common Use Casesโ€‹

Single Paymentโ€‹

Create token โ†’ Create charge โ†’ Done

// Client: Tokenize
Omise.createToken('card', cardData, (status, response) => {
// Server: Charge
omise.charges.create({ card: response.id, amount: 100000 });
});

Save Card for Laterโ€‹

Create token โ†’ Attach to customer โ†’ Charge customer

// Create customer with token
const customer = await omise.customers.create({
email: 'john@example.com',
card: tokenId
});

// Later: Charge customer's saved card
const charge = await omise.charges.create({
customer: customer.id,
amount: 100000
});

Multiple Cards per Customerโ€‹

Create token โ†’ Attach to existing customer โ†’ Select card to charge

// Add card to customer
const card = await omise.customers.updateCard(customerId, {
card: tokenId
});

// Charge specific card
const charge = await omise.charges.create({
customer: customerId,
card: card.id,
amount: 100000
});

Security Best Practicesโ€‹

โœ… Do Thisโ€‹

  • Use HTTPS for all pages with payment forms
  • Use Omise.js for client-side tokenization
  • Validate on server - Don't trust client-side validation alone
  • Never log tokens in plain text
  • Use public key client-side only
  • Use secret key server-side only
  • Implement CSP headers to prevent XSS attacks

โŒ Don't Do Thisโ€‹

  • Don't send card data to your server (use tokenization)
  • Don't store card numbers in your database
  • Don't reuse tokens (they're single-use)
  • Don't expose secret key in client-side code
  • Don't skip server-side validation
  • Don't tokenize on server unless necessary (use client-side)

Testingโ€‹

Test Card Numbersโ€‹

Use these test cards in test mode:

Card NumberDescriptionResult
4242424242424242VisaSuccessful charge
5555555555554444MastercardSuccessful charge
4111111111111111VisaSuccessful charge
4000000000000002VisaCard declined

Test Modeโ€‹

  • Use your test public key: pkey_test_...
  • Tokens created with test keys only work with test secret keys
  • No real money is charged in test mode

Error Handlingโ€‹

Common token errors:

Error CodeDescriptionSolution
invalid_cardInvalid card numberCheck card number format
invalid_expiration_dateInvalid or expired dateVerify expiration month/year
invalid_security_codeInvalid CVVCheck CVV is 3-4 digits
used_tokenToken already usedCreate new token
token_not_foundToken doesn't existVerify token ID

API Referenceโ€‹

SDKs and Librariesโ€‹


Need help? Check our Security Guide or contact support@omise.co