Liquidacion de compra POST
La liquidacion de compra se emite cuando el emisor adquiere bienes o servicios a
un proveedor. La estructura del comprobante es la misma que en
Factura ; cambia el contenido de info y el cuerpo de
ejemplo (comprobante.json).
Ejemplo en el ambiente de pruebas . Los comprobantes no tienen validez fiscal.
POST /v1/contribuyentes/{identificacion}/comprobantes
infoTributaria.codDoc = "03"
Estructura del comprobante#
Clave
Tipo
Obligatorio
Descripcion
origenReferencia
string
Si
Sistema de origen (max. 64)
referenciaExterna
string
Si
Referencia estable de tu sistema (max. 128)
infoTributaria
object
Si
Identidad del documento
info
object
Si
Cabecera de la liquidacion
detalles
array
Si
Lineas
infoAdicional
array
No
Hasta 20 objetos {nombre, valor}
infoTributaria: ruc (13), codDoc (03), estab (3), ptoEmi (3) y
secuencial (9) obligatorios. La clave de acceso la asigna la plataforma; no la envies.
Campos de info#
Campo
Tipo
Obligatorio
Regla
fechaEmision
string
Si
dd/MM/yyyy
tipoIdentificacionProveedor
string
Si
Catalogos: identificacion
identificacionProveedor
string
Si
Documento del proveedor
razonSocialProveedor
string
Si
Razon social o nombres
dirEstablecimiento
string
No
Direccion del establecimiento
direccionProveedor
string
No
Direccion del proveedor
totalSinImpuestos
number
Si
Suma de bases
totalDescuento
number
Si
Suma de descuentos de linea
totalConImpuestos
array
Si
codigo, codigoPorcentaje, baseImponible, valor
importeTotal
number
Si
Total a pagar
moneda
string
Si
Codigo de moneda
pagos
array
Si
formaPago y total obligatorios
detalles#
Lineas de la liquidacion.
Campo
Tipo
Obligatorio
Descripcion
codigoPrincipal
string
Si
Codigo del bien o servicio
codigoAuxiliar
string
No
Codigo auxiliar del emisor
descripcion
string
Si
Descripcion de la linea
unidadMedida
string
No
Unidad de medida
cantidad
number
Si
Cantidad (hasta 6 decimales)
precioUnitario
number
Si
Precio unitario (hasta 6 decimales)
descuento
number
Si
Descuento de la linea (importe, no porcentaje)
precioTotalSinImpuesto
number
Si
cantidad x precioUnitario - descuento
impuestos
array
Si
Impuestos de la linea (ver abajo)
detallesAdicionales
array
No
Hasta 3 objetos {nombre, valor}
detalles[].impuestos#
Campo
Tipo
Obligatorio
Descripcion
codigo
string
Si
Impuesto: 2 IVA, 3 ICE, 5 IRBPNR
codigoPorcentaje
string
Si
Codigo de tarifa (ve Catalogos )
tarifa
number
Si
Porcentaje de la tarifa
baseImponible
number
Si
Base sobre la que se calcula
valor
number
Si
Valor del impuesto
pagos#
Campo
Tipo
Obligatorio
Descripcion
formaPago
string
Si
Codigo de forma de pago
total
number
Si
Monto con esta forma de pago
plazo
number
No
Plazo
unidadTiempo
string
Condicional
Obligatorio si plazo > 0
infoAdicional#
Campo
Tipo
Obligatorio
Descripcion
nombre
string
Si
Nombre del campo adicional
valor
string
Si
Valor del campo adicional
Ejemplo de solicitud#
HTTP SDK
cURL .NET Python Node.js PHP Java
curl -s -X POST "https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes" \
-H "X-Api-Key: $ECUAFACT_API_KEY" \
-H "Idempotency-Key: LIQ-2026-0007" \
-H "Content-Type: application/json" \
-d @comprobante.json
using System.Text;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("X-Api-Key", apiKey);
http.DefaultRequestHeaders.Add("Idempotency-Key", "LIQ-2026-0007");
string json = await File.ReadAllTextAsync("comprobante.json");
using var contenido = new StringContent(json, Encoding.UTF8, "application/json");
using var respuesta = await http.PostAsync(
"https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes",
contenido);
Console.WriteLine($"{(int)respuesta.StatusCode} {await respuesta.Content.ReadAsStringAsync()}");
import json, os, requests
headers = {
"X-Api-Key": os.environ["ECUAFACT_API_KEY"],
"Idempotency-Key": "LIQ-2026-0007",
}
with open("comprobante.json", encoding="utf-8") as archivo:
cuerpo = json.load(archivo)
r = requests.post(
"https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes",
headers=headers, json=cuerpo, timeout=30)
print(r.status_code, r.text)
import { readFile } from 'node:fs/promises';
const cuerpo = await readFile('comprobante.json', 'utf8');
const res = await fetch(
'https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes',
{
method: 'POST',
headers: {
'X-Api-Key': process.env.ECUAFACT_API_KEY,
'Idempotency-Key': 'LIQ-2026-0007',
'Content-Type': 'application/json'
},
body: cuerpo
});
console.log(res.status, await res.text());
<?php
$ch = curl_init('https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'X-Api-Key: ' . getenv('ECUAFACT_API_KEY'),
'Idempotency-Key: LIQ-2026-0007',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => file_get_contents('comprobante.json'),
]);
$respuesta = curl_exec($ch);
$estado = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo $estado . ' ' . $respuesta;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
HttpClient cliente = HttpClient.newHttpClient();
String cuerpo = Files.readString(Path.of("comprobante.json"));
HttpRequest peticion = HttpRequest.newBuilder()
.uri(URI.create("https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes"))
.header("X-Api-Key", System.getenv("ECUAFACT_API_KEY"))
.header("Idempotency-Key", "LIQ-2026-0007")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(cuerpo))
.build();
HttpResponse<String> respuesta = cliente.send(peticion, HttpResponse.BodyHandlers.ofString());
System.out.println(respuesta.statusCode() + " " + respuesta.body());
.NET Python Node.js PHP Java
using Ecuafact.Sdk;
// client: cliente EcuafactClient - ver SDK .NET
EmisionResultado resultado = await client.EmitirAsync(comprobante);
Console.WriteLine($"Operacion {resultado.Admission.IdOperacion} / codigo: {resultado.Admission.Codigo}");
from ecuafact import EcuafactClient
# client: cliente EcuafactClient - ver SDK Python
resultado = client.emitir(comprobante)
print(f"Operacion {resultado.admission.id_operacion} / codigo: {resultado.admission.codigo}")
import { EcuafactClient } from "@ecuafact/sdk";
// client: cliente EcuafactClient - ver SDK Node.js
const resultado = await client.emitir(comprobante);
console.log(`Operacion ${resultado.admission.idOperacion} / codigo: ${resultado.admission.codigo}`);
<?php
use Ecuafact\Sdk\EcuafactClient;
// $client: cliente EcuafactClient - ver SDK PHP
$resultado = $client->emitir($comprobante);
echo 'Operacion ' . $resultado->admission->idOperacion . ' / codigo: ' . $resultado->admission->codigo;
import com.ecuafact.sdk.EcuafactClient;
// client: cliente EcuafactClient - ver SDK Java
EmisionResultado resultado = client.emitir(comprobante);
System.out.println("Operacion " + resultado.admission().idOperacion() + " / codigo: " + resultado.admission().codigo());
Cuerpo de la Liquidacion de compra#
{
"origenReferencia": "MiERP",
"referenciaExterna": "LIQ-2026-0007",
"infoTributaria": {
"ruc": "0123456789001",
"codDoc": "03",
"estab": "002",
"ptoEmi": "001",
"secuencial": "000000045"
},
"info": {
"fechaEmision": "07/09/2026",
"tipoIdentificacionProveedor": "05",
"identificacionProveedor": "0987654321",
"razonSocialProveedor": "PROVEEDOR DE EJEMPLO",
"totalSinImpuestos": 200,
"totalDescuento": 0,
"totalConImpuestos": [
{ "codigo": "2", "codigoPorcentaje": "0", "baseImponible": 200, "valor": 0 }
],
"importeTotal": 200,
"moneda": "DOLAR",
"pagos": [
{ "formaPago": "01", "total": 200 }
]
},
"detalles": [
{
"codigoPrincipal": "MP-001",
"descripcion": "Materia prima",
"cantidad": 2,
"precioUnitario": 100,
"descuento": 0,
"precioTotalSinImpuesto": 200,
"impuestos": [
{ "codigo": "2", "codigoPorcentaje": "0", "tarifa": 0, "baseImponible": 200, "valor": 0 }
]
}
]
}
Notas#
El emisor es quien liquida; el proveedor es la contraparte.
No recibe consumidor final como proveedor.
No referencia un documento modificado.
Respuesta#
La API responde 202 Accepted con la operacion creada:
{
"codigo": "200",
"mensaje": "Operacion exitosa.",
"idOperacion": "3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f",
"urlEstado": "https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f",
"uid": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d"
}
Campo
Significado
codigo
200 si es una emision nueva; 201 si es un reintento con la misma Idempotency-Key
mensaje
Descripcion del resultado
idOperacion
Identificador de seguimiento de la emision
urlEstado
Ruta para consultar el estado de esta operacion
uid
Identificador del documento
El 202 no es la autorizacion del SRI: el comprobante quedo recibido . Consulta urlEstado o espera el webhook .
Estados de este endpoint#
Codigo
HTTP
Cuando ocurre
Que hacer
200
202
Emision aceptada
Sigue el estado de la operacion
201
202
Reintento con la misma Idempotency-Key y el mismo contenido
Sigue la misma operacion
301
400
Falta Idempotency-Key o hay campos mal formados
Corrige la solicitud
302
422
El comprobante no cumple una regla fiscal o de estructura
Revisa errores
401
409
Numero o clave ya registrados (duplicado)
Consulta la operacion existente
403
409
Misma Idempotency-Key con otro contenido
Usa la misma intencion
501
429
Cupo agotado
Amplia tu cupo
101
401
API Key invalida
Revisa la API Key
103
403
Contribuyente o tipo no habilitado
Habilita el contribuyente
El catalogo completo esta en Errores .
Siguientes pasos#