# comprobantes.dev > API para leer comprobantes de transferencias (imagen o PDF) de Argentina, Uruguay y Paraguay: devuelve monto, fecha, cuentas, documentos, banco e ID de la operación, estructurados y validados. Integrá comprobantes.dev en este proyecto para leer comprobantes de transferencias. Seguí estos pasos. ## 1. Antes de escribir código - Buscá en el código dónde se reciben o se leen hoy los comprobantes (un parser con OCR o IA, una llamada a otro servicio como Convertix, una carga manual). Ahí va la integración: reemplazá la lectura actual por esta API, sin cambiar el resto del flujo. - La key va en la variable de entorno `COMPROBANTES_API_KEY`. Nunca la escribas en el código ni la commitees: agregala al `.env.example` (o equivalente) sin valor y pedile la key al usuario para probar. - Si el proyecto ya guarda los datos del comprobante en algún formato, mantenelo. Si es el formato de Convertix (`transfer_details`, `sender`, `recipient` con `cuit`, `cbu_cvu`...), la respuesta trae ese mismo formato en `legacy`. ## 2. El pedido ``` POST https://api.comprobantes.dev/v1/receipts Authorization: Bearer $COMPROBANTES_API_KEY Content-Type: multipart/form-data ``` | campo | | |---|---| | `file` | obligatorio. Imagen (JPEG, PNG, WebP, HEIC) o PDF, hasta 14 MB, con su content-type (`image/jpeg`, `application/pdf`...). Si tu cliente HTTP no lo manda, agregá el campo `mimeType`. Un comprobante por pedido | | `currency` | moneda del negocio: `ARS` (default), `UYU`, `PYG`, `PEN`, `MXN`. Define qué países se esperan (`ARS` → AR, `UYU` → UY y AR, `PYG` → PY y AR) | | `countries` | opcional, sobreescribe los países: `PY,AR` | | `idempotencyKey` | ID único del lado tuyo, por ejemplo el ID del mensaje que trajo el comprobante (también como header `Idempotency-Key`). Mandalo siempre: la misma key devuelve la misma respuesta sin leer ni cobrar de nuevo, así los reintentos son seguros | | `receivedAt` | fecha y hora ISO 8601 con zona en que llegó el comprobante (`2026-10-20T14:32:00-03:00`). Corrige fechas sin año o ambiguas. Mandalo si lo tenés | | `metadata` | opcional, JSON como string, hasta 20 claves con valores simples: contexto para métricas (`{"branchId":"12","channel":"whatsapp"}`). Sin datos personales | | `sourceRef` | opcional, referencia tuya hasta 200 caracteres (`pedidos:4821`) | Si es más cómodo mandar JSON: `POST https://api.comprobantes.dev/v1/receipts/parse` con `{"file": "", "mimeType": "image/jpeg", "currency": "ARS", "idempotencyKey": "...", ...}` (mismos campos; `metadata` como objeto). ```bash curl https://api.comprobantes.dev/v1/receipts \ -H "Authorization: Bearer $COMPROBANTES_API_KEY" \ -F file=@comprobante.jpg \ -F currency=ARS \ -F idempotencyKey=msg_8f2c41 ``` ## 3. La respuesta **200**: comprobante leído. ```json { "ok": true, "receipt": { "country": "AR", "currency": "ARS", "amount": "45000.00", "date": "2026-09-29T14:32:00", "issuer": "Mercado Pago", "ids": { "operationNumber": "128834105592", "transactionId": null, "interbank": { "network": "COELSA", "value": "K4NRXQ20DJ7WMP3LYE9VZ5" } }, "concept": "Varios", "sender": { "name": "María González", "taxId": { "type": "CUIL", "value": "27334455667" }, "account": { "type": "CVU", "value": "0000003101234567890126" }, "alias": null, "bank": "Mercado Pago" }, "recipient": { "name": "Distribuidora del Sur SA", "taxId": { "type": "CUIT", "value": "30712345671" }, "account": { "type": "CBU", "value": "0720123900000009876545" }, "alias": "distri.sur.ok", "bank": "Banco Santander" } }, "legacy": { "transfer_details": { "...": "..." }, "sender": { "...": "..." }, "recipient": { "...": "..." }, "additional_info": null }, "warnings": [], "fileUrl": "https://files.comprobantes.dev/receipts/3f1a7c...b8.jpg", "meta": { "requestId": "6b0e...", "durationMs": 3120 } } ``` - `amount`: string decimal con punto y 2 decimales, siempre positivo. - `date`: hora local del comprobante, sin zona (`YYYY-MM-DD` o `YYYY-MM-DDTHH:mm:ss`), o `null`. - Cualquier campo puede venir `null` si el comprobante no lo muestra o no validó. - `taxId.type`: `CUIT`, `CUIL`, `DNI`, `CDI`, `CI`, `RUC`, `RUT`, `OTHER`. `account.type`: `CBU`, `CVU`, `ACCOUNT`. - `ids.interbank`: ID de la transferencia en el sistema interbancario (`COELSA` en Argentina, `UY_INSTANT` en Uruguay). Es el mismo para quien envía y quien recibe. - `legacy`: los mismos datos en el formato de Convertix: `transfer_details` (`date`, `amount`, `operation_number`, `transaction_id`, `coelsa_id`, `concept`), y `sender` / `recipient` (`name`, `cuit`, `cbu_cvu`, `alias`, `account_identifier`, `bank`). - `warnings`: datos que se corrigieron o descartaron por no validar. Si no está vacío, guardá el comprobante igual pero marcalo "a revisar". - `fileUrl`: el archivo guardado, con una URL pública imposible de adivinar. Guardala para poder ver el comprobante después. - `meta.requestId`: guardalo junto al comprobante (sirve para mandar feedback y para soporte). **422**: no se pudo leer. `{"ok": false, "reason": "...", "detail": "...", "fileUrl": "..."}` - `reason: "not_a_receipt"`: no es un comprobante (una foto, un sticker, un video). Ignoralo o marcalo como "no es comprobante". - `invalid_structure`, `zero_amount`, `missing_parties`: parece un comprobante pero no se pudo leer bien. Marcalo para carga manual. **503** (`provider_error`), **429** (`rate_limited`), errores de red o timeouts: transitorios, reintentá. **400** (`invalid_request`, con `issues`) y **401** (`unauthorized`): error de integración o de key. No reintentes; registralo. ## 4. Reglas de la integración 1. **Timeout del cliente de 60 s.** Lo normal son 3 a 10 s, pero en picos puede tardar más. 2. **Reintentos solo en 503, 429, errores de red y timeouts**: hasta 3, con espera de 2, 4 y 8 s, siempre con la misma `idempotencyKey`. Nunca reintentes un 422, 400 o 401. 3. **Si leer comprobantes no es lo principal del flujo** (por ejemplo, un mensaje de WhatsApp que igual hay que guardar), que un error de la API no lo rompa: guardá el mensaje y marcá el comprobante como pendiente o "a revisar". 4. **Duplicados**: para saber si un comprobante ya se cargó, compará `receipt.ids.interbank.value`. Normalizalo antes de comparar: mayúsculas, sin espacios, `O` → `0` e `I` → `1` (se confunden al leer). Si no hay ID interbancario, usá `ids.operationNumber` + `amount` + `date`. 5. Un comprobante por pedido. Para varios, mandá pedidos en paralelo (con un límite razonable, por ejemplo 5 a la vez). ## 5. Feedback (opcional) Si en el sistema una persona aprueba o corrige los datos leídos, avisalo. Mejora la lectura y no cuesta nada. Si falla, ignoralo: no debe frenar nada. ``` POST https://api.comprobantes.dev/v1/receipts/{meta.requestId}/feedback Authorization: Bearer $COMPROBANTES_API_KEY Content-Type: application/json {"verdict": "approved"} {"verdict": "corrected", "fields": {"transfer_details.amount": "45000.00"}} {"verdict": "not_a_receipt"} ``` Sin el `requestId`: `POST https://api.comprobantes.dev/v1/receipts/feedback` con la `idempotencyKey` en el mismo body. ## 6. Verificá - Un test con la API simulada que cubra: 200 con y sin `warnings`, 422 `not_a_receipt`, 503 con reintento y la misma `idempotencyKey`. - Una prueba real con la key del usuario y una imagen de un comprobante: mostrale al usuario lo que devolvió y dónde quedó guardado. - Al terminar, resumí qué archivos cambiaste, qué variable de entorno hay que configurar en cada ambiente y cómo volver a la lectura anterior si hiciera falta.