Emitir una nota de crédito por API: POST /bill/receipts/credit-note/

Revierte total o parcialmente el importe de un comprobante autorizado. Elegís cómo acreditar: por renglón, por monto, por porcentaje o, si no indicás nada, por el cien por ciento del comprobante original. Los ejemplos de esta página se capturaron en sandbox (token yf_test_): el CAE y el número son simulados, ARCA no los emitió y no valen como comprobante fiscal; lo reconocés por simulated: true y livemode: false.

Operación
POST /bill/receipts/credit-note/
Scope
invoices:write
Autenticación
Header X-API-Key (o Authorization: Bearer) con un token de la cuenta.
Reintentos
Admite el header Idempotency-Key.
Recurso
Notas de crédito y débito

Qué hace

Revierte total o parcialmente el importe de un comprobante autorizado: por renglón (lineas), por monto (importe_a_acreditar), por porcentaje (porcentaje_aplicar) o, sin ninguno, el 100%. Con un token yf_test_* (sandbox) este endpoint no llama a AFIP: persiste un comprobante simulado (simulated: true, livemode: false, un CAE sintético) en la base sandbox aislada del tenant. Requiere scope invoices:write. En un tenant que factura con SIFEN (Paraguay) responde 409 con error_code: use_sifen_routes: emití con POST /sales/ y las notas con POST /sales/{sale_id}/credit_note/. Notas de crédito y débito sobre comprobantes de un CUIT dado de baja: se permiten mientras ese CUIT no lo haya registrado otra cuenta; si lo registró otra responde 409 API_PARTNER_NOTE_ISSUER_CLAIMED_ELSEWHERE, y si ARCA ya no lista la delegación la nota queda pendiente con API_PARTNER_NOTE_ISSUER_DELEGATION_MISSING.

Parámetros

ParámetroDóndeRequeridoTipoDescripción
Idempotency-KeyheadernostringClave elegida por el cliente (hasta 255 caracteres) para hacer este POST seguro de reintentar. Un segundo request con la MISMA clave y el MISMO body reproduce la respuesta original (200/201, header Idempotency-Replayed: true) en vez de crear un segundo recurso. La misma clave con un body DISTINTO devuelve 422. La clave está scopeada al token exacto (yf_live_*/yf_test_*) que la usó — dos tokens nunca colisionan aunque manden la misma clave. TTL: 24 horas.

Cuerpo del request

Formato application/json.

CampoTipoRequeridoDescripción
comprobante_asociado_idstringsíId del comprobante (factura) aprobado que esta nota acredita.
motivostringno
lineasarray de objectnoDevolución por renglón.
lineas[].lineaintegersíÍndice (desde 0) del renglón del comprobante original.
lineas[].cantidadnumbersíUnidades que se devuelven (no puede superar la cantidad original).
importe_a_acreditarnumbernoMonto a acreditar, IVA incluido (no puede superar el total del comprobante).
porcentaje_aplicarnumbernoPorcentaje del comprobante a acreditar.
itemsarray de objectnoYa no se usa para devoluciones parciales: usá lineas, importe_a_acreditar o porcentaje_aplicar.
importe_totalnumberno
ambientestringnoIgnorado: el ambiente sale de la configuración de la cuenta. Valores: production, testing. Por defecto: production.
autorizarbooleannoPor defecto: false.

Ejemplo real capturado

Los ejemplos se generaron en el entorno de pruebas: el CAE es simulado y no tiene validez fiscal.

Capturado el 2026-11-10 en el entorno de pruebas con un token yf_test_*: los datos personales están anonimizados y el CAE de un comprobante de prueba es sintético.

Request

{
  "comprobante_asociado_id": "6af28fe59d98ce51ca3bc5c7",
  "motivo": "Devolucion de mercaderia",
  "lineas": [
    {
      "linea": 1,
      "cantidad": 1
    }
  ],
  "autorizar": true
}

Respuesta (HTTP 200)

{
  "success": true,
  "data": {
    "motivo": "Devolucion de mercaderia",
    "lineas": [
      {
        "linea": 1,
        "cantidad": 1
      }
    ],
    "tipo_comprobante": 8,
    "punto_venta": 1,
    "numero_comprobante": 4261715,
    "cae": "05561320376600",
    "cae_vencimiento": "20261120",
    "fecha_comprobante": "20261110",
    "comprobante_asociado_id": "6af28fe59d98ce51ca3bc5c7",
    "estado": "autorizado",
    "ambiente": "sandbox",
    "livemode": false,
    "simulated": true,
    "simulated_note": "Sandbox test-mode document: no ARCA call was made. This CAE is synthetic and is not valid for a real fiscal document. For a real homologation CAE use a live token with \"ambiente\": \"testing\".",
    "created_at": "2026-11-10T03:30:46.939211+00:00",
    "email": "[email protected]",
    "id": "6af28fe69d98ce51ca3bc5cd",
    "sandbox": true
  },
  "message": "Simulated credit note created in sandbox mode (no real ARCA CAE)"
}

Campos de la respuesta 200

CampoTipoRequeridoDescripción
successbooleanno
dataobjectno
data.idstringno
data.tipo_comprobanteintegerno
data.punto_ventaintegerno
data.numero_comprobanteintegerno
data.caestringnoCódigo de Autorización Electrónico de AFIP (o sintético en sandbox).
data.cae_vencimientostringno
data.fecha_comprobantestringno
data.estadostringno
data.ambientestringno
data.livemodebooleannofalse cuando el comprobante fue emitido por un token yf_test_* (simulado, sin AFIP real).
data.simulatedbooleannotrue en modo sandbox: el CAE tiene el formato correcto pero NO es válido para un comprobante fiscal real.
data.iva_handlingobjectno
data.iva_handling.incluye_iva_discriminadobooleanno
data.iva_handling.tipo_comprobante_nombrestringno
data.iva_handling.condicion_fiscal_emisorstringno
data.idempotent_replaybooleannotrue si esta respuesta es la reproducción de un request anterior idéntico.
data.itemsarray de objectno
data.items[].Descripcionstringno
data.items[].Cantidadnumberno
data.items[].PrecionumbernoPrecio unitario (neto de IVA cuando el tipo discrimina IVA).
data.items[].Bonificacionnumberno
data.items[].IvaIdintegernoAlícuota AFIP (3=0%, 4=10.5%, 5=21%, 6=27%, 8=5%, 9=2.5%).
data.items[].importe_neto_lineanumbernoNeto de la línea: Precio x Cantidad - Bonificacion, redondeado a 2 decimales (ROUND_HALF_UP). Calculado por el backend.
data.items[].importe_iva_lineanumbernoIVA de la línea (0 si el tipo no discrimina IVA, 0% o exento). Calculado por el backend.
data.items[].importe_total_lineanumbernoimporte_neto_linea + importe_iva_linea. La suma de las líneas puede diferir de importe_total por el redondeo por línea y no incluye tributos.
messagestringno
_linksobjectnoMapa HATEOAS: cada valor es un link accionable relativo a este recurso.

Respuestas de error

Todo error tiene la forma {"success": false, "error": "...", "code": "..."}.

EstadoDescripciónCódigo
400Solicitud inválida (body ausente o con formato incorrecto).VALIDATION_ERROR
401Falta autenticación o el token es inválido/expiró.UNAUTHORIZED
403El token no tiene el/los scope(s) requeridos, o el plan del tenant no habilita el módulo.FORBIDDEN
409Conflicto de estado (p. ej. editar un recurso en un estado que no lo permite).CONFLICT
422Semánticamente inválido — incluye la reutilización de un Idempotency-Key con un body distinto.UNPROCESSABLE_ENTITY
429Se superó el rate limit del endpoint o del tenant. Ver headers X-RateLimit-* y Retry-After.RATE_LIMITED

Código para probarlo

Estos ejemplos corren contra el entorno de pruebas con un token yf_test_* en la variable $YF_TEST_TOKEN. En producción la base es https://api.yo-facturo.com/api/v1.

curl -sS -X POST "https://api.yo-facturo.com/api/v1/bill/receipts/credit-note/" \
  -H "X-API-Key: $YF_TEST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "comprobante_asociado_id": "6af28fe59d98ce51ca3bc5c7",
  "motivo": "Devolucion de mercaderia",
  "lineas": [
    {
      "linea": 1,
      "cantidad": 1
    }
  ],
  "autorizar": true
}'

Relacionado