Skip to content

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-in

Headers

HeaderTipoObrigatórioDescrição
AuthorizationStringSimApiKey {client_id}:{client_secret}
Content-TypeStringSimapplication/json
hmacStringSimAssinatura HMAC-SHA512 do body (saiba mais)
Idempotency-KeyStringNãoChave única para evitar processamento duplicado (max 256 chars)
X-Key-CaseStringNãoDefina como camelCase para receber os campos da resposta em camelCase (padrão é snake_case)

Request Body

CampoTipoObrigatórioDescriçãoExemplo
amountIntegerSimValor em centavos (R$ 30,00 = 3000)3000
descriptionStringNãoDescriçã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_idStringNãoIdentificador 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_keyStringNãoChave 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"
cityStringNãoCidade 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_secondsIntegerNãoValidade 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_imageBooleanNãoSe 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_documentStringNãoRestringe 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 como 30 centavos = 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:

js
const valorEmReais = 30.0;
const amount = Math.round(valorEmReais * 100); // 3000

Em 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

bash
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)

json
{
  "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"
}
CampoTipoDescrição
workedBooleantrue indica sucesso na operação
transaction_idString | nullCompatibilidade 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_codeString | nullCó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_imageStringImagem 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_idString | nullSeu identificador, retornado tal como enviado. null somente quando não informado
amountIntegerValor da cobrança em unidades base (÷ 10.000 para reais). 300000 = R$ 30,00
statusStringStatus 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)
typeString | nullTipo 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_urlString | nullURL 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_atString | nullData/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)

json
{
  "worked": false,
  "detail": "O campo amount é obrigatório"
}

Resposta de Erro (401)

json
{
  "error": {
    "status": 401,
    "message": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
  }
}

Resposta de Erro (422)

json
{
  "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:

json
{
  "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)

json
{
  "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

  1. Gere a cobrança com este endpoint
  2. Exiba o QR Code (qr_code_image) ou o código copia-e-cola (qr_code) ao pagador
  3. Receba a confirmação via Webhook quando o pagamento for efetuado
  4. 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:

EstadoOrigemDescrição
activeInicialQR gerado com sucesso, pronto para ser escaneado/pago
paidPagamento recebidoPagamento BACEN confirmado e linkado ao QR (via worker interno após ACCC)
expiredWorker QrExpirationCheckerTTL atingiu expires_at. Worker roda a cada 5 min marcando QRs active expirados e disparando webhook pix.charge.expired
cancelledManual ou em massaCancelado 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)
usedLegadoEstado 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.

MONETARIE SOCIEDADE DE CRÉDITO DIRETO S.A. - SCD · CNPJ 46.026.562/0001-05 · ISPB 46026562