Skip to content

PIX Cash-Out Copia y Pega

Realiza una transferencia PIX utilizando el codigo EMV (copia y pega) extraido de un QR Code PIX.

Endpoint

POST /api/external/pix/cash-out

Headers

HeaderTipoObligatorioDescripcion
AuthorizationStringSiApiKey {client_id}:{client_secret}
Content-TypeStringSiapplication/json
hmacStringSiFirma HMAC-SHA512 del body (hex)
Idempotency-KeyStringNoClave unica para evitar procesamiento duplicado (max 256 chars). Comportamiento identico al documentado en PIX Cash-Out por Clave

Permiso obligatorio

La API Key debe tener el permiso transfer:write para enviar PIX. Sin el, la solicitud retorna 403 Forbidden. Vea como configurar permisos.

Request Body

CampoTipoObligatorioDescripcion
amountIntegerSiValor en centavos. R$ 30,00 = 3000. En QR dinamico, este valor es sobrescrito por la consulta a la URL del QR — vea abajo
emvStringSiCodigo EMV copia y pega del QR Code PIX. El alias codigo_copia_cola tambien es aceptado pero emv es canonico — prefieralo
descriptionStringNoDescripcion de la transferencia (max 140 caracteres)
external_idStringNoIdentificador de su sistema para rastreo. Max 128 chars despues de trim. Solo caracteres a-zA-Z0-9._:-. Retornado en respuestas y webhooks. Valores invalidos son silenciosamente descartados (transaccion prosigue con external_id: null). Vea PIX Cash-Out por Clave para detalles.
end_to_end_idStringNoEnd-to-End ID en formato BACEN. Recomendado omitir — el backend genera determinista. Solo envie en escenario de reprocesamiento coordinado

Codigo Copia y Pega

El campo emv acepta el codigo EMV completo copiado de un QR Code PIX. La API extrae automaticamente la clave PIX, los datos del receptor y el valor original del cobro a partir del payload EMV. El backend valida el CRC-16/CCITT-FFFF y la estructura TLV antes de proseguir.

QR Estatico vs QR Dinamico

La API trata los dos tipos de forma distinta:

QR Estatico (PoIM=11, sin URL):

  • La clave PIX y los metadatos vienen del propio payload EMV
  • El amount enviado en la solicitud es usado directamente como valor de la transferencia
  • No hay consulta externa — liquidacion inmediata despues de validacion DICT

QR Dinamico (PoIM=12, con URL en el tag 26/25):

  • El backend hace Provider.consult_qrcode en la URL embebida en el payload EMV y recibe un JWS (BACEN Manual 2.9.0)
  • El valor autoritativo viene de la respuesta JWS (valor.original) y sobrescribe el amount enviado por el cliente
  • Si la consulta a la URL falla (timeout, JWS invalido, QR expirado en el emisor), retorna HTTP 422 con detail: "QR Code dinamico nao pode ser resolvido"
  • Use el valor sobrescrito como fuente de la verdad — net_amount en la respuesta refleja el valor real cobrado

No confie en el valor enviado en QR dinamico

En QR dinamico, siempre consulte la respuesta del POST para obtener el amount efectivo. El backend ignora cualquier divergencia entre el valor enviado y el valor retornado por el emisor del QR — eso es exigencia BACEN.

Valores monetarios

Los valores de entrada son en centavos (R$ 1,00 = 100). Los valores de respuesta son en unidades base (R$ 1,00 = 10000). Para convertir la respuesta a reales, divida por 10.000. Nunca use punto flotante.

Ejemplo

bash
curl -X POST https://api.owem.com.br/api/external/pix/cash-out \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "hmac: $HMAC" \
  -d '{
    "amount": 3000,
    "emv": "00020126580014br.gov.bcb.pix0136a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d5204000053039865802BR5913NOME RECEBEDOR6008BRASILIA62070503***6304ABCD",
    "description": "Pagamento via QR Code",
    "external_id": "invoice-4521"
  }'

Respuesta de Exito -- 200 / 202

json
{
  "worked": true,
  "final": false,
  "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
  "end_to_end_id": "E37839059202603091530abcdef01",
  "external_id": "invoice-4521",
  "amount": 300000,
  "fee_amount": 350,
  "net_amount": 300350,
  "status": "accepted",
  "detail": "PIX enviado para processamento"
}

HTTP 200 vs 202

  • HTTP 200: Transaccion ya liquidada (final: true, status: "settled").
  • HTTP 202: Transaccion aceptada para procesamiento (final: false). status puede ser "accepted" (flujo normal), "queued" (rate-limit DICT — retry automatico cada 3s por hasta 120min, session 155) o "pending_approval" (aguardando aprobacion). Acompane el status via polling o webhook.
CampoTipoDescripcion
workedBooleantrue indica que la solicitud fue aceptada
finalBooleantrue cuando la transaccion alcanzo estado terminal (liquidada o rechazada). false cuando aun en procesamiento
transaction_idStringIdentificador unico de la transaccion
end_to_end_idStringIdentificador End-to-End en el SPI/BACEN
external_idStringSu identificador, retornado tal como fue enviado. null si no informado
amountIntegerValor de la transferencia en unidades base (÷ 10.000 para reales). 300000 = R$ 30,00. En QR dinamico, refleja el valor autoritativo retornado por la consulta JWS — puede divergir del amount enviado en el request
fee_amountIntegerTarifa cobrada en unidades base (÷ 10.000 para reales)
net_amountIntegerValor bruto debitado en la cuenta pagadora (amount + fee_amount) — no es el valor que el destinatario recibe. Vea la nota en PIX Cash-Out por Clave sobre la asimetria de semantica entre cash-out y cash-in
statusStringUno de: accepted, settled, queued, pending_approval. Vea detalles en PIX Cash-Out por Clave
detailStringMensaje descriptivo

Codigos de Rechazo

Los rechazos del cash-out por EMV siguen exactamente el mismo patron del PIX Cash-Out por Clave — dos formatos de body (Formato A {status: "failed", errors: [...]} y Formato B {errors: {bad_request: "..."}}), tres clases de error (validacion / integracion / rate-limit encolado), y los mismos vocabularios UPPERCASE × lowercase. Los items abajo destacan solo los codigos especificos del camino EMV.

Errores de validacion especificos del EMV (HTTP 400 / 422)

HTTPFormatoCampo con codigoSignificado
400Berrors.bad_request: "invalid emv payload"Payload EMV malformado (CRC-16 invalido, TLV incompleto, tag obligatoria ausente) — detectado por el parser antes del Orchestrator
400Berrors.bad_request: "invalid or missing amount"amount ausente, cero, negativo o no-entero (QR estatico)
422Aerrors[0].code: "same_institution_transfer"QR generado por cuenta Owem — PIX intra-institucional no soportado (use TEF). Nota: HTTP 422 (no 400), con shape {status: "failed", errors: [{code: "same_institution_transfer", params: []}]}
422detail: "QR Code dinamico nao pode ser resolvido"Falla en la consulta a la URL del QR dinamico (timeout, JWS invalido, QR expirado en el emisor) — este camino es tratado por el controller antes del Orchestrator, retorna shape legacy {errors: {unprocessable_entity: "..."}}
422Aerrors[0].code: "insufficient_balance"Saldo disponible menor que amount + fee_amount

Otros errores

Para los codigos dict_key_not_found, dict_key_blocked, dict_rate_limited (sincronico), dict_bucket_exhausted (sincronico), dict_lookup_failed, provider_rejected, provider_schema_error, provider_unknown_errortodos retornan HTTP 400 en el Formato A (no 429 ni 503). Detalles en PIX Cash-Out por Clave — Errores de integracion.

Rate-limit con retry automatico (HTTP 202 queued)

Cuando el ClientLimiter per-merchant (default DICT_CLIENT_MAX_PER_MIN=120) o el DictBucket.Guard global (refill DICT_BUCKET_REFILL_RATE=18/min, capacity 250) detecta que el limite fue alcanzado antes de llegar al OnZ, el cash-out es encolado en Fluxiq.Workers.PixOutRetryWorker y retorna HTTP 202 con status: "queued". El flag pix_out_retry_queue_enabled esta ON en PRD desde session 155. Detalles completos en PIX Cash-Out por Clave — Rate-limit con retry automatico.

Rechazos BACEN asincronicos

Despues de aceptacion inicial (HTTP 202), el SPI/BACEN puede rechazar via PACS.002 RJCT. Ese rechazo:

  • No altera la respuesta HTTP original (ya fue enviada como 202)
  • Aparece via GET /transactions/:id con status: "failed" + reason_code (AC03, AB03, ED05 etc.) + reason_description en ingles
  • Dispara webhook pix.payout.rejected con los mismos campos estructurados

Vea la lista completa de codigos BACEN en Consultar Cash-Out por ID.

Proximos Pasos

Despues de crear la transferencia, acompane el status via:

O reciba la confirmacion automaticamente via Webhook.

Owem Pay Instituição de Pagamento — ISPB 37839059