Nota de credito POST
La nota de credito ajusta o anula un comprobante ya emitido (devoluciones,
descuentos, anulaciones). 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 = "04"
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 nota |
detalles |
array | Si | Lineas |
infoAdicional |
array | No | Hasta 20 objetos {nombre, valor} |
infoTributaria: ruc (13), codDoc (04), 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 |
tipoIdentificacionComprador |
string | Si | Catalogos de identificacion |
identificacionComprador |
string | Si | Documento del comprador |
razonSocialComprador |
string | Si | Razon social |
codDocModificado |
string | Si | Tipo del documento de referencia |
numDocModificado |
string | Si | Formato ddd-ddd-ddddddddd |
fechaEmisionDocSustento |
string | Si | dd/MM/yyyy |
totalDocumentoSustento |
number | No | Total del documento de referencia |
totalSinImpuestos |
number | Si | Base de la nota |
totalConImpuestos |
array | Si | codigo, codigoPorcentaje, baseImponible, valor |
valorModificacion |
number | Si | Valor de la modificacion |
moneda |
string | Si | Codigo de moneda |
motivo |
string | Si | Motivo de la nota |
detalles#
Lineas de la nota de credito. Usa codigoInterno (no codigoPrincipal).
| Campo | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
codigoInterno |
string | Si | Codigo del bien o servicio |
codigoAdicional |
string | No | Codigo adicional |
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 |
infoAdicional#
| Campo | Tipo | Obligatorio | Descripcion |
|---|---|---|---|
nombre |
string | Si | Nombre del campo adicional |
valor |
string | Si | Valor del campo adicional |
Ejemplo de solicitud#
curl -s -X POST "https://staging-api.mynexusapi.com/v1/contribuyentes/0123456789/comprobantes" \
-H "X-Api-Key: $ECUAFACT_API_KEY" \
-H "Idempotency-Key: NC-2026-0003" \
-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", "NC-2026-0003");
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": "NC-2026-0003",
}
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': 'NC-2026-0003',
'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: NC-2026-0003',
'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", "NC-2026-0003")
.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 Nota de credito#
{
"origenReferencia": "MiERP",
"referenciaExterna": "NC-2026-0003",
"infoTributaria": {
"ruc": "0123456789001",
"codDoc": "04",
"estab": "002",
"ptoEmi": "001",
"secuencial": "000000032"
},
"info": {
"fechaEmision": "07/09/2026",
"tipoIdentificacionComprador": "05",
"identificacionComprador": "0123456789",
"razonSocialComprador": "CONTRIBUYENTE DE EJEMPLO",
"codDocModificado": "01",
"numDocModificado": "002-001-000000123",
"fechaEmisionDocSustento": "01/09/2026",
"totalDocumentoSustento": 115,
"totalSinImpuestos": 20,
"totalConImpuestos": [
{ "codigo": "2", "codigoPorcentaje": "4", "baseImponible": 20, "valor": 3 }
],
"valorModificacion": 23,
"moneda": "DOLAR",
"motivo": "DEVOLUCION PARCIAL"
},
"detalles": [
{
"codigoInterno": "SERV-001",
"descripcion": "Devolucion de servicio",
"cantidad": 1,
"precioUnitario": 20,
"descuento": 0,
"precioTotalSinImpuesto": 20,
"impuestos": [
{ "codigo": "2", "codigoPorcentaje": "4", "tarifa": 15, "baseImponible": 20, "valor": 3 }
]
}
]
}
Reglas especificas#
- Si informas
totalDocumentoSustento,valorModificacionno puede superarlo. - Informa tu los datos del documento de referencia; la API no los completa por ti.
- Debe identificar al receptor (no consumidor final).
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.