The Moment JavaScript SDK enables seamless payment integration into any web application. Whether you need a modal overlay or inline embedded checkout — the SDK handles it all with a simple, unified API.Built with vanilla JavaScript (no dependencies), the SDK works with any frontend framework or plain HTML pages.
Page loads — Moment(clientKey) creates an SDK instance; moment.checkout() is called to create a checkout instance with your fetchClientToken, fetchSessionStatus, and event callbacks (onSuccess, onFailure, etc.)
Customer clicks Pay — checkout.launch() is called
SDK calls fetchClientToken — your callback creates a session on your backend (with a success_url) and returns the client_token
Checkout opens in your chosen variant (modal or inline)
Customer submits payment — Moment takes over the full page and redirects to the authentication page
Customer completes authentication on the external page
Customer is redirected back to your success_url with ?session_id=abc123 appended
Page loads again — moment.checkout() detects the session_id in the URL automatically and calls your fetchSessionStatus('abc123') callback
Your callback fetches the status from your backend, which queries Moment API
SDK routes to the right handler — onSuccess, onFailure, onExpired, or onCancel — and removes session_id from the URL silently
Webhooks are delivered to your backend regardless of outcome
Call Moment(clientKey) once when your page loads to create an SDK instance. Then call moment.checkout() with your fetch callbacks and event handlers — it returns a checkout instance, and the SDK calls your callbacks automatically at the right moments, so you never manage tokens or session IDs manually.Backend endpoints:
Node.js
Python
Go
Firebase
Supabase
Lambda
server.js
// Called by fetchClientToken when checkout.launch() is triggeredapp.post('/api/create-payment-session', async (req, res) => { const response = await fetch('https://api.momentpay.net/collect/payment_sessions', { method: 'POST', headers: { 'Authorization': 'Bearer sk_test_your_secret_key', 'Content-Type': 'application/json', }, body: JSON.stringify({ amount: 10000, // Amount in cents (e.g., R100.00) currency: 'ZAR', type: 'one_time', options: { checkout_options: { presentation_mode: { mode: 'embedded' }, success_url: 'https://yoursite.com/checkout?session_id={SESSION_ID}', // required for redirect payments }, }, }), }); const { client_token } = await response.json(); res.json({ client_token });});// Called by fetchSessionStatus after customer returns from a redirect payment.// The SDK extracts session_id from the URL (?session_id=abc123) and passes it here.app.get('/api/session-status', async (req, res) => { const sessionId = req.query.session_id; const response = await fetch( `https://api.momentpay.net/collect/payment_sessions/${sessionId}`, { headers: { 'Authorization': 'Bearer sk_test_your_secret_key' } } ); const session = await response.json(); res.json({ status: session.status, ...session });});
server.py
import requestsfrom flask import Flask, request, jsonifyapp = Flask(__name__)SECRET_KEY = 'sk_test_your_secret_key'# Called by fetchClientToken when checkout.launch() is triggered@app.route('/api/create-payment-session', methods=['POST'])def create_payment_session(): response = requests.post( 'https://api.momentpay.net/collect/payment_sessions', headers={ 'Authorization': f'Bearer {SECRET_KEY}', 'Content-Type': 'application/json', }, json={ 'amount': 10000, # Amount in cents (e.g., R100.00) 'currency': 'ZAR', 'type': 'one_time', 'options': { 'checkout_options': { 'presentation_mode': {'mode': 'embedded'}, 'success_url': 'https://yoursite.com/checkout?session_id={SESSION_ID}', # required for redirect payments }, }, }, ) data = response.json() return jsonify({'client_token': data['client_token']})# Called by fetchSessionStatus after customer returns from a redirect payment.# The SDK extracts session_id from the URL (?session_id=abc123) and passes it here.@app.route('/api/session-status', methods=['GET'])def get_session_status(): session_id = request.args.get('session_id') response = requests.get( f'https://api.momentpay.net/collect/payment_sessions/{session_id}', headers={'Authorization': f'Bearer {SECRET_KEY}'}, ) session = response.json() return jsonify({'status': session['status'], **session})
server.go
package mainimport ( "bytes" "encoding/json" "fmt" "io" "net/http")const secretKey = "sk_test_your_secret_key"const momentAPI = "https://api.momentpay.net"// Called by fetchClientToken when checkout.launch() is triggeredfunc createPaymentSession(w http.ResponseWriter, r *http.Request) { payload, _ := json.Marshal(map[string]any{ "amount": 10000, // Amount in cents (e.g., R100.00) "currency": "ZAR", "type": "one_time", "options": map[string]any{ "checkout_options": map[string]any{ "presentation_mode": map[string]string{"mode": "embedded"}, "success_url": "https://yoursite.com/checkout?session_id={SESSION_ID}", // required for redirect payments }, }, }) req, _ := http.NewRequest("POST", momentAPI+"/collect/payment_sessions", bytes.NewBuffer(payload)) req.Header.Set("Authorization", "Bearer "+secretKey) req.Header.Set("Content-Type", "application/json") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() var result map[string]any json.NewDecoder(resp.Body).Decode(&result) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]any{"client_token": result["client_token"]})}// Called by fetchSessionStatus after customer returns from a redirect payment.// The SDK extracts session_id from the URL (?session_id=abc123) and passes it here.func getSessionStatus(w http.ResponseWriter, r *http.Request) { sessionID := r.URL.Query().Get("session_id") req, _ := http.NewRequest("GET", fmt.Sprintf("%s/collect/payment_sessions/%s", momentAPI, sessionID), nil) req.Header.Set("Authorization", "Bearer "+secretKey) resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) w.Header().Set("Content-Type", "application/json") w.Write(body)}func main() { http.HandleFunc("/api/create-payment-session", createPaymentSession) http.HandleFunc("/api/session-status", getSessionStatus) http.ListenAndServe(":8080", nil)}
Factory function — creates an isolated SDK instance scoped to your publishable key. Returns an object with product namespaces (checkout, and more in the future).
Parameter
Type
Required
Description
clientKey
string
Yes
Your publishable key (pk_test_... or pk_live_...). Determines sandbox vs. production environment.
Creates and returns a checkout instance for this SDK. Detects any ?session_id= in the current URL and automatically calls fetchSessionStatus if provided. Returns a checkout object with launch, close, and submit methods.
Parameter
Type
Required
Description
fetchClientToken
function
Yes
Async function returning Promise<string> — a fresh client token. Called by the SDK when checkout.launch() is invoked.
fetchSessionStatus
function
No
Async function receiving a sessionId string, returning Promise<{ status: string, ... }>. Called when a session_id is found in the URL after a redirect-based payment. Required only if you use redirect mode.
onSuccess
function
No
Callback fired when payment succeeds (both embedded and redirect flows)
onFailure
function
No
Callback fired when payment fails
onCancel
function
No
Callback fired when user cancels
onAttemptFailed
function
No
Callback fired when a payment attempt fails (user can retry)
Opens the payment checkout. Internally calls your fetchClientToken function to retrieve a fresh token, then opens checkout. The display variant (modal or inline) is determined from the JWT payload variant claim, which is set when creating the session on your backend.
Parameter
Type
Required
Description
options.container
string or Element
No
CSS selector or DOM element — for inline variant only
Returns a Promise that resolves with { checkoutUrl, variant } once the checkout is open.Examples:
// Open checkout — SDK fetches token via your fetchClientToken callbackcheckout.launch();// Inline checkout with custom containercheckout.launch({ container: '#checkout-container' });
Triggers payment submission from outside the iframe — useful when you want an external “Pay” button rather than relying on the checkout UI’s built-in submit. Only available for the inline variant.
// Wire up an external Pay buttondocument.getElementById('payBtn').addEventListener('click', () => { checkout.submit();});