OpenAPI y JSON Schema
Spec OpenAPI 3.1 de la API de Sifende, generado desde el código — URLs estables para fijar en tu build, validación local de requests y generación de clientes.
El contrato de la API está publicado como un documento OpenAPI 3.1. La disponibilidad de los tipos de documento se detalla abajo.
URLs
| Recurso | URL |
|---|---|
| Explorador interactivo | /docs/referencia/api |
| Spec OpenAPI (URL estable, versionada) | https://sifende.com.py/openapi/v1.json |
| Spec servido por la API | https://api.sifende.com.py/v3/api-docs |
| JSON Schema de un modelo | https://sifende.com.py/schemas/v1/{Modelo}.json |
Las cuatro son públicas: no hace falta API key para leerlas.
El Explorador de la API se genera desde este mismo spec: trae el schema completo de cada endpoint, ejemplos en cURL, JavaScript, Python y Java, y un playground para probar las llamadas con tu API key.
Para fijar en tu build usá https://sifende.com.py/openapi/v1.json. El v1 es la versión de la API — la misma del prefijo /api/v1/ — y no cambia mientras no haya una v2. Ver Versionado.
Validar un request antes de mandarlo
El spec expresa los requisitos condicionales como if/then de JSON Schema, así que un validador los verifica localmente sin llamar a la API. El caso más común es el receptor:
{
"allOf": [
{
"if": {
"properties": { "tipoContribuyente": { "const": "CONTRIBUYENTE" } },
"required": ["tipoContribuyente"]
},
"then": { "required": ["tipoContribuyenteReceptor", "digitoVerificador"] }
},
{
"if": {
"properties": { "tipoContribuyente": { "const": "NO_CONTRIBUYENTE" } },
"required": ["tipoContribuyente"]
},
"then": { "required": ["tipoDocumento"] }
}
]
}Esa regla vive en el validador de la API. Publicarla en el schema es lo que evita el error más frecuente al integrar: mandar un receptor CONTRIBUYENTE sin tipoContribuyenteReceptor y descubrirlo recién con un 400. Ver Modelo Receptor.
JSON Schema suelto
Si sólo querés validar un request body, /schemas/v1/{Modelo}.json devuelve ese modelo como JSON Schema 2020-12 autocontenido, con las dependencias inlineadas en $defs:
curl https://sifende.com.py/schemas/v1/FacturaElectronicaRequest.jsonModelos útiles: FacturaElectronicaRequest, NotaCreditoElectronicaRequest, NotaDebitoElectronicaRequest, ReceptorDTO, ItemDTO, ProblemDetail.
Generar un cliente
npx @openapitools/openapi-generator-cli generate \
-i https://sifende.com.py/openapi/v1.json \
-g typescript-fetch \
-o ./sifende-clientEl spec usa OpenAPI 3.1 (JSON Schema 2020-12). Un generador que sólo soporte 3.0 puede ignorar if/then y const: la estructura sale bien, pero las reglas condicionales se pierden y hay que validarlas aparte.
Cómo está armado
tipoDocumentoes el discriminador. Actualmente se admitenFACTURA_ELECTRONICA,NOTA_DE_CREDITO_ELECTRONICAyNOTA_DE_DEBITO_ELECTRONICA; no envíes otros tipos.- Los valores de enumeración son los que la API deserializa (
CONTRIBUYENTE, no"CONTRIBUYENTE - Contribuyente"). El catálogo completo, con las descripciones, está enGET /api/v1/public/enums. - Los errores están en
components/responses, con el schemaProblemDetaily ejemplos reales de cada familia. Ver Errores. - El spec cubre la API de integración y los catálogos públicos, nada más. Los endpoints del panel web (los que se autentican con Keycloak) y los internos no se publican: no son parte del contrato que ofrecemos a terceros. Si estás construyendo un frontend sobre Sifende, esos endpoints siguen documentados en Endpoints de Sesión.
Para agentes de IA
https://sifende.com.py/llms-full.txt sirve la documentación completa con el spec incluido en un solo archivo, pensado para cargarlo como contexto. Es el punto de partida recomendado si estás integrando con un agente: la prosa da el contexto y el spec da el contrato exacto, incluidos los campos condicionales.
Enumeraciones
Todos los valores válidos de las enumeraciones SIFEN usadas en la API de Sifende — tipoDocumento, afectacionTributaria, condicionPago y más.
Emitir un documento electrónico POST
Registra el documento y lo encola para SIFEN. La respuesta es inmediata y el CDC ya viene calculado, pero el envío ocurre en segundo plano: estado es siempre PENDIENTE acá. El estado final se consulta con el statusUrl de la respuesta. El emisor no se envía en el body: sale de la API key. El timbrado y el correlativo los asigna Sifende.