đźš§ Bloque documentation is under development

Getting Started

Ship your first payment end-to-end (server + frontend + webhook) in minutes.

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 Keys

To use Bloque Payments, you'll need API keys. You can obtain them from the Bloque Dashboard.

Bloque uses a three-credential model:

CredentialPrefixWherePurpose
Secret keysk_test_ / sk_live_Server onlyExchanged for a short-lived JWT via /origins/api-keys/exchange
Publishable keypk_test_ / pk_live_BrowserIdentifies the merchant; safe to expose in client-side code
Client secretJWTBrowserCheckout-scoped JWT returned when creating a checkout with a secret key
Secret Key Security

Your secret key (sk_live_...) must never be exposed in client-side code. It should only be used on the server.

How It Works

1. Your backend creates a checkout session using @bloque/payments (secret key)
   ↓
2. Backend receives checkout_id + client_secret
   ↓
3. Pass checkout_id and client_secret to React component
   ↓
4. Component renders iframe with the checkout (publishable key + client secret)
   ↓
5. User completes payment (with 3D Secure if required)
   ↓
6. onSuccess/onError/onPending callbacks are triggered
7. Your webhook receives payment.status.updated for finality

Quick Start: Complete Integration (Hosted Checkout)

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

Backend Setup (Node.js/Bun)

First, create an endpoint to generate checkout sessions:

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

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

// Initialize Bloque SDK with your secret key
const bloque = new Bloque({
  secretKey: process.env.BLOQUE_SECRET_KEY!,
  mode: 'production', // or 'sandbox' for testing
});

// Checkout endpoint
app.post('/api/create-checkout', async (req, res) => {
  try {
    // 1) Create a checkout (payment link)
    const checkout = await bloque.checkout.create({
      name: 'My Product',
      description: 'Product description',
      items: [
        {
          name: 'Product',
          amount: 2999, // Amount in smallest currency unit (e.g., cents)
          quantity: 1,
        },
      ],
      success_url: 'https://yourapp.com/success',
    });

    // 2) Return checkoutId + clientSecret to the frontend
    res.json({
      id: checkout.id,
      url: checkout.url,
      clientSecret: checkout.client_secret,
    });
  } catch (error) {
    console.error('Checkout error:', error);
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
});

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

Frontend Setup (React)

import { init, BloqueCheckout } from '@bloque/payments-react';

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

interface CheckoutPageProps {
  checkoutId: string;
  clientSecret: string;
}

function CheckoutPage({ checkoutId, clientSecret }: CheckoutPageProps) {
  return (
    <BloqueCheckout
      checkoutId={checkoutId}
      clientSecret={clientSecret}
      // Optional: limit payment tabs shown in the hosted checkout UI
      paymentMethods={['card', 'pse', 'cash']}
      appearance={{
        primaryColor: '#10b981',
        borderRadius: '12px',
      }}
      onSuccess={(data) => {
        console.log('Payment successful!', data.payment_id);
        window.location.href = '/success';
      }}
      onPending={(data) => {
        console.log('Payment pending:', data.payment_id);
        // Common for PSE: treat as pending until webhook finality
      }}
      onError={(error) => {
        console.error('Payment failed:', error);
      }}
    />
  );
}

export default CheckoutPage;

For reliable final status (especially for asynchronous methods like PSE), set up a webhook endpoint and handle the payment.status.updated event.

See Webhooks Setup.

Environment Variables

Create a .env file in your backend project:

# .env
BLOQUE_SECRET_KEY=sk_live_your_secret_key_here
BLOQUE_WEBHOOK_SECRET=your_webhook_secret_here

And for your frontend:

# .env
NEXT_PUBLIC_BLOQUE_PUBLISHABLE_KEY=pk_live_your_publishable_key_here

Load them in your application:

import 'dotenv/config';

const bloque = new Bloque({
  secretKey: process.env.BLOQUE_SECRET_KEY!,
  mode: 'production',
});

Configuration Options

SDK Configuration (Backend)

OptionTypeRequiredDefaultDescription
secretKeystringYes*-Your Bloque secret key (sk_test_... / sk_live_...)
mode'production' | 'sandbox'Yes-Environment mode
webhookSecretstringNo-Secret for webhook verification
timeoutnumberNo-Request timeout in milliseconds
maxRetriesnumberNo-Maximum number of retry attempts

* Either secretKey (recommended) or legacy accessToken is required.

Modes

  • sandbox: For testing and development. No real transactions. Use sk_test_ / pk_test_ keys.
  • production: For live operations with real payments. Use sk_live_ / pk_live_ keys.

React Component Props

PropTypeRequiredDescription
checkoutIdstringYesCheckout session ID from your backend
clientSecretstringNoCheckout-scoped JWT from the create checkout response
onSuccessfunctionNoCalled on successful payment
onErrorfunctionNoCalled on payment error
onPendingfunctionNoCalled when payment is pending
onReadyfunctionNoCalled when iframe is ready
onThreeDSChallengefunctionNoCalled when a 3D Secure challenge starts
appearanceAppearanceConfigNoUI customization
iframeStylesRecord<string, string>NoCustom iframe styles

When to use Direct Payments

Hosted Checkout is the recommended integration. Use Direct Payments (server-side) when you need to submit card/PSE/cash from your backend.

See Direct Payments.

Appearance Configuration

Customize the look and feel:

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

Experiment with customization options in real-time in our interactive Playground.

TypeScript Support

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

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

const handleSuccess = (result: PaymentResult) => {
  console.log('Payment ID:', result.payment_id);
  console.log('Status:', result.status);
};

Testing in Sandbox Mode

Use sandbox mode for testing without real transactions:

// Backend
const bloque = new Bloque({
  secretKey: process.env.BLOQUE_SECRET_KEY!, // sk_test_...
  mode: 'sandbox',
});
// Frontend
init({
  publishableKey: 'pk_test_...',
  mode: 'sandbox',
});

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:

Need Help?