Todos nuestros endpoints son accesibles mediante la siguiente URL base:
La API espera el siguiente encabezado de autorización:
Las API Keys se gestionan desde el panel de nuestra plataforma.
Todas las respuestas JSON (tanto exitosas como errores) siguen la siguiente estructura envelope:
{
"response": { ... }, // Contenido específico del endpoint (puede ser null en errores)
"apiVersion": "1.0", // Versión actual de la API
"trackingId": "uuid-del-request", // Identificador único para seguimiento
"timeStamp": "2025-02-23T12:34:56Z",// Fecha y hora UTC de la respuesta
"error": false, // Indica si ocurrió un error
"errorDetail": null // Detalle del error (solo cuando error=true)
}
En caso de error, el campo errorDetail contiene:
{
"code": 400,
"message": "Descripción del error",
"stackTrace": null || string
}
El campo response varía según el endpoint; a continuación se detalla su contenido para cada caso.
| Método | Endpoint | Descripción detallada |
|---|---|---|
| POST | /Document/RedactAsync |
Procesamiento asíncrono de un PDF Request: multipart/form-data con:
response conteniendo:
{
"documentId": "guid",
"status": "Pending | Processing | Completed | Error | Deleted",
"expiresAt": "2025-03-01T12:00:00Z",
"statusUrl": "/Document/{id}/Status"
}
El documento se procesa en segundo plano. Puedes consultar su estado mediante la URL proporcionada.Errores: mismos códigos que el endpoint síncrono, más 400 si la expiración no es válida, siempre dentro del envelope con error: true.
|
| POST | /Document/Score |
Análisis de entidades PII en un PDF (sin redactar) Request: multipart/form-data con File y opcionalmente MinimunConfidenceScore (string que represente un decimal de 0 a 1 ej 0.8, opcional).Respuesta exitosa (200): Envelope con response conteniendo la lista de entidades detectadas:
[
{ "entityType": "RUT", "confidence": 0.98, "page": 1, "text": "12.345.678-9" }
]
Errores: similares a /Document/Redact (límite de páginas, archivo inválido, etc.) dentro del envelope.Nota: Este endpoint también registra el consumo de páginas. |
| POST | /Document/Type |
Detección del tipo de documento Request: multipart/form-data con File (PDF).Respuesta exitosa (200): Envelope con response conteniendo:
{ "documentType": "Invoice | Contract | ..." }
Errores: mismos que otros endpoints de subida, dentro del envelope.
|
| GET | /Document/{id}/Status |
Consulta el estado de un documento asíncrono Parámetros de ruta: id (GUID del documento).Respuesta (200): Envelope con response conteniendo:
{
"documentId": "guid",
"status": "Pending | Processing | Completed | Error | Deleted | NotFound",
"statusMessage": "mensaje opcional",
"expiresAt": "2025-03-01T12:00:00Z"
}
Si el documento no existe o no pertenece al cliente autenticado, response.status será "NotFound".
|
| DELETE | /Document/{id}/Remove |
Elimina un documento y sus artefactos Parámetros de ruta: id (GUID).Respuesta (200): Envelope con response conteniendo:
{
"documentId": "guid",
"status": "Deleted",
"statusMessage": "Documento eliminado correctamente",
"expiresAt": null
}
Si no se encuentra o no pertenece al cliente, response.status será "NotFound".
|
| GET | /Document/{id}/Download |
Descarga el documento procesado (redactado) Parámetros de ruta: id (GUID).Comportamiento:
status será "NotFound".
|
| GET | /Document/ActiveDocuments/{page}/{pageSize} |
Lista paginada de documentos activos (no eliminados ni expirados) Parámetros de ruta: page (int ≥ 1), pageSize (int, máx. 100).Respuesta (200): Envelope con response conteniendo:
{
"documents": [
{ "documentId": "guid", "fileName": "...", "pageCount": 5, "status": "...", "createdAt": "...", "expiresAt": "...", "processingTimeMinutes": 2.5 }
],
"page": 1,
"pageSize": 10,
"total": 42
}
Los documentos se ordenan por fecha de creación descendente.
|
| GET | /Document/ConsumptionHistory |
Historial de consumo de páginas por mes Respuesta (200): Envelope con response conteniendo lista de objetos:
[
{
"clientId": 123,
"businessName": "Empresa SA",
"taxId": "30-12345678-9",
"periodMonth": "2025-02",
"totalPagesProcessed": 150,
"totalRequests": 12,
"synchronousPages": 100,
"asynchronousPages": 50
}
]
Muestra el desglose mensual de páginas procesadas (síncronas y asíncronas).
|
| GET | /Document/CurrentMonthConsumption |
Consumo y límites del mes actual Respuesta (200): Envelope con response conteniendo:
{
"clientId": 123,
"businessName": "Empresa SA",
"taxId": "30-12345678-9",
"monthlyPageLimit": 500,
"bonusPagesAccumulated": 10,
"pagesConsumed": 350,
"availableMonthlyPages": 150,
"totalAvailablePages": 160,
"requestCount": 25,
"periodMonth": "2025-02"
}
Indica cuántas páginas se han consumido en el mes, el límite, páginas de bono y disponibles.
|
Una vez que el procesamiento asíncrono de un documento finaliza (con estado Completed, Error o Deleted),
nuestro sistema enviará automáticamente una solicitud HTTP POST a la URL que hayas configurado en el panel de administración.
Esto te permite reaccionar en tiempo real al resultado sin necesidad de realizar consultas periódicas (polling).
{
"ClientId": "uuid-del-cliente",
"DocumentId": "uuid-del-documento",
"Status": "Completed | Error | Deleted",
"ExpiresAt": "2025-03-01T12:00:00Z",
"StatusMessage": "Mensaje opcional (ej. error detallado)",
"TimeStamp": "1710000000", // Unix timestamp en segundos
"Hash": "Base64(HMAC-SHA256 de TimeStamp con MasterKey)"
}
Para garantizar que la petición realmente proviene de nuestros servidores y no de un tercero, cada webhook incluye un campo Hash.
Este hash se genera aplicando HMAC-SHA256 sobre el valor del campo TimeStamp (en bytes UTF-8) utilizando la Master Key (también en bytes UTF-8) que puedes configurar en el panel.
Debes calcular el hash en tu servidor y compararlo con el recibido; si coinciden, puedes confiar en que la petición es legítima.
Tu endpoint debe responder con un código HTTP 200 OK lo antes posible para confirmar la recepción. Nosotros no procesamos el contenido de la respuesta; simplemente necesitamos saber que el mensaje llegó. Si no recibimos un 200, el sistema reintentará el envío hasta 10 veces adicionales.
Nota: El timeout de la solicitud es de 30 segundos. Asegúrate de que tu endpoint responda rápidamente para evitar reintentos innecesarios.
app.post('/webhook', (req, res) => {
const { ClientId, DocumentId, Status, ExpiresAt, StatusMessage, TimeStamp, Hash } = req.body;
// 1. Obtener la Master Key desde las variables de entorno
const masterKey = process.env.WEBHOOK_MASTER_KEY;
// 2. Convertir a bytes (UTF-8)
const keyBytes = Buffer.from(masterKey, 'utf8');
const timeBytes = Buffer.from(TimeStamp, 'utf8');
// 3. Calcular HMAC-SHA256
const hmac = crypto.createHmac('sha256', keyBytes);
hmac.update(timeBytes);
const computedHash = hmac.digest().toString('base64');
// 4. Comparar ambos hashes
if (computedHash !== Hash) {
return res.status(401).send('Firma inválida');
}
// 5. Procesar según el estado (opcional)
console.log(`Documento ${DocumentId} para cliente ${ClientId} cambió a ${Status}`);
// 6. Responder inmediatamente
res.status(200).send('OK');
});