Dynamic QR Code Guide
This guide explains how to generate PIX charges using dynamic QR Codes.
Overview
The Dynamic QR Code allows you to create unique charges with a defined amount, expiration date, and payer information. It is ideal for:
- E-commerce - Order payments
- Billing - Invoices and bills
- Services - Payment for rendered services
Integration Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Create │ │ Customer │ │ Webhook │
│ Charge │ ───► │ Pays QR │ ───► │ Received │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
▼ ▼
Returns EMV Confirms
and payload Payment
Step 1: Create a Charge (Dynamic QR Code)
Request
curl -X POST "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-code/dynamic" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-12345" \
-d '{
"pixKey": "your-pix-key-here",
"value": 150.75,
"expirationDate": "2026-02-10T15:30:00Z",
"identifier": "order-12345",
"message": "Payment for order #12345"
}'
Body Parameters
| Field | Type | Required | Description |
|---|---|---|---|
pixKey | string | Yes | PIX key of the receiving account (must be registered) |
value | number | Yes | Charge amount in BRL. Max 2 decimal places (e.g., 150.75) |
expirationDate | datetime | Yes | Expiration date/time (RFC3339, e.g., 2026-02-10T15:30:00Z) |
identifier | string | Yes | Unique charge identifier (max 35 characters) |
message | string | No | Message displayed to the payer (max 140 characters) |
allowChangeValue | boolean | No | Allows changing the amount at payment time (default: false) |
allowedPayerTaxNumber | string | No | Specific CPF/CNPJ authorized to pay |
Important Headers
| Header | Description |
|---|---|
Idempotency-Key | Unique identifier to prevent duplicate charges |
Success Response (201 Created)
{
"statusCode": 201,
"title": "created",
"type": "dynamic_immediate",
"message": "QR code created successfully",
"data": {
"chave": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"identifier": "order-12345",
"location": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/88a38a908a92441a98dac228ee1d95075204000053039865802BR5912iDez Digital6004Lins62070503***63040BFF",
"payload": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/88a38a908a92441a98dac228ee1d95075204000053039865802BR5912iDez Digital6004Lins62070503***63040BFF",
"status": "ATIVA",
"txid": "88a38a908a92441a98dac228ee1d9507"
}
}
| Field | Description |
|---|---|
data.chave | PIX key used for the charge |
data.identifier | Unique charge ID (use for lookups) |
data.payload | PIX Copy and Paste code (EMV string) |
data.location | Same as payload - the EMV string for the QR code |
data.status | Charge status (ATIVA = active) |
data.txid | Internal transaction ID |
Step 2: Display the QR Code
Using PIX Copy and Paste
Display the payload field for the customer to copy:
<input type="text"
value="00020101021226790014br.gov.bcb.pix..."
readonly />
<button onclick="navigator.clipboard.writeText(this.previousElementSibling.value)">
Copy
</button>
You can generate a QR code image from the payload string using any QR code library (e.g., qrcode.js, python-qrcode).
Step 3: Check Charge Status
Poll the status of a charge by its identifier:
Request
curl -X GET "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-code?identifier=order-12345" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
Possible Statuses
| Status | Description |
|---|---|
active | Awaiting payment |
paid | Payment confirmed |
refunded | Payment was refunded (you returned the money) |
expired | Charge expired without payment |
cancelled | Charge cancelled manually |
Response Examples by Status
Active (awaiting payment)
{
"txid": "88a38a908a92441a98dac228ee1d9507",
"identifier": "order-12345",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"value": 150.75,
"status": "active",
"type": "dynamic",
"createdAt": "2026-02-09T01:50:36Z",
"expiresAt": "2026-02-09T02:50:34Z",
"description": "Payment for order #12345",
"emv": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/88a38a90...",
"location": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/88a38a90...",
"reconciled": false
}
Paid (payment confirmed)
{
"txid": "b091da7bba6a45d1a9f709daaba04e30",
"identifier": "order-12345",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"value": 150.75,
"status": "paid",
"type": "dynamic",
"createdAt": "2026-02-05T22:08:02Z",
"expiresAt": "2026-02-05T23:08:00Z",
"description": "Payment for order #12345",
"emv": "00020101021226790014br.gov.bcb.pix...",
"location": "00020101021226790014br.gov.bcb.pix...",
"paidAt": "2026-02-05T22:10:25.055",
"paidAmount": 150.75,
"endToEndId": "E303062942026020522100000005EXVX",
"payer": {
"name": "John Smith",
"document": "12345678901",
"bankCode": "30306294",
"branch": "0020",
"account": "004912314"
},
"reconciled": true,
"reconciledAt": "2026-02-05T22:10:25Z",
"transactionId": "e094058f-de94-40a8-99a0-cdd5cb4cc832"
}
Refunded (you returned the payment)
When you refund a received payment using POST /v1/accounts/{accountId}/pix/out/refund, the QR code status changes to refunded:
{
"txid": "b091da7bba6a45d1a9f709daaba04e30",
"identifier": "order-12345",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"value": 150.75,
"status": "refunded",
"type": "dynamic",
"createdAt": "2026-02-05T22:08:02Z",
"paidAt": "2026-02-05T22:10:25.055",
"paidAmount": 150.75,
"endToEndId": "E303062942026020522100000005EXVX",
"payer": {
"name": "John Smith",
"document": "12345678901"
},
"reconciled": true,
"reconciledAt": "2026-02-05T22:10:25Z",
"transactionId": "e094058f-de94-40a8-99a0-cdd5cb4cc832",
"refundEndToEndId": "D303062942026020613020000005Ft76",
"refundedAt": "2026-02-06T13:02:16Z",
"refundAmount": 150.75,
"refunds": [
{
"id": "refund-001",
"amount": 150.75,
"status": "DEVOLVIDO",
"endToEndId": "D303062942026020613020000005Ft76",
"requestedAt": "2026-02-06T13:02:00Z",
"processedAt": "2026-02-06T13:02:16Z"
}
],
"totalRefundAmount": 150.75
}
Expired (charge expired)
{
"txid": "c1234567890abcdef1234567890abcde",
"identifier": "order-99999",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"value": 50.00,
"status": "expired",
"type": "dynamic",
"createdAt": "2026-02-01T10:00:00Z",
"expiresAt": "2026-02-01T10:30:00Z",
"emv": "00020101021226790014br.gov.bcb.pix...",
"reconciled": false
}
Field Reference
| Field | Present | Description |
|---|---|---|
txid | Always | Internal QR code transaction ID |
identifier | Always | Your unique charge identifier |
value | Always | Charge amount in BRL |
status | Always | Current status (active, paid, refunded, expired, cancelled) |
type | Always | QR code type (dynamic or static) |
emv | Always | PIX Copy and Paste code |
expiresAt | Always | Charge expiration date |
reconciled | Always | Whether linked to a statement transaction |
paidAt | When paid | Payment timestamp |
paidAmount | When paid | Amount actually paid in BRL |
endToEndId | When paid | PIX E2E identifier (unique in PIX system) |
payer | When paid | Payer info (name, document, bankCode, branch, account) |
transactionId | When reconciled | Transaction ID for statement lookup |
refundEndToEndId | When refunded | Refund E2E identifier |
refundedAt | When refunded | Refund timestamp |
refundAmount | When refunded | Amount refunded in BRL |
refunds | When refunded | Array of refund details (supports partial refunds) |
totalRefundAmount | When refunded | Total of all refunds in BRL |
Lookup Endpoint (advanced search)
In addition to searching by identifier, you can use the dedicated lookup endpoint that supports qrcodeId (txid) or endToEndId:
# Search by identifier
curl -X GET "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-code/lookup?identifier=order-12345" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
# Search by txid (qrcodeId)
curl -X GET "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-code/lookup?qrcodeId=5774a2eb0e2f40ac" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
# Search by E2E (when paid)
curl -X GET "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-code/lookup?endToEndId=E22896431..." \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
Only one parameter can be sent at a time. The lookup returns enriched details including transaction data, payer, fees and related refunds.
Step 4: Receive Payment Webhook
When the customer pays, you receive a pix.in.completed webhook with method: QR_CODE_DYNAMIC:
{
"event": "qrcode.paid",
"timestamp": "2026-02-05T22:10:25Z",
"tenantId": "tenant-yourcompany",
"data": {
"identifier": "order-12345",
"txid": "b091da7bba6a45d1a9f709daaba04e30",
"status": "PAID",
"value": 150.75,
"paidAmount": 150.75,
"endToEndId": "E303062942026020522100000005EXVX",
"payer": {
"name": "John Smith",
"document": "12345678901"
}
}
}
Configure webhooks via POST /v1/webhooks with event type qrcode.paid. See the Webhooks Guide.
Step 5: Cancel a Charge (Optional)
Cancel a pending charge before it's paid:
curl -X DELETE "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-code?identifier=order-12345" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
Step 6: List All QR Codes
List QR codes for an account, optionally filtered by status:
curl -X GET "https://api.corpxapi.com/v1/accounts/{accountId}/pix/qr-codes?status=PAID" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
Response
{
"items": [
{
"txid": "8ab8a37b2e274c8dae51128a379c909a",
"identifier": "order-67890",
"status": "paid",
"value": 50.00,
"paidAmount": 50.00,
"endToEndId": "E303062942026020522130000005EYaT",
"reconciled": true,
"createdAt": "2026-02-05T22:09:32Z"
}
],
"count": 1
}
Full Example: E-commerce Integration
#!/bin/bash
# Configuration
API_URL="https://api.corpxapi.com"
TOKEN="your_token_here"
TENANT_ID="tenant-yourcompany"
ACCOUNT_ID="your-account-id"
PIX_KEY="your-pix-key"
# 1. Create charge for order
ORDER_ID="order-$(date +%s)"
AMOUNT=299.90
EXPIRATION=$(date -u -v+30M +"%Y-%m-%dT%H:%M:%SZ") # 30 minutes
echo "Creating charge: $ORDER_ID for R\$$AMOUNT..."
response=$(curl -s -X POST "$API_URL/v1/accounts/$ACCOUNT_ID/pix/qr-code/dynamic" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT_ID" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $ORDER_ID" \
-d "{
\"pixKey\": \"$PIX_KEY\",
\"value\": $AMOUNT,
\"expirationDate\": \"$EXPIRATION\",
\"identifier\": \"$ORDER_ID\",
\"message\": \"Store Purchase - $ORDER_ID\",
}")
# 2. Extract information
IDENTIFIER=$(echo $response | jq -r '.data.identifier')
PAYLOAD=$(echo $response | jq -r '.data.payload')
echo "Charge created!"
echo "ID: $IDENTIFIER"
echo "PIX Copy and Paste: $PAYLOAD"
# 3. Poll for payment (alternative to webhook)
while true; do
sleep 10
status_response=$(curl -s "$API_URL/v1/accounts/$ACCOUNT_ID/pix/qr-code?identifier=$IDENTIFIER" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT_ID")
current_status=$(echo $status_response | jq -r '.status')
if [ "$current_status" = "paid" ]; then
paid_amount=$(echo $status_response | jq -r '.paidAmount')
e2e=$(echo $status_response | jq -r '.endToEndId')
echo "Payment confirmed! Amount: R\$$paid_amount, E2E: $e2e"
break
elif [ "$current_status" = "expired" ]; then
echo "Charge expired"
break
fi
echo "Awaiting payment... Status: $current_status"
done
Best Practices
- Use Idempotency Key - Always send a unique identifier per charge to prevent duplicates
- Set appropriate expiration - 30 minutes for checkout, 24h for invoices
- Configure webhooks - Don't rely solely on polling; use
qrcode.paidevents - All amounts in BRL - Use max 2 decimal places (e.g.,
150.75for R$150,75) - Handle expiration - Notify the customer when the charge expires
- Store the identifier - Use it to check status and reconcile payments
Common Errors
| Error | Cause | Solution |
|---|---|---|
400 - pixKey is required | Missing PIX key | Include a valid PIX key registered for the account |
400 - value must be greater than zero | Invalid amount | Send a positive amount in BRL |
400 - value has too many decimal places | More than 2 decimals | Use max 2 decimal places (e.g., 150.75) |
400 - identifier is required | Missing identifier | Provide a unique charge identifier |
400 - expirationDate must be a valid RFC3339 timestamp | Invalid date | Use RFC3339 format (e.g., 2026-02-10T15:30:00Z) |
404 - QR code not found | Charge not found | Check the identifier and accountId |
Next Steps
- Cash Out Guide - Make PIX transfers
- Refund Guide - Reverse received payments
- Webhooks - Configure notifications