Terminal quickstart

Accept card-present payments on supported hardware with the @watenga/terminal SDK. The flow is connect → startSession → collectPaymentMethod → processPayment.

Initialise and connect

typescript
import { WatengaTerminal } from '@watenga/terminal';

// WatengaTerminal is a factory — it returns a terminal instance.
const terminal = WatengaTerminal({
  publicKey: 'pk_test_...',          // publishable key only — never the secret key
  apiBaseUrl: 'https://api.watenga.africa',
  deviceType: 'sunmi',               // sunmi | pax | telpo | zcs | newland | ingenico | generic
  terminalSerial: 'SUNMI-ABC123',    // a registered reader serial
  mode: 'sandbox',                   // 'live' enforces tamper + firmware checks
});

// connect() takes no arguments — it runs tamper/firmware checks then
// connects the card reader. Throws if the device is not trusted.
await terminal.connect();

Session tokens, not secret keys

The SDK never sees your secret key. Your host POS server exchanges its secret key for a short-lived sessionToken (via POST /v1/terminal/sessions) and passes only that token to the SDK.

Start a payment session

typescript
// 1. Your POS server mints a short-lived session token using its SECRET key:
//      POST /v1/terminal/sessions  ->  { sessionToken }
//    The SDK only ever sees the sessionToken, never the secret key.
terminal.startSession({
  sessionToken: process.env.WATENGA_SESSION_TOKEN,
  amount: 25.0,
  currency: 'USD',
  reference: 'POS-001',
});

Collect and process the payment

typescript
const request = { amount: 25.0, currency: 'USD', reference: 'POS-001' };

// 2. Read the card (chip / tap / swipe). Returns an opaque encrypted blob.
const cardResult = await terminal.collectPaymentMethod(request);

// 3. Submit to the gateway via POST /v1/terminals/process.
const result = await terminal.processPayment(cardResult, request);

if (result.status === 'approved') {
  console.log(result.transactionId, result.authCode);
  // The receipt is printed automatically on approval (result.receiptData).
}

On approval the SDK prints the receipt immediately — it does not wait for API confirmation. Print failures are logged but never fail the transaction. You can reprint at any time:

typescript
if (result.receiptData) {
  await terminal.printReceipt(result.receiptData);
}