Skip to Content
VantraAPI Docs
API reference

JavaScript request helpers

Preview, copy, and understand every helper function.

Downloading is optional: preview and copy the complete code below. Download the file.

Use these functions on a Node.js server, in Express, or in a Next.js Node.js Route Handler. No npm dependencies are required. Copy the complete module below into vantra-client.mjs (or src/lib/vantra-client.mjs in Next.js).

Function reference

signRequest

signRequest({ secret, timestamp, body = "" })

Returns lowercase HMAC-SHA256 of timestamp + dot + body using the API secret. Timestamp is Unix seconds; body is the exact serialized JSON to transmit, or empty for a bodyless GET. Method, URL and idempotency key are not signed. This function does not send a request.

gatewayRequest

await gatewayRequest({ origin, apiKey, secret, method = "POST", path, data, idempotencyKey = "", fetchImpl = fetch })

Signs and sends one request. origin is the deployment origin without /api/v1; path must start with /api/v1/. data is a JSON-serializable object, or omit it for an empty body. Payment creation does not require idempotencyKey; omit it to send no header. Supply orderId in data for duplicate-order checks. fetchImpl is an optional fetch-compatible function for tests. Returns the HTTP envelope’s data, not the whole envelope. Non-2xx responses throw an Error with status and response; retain these for reconciliation. Network/JSON failures also propagate. Redirects are rejected and no automatic retries occur.

Complete source code

vantra-client.mjs
import { createHmac } from 'node:crypto';

export function signRequest({ secret, timestamp, body = '' }) {
  return createHmac('sha256', secret)
    .update(`${timestamp}.${body}`)
    .digest('hex');
}

// Server-side only. Supply the deployed API origin (without /api/v1).
export async function gatewayRequest({ origin, apiKey, secret, method = 'POST', path,
  data, idempotencyKey = '', fetchImpl = fetch }) {
  if (!origin || !apiKey || !secret) throw new Error('Set the API origin and server-side credentials');
  if (!path.startsWith('/api/v1/')) throw new Error('Use an /api/v1/ path');
  const url = new URL(path, origin);
  if (url.origin !== new URL(origin).origin) throw new Error('Unexpected API origin');
  const body = data === undefined ? '' : JSON.stringify(data);
  const timestamp = Math.floor(Date.now() / 1000).toString();
  const response = await fetchImpl(url, {
    method,
    redirect: 'error',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey,
      'x-timestamp': timestamp,
      'x-signature': signRequest({ secret, timestamp, body }),
      ...(idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : {}),
    },
    ...(body ? { body } : {}),
  });
  const result = await response.json();
  if (!response.ok) {
    const error = new Error(`Vantra HTTP ${response.status}`);
    error.status = response.status;
    error.response = result; // retain transactionId for reconciliation after an unresolved result
    throw error;
  }
  return result.data;
}

Payment examples · Callback examples

On this page