Embedded Checkout

Embed a complete checkout form directly in your site using the Checkout Element. It handles card input, 3D Secure, and payment submission - all within a single element you mount to a container.

How it works

1 Create session (server)
2 Initialise SDK (client)
3 Mount checkout element
4 Customer pays inline
Single element - handles everything
Built-in submit button and validation
Customisable with themes and CSS variables
Automatic 3DS challenge handling
onSuccess / onError callbacks
Works with HTML/JS and React

Before getting started

1. Get your credentials

1 Request a development store with an ecommerce subscription from your Teya contact
2 Log in to the Staging Business Portal with your Teya ID
3 Select your store and go to Integrations
4 Create ecommerce API credentials and configure webhook URLs
You'll receive a Client ID and Client Secret for OAuth authentication
Use client_credentials grant to obtain access tokens
Each store has its own set of credentials
Staging vs Production
Use Staging for development and testing. When ready to go live, repeat the credential setup in Production. Keep separate credentials and token caches for each environment.

2. API URLs

ServiceStagingProduction
Online Payments APIhttps://api.teya.xyzhttps://api.teya.com
OAuthhttps://id.teya.xyz/oauth/v2/oauth-tokenhttps://id.teya.com/oauth/v2/oauth-token
Business Portalhttps://business.teya.xyzhttps://business.teya.com

3. Required scopes

Request these scopes when obtaining your access token:

ScopeDescription
checkout/sessions/createCreate a checkout session for the SDK
checkout/sessions/id/getGet checkout session by ID
Integrating on behalf of the merchants you serve?
Partners and platforms get credentials through the merchant registration flow instead. See Take payments online for partners.

Domain Verification

To use Apple Pay within the Embedded Checkout, your domain must be verified with Apple. Follow these steps:

1 Download the domain verification file from the Business Portal under Integrations > Apple Pay
2 Host the file at https://yourdomain.com/.well-known/apple-developer-merchantid-domain-association
3 Click Verify in the Business Portal to complete domain verification
Domain Verification for Apple Pay
Domain verification is only required if you want Apple Pay to appear in the Embedded Checkout. Card payments work without it. Verification must be completed for each domain (including staging and production).

Install the SDK

npm install @teyaproduct/teya-blocks-js

For React applications, also install the React wrapper:

npm install @teyaproduct/teya-blocks-js @teyaproduct/teya-blocks-react

See SDK Initialization for initTeyaBlocks() options, including developmentMode for staging.

Try it - Embed Checkout

Follow the interactive quickstart below to build a working integration with the Checkout element.

0 / 0 steps
server.js — staging
import express from 'express';

const app = express();
let cachedToken = null;
let tokenExpiry = 0;

async function getAccessToken() {
  if (cachedToken && Date.now() < tokenExpiry) return cachedToken;

  const res = await fetch('https://id.teya.xyz/oauth/v2/oauth-token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: process.env.TEYA_CLIENT_ID,
      client_secret: process.env.TEYA_CLIENT_SECRET,
      scope: 'checkout/sessions/create',
    }),
  });

  const data = await res.json();
  cachedToken = data.access_token;
  tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;
  return cachedToken;
}

app.get('/api/session', async (req, res) => {
  const token = await getAccessToken();
  const sessionRes = await fetch(
    'https://api.teya.xyz/v2/checkout/sessions',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
        'Idempotency-Key': crypto.randomUUID(),
      },
      body: JSON.stringify({
        store_id: process.env.TEYA_STORE_ID,
        amount: { currency: 'EUR', value: 1000 },
        type: 'SALE',
      }),
    }
  );

  const session = await sessionRes.json();
  res.json(session);
});

app.listen(3000, () => console.log('Server running on :3000'));
index.html — staging
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Payment</title>
  <style>
    body { font-family: sans-serif; max-width: 480px; margin: 40px auto; padding: 0 20px; }
    #checkout-container { margin: 20px 0; }
    #pay-button { width: 100%; padding: 12px; background: #008BB9; color: #fff; border: none; border-radius: 6px; font-size: 16px; cursor: pointer; }
  </style>
</head>
<body>
  <h1>Complete your payment</h1>
  <div id="checkout-container"></div>
  <script type="module" src="app.js"></script>
</body>
</html>
app.js — staging
import { initTeyaBlocks } from '@teyaproduct/teya-blocks-js';

// Fetch session token from your backend
const res = await fetch('/api/session');
const { session_token } = await res.json();

// Initialize the SDK
const teya = await initTeyaBlocks(session_token, {
  locale: 'en-GB',
  appearance: {
    theme: 'default',

  },
  // Routes SDK calls to Teya staging. Remove for production.
  developmentMode: true,
});

// Create and mount the element
const checkout = teya.elements.create('checkout', {
  onReady: () => console.log('Checkout ready'),
  onSuccess: (response, paymentMethod) => {
    console.log('Paid via', paymentMethod, response);
  },
  onError: (error, paymentMethod) => console.error(paymentMethod, error),
});

checkout.mount('#checkout-container');