PIX Cash-In (Receiving)
Overview
The PIX Cash-In endpoint allows you to generate dynamic PIX charges to receive payments. Each charge generates a unique QR Code and a PIX code (Copy and Paste) that your customers can use to make the payment.
This endpoint requires a valid Bearer token. See the authentication documentation for more details.
Features
- Dynamic QR Code generation
- PIX code in EMV format (Copy and Paste)
- Configurable expiration period (30 seconds to 7 days, subject to the account settlement provider's range)
- Unique identification via
externalId - Customizable additional information
- Payer CPF/CNPJ format validation
- Payment split (when enabled on the account): automatic division among multiple recipients
Endpoint
POST /api/pix/cash-in
Generates a new PIX charge.
Required Headers
Authorization: Bearer {token}
Content-Type: application/jsonRequest Body
{
"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
}
]
}Request
curl -X POST https://api.fypay.me/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
}
]
}'The splits field is optional and only accepted on accounts with split enabled (otherwise, the API responds 400 SPLIT_NOT_CONFIGURED). See the Payment Split guide for complete details on types, value formats, and frequencies.
Response (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..."
}The qrCodeImage field is returned only when generateQrCode: true is sent in the request. The value is a Base64-encoded PNG image of the QR Code in Data URL format.
Request Parameters
Transaction Object
transaction.valuenumberobrigatorioTransaction value in Brazilian Reais (BRL). Must have at most 2 decimal places.
Minimum: 0.01
Example: 150.00
transaction.descriptionstringobrigatorioTransaction description that will appear on the payer's statement.
Maximum: 100 characters
Example: "Payment for order #12345"
transaction.expirationTimenumberExpiration time in seconds.
Minimum: 30 (30 seconds)
Maximum: 604800 (7 days)
Default: 86400 (24 hours)
The account's settlement provider may accept a narrower range; in that case the API responds 400 with PROVIDER_EXPIRATION_BELOW_MINIMUM or PROVIDER_EXPIRATION_ABOVE_MAXIMUM. See Expiration limits.
transaction.externalIdstringobrigatorioUnique external identifier for the transaction, per account. Use it to correlate with your system. If repeated, the API returns 400 with code PIX_DUPLICATE_EXTERNAL_ID. Cannot start with MIRROR: (reserved prefix).
Maximum: 50 characters
Recommendation: Use a format that includes date/time to ensure uniqueness
Example: "ORDER-12345-20240119-1430"
transaction.generateQrCodebooleanWhether to generate the QR Code in Base64.
Default: false
Recommendation: Use true to display the QR Code to the user
Payer Object
The payer fields are required in the API, but they are informational: they serve for record-keeping (statement, audit, counterpart identification) and do not restrict who can pay the charge.
Simplified approach: If your use case does not require collecting payer data (e.g., e-commerce where anyone can pay), you can send fixed values such as the receiving account's CNPJ and company name. There is no need to ask the end payer for CPF/name.
payer.fullNamestringobrigatorioPayer name or fixed identifier.
Maximum: 100 characters
Usage: Informational field — stored in the transaction records for identification. It is not validated against any registry.
Examples:
- Real customer data:
"Carlos Oliveira" - Fixed value (account company name):
"Minha Empresa Ltda"
payer.documentstringobrigatorioCPF or CNPJ of the payer (numbers only). Format validation only (11 or 14 digits).
CPF: 11 digits | CNPJ: 14 digits
Usage: Informational field: it does not restrict who can pay the charge. It can be the integrator's own document.
Examples:
- Customer's real CPF:
"12345678901" - Fixed CNPJ of the receiving account:
"12345678000199"
Additional Info Object
additionalInfoobjectAdditional information in key-value format (string:string). Values must be strings. The mirror key is reserved and cannot be used.
Maximum: 10 keys
Example:
{
"orderId": "12345",
"customerId": "67890",
"storeName": "Tech Solutions"
}Splits Array (Optional)
splitsarrayList of recipients for automatic division of the received payment. When the PIX-IN is confirmed, the value is divided and automatically sent to the recipients. Only accepted on accounts with split enabled.
Maximum: 10 recipients per transaction (or the account limit, if lower)
splits[].pixKeystringobrigatorioPIX key of the split recipient.
Maximum: 255 characters
Example: "supplier@email.com"
splits[].pixKeyTypestringobrigatorioPIX key type of the recipient.
Possible values: EMAIL, PHONE, CPF, CNPJ, RANDOM
Example: "EMAIL"
splits[].namestringobrigatorioFull name of the recipient.
Maximum: 255 characters
Example: "Supplier Ltd"
splits[].documentstringobrigatorioCPF or CNPJ of the recipient (digits only).
CPF: 11 digits | CNPJ: 14 digits
Example: "12345678000199"
splits[].typestringobrigatorioSplit type: fixed value or percentage.
Possible values:
FIXED— Fixed value in BRL (e.g.:10.00= R$ 10.00)PERCENTAGE— Direct percentage (e.g.:10= 10%)
Example: "PERCENTAGE"
splits[].valuenumberobrigatorioSplit value according to the type:
- FIXED: Value in BRL with up to 2 decimal places.
10.50= R$ 10.50 - PERCENTAGE: Direct percentage.
10= 10%,25.5= 25.5%
Minimum: 0.01
Example: 10 (10% for PERCENTAGE) or 10.00 (R$ 10.00 for FIXED)
splits[].immediatebooleanIf true, the split is executed immediately after PIX-IN confirmation, ignoring the frequency configured on the account.
Default: false
The sum of splits (fixed values + percentages of the gross value) plus fees cannot exceed the transaction value, and the sum of percentages cannot exceed 100%. Otherwise, the API returns 400 (SPLIT_EXCEEDS_AMOUNT or SPLIT_PERCENTAGE_EXCEEDS_100).
Response Structure
transactionIdstringsempre presenteInternal transaction ID generated by FyPay.
Example: "7845"
correlationIdstringsempre presenteUUID for tracking and correlating the transaction.
Example: "550e8400-e29b-41d4-a716-446655440000"
externalIdstringsempre presenteExternal ID provided in the request (same value as input).
Example: "ORDER-12345-20240119"
statusstringsempre presenteCurrent transaction status.
Possible values:
PENDING: Awaiting paymentCONFIRMED: Payment confirmedERROR: Processing error
Example: "PENDING"
pixCodestringsempre presentePIX code in EMV format (Copy and Paste).
Example: "00020126580014br.gov.bcb.pix..."
generateTimestringsempre presenteDate and time of charge generation (ISO 8601 UTC).
Example: "2024-01-19T14:30:00.000Z"
expirationDatestringsempre presenteDate and time of charge expiration (ISO 8601 UTC).
Example: "2024-01-20T14:30:00.000Z"
qrCodeImagestringBase64 QR Code in Data URL format. Returned only when generateQrCode: true in the request.
Format: data:image/png;base64,{base64_encoded_image}
Example: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51..."
Usage: Can be displayed directly in an HTML <img> tag or decoded to save as a file.
Implementation Examples
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.fypay.me/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: float = 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.fypay.me/api/pix/cash-in'
payload = {
'transaction': {
'value': round(amount, 2),
'description': f'Payment for order {order_id}',
'expirationTime': int(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.fypay.me/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
);Use Cases
1. E-commerce - Checkout with 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. POS (Point of Sale)
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 - Subscription Billing
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, planValue);
// Schedule reminder 1 day before expiration
await this.scheduleReminder(user, charge, 24);
return charge;
}
async sendPaymentEmail(email: string, charge: CashInResponse, planValue: number) {
// 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$ ${planValue.toFixed(2)}</p>
<p>Due date: ${new Date(charge.expirationDate).toLocaleDateString('pt-BR')}</p>
<p><a href="${paymentLink}">Click here to pay with PIX</a></p>
`
});
}
}Payment Monitoring
To be notified when a payment is confirmed, you can:
Configure a webhook for the cash_in event to receive the CashIn event when the payment is confirmed. See Webhooks.
// Webhook endpoint on your server
app.post('/webhooks/pix', (req, res) => {
const { event, transactionId, status, externalId } = req.body;
if (event === 'CashIn' && status === 'CONFIRMED') {
// Process confirmed payment
processPaymentConfirmation(externalId);
}
res.sendStatus(200);
});Periodically query the status with GET /api/pix/transaction/\{id\} (accepts the numeric transactionId or your externalId).
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
}Response Codes
| Code | Description | Meaning |
|---|---|---|
201 | Charge Created | PIX charge generated successfully |
400 | Invalid Data | Required fields missing or in an invalid format (PUB_REQUEST_BODY_INVALID or validation error with per-field details), repeated externalId (PIX_DUPLICATE_EXTERNAL_ID), account limit exceeded (PIX_TRANSACTION_LIMIT_EXCEEDED, PIX_DAILY_LIMIT_EXCEEDED, PIX_NIGHT_LIMIT_EXCEEDED, PIX_LIMIT_EXCEEDED), expiration outside the settlement provider's range (PROVIDER_EXPIRATION_BELOW_MINIMUM, PROVIDER_EXPIRATION_ABOVE_MAXIMUM), or split error (SPLIT_*) |
401 | Invalid Token | Token not provided, expired, or invalid |
500 | Internal Error | Unexpected error generating the charge. Look it up by externalId before trying again |
See the API Reference for complete details of the response fields.
Best Practices
Important Notes
Expired charges cannot be reactivated. Generate a new charge if needed.
- Minimum value: R$ 0.01 | Decimal places: Maximum 2
- Minimum expiration: 30 seconds (
30), or the account settlement provider's minimum, if higher - Maximum expiration: 7 days (
604800), or the account settlement provider's maximum, if lower externalId: Maximum 50 characters, unique per accountdescription: Maximum 100 characterspayer.fullName: Maximum 100 characters