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-Key y el mismo contenido: 202 con codigo 201. Es la misma operacion.
  • Misma Idempotency-Key con otro contenido, o la misma referencia con otro contenido: 409 (codigo 403).
  • Numero o clave ya registrados: 409 (codigo 401). 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 (codigo 302).

Siguientes pasos#

No se pudo completar la operacion. Recargar ✕