kamiPay LogokamiPay Docs

QR Code Creation

Generate dynamic PIX QR Codes to receive payments in BRL, ARS, or USDt.

This endpoint generates a dynamic PIX QR Code that can be scanned from any Brazilian banking app. The only required field is amount — kamiPay handles the conversion and generates the QR automatically.

By default, amount is interpreted as BRL. If you want to charge in ARS or USDt instead, pass currency accordingly.

Wallet configuration: Your destination wallet is set up during onboarding — you don't need to send it in each request. If you operate with multiple stores or checkouts, you can use store_id and checkout_id to select a specific wallet. For more details, see Multi-Wallet Routing.

Request Body

NameTypeDescription
amountfloatRequired. Amount to charge, expressed in the currency specified by currency. Cannot have more than 2 decimals.
currencystringOptional. Accepted values: "ARS", "BRL", "USDT". Case-insensitive ("ars", "brl", "usdt" are all valid). If not sent, defaults to "BRL".
expireintegerOptional. QR Code expiration time in seconds. Default: 300 (5 min). Maximum: 86400 (24h).
external_idstringOptional. Your internal ID for this transaction. Recommended for deduplication and tracking.
external_datastringOptional. Free-text description for this charge (e.g. "Hotel booking #234"). Also accepted as external_reference — both have the same effect.
store_idintegerOptional. ID of your store. Default: 1. Only needed if you operate with multiple stores.
checkout_idintegerOptional. ID of your checkout. Default: 1. Only needed if you operate with multiple checkouts.
addressstringOptional. Wallet address to receive the USDt settlement. If omitted, kamiPay uses the wallet configured for the selected store/checkout.

Printed Dynamic QR Integration

When a checkout_id and store_id are provided and that checkout has a Printed Dynamic QR configured as its default, this endpoint behaves differently from a standard dynamic QR creation:

  1. A charge is automatically assigned to the existing printed QR for that checkout.
  2. A dynamic QR is also generated and returned as usual.
  3. The customer can pay using either QR — the physical printed one or the dynamic one — and the payment will be settled the same way.

This allows POS setups where a permanent QR is already on display, while still providing a digital QR for receipts, kiosks, or remote payment links. Both QRs represent the same charge and only one payment will be accepted.

The Printed Dynamic QR and the dynamic QR share the same underlying charge. Whichever the customer scans first completes the transaction — the other becomes invalid once payment is received.

Example Request

const url = `${baseURL}/v2/charge/create_dynamic_pix`;

const body = {
  amount: 150,
  currency: "BRL", // "ARS", "BRL", or "USDt"
  external_id: "order-001", // recommended
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${access_token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body),
});
import requests

url = f"{base_url}/v2/charge/create_dynamic_pix"

body = {
  "amount": 150,
  "currency": "BRL",  # "ARS", "BRL", or "USDt"
  "external_id": "order-001",  # recommended
}

headers = {
  "Authorization": f"Bearer {access_token}",
  "Content-Type": "application/json",
}

response = requests.post(url, json=body, headers=headers)
package main

import (
  "bytes"
  "encoding/json"
  "fmt"
  "net/http"
)

func main() {
  url := fmt.Sprintf("%s/v2/charge/create_dynamic_pix", baseURL)

  requestBody, _ := json.Marshal(map[string]interface{}{
    "amount":      150,
    "currency":    "BRL", // "ARS", "BRL", or "USDt"
    "external_id": "order-001", // recommended
  })

  req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
  req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", access_token))
  req.Header.Add("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error making request:", err)
    return
  }
  defer resp.Body.Close()
}

Response

QR Code Created Successfully

{
  "emv": "00020101021226810014br.gov.bcb.pix25...",
  "operation_id": "ptxr_01knhd0c2ten6t5d6",
  "kamipay_id": "dqr_01knhczzereejbh6fan",
  "amount_brl": 150.00,
  "amount_usdt": 27.34,
  "rate": 5.296199,
  "date": 1775479302,
  "expiration": 1775479602,
  "external_id": "order-abc-123"
}

When currency is "ARS", the response also includes amount_ars with the original ARS amount. This field is not present for BRL or USDt requests.

Bad Request

Invalid currency:

{
  "message": "Invalid currency. Must be one of: ARS, BRL, USDt",
  "request_id": "30e87ab5xxxxxxxxxxxxf8249f594cfb"
}

Invalid amount:

{
  "message": "Invalid amount. It must be a numeric value bigger than zero",
  "request_id": "30e87ab5xxxxxxxxxxxxf8249f594cfb"
}

Unauthorized

{
  "message": "Unauthorized",
  "request_id": "30e87ab5xxxxxxxxxxxxf8249f594cfb"
}

Internal Server Error

{
  "detail": "an unexpected error occurred"
}

Service Unavailable

{
  "detail": "service_unavailable"
}

Response Fields

FieldTypeDescription
emvstringThe PIX brcode to render as a QR Code. Pass this string to any QR library.
operation_idstringBanking-level tracking number for this transaction.
kamipay_idstringkamiPay's unique identifier for this transaction. Use this for tracking and support.
amount_brlfloatFinal amount in Brazilian Reais that the payer will pay.
amount_usdtfloatUSDt equivalent of the BRL amount (always present).
amount_arsfloatThe ARS amount sent in the request. Its BRL equivalent is what the payer will be charged. Only present when currency is "ARS".
ratefloatBRL/USDt exchange rate used for this transaction.
dateintegerUnix timestamp of QR Code creation.
expirationintegerUnix timestamp when the QR Code expires.
external_idstring | nullThe external_id you sent in the request. null if not provided.

Transaction Identifiers

IdentifierDescription
kamipay_idkamiPay's identifier for this transaction. Use this for tracking and when contacting support.
operation_idBanking-level tracking number assigned by the payment gateway.
external_idYour identifier. Reflects what you sent in the request. Useful for matching QR Codes to orders in your system.

Multi-Wallet Routing

kamiPay gives you flexibility in how USDt settlements are routed after a QR Code is paid. There are two common setups:

  • Centralized: All payments go to your main wallet. You collect and distribute funds to your users/clients on your end.
  • Direct to client: Payments go directly to your clients' wallets. kamiPay handles the routing per transaction using store_id and checkout_id.

This makes it easy to build platforms where each merchant, store, or user receives their own settlement without you having to redistribute manually.

Any wallet used for settlement must be previously whitelisted with kamiPay. Use store_id and checkout_id in your request to select which wallet receives each payment.

Contact us for more details on multi-wallet configurations so we can help you implement the setup that best fits your use case.

On this page