Getting Started

Get up and running with Bloque Payments in minutes. This guide will walk you through setting up both the frontend React component and the backend SDK.

Installation

Frontend (React)

Install the React components package:

npm
yarn
pnpm
bun
deno
npm add @bloque/payments-react

Backend (Node.js/Bun)

Install the backend SDK:

npm
yarn
pnpm
bun
deno
npm add @bloque/payments

API Key

To use Bloque Payments, you'll need an API key. You can obtain one from the Bloque Dashboard.

:::tip API Keys Bloque provides two types of API keys:

  • Public API Key: Can be safely used in the client (frontend) to initialize the SDK.
  • Secret API Key: Should only be used on the backend. Never expose it in client-side code. :::

Quick Start: Complete Integration

Here's a complete example showing how to integrate Bloque Payments with React on the frontend and Node.js/Bun on the backend.

Frontend Setup (React)

import { init, BloqueCheckout } from '@bloque/payments-react';
import type {
  CheckoutConfig,
  AppearanceConfig,
  PaymentResponse,
} from '@bloque/payments-react';

// Initialize SDK (do this once at app startup)
init({
  publicApiKey: 'pk_live_...',
  mode: 'sandbox',
});

function CheckoutPage() {
  // Configuration
  const config: CheckoutConfig = {
    payment_methods: ['card', 'pse', 'cash'],
    amount: 2999, // Amount in smallest currency unit (e.g., cents)
    currency: 'USD',
  };

  // Appearance customization
  const appearance: AppearanceConfig = {
    primaryColor: '#10b981',
    borderRadius: '12px',
    fontFamily: 'Inter, system-ui, sans-serif',
  };

  // Handle payment submission
  const handleSubmit = async (payload) => {
    const response = await fetch('/api/payments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    });

    if (!response.ok) {
      throw new Error('Payment failed');
    }

    return response.json();
  };

  return (
    <BloqueCheckout
      config={config}
      appearance={appearance}
      onSubmit={handleSubmit}
      onSuccess={(response) => {
        console.log('Payment successful!');
        console.log('Payment ID:', response.id);
        console.log('Status:', response.status);
        window.location.href = '/success';
      }}
      onError={(error) => {
        console.error('Payment failed:', error.message);
        alert(`Payment failed: ${error.message}`);
      }}
    />
  );
}

export default CheckoutPage;

Backend Setup (Node.js/Bun)

import { Bloque } from '@bloque/payments';
import express from 'express';

const app = express();
app.use(express.json());

// Initialize Bloque SDK
const bloque = new Bloque({
  apiKey: process.env.BLOQUE_API_KEY!,
  mode: 'production', // or 'sandbox' for testing
});

// Payment endpoint
app.post('/api/payments', async (req, res) => {
  try {
    const payload = req.body;

    // Process payment using Bloque SDK
    const payment = await bloque.payments.create({
      payment: payload,
    });

    res.json(payment);
  } catch (error) {
    console.error('Payment error:', error);
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

Environment Variables

Create a .env file in your backend project:

# .env
BLOQUE_API_KEY=your_api_key_here
BLOQUE_MODE=sandbox  # or 'production'

Load them in your application:

import 'dotenv/config';

const bloque = new Bloque({
  apiKey: process.env.BLOQUE_API_KEY!,
  mode: process.env.BLOQUE_MODE as 'sandbox' | 'production',
});

Configuration Options

SDK Configuration

OptionTypeRequiredDefaultDescription
apiKeystringYes-Your Bloque API key
mode'production' | 'sandbox'Yes-Environment mode
webhookSecretstringNo-Secret for webhook verification

Modes

  • sandbox: For testing and development. No real transactions.
  • production: For live operations with real payments.

Checkout Configuration

Configure the payment experience:

const config: CheckoutConfig = {
  payment_methods: ['card', 'pse', 'cash'], // Available payment methods
  amount: 2999,                           // Amount in smallest currency unit
  currency: 'USD',                           // Currency code
};

Appearance Configuration

Customize the look and feel:

const appearance: AppearanceConfig = {
  primaryColor: '#10b981',                   // Brand color
  borderRadius: '12px',                      // Border radius for inputs
  fontFamily: 'Inter, system-ui, sans-serif', // Font family
};

React Component Props

BloqueCheckout

PropTypeDefaultDescription
configCheckoutConfigundefinedPayment configuration
appearanceAppearanceConfigundefinedUI customization
amountnumberundefinedPayment amount (alternative to config.amount)
availableMethodsPaymentMethodType[]['card', 'pse', 'cash']Available payment methods
requireEmailbooleantrueRequire email for card payments
showMethodSelectorbooleantrueShow payment method selector
onSubmitfunctionundefinedCalled when user submits payment
onSuccessfunctionundefinedCalled on successful payment
onErrorfunctionundefinedCalled on payment error
classNamestringundefinedCSS class name
styleReact.CSSPropertiesundefinedInline styles

Payment Flow

Here's how the payment flow works:

1. User fills payment form in React component

2. Component calls onSubmit with payment data

3. Your frontend sends data to your backend API

4. Your backend processes payment using Bloque SDK

5. Bloque API processes the payment

6. Response flows back to frontend

7. onSuccess or onError callback is triggered

Error Handling

Always implement proper error handling:

<BloqueCheckout
  config={config}
  onSubmit={async (payload) => {
    try {
      const response = await fetch('/api/payments', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message || 'Payment failed');
      }

      return response.json();
    } catch (error) {
      console.error('Payment error:', error);
      throw error;
    }
  }}
  onSuccess={(response) => {
    // Handle success
    console.log('Payment successful:', response.id);
    window.location.href = `/success?payment=${response.id}`;
  }}
  onError={(error) => {
    // Handle error
    console.error('Payment failed:', error);
    alert(`Payment failed: ${error.message}`);
  }}
/>

Backend Error Handling

app.post('/api/payments', async (req, res) => {
  try {
    const payload = req.body;

    const payment = await bloque.payments.create({
      payment: payload,
    });

    res.json(payment);
  } catch (error) {
    console.error('Payment processing error:', error);

    // Send appropriate error response
    const statusCode = error.status || 500;
    res.status(statusCode).json({
      success: false,
      error: error.message,
      code: error.code,
    });
  }
});

TypeScript Support

The SDK is fully typed with TypeScript. Import types for better development experience:

import type {
  BloqueCheckoutProps,
  CheckoutConfig,
  AppearanceConfig,
  PaymentResponse,
  PaymentSubmitPayload,
  PaymentMethodType,
} from '@bloque/payments-react';

// Type-safe configuration
const config: CheckoutConfig = {
  payment_methods: ['card', 'pse'],
  amount: 2999,
  currency: 'USD',
};

// Type-safe event handlers
const handleSuccess = (response: PaymentResponse) => {
  console.log('Payment ID:', response.id);
  console.log('Status:', response.status);
};

Discriminated Union Types

The PaymentSubmitPayload uses discriminated unions for type safety:

import type { PaymentSubmitPayload } from '@bloque/payments-react';

const handleSubmit = async (payload: PaymentSubmitPayload) => {
  // TypeScript automatically narrows the type
  switch (payload.type) {
    case 'card':
      // payload.data is CardPaymentFormData
      console.log('Card ending in:', payload.data.cardNumber.slice(-4));
      break;
    case 'pse':
      // payload.data is PSEPaymentFormData
      console.log('Bank code:', payload.data.bankCode);
      break;
    case 'cash':
      // payload.data is CashPaymentFormData
      console.log('Customer:', payload.data.fullName);
      break;
  }

  // Send to backend...
};

Testing in Sandbox Mode

Use sandbox mode for testing without real transactions:

// Backend
const bloque = new Bloque({
  apiKey: process.env.BLOQUE_API_KEY!,
  mode: 'sandbox', // Test mode
});

Test Card Numbers

Use these test card numbers in sandbox mode:

Card NumberResult
4111111111111111Success
4000000000000002Declined
4000000000000259Insufficient funds

Next Steps

Now that you have basic integration working, explore more features:

Examples

Check out complete examples:

Need Help?