Forgedocs
Guías de Integración

PIX Cash-In (Recepción)

Descripción General

El endpoint de PIX Cash-In le permite generar cobros PIX dinámicos para recibir pagos. Cada cobro genera un QR Code único y un código PIX (Copiar y Pegar) que sus clientes pueden usar para realizar el pago.

Este endpoint requiere un Bearer token válido. Consulte la documentación de autenticación para más detalles.

Características

  • Generación dinámica de QR Code
  • Código PIX en formato EMV (Copiar y Pegar)
  • Período de expiración configurable (5 minutos a 7 días)
  • Identificación única vía externalId
  • Información adicional personalizable
  • Validación automática de CPF/CNPJ
  • División de pago: distribución automática entre múltiples destinatarios

Endpoint

POST /api/pix/cash-in

Genera un nuevo cobro PIX.

Encabezados Requeridos

Authorization: Bearer {token}
Content-Type: application/json

Cuerpo de la Solicitud

{
  "transaction": {
    "value": 150.00,
    "description": "Payment for order #12345",
    "expirationTime": 86400,
    "externalId": "ORDER-12345-20240119",
    "generateQrCode": true
  },
  "payer": {
    "fullName": "Carlos Oliveira",
    "document": "12345678901"
  },
  "additionalInfo": {
    "orderId": "12345",
    "storeName": "Tech Solutions",
    "productCategory": "Electronics"
  },
  "splits": [
    {
      "pixKey": "supplier@email.com",
      "pixKeyType": "EMAIL",
      "name": "Supplier Ltd",
      "document": "12345678000199",
      "type": "PERCENTAGE",
      "value": 10,
      "immediate": false
    }
  ]
}

Solicitud

curl -X POST https://api.gateway.goforge.com.br/api/pix/cash-in \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "transaction": {
      "value": 150.00,
      "description": "Payment for order #12345",
      "expirationTime": 86400,
      "externalId": "ORDER-12345-20240119",
      "generateQrCode": true
    },
    "payer": {
      "fullName": "Carlos Oliveira",
      "document": "12345678901"
    },
    "additionalInfo": {
      "orderId": "12345"
    },
    "splits": [
      {
        "pixKey": "supplier@email.com",
        "pixKeyType": "EMAIL",
        "name": "Supplier Ltd",
        "document": "12345678000199",
        "type": "PERCENTAGE",
        "value": 70,
        "immediate": false
      }
    ]
  }'

El campo splits es opcional. Consulte la guía de División de Pago para detalles completos sobre tipos, formatos de valor y frecuencias.

Respuesta (201 Created)

{
  "transactionId": "7845",
  "correlationId": "550e8400-e29b-41d4-a716-446655440000",
  "externalId": "ORDER-12345-20240119",
  "status": "PENDING",
  "pixCode": "00020126580014br.gov.bcb.pix0136550e8400-e29b-41d4-a716-4466554400005204000053039865802BR5916Tech Solutions Ltda6009SAO PAULO62070503***63041D3D",
  "generateTime": "2024-01-19T14:30:00.000Z",
  "expirationDate": "2024-01-20T14:30:00.000Z",
  "qrCodeImage": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51..."
}

El campo qrCodeImage se retorna solo cuando se envía generateQrCode: true en la solicitud. El valor es una imagen PNG codificada en Base64 del QR Code en formato Data URL.

Parámetros de la Solicitud

Objeto Transaction

transaction.valuenumberobrigatorio

Valor de la transacción en Reales brasileños (BRL). Debe tener como máximo 2 decimales.

Mínimo: 0.01

Ejemplo: 150.00

transaction.descriptionstringobrigatorio

Descripción de la transacción que aparecerá en el extracto del pagador.

Máximo: 140 caracteres

Ejemplo: "Payment for order #12345"

transaction.expirationTimenumber

Tiempo de expiración en segundos.

Mínimo: 300 (5 minutos)

Máximo: 604800 (7 días)

Predeterminado: 86400 (24 horas)

transaction.externalIdstringobrigatorio

Identificador externo único para la transacción. Úselo para correlacionar con su sistema.

Máximo: 255 caracteres

Recomendación: Use un formato que incluya fecha/hora para garantizar unicidad

Ejemplo: "ORDER-12345-20240119-143000"

transaction.generateQrCodeboolean

Si se debe generar el QR Code en Base64.

Predeterminado: false

Recomendación: Use true para mostrar el QR Code al usuario

Objeto Payer

payer.fullNamestringobrigatorio

Nombre completo del pagador.

Ejemplo: "Carlos Oliveira"

payer.documentstringobrigatorio

CPF o CNPJ del pagador (solo números).

CPF: 11 dígitos

CNPJ: 14 dígitos

Ejemplo: "12345678901" o "12345678000199"

Objeto Additional Info

additionalInfoobject

Información adicional en formato clave-valor (string:string).

Máximo: 10 claves

Ejemplo:

{
  "orderId": "12345",
  "customerId": "67890",
  "storeName": "Tech Solutions"
}

Array Splits (Opcional)

splitsarray

Lista de destinatarios para la división automática del pago recibido. Cuando el PIX-IN es confirmado, el valor se divide y se envía automáticamente a cada destinatario vía PIX.

Máximo: 10 destinatarios por transacción

splits[].pixKeystringobrigatorio

Clave PIX del destinatario del split.

Máximo: 255 caracteres

Ejemplo: "supplier@email.com"

splits[].pixKeyTypestringobrigatorio

Tipo de clave PIX del destinatario.

Valores posibles: EMAIL, PHONE, CPF, CNPJ, RANDOM

Ejemplo: "EMAIL"

splits[].namestringobrigatorio

Nombre completo del destinatario.

Máximo: 255 caracteres

Ejemplo: "Supplier Ltd"

splits[].documentstringobrigatorio

CPF o CNPJ del destinatario (solo dígitos).

CPF: 11 dígitos | CNPJ: 14 dígitos

Ejemplo: "12345678000199"

splits[].typestringobrigatorio

Tipo de split: valor fijo o porcentaje.

Valores posibles:

  • FIXED -- Valor fijo en BRL (ej.: 10.00 = R$ 10.00)
  • PERCENTAGE -- Porcentaje directo (ej.: 10 = 10%)

Ejemplo: "PERCENTAGE"

splits[].valuenumberobrigatorio

Valor del split según el tipo:

  • FIXED: Valor en BRL con hasta 2 decimales. 10.50 = R$ 10.50
  • PERCENTAGE: Porcentaje directo. 10 = 10%, 25.5 = 25.5%

Mínimo: 0.01

Ejemplo: 10 (10% para PERCENTAGE) o 10.00 (R$ 10.00 para FIXED)

splits[].immediateboolean

Si es true, el split se ejecuta inmediatamente después de la confirmación del PIX-IN, ignorando la frecuencia configurada en la cuenta.

Predeterminado: false

La suma de los splits (valores fijos + porcentajes del valor bruto) más las tarifas no puede exceder el valor de la transacción. Si lo excede, la API retornará error 400.

Estructura de la Respuesta

transactionIdstringsempre presente

ID interno de la transacción generado por Avista.

Ejemplo: "7845"

correlationIdstringsempre presente

UUID para rastreo y correlación de la transacción.

Ejemplo: "550e8400-e29b-41d4-a716-446655440000"

externalIdstringsempre presente

ID externo proporcionado en la solicitud (mismo valor que la entrada).

Ejemplo: "ORDER-12345-20240119"

statusstringsempre presente

Estado actual de la transacción.

Valores posibles:

  • PENDING: Esperando pago
  • CONFIRMED: Pago confirmado
  • ERROR: Error de procesamiento

Ejemplo: "PENDING"

pixCodestringsempre presente

Código PIX en formato EMV (Copiar y Pegar).

Ejemplo: "00020126580014br.gov.bcb.pix..."

generateTimestringsempre presente

Fecha y hora de generación del cobro (ISO 8601 UTC).

Ejemplo: "2024-01-19T14:30:00.000Z"

expirationDatestringsempre presente

Fecha y hora de expiración del cobro (ISO 8601 UTC).

Ejemplo: "2024-01-20T14:30:00.000Z"

qrCodeImagestring

QR Code en Base64 en formato Data URL. Se retorna solo cuando generateQrCode: true en la solicitud.

Formato: data:image/png;base64,{base64_encoded_image}

Ejemplo: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51..."

Uso: Puede mostrarse directamente en una etiqueta HTML <img> o decodificarse para guardar como archivo.

Ejemplos de Implementación

Node.js / TypeScript

import axios from 'axios';

interface CashInRequest {
  transaction: {
    value: number;
    description: string;
    expirationTime?: number;
    externalId: string;
    generateQrCode?: boolean;
  };
  payer: {
    fullName: string;
    document: string;
  };
  additionalInfo?: Record<string, string>;
}

interface CashInResponse {
  transactionId: string;
  correlationId: string;
  externalId: string;
  status: 'PENDING' | 'CONFIRMED' | 'ERROR';
  pixCode: string;
  generateTime: string;
  expirationDate: string;
  qrCodeImage?: string; // Present only when generateQrCode: true
}

async function createPixCharge(
  token: string,
  orderId: string,
  amount: number,
  customerName: string,
  customerDocument: string
): Promise<CashInResponse> {
  const payload: CashInRequest = {
    transaction: {
      value: amount,
      description: `Payment for order ${orderId}`,
      expirationTime: 3600, // 1 hour
      externalId: `ORDER-${orderId}-${Date.now()}`,
      generateQrCode: true
    },
    payer: {
      fullName: customerName,
      document: customerDocument
    },
    additionalInfo: {
      orderId: orderId,
      timestamp: new Date().toISOString()
    }
  };

  try {
    const response = await axios.post<CashInResponse>(
      'https://api.gateway.goforge.com.br/api/pix/cash-in',
      payload,
      {
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        }
      }
    );

    console.log('PIX charge generated successfully!');
    console.log(`Transaction ID: ${response.data.transactionId}`);
    console.log(`PIX Code: ${response.data.pixCode}`);
    console.log(`Expires at: ${new Date(response.data.expirationDate).toLocaleString('pt-BR')}`);
    if (response.data.qrCodeImage) {
      console.log('QR Code Image available for display');
    }

    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('Error generating charge:', error.response?.data);
      throw new Error(error.response?.data?.message || 'Error generating PIX charge');
    }
    throw error;
  }
}

// Usage
const token = 'your_token_here';
createPixCharge(token, '12345', 150.00, 'Carlos Oliveira', '12345678901');

Python

import requests
from datetime import datetime, timedelta
from typing import Dict, Optional

def create_pix_charge(
    token: str,
    order_id: str,
    amount: float,
    customer_name: str,
    customer_document: str,
    expiration_hours: int = 1,
    additional_info: Optional[Dict[str, str]] = None
) -> Dict:
    """
    Generate a PIX charge

    Args:
        token: Valid Bearer token
        order_id: Order ID
        amount: Value in BRL
        customer_name: Customer name
        customer_document: CPF or CNPJ (numbers only)
        expiration_hours: Hours until expiration (default: 1)
        additional_info: Additional information

    Returns:
        Generated charge data
    """
    url = 'https://api.gateway.goforge.com.br/api/pix/cash-in'

    payload = {
        'transaction': {
            'value': round(amount, 2),
            'description': f'Payment for order {order_id}',
            'expirationTime': expiration_hours * 3600,
            'externalId': f'ORDER-{order_id}-{int(datetime.now().timestamp())}',
            'generateQrCode': True
        },
        'payer': {
            'fullName': customer_name,
            'document': customer_document
        },
        'additionalInfo': additional_info or {}
    }

    headers = {
        'Authorization': f'Bearer {token}',
        'Content-Type': 'application/json'
    }

    try:
        response = requests.post(url, json=payload, headers=headers)
        response.raise_for_status()

        data = response.json()

        print('PIX charge generated successfully!')
        print(f"Transaction ID: {data['transactionId']}")
        print(f"PIX Code: {data['pixCode']}")
        print(f"Status: {data['status']}")

        expiration = datetime.fromisoformat(data['expirationDate'].replace('Z', '+00:00'))
        print(f"Expires at: {expiration.strftime('%d/%m/%Y %H:%M:%S')}")

        if 'qrCodeImage' in data:
            print('QR Code Image available for display')

        return data

    except requests.exceptions.RequestException as e:
        print(f'Error generating charge: {e}')
        if hasattr(e.response, 'json'):
            print(f'Details: {e.response.json()}')
        raise

# Usage
token = 'your_token_here'
charge = create_pix_charge(
    token=token,
    order_id='12345',
    amount=150.00,
    customer_name='Carlos Oliveira',
    customer_document='12345678901',
    expiration_hours=24,
    additional_info={
        'storeName': 'Tech Solutions',
        'productCategory': 'Electronics'
    }
)

PHP

<?php

function createPixCharge(
    string $token,
    string $orderId,
    float $amount,
    string $customerName,
    string $customerDocument,
    int $expirationHours = 1
): array {
    $url = 'https://api.gateway.goforge.com.br/api/pix/cash-in';

    $payload = [
        'transaction' => [
            'value' => round($amount, 2),
            'description' => "Payment for order $orderId",
            'expirationTime' => $expirationHours * 3600,
            'externalId' => "ORDER-$orderId-" . time(),
            'generateQrCode' => true
        ],
        'payer' => [
            'fullName' => $customerName,
            'document' => $customerDocument
        ],
        'additionalInfo' => [
            'orderId' => $orderId
        ]
    ];

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . $token,
        'Content-Type: application/json'
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 201) {
        throw new Exception("Error generating charge: HTTP $httpCode - $response");
    }

    $data = json_decode($response, true);

    echo "PIX charge generated successfully!" . PHP_EOL;
    echo "Transaction ID: {$data['transactionId']}" . PHP_EOL;
    echo "PIX Code: {$data['pixCode']}" . PHP_EOL;
    echo "Status: {$data['status']}" . PHP_EOL;
    if (isset($data['qrCodeImage'])) {
        echo "QR Code Image available for display" . PHP_EOL;
    }

    return $data;
}

// Usage
$token = 'your_token_here';
$charge = createPixCharge(
    $token,
    '12345',
    150.00,
    'Carlos Oliveira',
    '12345678901',
    24
);

Casos de Uso

1. E-commerce - Checkout con PIX

// E-commerce checkout integration
class PixCheckout {
  constructor(token) {
    this.token = token;
  }

  async generatePayment(order) {
    const charge = await createPixCharge(
      this.token,
      order.id,
      order.total,
      order.customer.name,
      order.customer.document
    );

    // Display QR Code on the page (using API image or generating locally)
    this.displayQrCode(charge);

    // Start polling to check payment
    this.startPaymentPolling(charge.transactionId);

    return charge;
  }

  displayQrCode(charge) {
    const qrCanvas = document.getElementById('qr-canvas');
    const qrImage = document.getElementById('qr-image');

    // Use Base64 image from API (preferred - avoids client-side processing)
    if (charge.qrCodeImage) {
      qrImage.src = charge.qrCodeImage;
      qrImage.style.display = 'block';
      qrCanvas.style.display = 'none';
    } else {
      // Fallback: generate QR Code locally using a library (e.g.: qrcode.js)
      QRCode.toCanvas(qrCanvas, charge.pixCode, {
        width: 300,
        margin: 2
      });
      qrCanvas.style.display = 'block';
      qrImage.style.display = 'none';
    }

    // Also show the PIX Copy and Paste code
    document.getElementById('pix-code').textContent = charge.pixCode;
  }

  startPaymentPolling(transactionId) {
    // Check status every 3 seconds
    const interval = setInterval(async () => {
      const status = await this.checkPaymentStatus(transactionId);

      if (status === 'CONFIRMED') {
        clearInterval(interval);
        this.onPaymentConfirmed();
      }
    }, 3000);

    // Stop after 10 minutes
    setTimeout(() => clearInterval(interval), 10 * 60 * 1000);
  }

  onPaymentConfirmed() {
    // Redirect to success page
    window.location.href = '/payment/success';
  }
}

2. PDV (Punto de Venta)

class PixPDV:
    """POS system with PIX charge"""

    def __init__(self, token: str):
        self.token = token

    def process_sale(self, items: list, customer: dict) -> dict:
        """Process sale and generate PIX charge"""

        # Calculate total
        total = sum(item['price'] * item['quantity'] for item in items)

        # Generate description
        description = self.generate_sale_description(items)

        # Create PIX charge (expires in 15 minutes)
        charge = create_pix_charge(
            token=self.token,
            order_id=self.generate_sale_id(),
            amount=total,
            customer_name=customer['name'],
            customer_document=customer['document'],
            expiration_hours=0.25,  # 15 minutes
            additional_info={
                'items_count': str(len(items)),
                'cashier_id': self.get_cashier_id()
            }
        )

        # Print receipt with QR Code
        self.print_receipt(charge, items, total)

        return charge

    def generate_sale_description(self, items: list) -> str:
        """Generate a summary description of the sale"""
        if len(items) == 1:
            return f"{items[0]['name']}"
        else:
            return f"{len(items)} items - {items[0]['name']} and more"

    def print_receipt(self, charge: dict, items: list, total: float):
        """Print receipt with QR Code"""
        # Implement thermal printing or generate PDF
        print("\n" + "="*50)
        print("PIX CHARGE RECEIPT")
        print("="*50)
        for item in items:
            print(f"{item['name']}: R$ {item['price']:.2f}")
        print("-"*50)
        print(f"TOTAL: R$ {total:.2f}")
        print(f"\nTransaction ID: {charge['transactionId']}")
        print(f"PIX Code:\n{charge['pixCode']}")
        print("="*50 + "\n")

3. SaaS - Facturación de Suscripciones

class SubscriptionBilling {
  constructor(private token: string) {}

  async chargeMonthlySubscription(
    subscriptionId: string,
    userId: string,
    planValue: number
  ) {
    // Fetch user data
    const user = await this.getUserData(userId);

    // Generate charge with 3-day expiration
    const charge = await createPixCharge(
      this.token,
      `SUB-${subscriptionId}-${new Date().getMonth() + 1}`,
      planValue,
      user.name,
      user.document
    );

    // Send email with payment link
    await this.sendPaymentEmail(user.email, charge);

    // Schedule reminder 1 day before expiration
    await this.scheduleReminder(user, charge, 24);

    return charge;
  }

  async sendPaymentEmail(email: string, charge: CashInResponse) {
    // Implement email sending
    const paymentLink = `https://app.example.com/payment/${charge.transactionId}`;

    await sendEmail({
      to: email,
      subject: 'Invoice available - Pay with PIX',
      html: `
        <h2>Your invoice is available</h2>
        <p>Amount: R$ ${charge.value}</p>
        <p>Due date: ${new Date(charge.expirationDate).toLocaleDateString('pt-BR')}</p>
        <p><a href="${paymentLink}">Click here to pay with PIX</a></p>
      `
    });
  }
}

Monitoreo de Pagos

Para ser notificado cuando se confirma un pago, puede:

Configure webhooks para recibir notificaciones automáticas cuando cambie el estado.

// Webhook endpoint on your server
app.post('/webhooks/pix', (req, res) => {
  const { transactionId, status, externalId } = req.body;

  if (status === 'CONFIRMED') {
    // Process confirmed payment
    processPaymentConfirmation(externalId);
  }

  res.sendStatus(200);
});

Consulte periódicamente el estado de la transacción.

async function monitorPayment(transactionId, maxAttempts = 200) {
  for (let i = 0; i < maxAttempts; i++) {
    const status = await checkTransactionStatus(transactionId);

    if (status === 'CONFIRMED') {
      return true;
    }

    // Wait 3 seconds before trying again
    await new Promise(resolve => setTimeout(resolve, 3000));
  }

  return false; // Timeout
}

Códigos de Respuesta

CódigoDescripciónSignificado
201Cobro CreadoCobro PIX generado exitosamente
400Datos InválidosVerifique los campos requeridos y formatos
401Token InválidoToken no proporcionado, expirado o inválido

Consulte la Referencia de la API para detalles completos de los campos de respuesta.

Mejores Prácticas

Notas Importantes

Los cobros expirados no pueden ser reactivados. Genere un nuevo cobro si es necesario.

  • Valor mínimo: R$ 0.01
  • Expiración mínima: 5 minutos (300 segundos)
  • Expiración máxima: 7 días (604,800 segundos)

Próximos Pasos

En esta página