Comprobantes electronicos POST
Todos los tipos de comprobante se emiten con el mismo endpoint y la misma
estructura. Lo unico que cambia es el codDoc, los campos de info y las
colecciones que uses. Al enviar la solicitud recibes un idOperacion para hacer
seguimiento; el resultado del SRI llega despues y se consulta o se recibe por
webhook.
Endpoint#
POST /v1/contribuyentes/{identificacion}/comprobantes
Content-Type: application/json
X-Api-Key: <API Key>
Idempotency-Key: <intencion estable>
El cuerpo no puede superar 2 MiB ni una profundidad JSON de 32 niveles.
Ejemplo de emision#
curl -s -X POST \
"https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes" \
-H "X-Api-Key: $ECUAFACT_API_KEY" \
-H "Idempotency-Key: FACTURA-2026-0001" \
-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", "FACTURA-2026-0001");
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": "FACTURA-2026-0001",
}
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': 'FACTURA-2026-0001',
'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: FACTURA-2026-0001',
'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", "FACTURA-2026-0001")
.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());
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());
Cada tipo tiene su propia pagina con el detalle de info y la coleccion que
usa.
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 Seguimiento de una operacion o espera
el webhook.
Tipos de comprobante#
Todos los tipos comparten la misma estructura: solo cambian info, la coleccion
y el codDoc.
Factura (01). Venta de bienes o servicios a un comprador. Cabecera con los
datos del comprador, totales y pagos, y las lineas en detalles. Ve
Factura.
Liquidacion de compra (03). Adquisicion de bienes o servicios a un
proveedor. Como la factura, pero centrada en el proveedor. Ve
Liquidacion de compra.
Nota de credito (04). Ajusta o anula un comprobante ya emitido
(devoluciones, descuentos, anulaciones) y referencia el documento modificado. Ve
Nota de credito.
Nota de debito (05). Incrementa el valor de un comprobante ya emitido
(intereses, recargos); usa motivos. Ve Nota de debito.
Guia de remision (06). Acompana el traslado de bienes; sin importes, con
destinatarios. Ve Guia de remision.
Comprobante de retencion (07). Acredita impuestos retenidos a un proveedor
en docsSustento. Ve Comprobante de retencion.
Los codigos de tipo y las tablas de referencia estan en Catalogos.
Estructura del comprobante#
| Clave | Contenido |
|---|---|
origenReferencia, referenciaExterna |
Identificadores de tu sistema. Los usas para rastrear y reintentar sin duplicar |
infoTributaria |
ruc, codDoc, estab, ptoEmi, secuencial |
info |
Cabecera del tipo; solo recibe los campos de ese codDoc |
detalles, motivos, destinatarios, docsSustento |
Coleccion segun el tipo |
infoAdicional |
Hasta 20 objetos {nombre, valor} |
Reglas transversales: importes como numeros JSON decimales (punto decimal, sin
comillas); codigos e identificaciones como cadena; fechas dd/MM/yyyy; periodo
MM/yyyy.
Clave de acceso#
Cada comprobante recibe una clave de acceso de 49 digitos que asigna la
plataforma; no la envias en la solicitud. La ves en el seguimiento de la
operacion o en el webhook. En pruebas puedes usar la excepcion de secuencial de
9 ceros y una clave de 49 ceros.
Validacion#
Antes de procesar el comprobante, la API valida dos cosas: que la solicitud tenga los campos y formatos correctos, y que se cumplan las reglas fiscales (totales, impuestos, referencias y retenciones). Si algo no concuerda, responde con un error de validacion y no descuenta cupo.
Reintentos y conflictos#
- Reintento con la misma
Idempotency-Keyy el mismo contenido:202concodigo201. Es la misma operacion. - Misma
Idempotency-Keycon otro contenido, o la misma referencia con otro contenido:409(codigo403). - Numero o clave ya registrados:
409(codigo401). Si el comprobante anterior esta rechazado o con error, el reenvio reutiliza la operacion sin descontar cupo. - Enviar campos de otro tipo en
info:422(codigo302).