SDK Integration Guide
Use this guide when you want to integrate checkout with the JavaScript SDK. The SDK flow is recommended when you do not want raw card data to touch your application.
Working with an LLM agent? Ask it to read this file first, then implement the server endpoint that creates a payment, the frontend SDK checkout, webhook verification, retries, and status handling according to this guide.
Related integration guides:
- API integration guide:
https://docs.v2.paychtec.com/docs/INTEGRATION_API - SDK integration guide:
https://docs.v2.paychtec.com/docs/INTEGRATION_SDK
LLM Agent Prompt
Read the SDK integration guide at https://docs.v2.paychtec.com/docs/INTEGRATION_SDK and the API integration guide at https://docs.v2.paychtec.com/docs/INTEGRATION_API. Build a merchant SDK integration using the JavaScript SDK. Keep secret keys on the server, use publishable keys in the browser, create payments server-side with confirm=false, pass client_secret to the frontend, confirm payments with the JavaScript SDK, verify webhooks, and update order state from webhook events.
SDK Flow
- Your server creates a payment with
confirm: false. - Your server returns
client_secretandpayment_idto your frontend. - Your frontend initializes the SDK with a publishable key.
- The SDK renders payment UI and collects payment details.
- The SDK confirms the payment and handles required customer actions.
- Your webhook endpoint receives final status updates.
- Your server fulfills the order only after a successful status is confirmed.
Environments
Use sandbox while building and testing:
https://api.sandbox.paychtec.com
Use production only after testing:
https://api.v2.paychtec.com
Use the SDK host for browser SDK assets:
https://sdk.paychtec.com
Keys
Use secret keys only on your server:
api-key: snd_YOUR_SECRET_API_KEYUse publishable keys only in the browser:
pk_snd_YOUR_PUBLISHABLE_KEYNever expose a secret API key in JavaScript sent to the browser.
Server Payload Reference
Create SDK Payment
Your server must create a payment before the SDK can render checkout.
POST /payments
{
"amount": 5000,
"currency": "USD",
"profile_id": "YOUR_PROFILE_ID",
"customer_id": "cus_acme_42",
"confirm": false,
"capture_method": "automatic",
"description": "Order #123",
"return_url": "https://example.com/payment-return",
"metadata": {
"order_id": "order_123",
"cart_id": "cart_456"
}
}Response fields your server should return to the frontend:
{
"payment_id": "pay_1234567890abcdef",
"client_secret": "pay_123_secret_abcdef",
"status": "requires_payment_method"
}Important fields:
| Field | Required | Notes |
|---|---|---|
amount | Yes | Smallest currency unit. |
currency | Yes | Three-letter ISO currency code. |
profile_id | Yes | Merchant business profile for this payment. |
confirm | Yes | Use false; the SDK confirms the payment after collecting details. |
customer_id | No | Recommended for saved payment methods or repeat customers. |
return_url | Recommended | Required for redirect and 3DS flows. |
metadata | No | Store order/cart references only. |
Example Server Endpoint
app.post('/create-payment', async (req, res) => {
const { amount, currency, orderId, customerId } = req.body;
const response = await fetch(`${process.env.API_BASE_URL}/payments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'api-key': process.env.SECRET_API_KEY,
'X-Idempotency-Key': `payment_${orderId}`,
},
body: JSON.stringify({
amount,
currency,
profile_id: process.env.PROFILE_ID,
customer_id: customerId,
confirm: false,
return_url: `${process.env.APP_URL}/payment/return`,
metadata: {
order_id: orderId,
},
}),
});
const payment = await response.json();
if (!response.ok) {
return res.status(response.status).json(payment);
}
res.json({
paymentId: payment.payment_id,
clientSecret: payment.client_secret,
});
});JavaScript SDK Integration
Load The SDK
Use the SDK URL for your environment.
Production SDK script URL:
<script src="https://sdk.paychtec.com/HyperLoader.js"></script>
For sandbox, use the sandbox SDK host:
<script src="https://sdk.sandbox.paychtec.com/web/0.127.0/v1/HyperLoader.js"></script>
HTML
<form id="payment-form">
<div id="payment-element"></div>
<button type="submit" id="submit-button">Pay</button>
<div id="error-message" role="alert"></div>
</form>Client Script
const hyper = Hyper('pk_snd_YOUR_PUBLISHABLE_KEY');
const { clientSecret, paymentId } = await fetch('/create-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 5000,
currency: 'USD',
orderId: 'order_123',
customerId: 'cus_acme_42',
}),
}).then((response) => response.json());
const unifiedCheckout = hyper.widgets({
clientSecret,
appearance: {
variables: {
colorPrimary: '#41175e',
borderRadius: '8px',
},
},
});
const paymentElement = unifiedCheckout.create('payment');
paymentElement.mount('#payment-element');
document.getElementById('payment-form').addEventListener('submit', async (event) => {
event.preventDefault();
const { error, status } = await hyper.confirmPayment({
elements: unifiedCheckout,
confirmParams: {
return_url: `${window.location.origin}/payment/return?payment_id=${paymentId}`,
},
});
if (error) {
document.getElementById('error-message').textContent = error.message;
return;
}
if (status) {
// Show a pending state and wait for your webhook/order status endpoint.
}
});Return URL Handling
Your return_url page should:
- Read the
payment_idfrom the URL or from your stored order session. - Show a processing state first.
- Ask your backend for the latest order or payment status.
- Avoid fulfilling from browser-only state.
- Let your webhook handler perform final fulfillment.
Webhook Payload Shape
The SDK confirms the payment in the browser, but your server should still rely on webhooks for final state.
{
"merchant_id": "1234567890",
"event_id": "evt_1234567890",
"event_type": "payment_succeeded",
"content": {
"type": "payment_details",
"object": {
"payment_id": "pay_1234567890abcdef",
"status": "succeeded",
"amount": 5000,
"currency": "USD",
"metadata": {
"order_id": "order_123"
}
}
},
"timestamp": "2024-01-22T10:20:00Z"
}Webhook handling requirements:
- Read the raw body.
- Verify the signature.
- Process each event once.
- Update your order by
content.object.payment_idorcontent.object.metadata.order_id. - Fulfill only after a successful terminal status.
- Return a fast 2xx response after durable processing or enqueueing.
Status Handling
The SDK may return an immediate error, a redirect, or an intermediate status. Your application should:
- Show inline validation and payment errors from the SDK.
- Redirect or wait when the SDK starts 3DS or another customer action.
- Show an order-processing page after confirmation.
- Poll your backend only as a backup; webhooks should perform final state updates.
- Fulfill from server-side state, not browser-only state.
Production Checklist
- Server creates payments with
confirm: false. - Server returns only
client_secretand safe public data to the browser. - Secret API key is never exposed to frontend code.
- Publishable key is used for SDK initialization.
- Idempotency key is used when creating the payment.
- SDK is loaded from the correct environment host.
return_urlis configured and tested.- Webhook signatures are verified.
- Duplicate webhook events do not duplicate fulfillment.
- Order state is stored server-side.
- Sandbox card, 3DS, redirect, failure, refund, and webhook flows are tested.