Descargar KuDE
GET /api/v1/documento-electronico/:cdc/kude — descargá el KuDE (comprobante) en PDF o seguí la preparación asincrónica cuando todavía no está disponible.
El KuDE de SANDBOX lleva el rótulo SANDBOX — SIN VALIDEZ FISCAL. Descargalo con una clave del mismo contribuyente y ambiente; el CDC y la ruta de descarga se usan igual que en los otros ambientes.
GET /api/v1/documento-electronico/:cdc/kude
Retorna el KuDE (Kuatia Ñe'ẽ Mba'eporu — comprobante electrónico) en formato PDF binario cuando ya existe una copia legible. Si falta el PDF, la llamada inicial puede solicitar su preparación y responder 202 Accepted.
Autenticación
Authorization: Bearer {api-key} — requerido
Path parameters
| Parámetro | Tipo | Descripción |
|---|---|---|
cdc | string | CDC del documento aprobado |
Query parameters
| Parámetro | Tipo | Default | Descripción |
|---|---|---|---|
soloConsulta | boolean | false | Si es true, consulta el estado de preparación del PDF. |
Respuestas
200 OK
Content-Type: application/pdf
El body es el PDF binario del KuDE. Conserva Content-Disposition y Content-Length.
202 Accepted
Content-Type: application/json
La preparación del PDF está pendiente. Esta respuesta no es un PDF y no debe guardarse como archivo.
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: /api/v1/documento-electronico/01800123451001001000000122026042710000000006/kude?soloConsulta=true
Retry-After: 5
Cache-Control: no-store{
"estado": "PENDIENTE",
"url": null
}Seguí exactamente el Location recibido; consultar no acelera la preparación. Retry-After: 5 indica el intervalo mínimo recomendado para volver a consultar.
Si sigue en 202 después de 2 minutos, repetí una vez la descarga sin soloConsulta: el Location sólo consulta y no vuelve a pedir la preparación. Si después de otros 2 minutos sigue pendiente, dejá de consultar y contactá a soporte con el CDC.
Errores
| Status | Tipo | Descripción |
|---|---|---|
| 403 | document-archived | El período de acceso del plan actual finalizó |
| 403 | — (sin Problem Details) | La NRE no está en APROBADO ni APROBADO_OBSERVACION. Consultá su estado y esperá la aprobación sólo si sigue en proceso |
| 404 | documento-electronico-not-found | Documento no encontrado o no accesible para esta clave |
| 500 | kude-generation-error | Error técnico interno al obtener o preparar el KuDE |
| 501 | kude-not-supported | El tipo no admite KuDE; los tipos disponibles son FE, NCE, NDE y NRE |
| 503 | kude-unavailable | No se pudo obtener el PDF en este intento; ver kude-unavailable |
Los errores técnicos de KuDE se informan como 500 o 503 según la causa. No se clasifican como 422, porque no son problemas semánticos del documento enviado.
Un documento archivado responde el Problem Detail document-archived y no entrega el PDF. Estado y cancelación aplican el mismo comportamiento.
Ejemplo — polling seguro y guardar sólo el 200
type KuDePendiente = {
estado: 'PENDIENTE';
url: null;
};
type ProblemDetail = {
type: string;
title: string;
status: number;
detail: string;
traceId?: string;
estado?: 'FALLIDO';
};
async function descargarKuDE(cdc: string): Promise<Uint8Array> {
const urlInicial = `https://api.sifende.com.py/api/v1/documento-electronico/${cdc}/kude`;
let url = urlInicial;
let limite = Date.now() + 2 * 60_000;
let volvioAPedir = false;
for (;;) {
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.SIFENDE_API_KEY}` },
});
if (res.status === 200 && res.headers.get('content-type')?.includes('application/pdf')) {
return new Uint8Array(await res.arrayBuffer());
}
if (res.status === 202) {
const location = res.headers.get('location');
if (!location) throw new Error('KuDE pendiente sin Location');
await res.json() as KuDePendiente;
await new Promise(resolve => setTimeout(resolve, Number(res.headers.get('retry-after') ?? '5') * 1000));
if (Date.now() < limite) {
url = new URL(location, url).toString();
} else if (!volvioAPedir) {
volvioAPedir = true;
url = urlInicial;
limite = Date.now() + 2 * 60_000;
} else {
throw new Error('KuDE pendiente por más de 4 minutos; contactá a soporte');
}
continue;
}
const problem = await res.json() as ProblemDetail;
throw new Error(`No se pudo descargar KuDE (${problem.status}): ${problem.type}`);
}
}