PIX Cash-In -- Gerar QR Code
Gera uma cobrança PIX com QR Code para recebimento de valores na conta associada à sua API Key.
Endpoint
POST /api/external/pix/cash-inHeaders
| Header | Tipo | Obrigatório | Descrição |
|---|---|---|---|
Authorization | String | Sim | ApiKey {client_id}:{client_secret} |
Content-Type | String | Sim | application/json |
hmac | String | Sim | Assinatura HMAC-SHA512 do body (saiba mais) |
Idempotency-Key | String | Não | Chave única para evitar processamento duplicado (max 256 chars) |
X-Key-Case | String | Não | Defina como camelCase para receber os campos da resposta em camelCase (padrão é snake_case) |
Request Body
| Campo | Tipo | Obrigatório | Descrição | Exemplo |
|---|---|---|---|---|
amount | Integer | Sim | Valor em centavos (R$ 30,00 = 3000) | 3000 |
description | String | Não | Descrição da cobrança. Se omitido, o padrão é "Cobranca PIX". Em QR estático, o limite depende do tamanho da chave PIX porque ambos compartilham a tag EMV 26. Com uma EVP de 36 caracteres, o máximo é 37 caracteres após normalização. Se excedido, retorna 422 com field e max_length. | "Pedido #1234" |
external_id | String | Não | Identificador opcional da ordem. Após trim, aceita 1 a 128 bytes e apenas a-zA-Z0-9._:-. Quando presente, é único e idempotente por conta em cash-in e cash-out. Valor inválido retorna HTTP 422 e nenhum QR é criado. | "order-9876" |
pix_key | String | Não | Chave PIX ativa e vinculada à conta para gerar o QR Code. Se omitida, usa a chave ativa mais recente da conta (ordem por data de criação DESC). Se não houver chave ativa, retorna 422; a API nunca presume CPF/CNPJ como chave. | "12345678901" |
city | String | Não | Cidade do recebedor no QR Code. Se omitida, a API consulta o cadastro mestre verificado do titular, depois o cadastro declarado de onboarding. O fallback legado é SAO PAULO. Truncada automaticamente para 15 caracteres. | "RIO DE JANEIRO" |
expiration_seconds | Integer | Não | Validade do QR Code em segundos. Faixa 3 a 86400 (3 s a 24h); fora da faixa retorna 400. Se omitido, usa o padrão do sistema (15 min). Use para limitar a exposição de QRs dinâmicos (ex.: 300 = 5 min, antifraude). | 300 |
include_image | Boolean | Não | Se false, a resposta vem com qr_code_image vazio ("") e a geração da imagem é pulada. Use quando você só precisa do copia-e-cola (qr_code). Padrão: true. | false |
expected_payer_document | String | Não | Restringe quem pode pagar a cobrança. Informe o CPF (11 dígitos) ou CNPJ (14 dígitos) do pagador esperado; pontuação é aceita e removida. Com o campo presente, um PIX vindo de qualquer outro documento é rejeitado antes do crédito (código BACEN AC06), incluindo pagamentos sem pagador identificável. Formato inválido retorna 400 e nenhum QR é criado. Alias: expectedPayerDocument. | "064.876.870-90" |
Envie amount SEMPRE como inteiro (em centavos)
O campo amount DEVE ser um inteiro em centavos. NUNCA envie valores float/decimal:
- ✅
"amount": 3000→ R$ 30,00 - ❌
"amount": 30.00→ interpretado como30centavos = R$ 0,30 (cobrança 100× menor do que pretendido) - ❌
"amount": 30→ R$ 0,30 (também incorreto)
Em JavaScript, converta sempre com Math.round antes de enviar:
const valorEmReais = 30.0;
const amount = Math.round(valorEmReais * 100); // 3000Em Python: amount = round(valor_em_reais * 100). Em Go: amount := int(math.Round(valorEmReais * 100)).
Valores monetários (entrada × resposta)
Valores de entrada são em centavos (R$ 1,00 = 100). Valores de resposta são em unidades base (R$ 1,00 = 10000). Para converter a resposta para reais, divida por 10.000. Nunca use ponto flutuante em nenhum sentido.
Identidade idempotente opcional
Sem external_id, cada POST cria uma nova cobrança. Com external_id, o primeiro comando reserva (account_id, external_id) antes da cabine. Repetir o mesmo payload retorna a mesma cobrança sem gerar outro QR; reutilizar o valor em outra cobrança ou em um cash-out retorna HTTP 409.
Pagador esperado ainda não disponível
Não existe enforcement ponta a ponta desse controle. Por segurança, a API recusa o campo com HTTP 422 em vez de aceitá-lo sem efeito. Veja Controles de Conta.
Exemplo
BODY='{"amount":3000,"description":"Pedido #1234","external_id":"order-9876"}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')
curl -X POST https://api.monetarie.com/api/external/pix/cash-in \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "hmac: $HMAC" \
-d "$BODY"Resposta de Sucesso (200)
{
"worked": true,
"transaction_id": "7popu57v6us7p6pcicgq12345",
"qr_code": "00020126580014br.gov.bcb.pix...",
"qr_code_image": "data:image/png;base64,iVBORw0KGgo...",
"external_id": "order-9876",
"amount": 300000,
"status": "active",
"type": "dynamic",
"location_url": "https://qrcode-h.monetarie.com/pix/v2/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"expires_at": "2026-03-07T16:30:00Z"
}| Campo | Tipo | Descrição |
|---|---|---|
worked | Boolean | true indica sucesso na operação |
transaction_id | String | null | Compatibilidade histórica: este campo contém o TXID da cobrança/QR, não o transactionId da transação financeira. Pode ser usado no refund; após o pagamento, prefira transactionId ou endToEndId recebidos em pix.charge.paid. null apenas em falhas internas raras de persistência |
qr_code | String | null | Código EMV copia-e-cola para pagamento. null (valor JSON literal, não a string "null") apenas em falhas internas raras de persistência |
qr_code_image | String | Imagem do QR Code codificada em base64 (PNG, prefixo data:image/png;base64,). String vazia ("") em falhas internas raras. Também vazia quando o request envia include_image: false. |
external_id | String | null | Seu identificador, retornado tal como enviado. null somente quando não informado |
amount | Integer | Valor da cobrança em unidades base (÷ 10.000 para reais). 300000 = R$ 30,00 |
status | String | Status inicial sempre active (QR Code ativo para pagamento). A evolução posterior (paid/expired/cancelled) é visível em consultas e webhooks (veja ciclo de vida do QR) |
type | String | null | Tipo do QR Code: dynamic (padrão desde abril/2026) ou static. Dinâmico requer que o banco do pagador consulte location_url e valide o JWS |
location_url | String | null | URL de consulta do payload dinâmico do BACEN (ex: https://qrcode-h.monetarie.com/pix/v2/{uuid}). Não é o JWS em si -- o banco do pagador faz um GET neste endpoint para receber o payload ISO 20022 assinado (JWS PS256). Presente apenas em QR dinâmico; null em estático |
expires_at | String | null | Data/hora de expiração do QR Code em ISO 8601 UTC com sufixo Z (ex: 2026-03-07T16:30:00Z). null se QR sem expiração |
QR dinâmico é o padrão
Todas as contas em produção usam QR dinâmico por padrão desde abril/2026. O QR dinâmico inclui uma URL (location_url) que o banco do pagador consulta para obter o payload assinado via JWS -- compatibilidade maximizada com bancos BACEN-strict.
Resposta de Erro (400)
{
"worked": false,
"detail": "O campo amount é obrigatório"
}Resposta de Erro (401)
{
"error": {
"status": 401,
"message": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
}
}Resposta de Erro (422)
{
"worked": false,
"detail": "pix_key deve ser uma chave PIX ativa vinculada à conta"
}Para QR estático, um campo que exceda o orçamento real do padrão retorna uma resposta acionável. O limite não é sempre 99: 99 é o teto do TLV agregado da tag 26, que também contém GUI e chave PIX. Exemplo com EVP:
{
"worked": false,
"detail": "description excede o limite de 37 caracteres para o QR Code estático desta conta",
"field": "description",
"max_length": 37,
"request_id": "GMxpwW_Rbk5DUiMACiZx"
}Use request_id ao acionar o suporte. Erros de validação como este não indicam falha de HMAC, ALB ou indisponibilidade da cabine PIX.
Resposta de Erro (502)
{
"worked": false,
"detail": "serviço de chaves PIX temporariamente indisponível"
}O 502 também é usado quando o serviço de geração de QR Code não devolve um BR Code válido. Nesses casos, a API não retorna sucesso nem fabrica dados.
Fluxo Recomendado
- Gere a cobrança com este endpoint
- Exiba o QR Code (
qr_code_image) ou o código copia-e-cola (qr_code) ao pagador - Receba a confirmação via Webhook quando o pagamento for efetuado
- Ou consulte o status: por ID, por E2E, por Tag
Validade do QR Code
Por padrão, o QR Code tem validade de 15 minutos. Você pode sobrescrever isso por requisição com expiration_seconds (faixa 3 a 86400 s). Precedência: expiration_seconds (requisição) > padrão do sistema. Verifique sempre o expires_at retornado na resposta para a data/hora exata.
Após o vencimento, o status muda para expired automaticamente (via worker interno, rotina a cada 5 minutos). Para cobranças canceladas manualmente pelo merchant, o status é cancelled. Veja a lista completa de status em Consultar Cash-In por ID.
Ciclo de Vida do QR Code
O QR Code passa por estes estados após a criação:
| Estado | Origem | Descrição |
|---|---|---|
active | Inicial | QR gerado com sucesso, pronto para ser escaneado/pago |
paid | Pagamento recebido | Pagamento BACEN confirmado e linkado ao QR (via worker interno após ACCC) |
expired | Worker QrExpirationChecker | TTL atingiu expires_at. Worker roda a cada 5 min marcando QRs active expirados e disparando webhook pix.charge.expired |
cancelled | Manual ou em massa | Cancelado pelo merchant (via portal) ou em operações administrativas (ex: migração estático→dinâmico em abril/2026 cancelou QRs estáticos ativos com valor) |
used | Legado | Estado intermediário transitório do pipeline antigo. Clientes novos devem tratar como equivalente a paid |
Em consultas, paid pode aparecer como settled
Os endpoints GET /transactions/:id e equivalentes retornam o campo status do ponto de vista da transação (não do QR). Um QR pago aparece como status: "settled" na consulta, com type: "pix" (ou type: "pix_qrcode" em janela curta pós-settlement enquanto a linha final em transactions ainda é persistida). Veja Consultar Cash-In por ID para a tabela completa.