Skip to content

Boleto Flow

This guide describes the complete lifecycle of a boleto on the FluxiQ NPC platform, from creation to final settlement.

Overview

The diagram below illustrates the states of a boleto throughout its lifecycle:

+-----------------------------------------------------------------------------+
|                         Boleto Lifecycle                                     |
+-----------------------------------------------------------------------------+

    +---------+      +------------+      +--------+      +----------+
    |  DRAFT  |----->| REGISTERED |----->|  PAID  |----->| SETTLED  |
    +---------+      +------------+      +--------+      +----------+
         |                 |
         |                 |
         v                 v
    +-----------------------+
    |      CANCELLED        |
    +-----------------------+

    Status:
    - DRAFT      : Boleto created, awaiting registration
    - REGISTERED : Registered with Nuclea (PCR)
    - PAID       : Payment confirmed
    - SETTLED    : Settled (funds credited)
    - CANCELLED  : Cancelled

Step 1: Create Boleto

The first step is to create the boleto via API. The boleto will be automatically registered with Nuclea (PCR).

bash
curl -X POST "https://api.pixconnect.com.br/api/v1/central/boletos" \
  -H "X-API-Key: pk_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "boleto": {
      "nosso_numero": "12345678901",
      "amount_cents": 15000,
      "due_date": "2026-03-15",
      "payer_document": "12345678901",
      "payer_name": "Joao Silva Santos",
      "beneficiary_ispb": "02992335",
      "beneficiary_name": "Empresa XYZ Ltda"
    }
  }'
javascript
async function createBoleto() {
  const response = await fetch(
    "https://api.pixconnect.com.br/api/v1/central/boletos",
    {
      method: "POST",
      headers: {
        "X-API-Key": "pk_live_abc123def456",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        boleto: {
          nosso_numero: "12345678901",
          amount_cents: 15000,
          due_date: "2026-03-15",
          payer_document: "12345678901",
          payer_name: "Joao Silva Santos",
          beneficiary_ispb: "02992335",
          beneficiary_name: "Empresa XYZ Ltda"
        }
      }),
    }
  );

  const data = await response.json();

  if (data.success) {
    console.log("Boleto created:", data.data.nosso_numero);
    console.log("Barcode:", data.data.barcode);
    console.log("Typeable line:", data.data.linha_digitavel);
  }

  return data;
}
python
import requests

def create_boleto():
    url = "https://api.pixconnect.com.br/api/v1/central/boletos"
    headers = {
        "X-API-Key": "pk_live_abc123def456",
        "Content-Type": "application/json"
    }
    payload = {
        "boleto": {
            "nosso_numero": "12345678901",
            "amount_cents": 15000,
            "due_date": "2026-03-15",
            "payer_document": "12345678901",
            "payer_name": "Joao Silva Santos",
            "beneficiary_ispb": "02992335",
            "beneficiary_name": "Empresa XYZ Ltda"
        }
    }

    response = requests.post(url, headers=headers, json=payload)
    data = response.json()

    if data.get("success"):
        print(f"Boleto created: {data['data']['nosso_numero']}")
        print(f"Barcode: {data['data']['barcode']}")
        print(f"Typeable line: {data['data']['linha_digitavel']}")

    return data

Expected response:

json
{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "nosso_numero": "12345678901",
    "barcode": "23793381286000000000000000012345678901500001",
    "linha_digitavel": "23793.38128 60000.000003 00001.234567 8 90150000015000",
    "amount_cents": 15000,
    "due_date": "2026-03-15",
    "status": "registered",
    "pcr_protocol": "PCR2026021512345678"
  }
}

Step 2: Wait for Registration

After creation, the boleto is automatically registered with Nuclea. You can track this in two ways:

Configure an endpoint to receive the boleto_registered event:

javascript
// Your server (Express.js example)
app.post("/webhooks/pixconnect", async (req, res) => {
  const { event, data } = req.body;

  // Validate signature first (see Webhooks documentation)
  if (!validateSignature(req)) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  if (event === "boleto_registered") {
    console.log("Boleto registered:", data.nosso_numero);
    console.log("PCR Protocol:", data.pcr_protocol);

    // Update your database
    await updateBoletoStatus(data.nosso_numero, "registered", {
      pcr_protocol: data.pcr_protocol,
      registered_at: data.registered_at
    });
  }

  res.status(200).json({ received: true });
});

Option B: Polling

If you cannot use webhooks, query the status periodically:

javascript
async function waitForRegistration(nossoNumero, maxAttempts = 10) {
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `https://api.pixconnect.com.br/api/v1/central/boletos/${nossoNumero}`,
      {
        headers: {
          "X-API-Key": "pk_live_abc123def456",
          "Content-Type": "application/json",
        },
      }
    );

    const data = await response.json();

    if (data.data.status === "registered") {
      console.log("Boleto registered successfully!");
      return data.data;
    }

    // Wait 2 seconds before next attempt
    await new Promise(resolve => setTimeout(resolve, 2000));
  }

  throw new Error("Timeout waiting for boleto registration");
}

Polling Usage

Polling consumes more API resources. Use webhooks whenever possible. If using polling, respect the rate limits.

Step 3: Display Boleto to Customer

With the boleto registered, display the payment information to the customer:

javascript
function displayBoleto(boleto) {
  return {
    // Barcode (44 digits - for scanner reading)
    barcode: boleto.barcode,

    // Typeable line (47 formatted digits - for manual typing)
    linhaDigitavel: boleto.linha_digitavel,

    // Formatted value
    valor: (boleto.amount_cents / 100).toLocaleString("pt-BR", {
      style: "currency",
      currency: "BRL"
    }),

    // Formatted due date
    vencimento: new Date(boleto.due_date).toLocaleDateString("pt-BR"),

    // Beneficiary
    beneficiario: boleto.beneficiary_name
  };
}

// Usage example
const boletoDisplay = displayBoleto(boleto);
// {
//   barcode: "23793381286000000000000000012345678901500001",
//   linhaDigitavel: "23793.38128 60000.000003 00001.234567 8 90150000015000",
//   valor: "R$ 150.00",
//   vencimento: "15/03/2026",
//   beneficiario: "Empresa XYZ Ltda"
// }

PDF Generation

To generate a boleto PDF, include the following elements:

  • Barcode: Use a barcode library to generate the image
  • Typeable line: Display legibly for typing
  • Beneficiary data: Name, CNPJ/CPF, address
  • Payer data: Name, CPF/CNPJ
  • Value and due date: Clearly visible
  • Instructions: Information for the teller

Step 4: Receive Payment Notification

When the customer pays the boleto, you will receive the boleto_paid webhook:

javascript
app.post("/webhooks/pixconnect", async (req, res) => {
  const { event, data } = req.body;

  if (!validateSignature(req)) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  switch (event) {
    case "boleto_paid":
      console.log("Payment received!");
      console.log("Nosso numero:", data.nosso_numero);
      console.log("Amount paid:", data.valor_pago / 100);
      console.log("Payment date:", data.data_pagamento);

      // Update status in your system
      await updateBoletoStatus(data.nosso_numero, "paid", {
        valor_pago: data.valor_pago,
        data_pagamento: data.data_pagamento,
        canal_pagamento: data.canal_pagamento,
        settlement_id: data.settlement_id
      });

      // Release service/product to customer
      await fulfillOrder(data.nosso_numero);

      // Send confirmation email
      await sendPaymentConfirmation(data.nosso_numero);
      break;

    // ... other events
  }

  res.status(200).json({ received: true });
});

boleto_paid event payload:

json
{
  "event": "boleto_paid",
  "timestamp": "2026-02-04T09:15:00Z",
  "data": {
    "nosso_numero": "12345678901",
    "valor_original": 15000,
    "valor_pago": 15000,
    "valor_desconto": 0,
    "valor_juros": 0,
    "valor_multa": 0,
    "data_pagamento": "2026-02-04",
    "data_credito": "2026-02-05",
    "canal_pagamento": "internet_banking",
    "settlement_id": "stl_abc123def456"
  }
}

Step 5: Settlement Reconciliation

The cycle completes with settlement, when funds are effectively credited:

javascript
app.post("/webhooks/pixconnect", async (req, res) => {
  const { event, data } = req.body;

  if (!validateSignature(req)) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  switch (event) {
    case "settlement_completed":
      console.log("Settlement cycle completed!");
      console.log("ID:", data.settlement_id);
      console.log("Total boletos:", data.total_boletos);
      console.log("Total value:", data.total_valor / 100);

      // Update accounting
      await updateAccountingRecords(data);

      // Generate cycle report
      await generateSettlementReport(data);
      break;

    case "payment_received":
      // Individual confirmation of each payment in the cycle
      console.log("Payment settled:", data.nosso_numero);
      console.log("Value:", data.valor_pago / 100);

      // Mark as settled
      await updateBoletoStatus(data.nosso_numero, "settled", {
        data_credito: data.data_credito
      });
      break;
  }

  res.status(200).json({ received: true });
});

Error Handling

Registration Failure

If the boleto fails to register with Nuclea, you may receive an error event:

javascript
app.post("/webhooks/pixconnect", async (req, res) => {
  const { event, data } = req.body;

  if (event === "boleto_registration_failed") {
    console.error("Registration failure:", data.nosso_numero);
    console.error("Reason:", data.error_code, data.error_message);

    // Notify support team
    await alertSupport({
      type: "registration_failed",
      boleto: data.nosso_numero,
      error: data.error_message
    });

    // Retry or cancel
    if (isRetryable(data.error_code)) {
      await retryRegistration(data.nosso_numero);
    } else {
      await cancelBoleto(data.nosso_numero);
    }
  }

  res.status(200).json({ received: true });
});

function isRetryable(errorCode) {
  const retryableCodes = ["TIMEOUT", "SERVICE_UNAVAILABLE", "RATE_LIMITED"];
  return retryableCodes.includes(errorCode);
}

Expired Boleto

Handle boletos that expired without payment:

javascript
// Daily check for expired boletos
async function checkExpiredBoletos() {
  const today = new Date().toISOString().split("T")[0];

  const response = await fetch(
    `https://api.pixconnect.com.br/api/v1/central/boletos?status=registered&due_date_lt=${today}`,
    {
      headers: {
        "X-API-Key": "pk_live_abc123def456",
        "Content-Type": "application/json",
      },
    }
  );

  const { data: boletos } = await response.json();

  for (const boleto of boletos) {
    console.log("Expired boleto:", boleto.nosso_numero);

    // Check business policy
    const daysExpired = daysSince(boleto.due_date);

    if (daysExpired > 30) {
      // Cancel after 30 days
      await cancelBoleto(boleto.nosso_numero);
      await notifyCustomerCancelled(boleto);
    } else if (daysExpired > 7) {
      // Reminder after 7 days
      await sendPaymentReminder(boleto);
    }
  }
}

function daysSince(dateString) {
  const date = new Date(dateString);
  const now = new Date();
  return Math.floor((now - date) / (1000 * 60 * 60 * 24));
}

Sequence Diagram

+--------+          +------------+          +-----------+         +--------+
| Client |          |  Your API  |          | FluxiQ NPC|         | Nuclea |
+---+----+          +-----+------+          +-----+-----+         +---+----+
    |                     |                       |                   |
    |  1. Request boleto  |                       |                   |
    |------------------->|                       |                   |
    |                     |                       |                   |
    |                     |  2. POST /boletos     |                   |
    |                     |---------------------->|                   |
    |                     |                       |                   |
    |                     |                       |  3. Register PCR  |
    |                     |                       |------------------>|
    |                     |                       |                   |
    |                     |                       |  4. Confirmation  |
    |                     |                       |<------------------|
    |                     |                       |                   |
    |                     |  5. 201 Created       |                   |
    |                     |<----------------------|                   |
    |                     |  (barcode, line)      |                   |
    |                     |                       |                   |
    |  6. Display boleto  |                       |                   |
    |<--------------------|                       |                   |
    |                     |                       |                   |
    |  7. Pay boleto      |                       |                   |
    |-------------------------------------------------------------------->
    |                     |                       |                   |
    |                     |                       |  8. Payment       |
    |                     |                       |<------------------|
    |                     |                       |                   |
    |                     |  9. Webhook           |                   |
    |                     |     boleto_paid       |                   |
    |                     |<----------------------|                   |
    |                     |                       |                   |
    |  10. Confirm        |                       |                   |
    |      payment        |                       |                   |
    |<--------------------|                       |                   |
    |                     |                       |                   |
    |                     |  11. Webhook          |                   |
    |                     |      settlement_      |                   |
    |                     |      completed        |                   |
    |                     |<----------------------|                   |
    |                     |                       |                   |
+---+----+          +-----+------+          +-----+-----+         +---+----+

Integration Checklist

Use this checklist to validate your integration:

Boleto Creation

  • [ ] Generate unique nosso_numero (11 digits)
  • [ ] Send value in cents (amount_cents)
  • [ ] Format due date (YYYY-MM-DD)
  • [ ] Validate payer CPF/CNPJ
  • [ ] Configure beneficiary ISPB correctly

Webhooks

  • [ ] HTTPS endpoint configured
  • [ ] HMAC signature validation implemented
  • [ ] Handler for boleto_registered
  • [ ] Handler for boleto_paid
  • [ ] Handler for settlement_completed
  • [ ] Return 200 OK within 30 seconds

Display

  • [ ] Readable barcode (scanner)
  • [ ] Correctly formatted typeable line
  • [ ] Visible value and due date
  • [ ] Beneficiary data displayed

Error Handling

  • [ ] Handler for registration failures
  • [ ] Check for expired boletos
  • [ ] Logs for debugging
  • [ ] Alerts for support team

Reconciliation

  • [ ] Status tracking
  • [ ] Payment records
  • [ ] Accounting integration
  • [ ] Settlement reports

Next Steps

Documentação da API FluxiQ NPC