Primeros pasos

Camino de cero a tu primer comprobante autorizado en el ambiente de pruebas.

Antes de empezar#

  • RUC del emisor habilitado para tu integracion.
  • API Key de la integracion.
  • IP de salida registrada.
  • Un cliente HTTP (cURL, .NET, JavaScript o PHP).

1. API Key#

Tu integracion parte del ambiente de pruebas. Envia tu API Key en la cabecera X-Api-Key. Solo las direcciones IP registradas pueden consumir la API.

Si no tienes credencial, crea un sandbox de pruebas en Crear sandbox: cargas tu emisor y tu certificado, y recibes por correo la API Key y tu acceso al Portal del Cliente. El sandbox usa el plan Sandbox MyNexusApi (5.000 documentos, 2 meses), no tiene validez fiscal y vence a los 2 meses. Tambien puedes solicitarla con el formulario de solicitud indicando tu RUC y las IP de salida; el detalle esta en Autenticacion.

2. Verifica tu contexto#

GET /v1/contexto devuelve tu cliente y los contribuyentes habilitados, con la identificacion que usas en las rutas. Empieza por aqui para saber para quien puedes emitir.

curl -s "https://staging-api.mynexusapi.com/v1/contexto" \
  -H "X-Api-Key: $ECUAFACT_API_KEY"
{
  "datos": {
    "idCliente": "1f2e3d4c-5b6a-4789-9012-abcdef012345",
    "nombre": "Integracion de ejemplo",
    "contribuyentes": [
      {
        "identificacion": "0123456789",
        "identificacionCompleta": "0123456789001",
        "puedeEmitir": true,
        "puedeRecibir": true,
        "tiposComprobante": ["01", "03", "04", "05", "06", "07"]
      }
    ]
  }
}

Usa el valor identificacion que aparece aqui en las rutas. El detalle de los campos esta en Contexto.

3. Emite un comprobante#

POST /v1/contribuyentes/0123456789/comprobantes con cuerpo JSON y la cabecera Idempotency-Key obligatoria.

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 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
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={"X-Api-Key": os.environ["ECUAFACT_API_KEY"], "Idempotency-Key": "factura-2026-0001"},
    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'),
]);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . ' ' . curl_exec($ch);
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());

Cuerpo de la factura:

{
  "origenReferencia": "MiERP",
  "referenciaExterna": "FACTURA-2026-0001",
  "infoTributaria": {
    "ruc": "0123456789001",
    "codDoc": "01",
    "estab": "002",
    "ptoEmi": "001",
    "secuencial": "000000123"
  },
  "info": {
    "fechaEmision": "07/09/2026",
    "tipoIdentificacionComprador": "05",
    "identificacionComprador": "0123456789",
    "razonSocialComprador": "CONTRIBUYENTE DE EJEMPLO",
    "totalSinImpuestos": 100,
    "totalDescuento": 0,
    "totalConImpuestos": [
      { "codigo": "2", "codigoPorcentaje": "4", "baseImponible": 100, "valor": 15, "tarifa": 15 }
    ],
    "importeTotal": 115,
    "moneda": "DOLAR",
    "pagos": [
      { "formaPago": "01", "total": 115 }
    ]
  },
  "detalles": [
    {
      "codigoPrincipal": "SERV-001",
      "descripcion": "Servicio de ejemplo",
      "cantidad": 1,
      "precioUnitario": 100,
      "descuento": 0,
      "precioTotalSinImpuesto": 100,
      "impuestos": [
        { "codigo": "2", "codigoPorcentaje": "4", "tarifa": 15, "baseImponible": 100, "valor": 15 }
      ]
    }
  ]
}

La API responde 202 Accepted con la operacion creada. Describe cada campo:

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 (guardalo)
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. Sigue con el paso 4.

{
  "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"
}

4. Consulta el estado#

Mientras la plataforma procesa el comprobante, consulta su estado con el idOperacion (o espera el webhook). La respuesta trae el estado del envio (estado) y el resultado fiscal (estadoAutorizacion).

curl -s "https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f" \
  -H "X-Api-Key: $ECUAFACT_API_KEY"
string json = await http.GetStringAsync(
    "https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f");
Console.WriteLine(json);
r = requests.get(
    "https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f",
    headers={"X-Api-Key": os.environ["ECUAFACT_API_KEY"]}, timeout=30)
print(r.status_code, r.text)
const res = await fetch(
  'https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f',
  { headers: { 'X-Api-Key': process.env.ECUAFACT_API_KEY } });
console.log(res.status, await res.text());
<?php
$ch = curl_init('https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['X-Api-Key: ' . getenv('ECUAFACT_API_KEY')],
]);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . ' ' . curl_exec($ch);
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpRequest peticion = HttpRequest.newBuilder()
    .uri(URI.create("https://staging-api.mynexusapi.com/v1/operaciones/3f1c8c1e-6f2a-4b7e-9c3d-2a1b0c9d8e7f"))
    .header("X-Api-Key", System.getenv("ECUAFACT_API_KEY"))
    .GET().build();
HttpClient cliente = HttpClient.newHttpClient();
System.out.println(cliente.send(peticion, HttpResponse.BodyHandlers.ofString()).body());
using Ecuafact.Sdk;
using Ecuafact.Sdk.Contracts;

// client: cliente EcuafactClient - ver SDK .NET
Operation operacion = await client.GetOperacionAsync(idOperacion);
Console.WriteLine(operacion.Estado);
from ecuafact import EcuafactClient

# client: cliente EcuafactClient - ver SDK Python
operacion = client.get_operacion(id_operacion)
print(operacion.estado)
import { EcuafactClient } from "@ecuafact/sdk";

// client: cliente EcuafactClient - ver SDK Node.js
const operacion = await client.getOperacion(idOperacion);
console.log(operacion.estado);
<?php
use Ecuafact\Sdk\EcuafactClient;

// $client: cliente EcuafactClient - ver SDK PHP
$operacion = $client->getOperacion($idOperacion);
echo $operacion->estado;
import com.ecuafact.sdk.EcuafactClient;

// client: cliente EcuafactClient - ver SDK Java
Operation operacion = client.getOperacion(idOperacion);
System.out.println(operacion.estado());

El resultado fiscal final tambien llega por webhook.

estado Significado
en_cola Registrado, aun no enviado
enviando En despacho
enviado Enviado para procesamiento fiscal
resultado_desconocido El resultado aun no se confirma
cancelado Operacion cancelada
estadoAutorizacion Significado
no_disponible Aun sin resultado fiscal
pendiente En procesamiento por el SRI
autorizado Autorizacion confirmada
error Rechazo fiscal

El detalle completo esta en Seguimiento de una operacion.

Siguientes pasos#

No se pudo completar la operacion. Recargar ✕