Factura simple
Venta a una empresa. Exige un comprador con RUC.
POST
https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantesCabecera Authorization: Bearer TU_LLAVE. Es la misma llave en pruebas y en producción: lo que cambia es la dirección (cpe-dev o cpe-prod).
Solicitud
curl -X POST "https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes" \
-H "Authorization: Bearer TU_LLAVE" \
-H "Content-Type: application/json" \
-d '{
"tipo": "FACTURA",
"serie": "F001",
"referencia_externa": "venta-3104",
"cliente": {
"tipo_documento": "RUC",
"numero_documento": "20123456789",
"nombre": "Distribuidora Lima SAC",
"direccion": "Av. Republica de Panama 3055"
},
"items": [
{
"descripcion": "Consultoria",
"cantidad": "1",
"valor_unitario": "1500.00",
"unidad": "SERVICIO"
}
]
}'const respuesta = await fetch("https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes", {
method: "POST",
headers: {
"Authorization": "Bearer TU_LLAVE",
"Content-Type": "application/json",
},
body: JSON.stringify({
"tipo": "FACTURA",
"serie": "F001",
"referencia_externa": "venta-3104",
"cliente": {
"tipo_documento": "RUC",
"numero_documento": "20123456789",
"nombre": "Distribuidora Lima SAC",
"direccion": "Av. Republica de Panama 3055"
},
"items": [
{
"descripcion": "Consultoria",
"cantidad": "1",
"valor_unitario": "1500.00",
"unidad": "SERVICIO"
}
]
}),
});
console.log(respuesta.status, await respuesta.json());# pip install requests
import requests
respuesta = requests.post(
"https://cpe-dev.facturamovilai.me/v1/emisores/TU_RUC/comprobantes",
headers={"Authorization": "Bearer TU_LLAVE"},
json={
"tipo": "FACTURA",
"serie": "F001",
"referencia_externa": "venta-3104",
"cliente": {
"tipo_documento": "RUC",
"numero_documento": "20123456789",
"nombre": "Distribuidora Lima SAC",
"direccion": "Av. Republica de Panama 3055",
},
"items": [
{
"descripcion": "Consultoria",
"cantidad": "1",
"valor_unitario": "1500.00",
"unidad": "SERVICIO",
},
],
},
)
print(respuesta.status_code, respuesta.json())Campos
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
tipo | opción | Sí | BOLETA, FACTURA o NOTA_CREDITO. Es lo único que cambia entre los tres casosValores: FACTURA · BOLETA · NOTA_CREDITO |
serie | texto | Sí | Cuatro caracteres: una boleta empieza con B (B001) y una factura con F (F001). En una nota de crédito es la serie del documento que anula, no una propia |
cliente.tipo_documento | opción | Sí | Cómo se identifica el comprador: DNI, RUC o SIN_DOCUMENTO. SIN_DOCUMENTO solo vale en una boleta de hasta S/ 700; una factura exige RUCValores: RUC · DNI · SIN_DOCUMENTO |
cliente.numero_documento | texto | Sí | 8 dígitos si es DNI, 11 si es RUC. No se manda con SIN_DOCUMENTO |
cliente.nombre | texto | Sí | Nombre o razón social. Obligatorio cuando el comprador tiene documento |
cliente.direccion | texto | No | Dirección del comprador. Opcional: si no la mandas, el comprobante la declara con un guion |
items[].descripcion | texto | Sí | Nombre del producto o servicio, tal como debe verse en el comprobante |
items[].cantidad | decimal | Sí | Cuántas unidades se venden, en la unidad indicada. Admite decimales (2.5 kg). Debe ser mayor que cero |
items[].valor_unitario | decimal | Sí | Precio de una unidad. Con precios_incluyen_igv: true es el precio de vitrina, con IGV; con false, el valor neto. No puede ser negativo |
items[].unidad | opción | No | En qué se vende esto (catálogo 03 de SUNAT). UNIDAD por defecto, que es vender de a una. Usa KILOGRAMO, LITRO, BOLSA, CAJA, DOCENA y demás cuando corresponda: va declarado en el comprobante, así que vender 2 kg de lentejas como 2 UNIDAD declara algo distinto de lo que vendiste. SERVICIO para lo que no es un bienLista completa: GET /v1/unidadesPor defecto: UNIDAD |
items[].afectacion | opción | No | Qué dice la ley del IGV de este producto. GRAVADO (18%) por defecto. EXONERADO para lo que no paga IGV -menestras, arroz, verduras, libros- e INAFECTO para exportaciones. Una bodega puede vender los dos en la misma boleta. Si lo marcas mal, el total igual cuadra pero declaras IGV que no debesValores: GRAVADO · EXONERADO · INAFECTOPor defecto: GRAVADO |
referencia_externa | texto | No | El id de esta venta en TU sistema. Mándalo siempre: es lo único que evita emitir dos comprobantes si reintentas. Repetirlo con los mismos datos devuelve el comprobante ya emitido; repetirlo con datos distintos responde 409 |
precios_incluyen_igv | booleano | No | true si mandas precios de vitrina -lo que cobra la caja- y nosotros quitamos el IGV con 6 decimales. false si mandas valores netos. Un item EXONERADO no se convierte: no hay IGV que quitarlePor defecto: false |
total_esperado | decimal | No | Dígito de control opcional: lo que tu caja dice que suma. Si no coincide con lo calculado, se rechaza con 422 y no se emite nada |
fecha_emision | fecha | No | Por defecto, hoy en hora de Perú. Se admite hasta 5 días atrás en una boleta y 3 en una factura; una fecha más vieja responde 422 |
Respuestas
{
"id": "FACTURA-F001-5",
"emisor": "TU_RUC",
"ambiente": "dev",
"tipo": "FACTURA",
"serie": "F001",
"numero": 5,
"estado": "ACEPTADO",
"mensaje": "El documento fue enviado correctamente y aceptado por SUNAT.",
"total": "1770.00",
"referencia_externa": "venta-3104",
"pdf_factuapi_a4_url": "https://cpe-dev.facturamovilai.me/v1/pdf/<token>",
"desglose": {
"gravado": "1500.00",
"exonerado": "0.00",
"inafecto": "0.00",
"igv": "270.00",
"total": "1770.00",
"items": [
{
"descripcion": "Consultoria",
"valor_unitario": "1500.00",
"igv": "270.00",
"total": "1770.00"
}
]
}
}El mismo pedido con "tipo_documento": "SIN_DOCUMENTO"
{
"error": "DatosInvalidos",
"mensaje": "Una factura y sus notas de credito requieren un cliente con RUC"
}Con una llave que no existe
{
"detail": "Credencial invalida"
}Con un RUC que no es de tu cuenta
{
"error": "EmisorNoAutorizado",
"mensaje": "El emisor 20999999999 no pertenece a esta cuenta"
}Repetir venta-3101 con otros productos
{
"error": "ReferenciaReutilizada",
"mensaje": "La referencia 'venta-3101' ya se uso para un comprobante con otros datos"
}estado |
Significa |
|---|---|
ACEPTADO |
el comprobante existe ante SUNAT |
RECHAZADO |
SUNAT lo procesó y lo rechazó. Llega con 201, no con un error: lee mensaje |
PENDIENTE |
SUNAT sigue procesando. Consúltalo más tarde |
La respuesta puede traer campos adicionales a los que ves aquí: usa los de estos ejemplos.