Emitir factura por API: POST /bill/receipts/invoice/
Con esta operación creás una factura electrónica y, si mandás autorizar: true, la autorizás en el mismo llamado. Los precios de cada renglón son finales (IVA incluido) salvo que indiques lo contrario, y el header Idempotency-Key evita emitir dos veces ante un reintento. 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.
Qué hace
Crea (y opcionalmente autoriza) una factura electrónica AFIP. 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. Soporta reintentos seguros vía Idempotency-Key; si no se envía ese header, igual se deduplica por huella del payload durante 5 minutos para no emitir dos comprobantes fiscales por un reintento de red. Los precios de items son finales (IVA incluido); precios_con_iva: false los toma netos. 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/.
Parámetros
| Parámetro | Dónde | Requerido | Tipo | Descripción |
|---|---|---|---|---|
Idempotency-Key | header | no | string | Clave 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.
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tipo_comprobante | integer | no | Código AFIP del tipo de comprobante (6=Factura B, 1=Factura A, 11=Factura C, ...). Opcional: se infiere si se omite. 19 = Factura E (exportación de servicios): se infiere si mandás export. |
punto_venta | integer | sí | Punto de venta habilitado en ARCA para facturación electrónica. Obligatorio. |
concepto | integer | sí | Concepto ARCA: 1 = productos, 2 = servicios, 3 = productos y servicios. Obligatorio. Valores: 1, 2, 3. |
tipo_documento | integer | sí | Código AFIP del tipo de documento del receptor (80=CUIT, 96=DNI, 99=Consumidor Final). |
numero_documento | string | sí | |
razon_social | string | no | |
condicion_iva_receptor_id | integer | no | Condición frente al IVA del receptor. Código ARCA: 1 = Responsable Inscripto, 4 = Exento, 5 = Consumidor Final, 6 = Monotributo (otros códigos ARCA también se aceptan). Equivale a receptor_condicion_iva y condicion_iva. |
receptor_condicion_iva | string | no | Condición del receptor por nombre (responsable_inscripto, monotributo, exento, consumidor_final). Equivale a condicion_iva_receptor_id. |
condicion_iva | string | no | Alias de receptor_condicion_iva. Equivale a condicion_iva_receptor_id. |
domicilio | string | no | |
items | array de object | sí | |
items[].descripcion | string | no | |
items[].cantidad | number | no | |
items[].precio_unitario | number | no | Precio unitario FINAL (IVA incluido) salvo precios_con_iva: false. |
items[].iva_id | integer | no | Alícuota de IVA de la línea, código ARCA: 5 = 21%, 4 = 10,5%, 6 = 27%, 3 = 0%, 2 = exento. Si se omite, 21%. Por defecto: 5. |
items[].bonificacion | number | no | Descuento de la línea, en importe, sobre cantidad x precio. |
importe_total | number | no | Opcional: el backend lo calcula. Si lo mandás, tiene que coincidir con el total de los items. |
customer_id | string | no | Id del cliente en YoFacturo (alternativa a mandar los datos fiscales sueltos). |
sale_id | string | no | Venta de origen, si corresponde. |
ambiente | string | no | Ignorado: el ambiente sale de la configuración de la cuenta. Valores: production, testing. Por defecto: production. |
autorizar | boolean | no | Si true, dispara la autorización (obtención del CAE) en background inmediatamente después de crear el borrador. Por defecto: false. |
precios_con_iva | boolean | no | true: los precio_unitario son finales, IVA incluido (default con API token). false: son netos de IVA y el backend suma el IVA (el comportamiento anterior al 5-oct-2026). |
taxpayer_id | string | no | Solo cuentas API partner: id del contribuyente registrado en POST /partner/taxpayers/. La letra, el punto de venta y el CUIT emisor salen de ese contribuyente. Las notas de crédito y débito no lo reciben: toman el emisor del comprobante original. |
export | object | no | Datos de una exportación de SERVICIOS (Factura E, autorizada por el web service de exportación de ARCA, WSFEX). Si mandás este objeto el comprobante es una Factura E (tipo 19): no lleva IVA y la cotización la fija el backend con la cotización oficial de ARCA (no se envía). Requiere un punto de venta de exportación (wsfex_punto_venta) habilitado en ARCA. Los importes de items van en la moneda de moneda_id. |
export.pais_destino | integer | sí | Código de país de destino de ARCA (FEXGetPARAM_DST_pais), nunca Argentina (200). Ej.: 212 = Estados Unidos. |
export.domicilio_cliente | string | sí | Domicilio del cliente del exterior. |
export.moneda_id | string | sí | Moneda del comprobante, código MonId de ARCA: DOL = dólar estadounidense, 060 = euro, 012 = real, PES = peso. Valores: DOL, 060, 012, PES. |
export.fecha_pago | string (date) | sí | Fecha de pago (YYYY-MM-DD). Obligatoria para servicios. |
export.cuit_pais_cliente | string | no | CUIT país del cliente (tabla DST_CUIT de ARCA). Hace falta este o id_impositivo. |
export.id_impositivo | string | no | Identificación tributaria del cliente en su país. Hace falta este o cuit_pais_cliente. |
export.idioma_cbte | integer | no | Idioma del comprobante: 1 = español, 2 = inglés, 3 = portugués. Valores: 1, 2, 3. Por defecto: 1. |
export.forma_pago | string | no | Forma de pago (texto). |
export.obs_comerciales | string | no | Observaciones comerciales. |
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
{
"tipo_comprobante": 6,
"punto_venta": 1,
"concepto": 1,
"tipo_documento": 99,
"numero_documento": "0",
"razon_social": "Empresa Demo SRL",
"items": [
{
"descripcion": "Camiseta basica",
"cantidad": 2,
"precio_unitario": 12100,
"iva_id": 5
}
],
"autorizar": true,
"precios_con_iva": true
}Respuesta (HTTP 200)
{
"success": true,
"data": {
"tipo_comprobante": 6,
"punto_venta": 1,
"concepto": 1,
"tipo_documento": 99,
"numero_documento": "0",
"razon_social": "Empresa Demo SRL",
"items": [
{
"descripcion": "Camiseta basica",
"cantidad": 2,
"precio_unitario": 12100,
"iva_id": 5
}
],
"precios_con_iva": true,
"numero_comprobante": 47862880,
"cae": "67418234091409",
"cae_vencimiento": "20261120",
"fecha_comprobante": "20261110",
"estado": "autorizado",
"ambiente": "sandbox",
"livemode": false,
"sandbox": true,
"simulated": true,
"simulated_note": "Sandbox test-mode invoice: no AFIP call was made. This CAE is not issued by AFIP and is not valid for a real fiscal document.",
"created_at": "2026-11-10T04:52:53.840887+00:00",
"email": "[email protected]",
"id": "6af2a325ee50f6ede94d9846"
},
"message": "Factura simulada creada en modo sandbox (sin CAE real de AFIP)",
"message_code": "INVOICE_SANDBOX_CREATED"
}Campos de la respuesta 200
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
success | boolean | no | |
data | object | no | |
data.id | string | no | |
data.tipo_comprobante | integer | no | |
data.punto_venta | integer | no | |
data.numero_comprobante | integer | no | |
data.cae | string | no | Código de Autorización Electrónico de AFIP (o sintético en sandbox). |
data.cae_vencimiento | string | no | |
data.fecha_comprobante | string | no | |
data.estado | string | no | |
data.ambiente | string | no | |
data.livemode | boolean | no | false cuando el comprobante fue emitido por un token yf_test_* (simulado, sin AFIP real). |
data.simulated | boolean | no | true en modo sandbox: el CAE tiene el formato correcto pero NO es válido para un comprobante fiscal real. |
data.iva_handling | object | no | |
data.iva_handling.incluye_iva_discriminado | boolean | no | |
data.iva_handling.tipo_comprobante_nombre | string | no | |
data.iva_handling.condicion_fiscal_emisor | string | no | |
data.idempotent_replay | boolean | no | true si esta respuesta es la reproducción de un request anterior idéntico. |
data.items | array de object | no | |
data.items[].Descripcion | string | no | |
data.items[].Cantidad | number | no | |
data.items[].Precio | number | no | Precio unitario (neto de IVA cuando el tipo discrimina IVA). |
data.items[].Bonificacion | number | no | |
data.items[].IvaId | integer | no | Alícuota AFIP (3=0%, 4=10.5%, 5=21%, 6=27%, 8=5%, 9=2.5%). |
data.items[].importe_neto_linea | number | no | Neto de la línea: Precio x Cantidad - Bonificacion, redondeado a 2 decimales (ROUND_HALF_UP). Calculado por el backend. |
data.items[].importe_iva_linea | number | no | IVA de la línea (0 si el tipo no discrimina IVA, 0% o exento). Calculado por el backend. |
data.items[].importe_total_linea | number | no | importe_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. |
message | string | no | |
_links | object | no | Mapa HATEOAS: cada valor es un link accionable relativo a este recurso. |
Respuestas de error
Todo error tiene la forma {"success": false, "error": "...", "code": "..."}.
| Estado | Descripción | Código |
|---|---|---|
| 400 | Solicitud inválida (body ausente o con formato incorrecto). | VALIDATION_ERROR |
| 401 | Falta autenticación o el token es inválido/expiró. | UNAUTHORIZED |
| 403 | El token no tiene el/los scope(s) requeridos, o el plan del tenant no habilita el módulo. | FORBIDDEN |
| 422 | Semánticamente inválido — incluye la reutilización de un Idempotency-Key con un body distinto. | UNPROCESSABLE_ENTITY |
| 429 | Se superó el rate limit del endpoint o del tenant. Ver headers X-RateLimit-* y Retry-After. | RATE_LIMITED |
| 503 | ARCA/AFIP no disponible. |
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/invoice/" \
-H "X-API-Key: $YF_TEST_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"tipo_comprobante": 6,
"punto_venta": 1,
"concepto": 1,
"tipo_documento": 99,
"numero_documento": "0",
"razon_social": "Empresa Demo SRL",
"items": [
{
"descripcion": "Camiseta basica",
"cantidad": 2,
"precio_unitario": 12100,
"iva_id": 5
}
],
"autorizar": true,
"precios_con_iva": true
}'


