Skip to main content
Accept debit and credit card payments through Payvessel’s card payment APIs. Card flows support 3D Secure (3DS), OTP, and PIN authentication depending on the issuer.

Base URLs

EnvironmentBase URL
Productionhttps://api.payvessel.com
Sandboxhttps://sandbox.payvessel.com
All card endpoints live under /pms/checkout/card-payment/.

Authentication

Every request must include:
HeaderRequiredDescription
api-keyYesYour Payvessel public API key (safe for frontend)
api-secretYes (for charge/validate)Bearer YOUR_SECRET_KEYnever expose in client-side code
Content-TypeYesapplication/json
Security: Use the public key only to encrypt card data. Never send the secret key from the browser. Charge and validate calls must be made from your backend.

Typical flow (production-ready)

  1. Get public key (frontend or backend) → encrypt card details.
  2. Charge (backend only) → send encrypted card + key; may return pending for 3DS/OTP/PIN.
  3. Validate OTP / PIN / Phone (backend) when required.
  4. Confirm status (backend) → poll or callback to get final success/failure.
Below is production-style code with comments for a minimal backend charge + confirm flow. Replace with your own error handling, logging, and idempotency as needed.
// =============================================================================
// CARD PAYMENT — BACKEND (Node.js). Never expose API secret to the client.
// =============================================================================

const PAYVESSEL_BASE = process.env.PAYVESSEL_BASE_URL || 'https://api.payvessel.com';
const API_KEY = process.env.PAYVESSEL_API_KEY;
const API_SECRET = process.env.PAYVESSEL_API_SECRET;

const headers = {
  'Content-Type': 'application/json',
  'api-key': API_KEY,
  'api-secret': `Bearer ${API_SECRET}`,
};

/**
 * Step 1 — Charge the card with encrypted payload from your frontend.
 * Frontend must encrypt card using the public key from GET /pms/checkout/card-payment/public-key/
 */
async function chargeCard(encryptedCardData, encryptionKey, reference) {
  const res = await fetch(`${PAYVESSEL_BASE}/pms/checkout/card-payment/charge/`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      cardData: encryptedCardData,  // from your frontend (encrypted with public key)
      key: encryptionKey,
      reference,                    // unique per transaction, e.g. txn_xxx
    }),
  });

  const data = await res.json();
  if (!res.ok) {
    throw new Error(data.message || 'Charge failed');
  }
  return data;
}

/**
 * Step 2 — If the issuer requires OTP, call this after the customer submits OTP.
 */
async function validateOtp(transactionRef, otp) {
  const res = await fetch(`${PAYVESSEL_BASE}/pms/checkout/card-payment/validate-otp/`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      transactionRef,
      otp,
    }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.message || 'OTP validation failed');
  return data;
}

/**
 * Step 3 — If the issuer requires PIN, call this with the card PIN.
 */
async function validatePin(transactionRef, pin) {
  const res = await fetch(`${PAYVESSEL_BASE}/pms/checkout/card-payment/validate-pin/`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      transactionRef,
      pin,
    }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.message || 'PIN validation failed');
  return data;
}

/**
 * Step 4 — Confirm final status (poll or call after redirect/callback).
 */
async function confirmPaymentStatus(transactionRef) {
  const res = await fetch(
    `${PAYVESSEL_BASE}/pms/checkout/card-payment/confirm-status/?reference=${encodeURIComponent(transactionRef)}`,
    { headers }
  );
  const data = await res.json();
  if (!res.ok) throw new Error(data.message || 'Confirm status failed');
  return data;
}

// Example usage (pseudo): charge → then if pending, validate OTP or PIN → then confirm status
// const chargeResult = await chargeCard(cardData, key, 'txn_123');
// if (chargeResult.status === 'pending' && chargeResult.requiresOtp) {
//   await validateOtp(chargeResult.transactionRef, userEnteredOtp);
// }
// const final = await confirmPaymentStatus(chargeResult.transactionRef);

Endpoints quick reference

ActionMethodEndpoint
Get public keyGET/pms/checkout/card-payment/public-key/
ChargePOST/pms/checkout/card-payment/charge/
Confirm statusGET/pms/checkout/card-payment/confirm-status/
Resend OTPPOST/pms/checkout/card-payment/resend-otp/
Resolve BINGET/pms/checkout/card-payment/resolve-bin/{bin}/
Validate OTPPOST/pms/checkout/card-payment/validate-otp/
Validate phonePOST/pms/checkout/card-payment/validate-phone/
Validate PINPOST/pms/checkout/card-payment/validate-pin/
Simulate 3DS (sandbox only)GET/pms/checkout/card-payment/simulate-3ds-callback/

Testing (sandbox)

  • Use sandbox base URL and sandbox API keys.
  • Use test card numbers and OTP/PIN values from the Testing guide.
  • Simulate 3DS: GET .../simulate-3ds-callback/?status=success&transactionId=YOUR_TXN_ID (sandbox only).
For a ready-made hosted checkout (cards + bank transfer), use Payvessel Checkout and the payvessel-checkout npm package.