Autenticación
Un administrador de la empresa crea la credencial en BENQIT › Administración › Integraciones (API), eligiendo sus permisos, IP permitidas y vencimiento. La clave se muestra una sola vez; se envía en cada llamada:
Authorization: Bearer bqk_live_XXXXXXXXXXXXXXXX_YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
URL base: https://benqit.com/api/integration/v1
curl -H "Authorization: Bearer $BENQIT_KEY" \
"https://benqit.com/api/integration/v1/ping"
Cada credencial opera sólo sobre su empresa y con los permisos elegidos: de lectura (employees:read, requests:read…) y de escritura (employees:write, structure:write, requests:write). Lo que una credencial modifica queda en la auditoría a su nombre. Guarda la clave como un secreto (variable de entorno o bóveda), nunca en el código ni en una app móvil.
Sandbox
En Integraciones (API) › Sandbox el administrador crea, con un clic, una empresa de pruebas asociada a la suya: copia sus beneficios y tipos de documento, y agrega trabajadores ficticios (SBX0001 a SBX0008), centros de costo, niveles de cargo y solicitudes de ejemplo.
- Las credenciales del sandbox empiezan con
bqk_test_ y sólo ven esos datos; la URL base es la misma.
- Los webhooks del sandbox se configuran aparte y llegan con
"environment": "TEST".
- Con
POST /sandbox/requests/{id}/state puedes aprobar, rechazar o pagar una solicitud de prueba y ver llegar el webhook.
Respuestas y errores
Las respuestas exitosas traen data (y meta en los listados). Los errores traen error con un código estable, un mensaje y el requestId, que también llega en el encabezado X-Request-Id y aparece en el registro de llamadas del portal.
{
"error": {
"code": "insufficient_scope",
"message": "La credencial no tiene el permiso \"requests:read\".",
"requestId": "req_3f2a91c0d4e5b6a7c8d9"
}
}
| HTTP | code | Cuándo |
| 400 | invalid_request / invalid_json / idempotency_key_required | Parámetro o cuerpo con formato no válido, campo desconocido, o falta Idempotency-Key. |
| 401 | unauthorized | Clave ausente, inválida, revocada o vencida. |
| 403 | insufficient_scope / forbidden / plan_not_included | Falta el permiso, la IP de origen no está autorizada, o el plan de la empresa no incluye la API (o el sandbox, o la escritura: el plan Profesional permite sólo lectura). |
| 404 | not_found / module_not_enabled | El registro no existe en tu empresa, o el endpoint es de un módulo que la empresa no tiene contratado (ej. rendiciones). |
| 409 | idempotency_in_progress / conflict | Otra llamada con la misma clave aún se procesa, o la operación no aplica al estado actual. |
| 415 | unsupported_media_type | El cuerpo no es application/json ni multipart/form-data. |
| 422 | invalid_request / idempotency_mismatch | Regla de negocio no cumplida (detalle por campo en fields), o la clave se usó con otro contenido. |
| 429 | rate_limited | Superaste el límite por minuto; respeta Retry-After. |
| 500 | server_error | Error inesperado; indica el requestId al soporte. |
Fechas-hora en ISO 8601 con la diferencia horaria de la empresa (ej. 2026-09-28T09:30:00-03:00); fechas sin hora como AAAA-MM-DD; montos como números.
Idempotencia
Si una llamada de escritura se corta (timeout, caída de red), reintenta sin miedo a duplicar: envía el encabezado Idempotency-Key con un valor único por operación (recomendamos un UUID). Es obligatorio en POST y opcional en PUT, que ya es idempotente por naturaleza.
curl -X POST "https://benqit.com/api/integration/v1/requests" \
-H "Authorization: Bearer $BENQIT_KEY" \
-H "Idempotency-Key: 5f0c2a8e-4b1d-4f7a-9d3e-1c2b3a4d5e6f" \
-F employeeNo=DEMO0006 -F benefit=LENSES -F amount=45000 -F serviceDate=2026-09-20 \
-F "documents[INVOICE]=@boleta.pdf"
- La misma clave con el mismo contenido devuelve la respuesta original, con el encabezado
Idempotent-Replayed: true, durante 24 horas.
- La misma clave con otro contenido responde 422
idempotency_mismatch.
- Si la primera llamada falló con error 500, la clave queda libre para reintentar.
Sincronización incremental
Los listados van ordenados por fecha de actualización. Para mantener tu sistema al día sin descargar todo cada vez:
- La primera vez consulta con
updatedSince (por ejemplo, una fecha antigua para traer todo).
- Mientras
meta.hasMore sea true, vuelve a consultar enviando cursor con el valor de meta.nextCursor.
- Guarda el último
meta.nextCursor. En la próxima sincronización (en una hora o mañana) consulta sólo con ese cursor: recibirás únicamente lo que cambió.
GET /employees?updatedSince=2000-01-01T00:00:00Z&pageSize=200
GET /employees?cursor=WyIyMDI2LTA5LTI4VDExOjUwOjI3LjYxNjM4M1oiLDVd&pageSize=200
El cursor no pierde ni repite registros, aunque muchos cambien en el mismo segundo. Sin cursor ni updatedSince puedes paginar con page y recibir meta.total.
Webhooks
En lugar de consultar la API a cada rato, registra una URL HTTPS pública en Integraciones (API) › Nuevo webhook y elige los eventos. BENQIT enviará un POST JSON por cada evento, en menos de un minuto.
| Evento | Cuándo | data |
request.created | Se ingresó una solicitud (web, app o API). | Solicitud (como GET /requests/{id}) |
request.state_changed | Una solicitud cambió de estado: revisión, corrección, aprobada, rechazada, programada, pagada o anulada. | Solicitud (como GET /requests/{id}) |
payment.paid | El banco confirmó el pago de una línea de un lote. | Línea de pago (como GET /payments) |
payment.rejected | El banco rechazó el pago de una línea de un lote. | Línea de pago (como GET /payments) |
expense.state_changed | Una rendición cambió de estado: enviada, devuelta, aprobada, rechazada, programada, pagada o anulada. | Rendición con gastos (como GET /expenses/{id}) |
fund.state_changed | Se solicitó un fondo o cambió de estado: aprobado, vigente (entregado), cerrado, rechazado o anulado. | Fondo con saldos (como GET /funds, sin cartola) |
trip.state_changed | Se solicitó un viaje o cambió de estado: aprobado, cerrado (liquidado), rechazado o anulado. | Viaje con viático y pagos (como GET /trips/{id}) |
trip.payment_done | Se realizó un pago, complemento o devolución de viático. | Pago de viático (como GET /trip-payments) |
fund.movement_done | Se realizó un movimiento en la cartola de un fondo: entrega, rendición descontada, reposición, devolución o ajuste. | Movimiento (como GET /fund-movements) |
webhook.test | Evento de prueba enviado desde el portal. | Mensaje de prueba |
Ejemplo de contenido
{
"id": "evt_6bb6fe0a9de1194a5a233aeb",
"type": "request.state_changed",
"createdAt": "2026-09-28T09:10:00-03:00",
"environment": "LIVE",
"company": "ACME",
"data": {
"id": 24,
"number": "BEN-2026-000024",
"state": "APPROVED",
"stateName": "Aprobada",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"benefit": {
"code": "LENSES",
"name": "Reembolso de lentes"
},
"costCenter": "OPS-NORTE",
"requestedAt": "2026-09-27T18:20:00-03:00",
"eventDate": null,
"serviceDate": "2026-09-20",
"amount": {
"requested": 45000,
"approved": 45000,
"currency": "CLP"
},
"benefitAmount": {
"requested": 1.0967,
"approved": 1.0967,
"currency": "UF"
},
"onBehalf": false,
"approvedAt": "2026-09-28T09:10:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"payPeriod": null,
"paidAt": null,
"updatedAt": "2026-09-28T09:10:00-03:00"
}
}
Encabezados y firma
Cada aviso trae BenQit-Event, BenQit-Delivery (id del evento, úsalo para ignorar duplicados) y BenQit-Signature: t=<unix>,v1=<firma>. La firma es HMAC-SHA256, con el secreto whsec_… del webhook, de t + "." + cuerpo. Verifícala con el cuerpo tal como llegó y rechaza marcas de tiempo de más de 5 minutos.
// PHP
[$t, $v1] = sscanf($_SERVER['HTTP_BENQIT_SIGNATURE'], 't=%d,v1=%s');
$body = file_get_contents('php://input');
$ok = hash_equals(hash_hmac('sha256', $t . '.' . $body, getenv('BENQIT_WEBHOOK_SECRET')), $v1)
&& abs(time() - $t) < 300;
// Node.js
const [t, v1] = req.get('BenQit-Signature').split(',').map(p => p.split('=')[1]);
const expected = crypto.createHmac('sha256', process.env.BENQIT_WEBHOOK_SECRET).update(`${t}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1)) && Math.abs(Date.now() / 1000 - t) < 300;
Respuesta y reintentos
Responde con un código 2xx en menos de 10 segundos y procesa después. Si no, reintentamos a 1 min, 5 min, 30 min, 2 h, 6 h, 12 h y 24 h (8 intentos). Tras 5 avisos fallidos seguidos el webhook se desactiva y lo ves en el portal, donde también puedes enviar un evento de prueba y reintentar envíos. El contenido refleja el registro al momento de enviar; si necesitas el estado más reciente, consulta la API.
Límites
Por defecto, 120 llamadas por minuto por credencial y hasta 200 registros por página. Si necesitas más, conversemos en soporte.
Endpoints
General
GET/ping
Verificar la credencial
Devuelve la empresa, la credencial, sus permisos y la hora del servidor. Útil para probar la conexión.
Ejemplo de respuesta
{
"data": {
"company": {
"code": "ACME",
"name": "ACME S.A.",
"country": "CL",
"timezone": "America/Santiago"
},
"credential": {
"name": "ERP producción",
"environment": "LIVE",
"scopes": [
"employees:read"
],
"rateLimitPerMinute": 120
},
"serverTime": "2026-09-28T09:30:00-03:00"
}
}
Trabajadores
GET/employeesemployees:read
Listar trabajadores
Trabajadores con su unidad, centro de costo, nivel de cargo y jefatura directa. Ordenados por fecha de actualización para sincronizar de forma incremental.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
Ejemplo de respuesta
{
"data": [
{
"id": 5,
"employeeNo": "DEMO0006",
"taxId": "12.345.678-5",
"firstName": "Lucas",
"secondName": null,
"lastName": "Contreras",
"secondLastName": "Díaz",
"email": "lucas@empresa.cl",
"phone": null,
"orgUnit": {
"code": "OPS",
"name": "Operaciones"
},
"costCenter": "OPS-NORTE",
"jobGrade": "G1",
"bossEmployeeNo": "DEMO0001",
"isBoss": false,
"hireDate": "2022-03-01",
"endDate": null,
"active": true,
"updatedAt": "2026-09-20T10:15:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTIwVDEzOjE1OjAwLjAwMDAwMFoiLDVd"
}
}
GET/employees/{employeeNo}employees:read
Consultar un trabajador
Busca por el número de trabajador de la empresa.
| Parámetro | En | Tipo | Descripción |
employeeNo obligatorio | ruta | string | Número de trabajador. |
Ejemplo de respuesta
{
"data": {
"id": 5,
"employeeNo": "DEMO0006",
"taxId": "12.345.678-5",
"firstName": "Lucas",
"secondName": null,
"lastName": "Contreras",
"secondLastName": "Díaz",
"email": "lucas@empresa.cl",
"phone": null,
"orgUnit": {
"code": "OPS",
"name": "Operaciones"
},
"costCenter": "OPS-NORTE",
"jobGrade": "G1",
"bossEmployeeNo": "DEMO0001",
"isBoss": false,
"hireDate": "2022-03-01",
"endDate": null,
"active": true,
"updatedAt": "2026-09-20T10:15:00-03:00"
}
}
GET/employees/{employeeNo}/balancesbalances:read
Cupos y saldos de un trabajador
Tope, usado, pendiente y disponible por beneficio y beneficiario, en la moneda del beneficio.
| Parámetro | En | Tipo | Descripción |
employeeNo obligatorio | ruta | string | Número de trabajador. |
Ejemplo de respuesta
{
"data": [
{
"benefit": {
"code": "DENTAL",
"name": "Reembolso dental"
},
"beneficiary": "Lucas Contreras",
"year": 2026,
"currency": "UF",
"limit": 10,
"used": 4.2,
"pending": 0,
"available": 5.8
}
]
}
PUT/employees/{employeeNo}employees:write
Crear o actualizar un trabajador
Si el número no existe, crea el trabajador (taxId, firstName y lastName obligatorios). Si existe, actualiza sólo los campos enviados. Unidad, centro de costo y nivel se indican por código; la jefatura, por número de trabajador (debe estar marcada como jefatura). Responde 201 al crear y 200 al actualizar.
Idempotency-Key: opcional.
| Parámetro | En | Tipo | Descripción |
employeeNo obligatorio | ruta | string | Número de trabajador (hasta 40 caracteres). |
| Campo del cuerpo | Tipo | Descripción |
taxId | string | RUT con dígito verificador. Obligatorio al crear. |
firstName | string | Nombre. Obligatorio al crear. |
secondName | string|null | Segundo nombre. |
lastName | string | Apellido. Obligatorio al crear. |
secondLastName | string|null | Segundo apellido. |
email | string|null | Correo. |
phone | string|null | Teléfono. |
orgUnit | string|null | Código de la unidad organizacional. |
costCenter | string|null | Código del centro de costo. |
jobGrade | string|null | Código del nivel de cargo. |
bossEmployeeNo | string|null | Número de la jefatura directa (null la quita). |
isBoss | boolean | true si puede ser jefatura de otros. |
hireDate | string | Fecha de ingreso AAAA-MM-DD. |
endDate | string|null | Fecha de término AAAA-MM-DD. |
active | boolean | false para desactivar. |
Ejemplo de cuerpo
{
"taxId": "12.345.678-5",
"firstName": "Lucas",
"lastName": "Contreras",
"email": "lucas@empresa.cl",
"orgUnit": "OPS",
"costCenter": "OPS-NORTE",
"jobGrade": "G1",
"bossEmployeeNo": "DEMO0001",
"hireDate": "2022-03-01"
}
Ejemplo de respuesta
{
"data": {
"id": 5,
"employeeNo": "DEMO0006",
"taxId": "12.345.678-5",
"firstName": "Lucas",
"secondName": null,
"lastName": "Contreras",
"secondLastName": "Díaz",
"email": "lucas@empresa.cl",
"phone": null,
"orgUnit": {
"code": "OPS",
"name": "Operaciones"
},
"costCenter": "OPS-NORTE",
"jobGrade": "G1",
"bossEmployeeNo": "DEMO0001",
"isBoss": false,
"hireDate": "2022-03-01",
"endDate": null,
"active": true,
"updatedAt": "2026-09-20T10:15:00-03:00"
}
}
Estructura
GET/cost-centersstructure:read
Centros de costo
Todos los centros de costo de la empresa, activos e inactivos.
Ejemplo de respuesta
{
"data": [
{
"code": "OPS-NORTE",
"name": "Operaciones Norte",
"active": true,
"updatedAt": "2026-09-01T12:00:00-03:00"
}
]
}
GET/job-gradesstructure:read
Niveles de cargo
Niveles de cargo ordenados por rango (1 = base).
Ejemplo de respuesta
{
"data": [
{
"code": "G1",
"name": "Operario",
"rank": 1,
"active": true,
"updatedAt": "2026-09-01T12:00:00-03:00"
}
]
}
PUT/cost-centers/{code}structure:write
Crear o actualizar un centro de costo
Crea el centro de costo si el código no existe o actualiza los campos enviados. Usa el mismo código que en tu ERP.
Idempotency-Key: opcional.
| Parámetro | En | Tipo | Descripción |
code obligatorio | ruta | string | Código (letras, números, punto, guion o guion bajo; se guarda en mayúsculas). |
| Campo del cuerpo | Tipo | Descripción |
name | string | Nombre. Obligatorio al crear. |
description | string|null | Descripción. |
active | boolean | false para desactivar. |
Ejemplo de cuerpo
{
"name": "Operaciones Norte",
"active": true
}
Ejemplo de respuesta
{
"data": {
"code": "OPS-NORTE",
"name": "Operaciones Norte",
"description": null,
"active": true,
"updatedAt": "2026-09-28T10:00:00-03:00"
}
}
PUT/job-grades/{code}structure:write
Crear o actualizar un nivel de cargo
Crea el nivel si el código no existe o actualiza los campos enviados.
Idempotency-Key: opcional.
| Parámetro | En | Tipo | Descripción |
code obligatorio | ruta | string | Código del nivel. |
| Campo del cuerpo | Tipo | Descripción |
name | string | Nombre. Obligatorio al crear. |
rank | integer | Rango de 1 (base) a 99. |
description | string|null | Descripción. |
active | boolean | false para desactivar. |
Ejemplo de cuerpo
{
"name": "Jefatura",
"rank": 3
}
Ejemplo de respuesta
{
"data": {
"code": "G3",
"name": "Jefatura",
"rank": 3,
"description": null,
"active": true,
"updatedAt": "2026-09-28T10:00:00-03:00"
}
}
Solicitudes
GET/requestsrequests:read
Listar solicitudes de beneficios
Solicitudes con estado, montos solicitados y aprobados, centro de costo y pago. Filtra por estado o trabajador.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
state | consulta | string | SUBMITTED, REVIEW, CORRECTION, APPROVED, REJECTED, SCHEDULED, PAID o CANCELLED. |
employeeNo | consulta | string | Sólo las solicitudes de este trabajador. |
Ejemplo de respuesta
{
"data": [
{
"id": 24,
"number": "BEN-2026-000024",
"state": "APPROVED",
"stateName": "Aprobada",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"benefit": {
"code": "LENSES",
"name": "Reembolso de lentes"
},
"costCenter": "OPS-NORTE",
"requestedAt": "2026-09-27T18:20:00-03:00",
"eventDate": null,
"serviceDate": "2026-09-20",
"amount": {
"requested": 45000,
"approved": 45000,
"currency": "CLP"
},
"benefitAmount": {
"requested": 1.0967,
"approved": 1.0967,
"currency": "UF"
},
"onBehalf": false,
"approvedAt": "2026-09-28T09:10:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"payPeriod": null,
"paidAt": null,
"updatedAt": "2026-09-28T09:10:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTI4VDEyOjEwOjAwLjAwMDAwMFoiLDI0XQ"
}
}
GET/requests/{id}requests:read
Consultar una solicitud
Incluye los niveles de aprobación, los documentos (sin el archivo) y el historial.
| Parámetro | En | Tipo | Descripción |
id obligatorio | ruta | integer | Identificador de la solicitud. |
Ejemplo de respuesta
{
"data": {
"id": 24,
"number": "BEN-2026-000024",
"state": "APPROVED",
"stateName": "Aprobada",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"benefit": {
"code": "LENSES",
"name": "Reembolso de lentes"
},
"costCenter": "OPS-NORTE",
"requestedAt": "2026-09-27T18:20:00-03:00",
"eventDate": null,
"serviceDate": "2026-09-20",
"amount": {
"requested": 45000,
"approved": 45000,
"currency": "CLP"
},
"benefitAmount": {
"requested": 1.0967,
"approved": 1.0967,
"currency": "UF"
},
"onBehalf": false,
"approvedAt": "2026-09-28T09:10:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"payPeriod": null,
"paidAt": null,
"updatedAt": "2026-09-28T09:10:00-03:00",
"approvals": [
{
"level": 1,
"label": "Jefatura directa: Javier Rojas",
"state": "APPROVED",
"decidedBy": "Javier Rojas",
"decidedAt": "2026-09-28T09:05:00-03:00",
"comment": "OK"
}
],
"documents": [
{
"type": "Boleta o factura",
"fileName": "boleta.pdf",
"valid": true
}
],
"history": [
{
"action": "SUBMIT",
"state": "SUBMITTED",
"comment": "Solicitud ingresada.",
"at": "2026-09-27T18:20:00-03:00"
}
]
}
}
POST/requestsrequests:write
Ingresar una solicitud de beneficio
Ingresa la solicitud en representación del trabajador, con las mismas reglas que la web (vigencia, saldo, documentos obligatorios) y entra al flujo de revisión y aprobación. Documentos: en multipart/form-data como documents[CODIGO] (PDF, JPG o PNG, hasta 10 MB cada uno), o en JSON como lista con contentBase64. Requiere Idempotency-Key.
Idempotency-Key: obligatoria.
| Campo del cuerpo | Tipo | Descripción |
employeeNo obligatorio | string | Número de trabajador. |
benefit obligatorio | string | Código del beneficio vigente. |
amount obligatorio | number | Monto del gasto en la moneda base. |
serviceDate | string | Fecha de prestación AAAA-MM-DD (obligatoria en reembolsos). |
eventDate | string | Fecha del evento AAAA-MM-DD (obligatoria en beneficios por evento). |
dependentTaxId | string | RUT de la carga, si el beneficio es para una carga. |
deathBeneficiaryTaxId | string | RUT del beneficiario, en beneficios por fallecimiento. |
reason | string | Motivo del ingreso en representación (por defecto, el nombre de la integración). |
documents | array | JSON: [{"type": "INVOICE", "fileName": "boleta.pdf", "contentBase64": "..."}]. Multipart: campos documents[INVOICE]. |
taxDocument | object | Opcional: {"type": "BOLETA|FACTURA|BHE", "issuerTaxId": "76.086.428-5", "number": "1234"}. Evita que la misma boleta se presente dos veces (también contra rendiciones). |
Ejemplo de cuerpo
{
"employeeNo": "DEMO0006",
"benefit": "LENSES",
"amount": 45000,
"serviceDate": "2026-09-20",
"documents": [
{
"type": "INVOICE",
"fileName": "boleta.pdf",
"contentBase64": "JVBERi0xLjQK..."
}
]
}
Ejemplo de respuesta (201)
{
"data": {
"id": 24,
"number": "BEN-2026-000024",
"state": "SUBMITTED",
"stateName": "Enviada",
"employeeNo": "DEMO0006",
"benefit": {
"code": "LENSES",
"name": "Reembolso de lentes"
},
"amount": {
"requested": 45000,
"approved": null,
"currency": "CLP"
},
"onBehalf": true,
"documents": [
{
"type": "Boleta o factura",
"fileName": "boleta.pdf",
"valid": false
}
]
},
"meta": {
"message": "La solicitud fue ingresada correctamente.",
"limitedToBalance": false
}
}
Pagos
GET/paymentspayments:read
Líneas de pago
Cada pago de una solicitud de beneficio, reembolso de rendición o entrega/reposición de fondo o viático dentro de un lote bancario, con su resultado (source BENEFIT, EXPENSE, FUND o TRIP). Ideal para contabilizar en el ERP.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
paid | consulta | boolean | true para sólo pagadas, false para no pagadas. |
Ejemplo de respuesta
{
"data": [
{
"id": 88,
"batch": {
"number": "LOT-2026-0009",
"state": "EXPORTED",
"payDate": "2026-09-30",
"period": "2026-09"
},
"source": "BENEFIT",
"requestId": 24,
"requestNumber": "BEN-2026-000024",
"expenseReportId": null,
"expenseReportNumber": null,
"fundId": null,
"fundNumber": null,
"tripId": null,
"tripNumber": null,
"employeeNo": "DEMO0006",
"benefit": "LENSES",
"costCenter": "OPS-NORTE",
"amount": 45000,
"paid": true,
"paidAt": "2026-09-30T11:00:00-03:00",
"result": "PAID",
"bankReference": "TRX-5561",
"rejectReason": null,
"updatedAt": "2026-09-30T11:00:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTMwVDE0OjAwOjAwLjAwMDAwMFoiLDg4XQ"
}
}
Rendiciones
GET/expensesexpenses:read
Listar rendiciones de gastos
Rendiciones enviadas (no borradores) con estado, totales y centro de costo, ordenadas por actualización para sincronizar. Requiere el módulo Rendiciones.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
state | consulta | string | SUBMITTED, CORRECTION, APPROVED, REJECTED, SCHEDULED, PAID o CANCELLED. |
employeeNo | consulta | string | Sólo las rendiciones de este trabajador. |
Ejemplo de respuesta
{
"data": [
{
"id": 5,
"number": "REN-2026-000005",
"title": "Visita clientes zona norte",
"purpose": null,
"state": "APPROVED",
"stateName": "Aprobada",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"costCenter": {
"id": 1,
"code": "OPS-NORTE",
"name": "Operaciones Norte"
},
"funding": "OWN",
"lineCount": 3,
"overPolicyCount": 1,
"amount": {
"total": 58923,
"approved": 58923,
"currency": "CLP"
},
"createdAt": "2026-09-25T09:00:00-03:00",
"submittedAt": "2026-09-25T18:00:00-03:00",
"approvedAt": "2026-09-28T10:18:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"paidAt": null,
"updatedAt": "2026-09-28T10:18:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTI4VDEzOjE1OjAwLjAwMDAwMFoiLDVd"
}
}
GET/expenses/{id}expenses:read
Consultar una rendición
Incluye cada gasto con categoría, cuenta contable, centro de costo y documento (RUT emisor, folio), los niveles de aprobación y el historial.
| Parámetro | En | Tipo | Descripción |
id obligatorio | ruta | integer | Identificador de la rendición. |
Ejemplo de respuesta
{
"data": {
"id": 5,
"number": "REN-2026-000005",
"title": "Visita clientes zona norte",
"purpose": null,
"state": "APPROVED",
"stateName": "Aprobada",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"costCenter": {
"id": 1,
"code": "OPS-NORTE",
"name": "Operaciones Norte"
},
"funding": "OWN",
"lineCount": 3,
"overPolicyCount": 1,
"amount": {
"total": 58923,
"approved": 58923,
"currency": "CLP"
},
"createdAt": "2026-09-25T09:00:00-03:00",
"submittedAt": "2026-09-25T18:00:00-03:00",
"approvedAt": "2026-09-28T10:18:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"paidAt": null,
"updatedAt": "2026-09-28T10:18:00-03:00",
"lines": [
{
"id": 12,
"date": "2026-09-25",
"category": {
"id": 1,
"code": "ALIM",
"name": "Alimentación",
"account": "5105-010"
},
"costCenter": "OPS-NORTE",
"description": "Almuerzo con cliente",
"document": {
"type": "BOLETA",
"typeName": "Boleta",
"issuerTaxId": "76.086.428-5",
"issuerName": "Restaurant El Puerto",
"number": "1234"
},
"originalAmount": {
"amount": 15500,
"currency": "CLP",
"rate": 1
},
"amount": 15500,
"overPolicy": false,
"policyNote": null,
"justification": null,
"hasReceipt": true
}
],
"approvals": [
{
"level": 1,
"label": "Jefatura directa: Javier Rojas",
"state": "APPROVED",
"decidedBy": "Javier Rojas",
"decidedAt": "2026-09-28T10:18:00-03:00",
"comment": "OK"
}
]
}
}
GET/expense-categoriesexpenses:read
Categorías de gasto
Categorías con su cuenta contable, política de documento y tope por gasto.
Ejemplo de respuesta
{
"data": [
{
"code": "ALIM",
"name": "Alimentación",
"account": "5105-010",
"documentPolicy": "REQUIRED",
"maxAmount": 20000,
"active": true
}
]
}
Fondos
GET/fundsfunds:read
Listar fondos
Fondos fijos (caja chica), por rendir y esporádicos con custodio, monto asignado, saldo, disponible y vencimiento, ordenados por actualización para sincronizar. Requiere el módulo Fondos por rendir y caja chica.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
state | consulta | string | REQUESTED, APPROVED, ACTIVE, CLOSED, REJECTED o CANCELLED. |
type | consulta | string | FIXED, TEMPORARY o SPORADIC. |
employeeNo | consulta | string | Sólo los fondos de este custodio. |
Ejemplo de respuesta
{
"data": [
{
"id": 1,
"number": "FON-2026-000001",
"type": "SPORADIC",
"typeName": "Fondo esporádico",
"name": "Compra repuestos parada",
"purpose": "Repuestos menores parada de planta",
"state": "ACTIVE",
"stateName": "Vigente",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"costCenter": {
"id": 1,
"code": "OPS-NORTE",
"name": "Operaciones Norte"
},
"amount": {
"assigned": 200000,
"balance": 200000,
"available": 20000,
"inReview": 180000,
"spent": 0,
"toPay": 0,
"currency": "CLP"
},
"expiryDate": "2026-10-28",
"expired": false,
"lowBalance": false,
"lowBalancePercent": 20,
"requestedAt": "2026-09-28T09:00:00-03:00",
"approvedAt": "2026-09-28T09:30:00-03:00",
"deliveredAt": "2026-09-28T11:00:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"closedAt": null,
"updatedAt": "2026-09-28T11:00:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTI4VDE0OjAwOjAwLjAwMDAwMFoiLDFd"
}
}
GET/funds/{id}funds:read
Consultar un fondo
Incluye la cartola (movimientos con saldo acumulado), las rendiciones con cargo al fondo, los niveles de aprobación y el historial.
| Parámetro | En | Tipo | Descripción |
id obligatorio | ruta | integer | Identificador del fondo. |
Ejemplo de respuesta
{
"data": {
"id": 1,
"number": "FON-2026-000001",
"type": "SPORADIC",
"typeName": "Fondo esporádico",
"name": "Compra repuestos parada",
"purpose": "Repuestos menores parada de planta",
"state": "ACTIVE",
"stateName": "Vigente",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"costCenter": {
"id": 1,
"code": "OPS-NORTE",
"name": "Operaciones Norte"
},
"amount": {
"assigned": 200000,
"balance": 200000,
"available": 20000,
"inReview": 180000,
"spent": 0,
"toPay": 0,
"currency": "CLP"
},
"expiryDate": "2026-10-28",
"expired": false,
"lowBalance": false,
"lowBalancePercent": 20,
"requestedAt": "2026-09-28T09:00:00-03:00",
"approvedAt": "2026-09-28T09:30:00-03:00",
"deliveredAt": "2026-09-28T11:00:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"closedAt": null,
"updatedAt": "2026-09-28T11:00:00-03:00",
"movements": [
{
"id": 1,
"type": "DELIVERY",
"typeName": "Entrega",
"amount": 200000,
"state": "DONE",
"stateName": "Realizado",
"method": "BATCH",
"reference": "PAG-2026-000003 / TRX-5561",
"description": "Entrega inicial del fondo.",
"expenseReportId": null,
"expenseReportNumber": null,
"date": "2026-09-28T11:00:00-03:00",
"balanceAfter": 200000,
"createdAt": "2026-09-28T09:00:00-03:00",
"updatedAt": "2026-09-28T11:00:00-03:00"
},
{
"id": 9,
"type": "EXPENSE",
"typeName": "Rendición aprobada",
"amount": -180000,
"state": "DONE",
"stateName": "Realizado",
"method": "SYSTEM",
"reference": null,
"description": "Rendición REN-2026-000012: Repuestos parada",
"expenseReportId": 12,
"expenseReportNumber": "REN-2026-000012",
"date": "2026-10-02T16:00:00-03:00",
"balanceAfter": 20000,
"createdAt": "2026-10-02T16:00:00-03:00",
"updatedAt": "2026-10-02T16:00:00-03:00"
}
]
}
}
GET/fund-movementsfunds:read
Movimientos de fondos
Cartola de todos los fondos para contabilizar: entregas y reposiciones (+), rendiciones descontadas y devoluciones (−) y ajustes de arqueo (±). Por defecto sólo realizados; ordenados por actualización para sincronizar.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
state | consulta | string | DONE (por defecto), PENDING, SCHEDULED, CANCELLED o ALL. |
type | consulta | string | DELIVERY, EXPENSE, REPLENISH, RETURN, ADJUSTMENT u OPENING (saldo inicial migrado). |
fundNumber | consulta | string | Sólo los movimientos de este fondo (ej. FON-2026-000001). |
Ejemplo de respuesta
{
"data": [
{
"id": 9,
"fund": {
"id": 1,
"number": "FON-2026-000001",
"type": "SPORADIC",
"name": "Compra repuestos parada"
},
"employeeNo": "DEMO0006",
"costCenter": "OPS-NORTE",
"type": "EXPENSE",
"typeName": "Rendición aprobada",
"amount": -180000,
"state": "DONE",
"stateName": "Realizado",
"method": "SYSTEM",
"reference": null,
"description": "Rendición REN-2026-000012: Repuestos parada",
"expenseReportId": 12,
"expenseReportNumber": "REN-2026-000012",
"date": "2026-10-02T16:00:00-03:00",
"createdAt": "2026-10-02T16:00:00-03:00",
"updatedAt": "2026-10-02T16:00:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTEwLTAyVDE5OjAwOjAwLjAwMDAwMFoiLDld"
}
}
Viajes
GET/tripstrips:read
Listar viajes
Viajes con destino, fechas, viático, anticipo y estado, ordenados por actualización para sincronizar. Requiere el módulo Viajes y viáticos.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
state | consulta | string | REQUESTED, APPROVED, CLOSED, REJECTED o CANCELLED. |
employeeNo | consulta | string | Sólo los viajes de este trabajador. |
Ejemplo de respuesta
{
"data": [
{
"id": 1,
"number": "VIA-2026-000001",
"state": "APPROVED",
"stateName": "Aprobado",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"costCenter": {
"id": 1,
"code": "OPS-NORTE",
"name": "Operaciones Norte"
},
"zone": {
"id": 1,
"code": "NAC",
"name": "Nacional"
},
"destination": "Calama, planta norte",
"purpose": "Mantención de bombas",
"transport": "Avión",
"startDate": "2026-09-30",
"endDate": "2026-10-02",
"actualEndDate": null,
"amount": {
"perDiem": 130000,
"advance": 60000,
"paid": 130000,
"toPay": 0,
"currency": "CLP"
},
"advanceFund": {
"id": 6,
"number": "FON-2026-000006",
"state": "ACTIVE"
},
"requestedAt": "2026-09-28T11:30:00-03:00",
"approvedAt": "2026-09-28T11:40:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"closedAt": null,
"cancelledAt": null,
"updatedAt": "2026-09-28T11:40:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTI4VDE0OjMwOjAwLjAwMDAwMFoiLDFd"
}
}
GET/trips/{id}trips:read
Consultar un viaje
Incluye el cálculo del viático por concepto (cantidad, tarifa, cuenta contable y, en zonas en otra moneda, la tarifa original y el tipo de cambio), los pagos, las rendiciones del viaje, los niveles de aprobación y el historial.
| Parámetro | En | Tipo | Descripción |
id obligatorio | ruta | integer | Identificador del viaje. |
Ejemplo de respuesta
{
"data": {
"id": 1,
"number": "VIA-2026-000001",
"state": "APPROVED",
"stateName": "Aprobado",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"costCenter": {
"id": 1,
"code": "OPS-NORTE",
"name": "Operaciones Norte"
},
"zone": {
"id": 1,
"code": "NAC",
"name": "Nacional"
},
"destination": "Calama, planta norte",
"purpose": "Mantención de bombas",
"transport": "Avión",
"startDate": "2026-09-30",
"endDate": "2026-10-02",
"actualEndDate": null,
"amount": {
"perDiem": 130000,
"advance": 60000,
"paid": 130000,
"toPay": 0,
"currency": "CLP"
},
"advanceFund": {
"id": 6,
"number": "FON-2026-000006",
"state": "ACTIVE"
},
"requestedAt": "2026-09-28T11:30:00-03:00",
"approvedAt": "2026-09-28T11:40:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"closedAt": null,
"cancelledAt": null,
"updatedAt": "2026-09-28T11:40:00-03:00",
"perDiem": [
{
"concept": {
"code": "ALIM",
"name": "Alimentación",
"account": "5110-020"
},
"unit": "DAY",
"quantity": 2.5,
"rate": 40000,
"originalRate": null,
"amount": 100000,
"included": true,
"note": null
},
{
"concept": {
"code": "ALOJ",
"name": "Alojamiento",
"account": "5110-030"
},
"unit": "NIGHT",
"quantity": 2,
"rate": 50000,
"originalRate": null,
"amount": 0,
"included": false,
"note": "Provisto por la empresa"
}
],
"payments": [
{
"id": 1,
"type": "PERDIEM",
"typeName": "Pago de viático",
"amount": 130000,
"state": "DONE",
"stateName": "Realizado",
"method": "BATCH",
"reference": "PAG-2026-000004 / TRX-5561",
"description": "Viático del viaje.",
"date": "2026-09-29T11:00:00-03:00",
"createdAt": "2026-09-28T11:40:00-03:00",
"updatedAt": "2026-09-29T11:00:00-03:00"
}
]
}
}
GET/trip-paymentstrips:read
Pagos de viático
Pagos (PERDIEM), complementos (SUPPLEMENT) y devoluciones (RETURN, monto negativo) de viático, para contabilizar. Por defecto sólo realizados; ordenados por actualización para sincronizar.
| Parámetro | En | Tipo | Descripción |
pageSize | consulta | integer | Registros por página, de 1 a 200 (por defecto 50). |
updatedSince | consulta | string | Primera sincronización: sólo registros modificados después de esta fecha-hora ISO 8601. |
cursor | consulta | string | Siguientes sincronizaciones: el valor de meta.nextCursor de la respuesta anterior. |
page | consulta | integer | Sólo para consultas sin cursor ni updatedSince: página desde 1 (incluye meta.total). |
state | consulta | string | DONE (por defecto), PENDING, SCHEDULED, CANCELLED o ALL. |
tripNumber | consulta | string | Sólo los pagos de este viaje (ej. VIA-2026-000001). |
Ejemplo de respuesta
{
"data": [
{
"id": 1,
"trip": {
"id": 1,
"number": "VIA-2026-000001",
"destination": "Calama, planta norte"
},
"employeeNo": "DEMO0006",
"costCenter": "OPS-NORTE",
"type": "PERDIEM",
"typeName": "Pago de viático",
"amount": 130000,
"state": "DONE",
"stateName": "Realizado",
"method": "BATCH",
"reference": "PAG-2026-000004 / TRX-5561",
"description": "Viático del viaje.",
"date": "2026-09-29T11:00:00-03:00",
"createdAt": "2026-09-28T11:40:00-03:00",
"updatedAt": "2026-09-29T11:00:00-03:00"
}
],
"meta": {
"pageSize": 50,
"hasMore": false,
"nextCursor": "WyIyMDI2LTA5LTI4VDE1OjAwOjAwLjAwMDAwMFoiLDFd"
}
}
Contabilidad
GET/journal-entriesaccounting:read
Asientos contables
Los mismos asientos cuadrados de Contabilidad › Asientos contables (aprobación y pago de rendiciones y beneficios, movimientos de fondos y pagos de viático), con las cuentas configuradas por la empresa. Se calculan con el estado actual de cada documento. Requiere un plan con exportación contable (Profesional o superior). Rango máximo: un año.
| Parámetro | En | Tipo | Descripción |
from obligatorio | consulta | string | Desde (AAAA-MM-DD, fecha del hecho). |
to obligatorio | consulta | string | Hasta (AAAA-MM-DD). |
sources | consulta | string | Orígenes separados por coma: EXPENSE, FUND, TRIP, BENEFIT (por defecto todos los contratados). |
grouping | consulta | string | DETAIL (un comprobante por documento, por defecto) o SUMMARY (uno por día y tipo de hecho). |
page | consulta | integer | Página desde 1. |
pageSize | consulta | integer | Comprobantes por página, de 1 a 500 (por defecto 200). |
Ejemplo de respuesta
{
"data": [
{
"number": 1,
"date": "2026-09-28",
"type": "EXPENSE_APPROVED",
"typeName": "Rendiciones aprobadas",
"document": "REN-2026-000005",
"description": "Rendición REN-2026-000005 Lucas Contreras",
"lines": [
{
"line": 1,
"account": "5110-01",
"debit": 85000,
"credit": 0,
"costCenter": "OPS-NORTE",
"auxiliary": null,
"description": "Hotel · REN-2026-000005",
"taxDocument": {
"type": "FACTURA",
"number": "88001",
"issuerTaxId": "96.505.760-9"
}
},
{
"line": 2,
"account": "2110-01",
"debit": 0,
"credit": 85000,
"costCenter": "OPS-NORTE",
"auxiliary": {
"taxId": "12.345.678-5",
"name": "Lucas Contreras",
"employeeNo": "DEMO0005"
},
"description": "Reembolso por pagar · REN-2026-000005",
"taxDocument": null
}
]
}
],
"meta": {
"from": "2026-09-01",
"to": "2026-09-30",
"sources": [
"EXPENSE",
"FUND",
"TRIP",
"BENEFIT"
],
"grouping": "DETAIL",
"currency": "CLP",
"page": 1,
"pageSize": 200,
"total": 1,
"hasMore": false,
"totals": {
"debit": 85000,
"credit": 85000
},
"warnings": []
}
}
Monedas
GET/ratesrates:read
Tasas de conversión del día
Valor de UF, UTM, dólar y euro en la moneda base para una fecha.
| Parámetro | En | Tipo | Descripción |
date | consulta | string | Fecha AAAA-MM-DD (por defecto hoy). |
Ejemplo de respuesta
{
"data": [
{
"from": "UF",
"to": "CLP",
"rate": 41032.64,
"date": "2026-09-28",
"source": "mindicador.cl"
}
]
}
Sandbox
POST/sandbox/requests/{id}/staterequests:write
Simular un cambio de estado (sólo sandbox)
Con claves bqk_test_ fuerza el estado de una solicitud del sandbox para probar tu sincronización y tus webhooks sin esperar a un aprobador. En producción responde 403.
Idempotency-Key: opcional.
| Parámetro | En | Tipo | Descripción |
id obligatorio | ruta | integer | Identificador de la solicitud. |
| Campo del cuerpo | Tipo | Descripción |
state obligatorio | string | REVIEW, CORRECTION, APPROVED, REJECTED, PAID o CANCELLED. |
comment | string | Comentario (en REJECTED, motivo del rechazo). |
Ejemplo de cuerpo
{
"state": "APPROVED"
}
Ejemplo de respuesta
{
"data": {
"id": 24,
"number": "BEN-2026-000024",
"state": "APPROVED",
"stateName": "Aprobada",
"employeeNo": "DEMO0006",
"employeeName": "Lucas Contreras",
"benefit": {
"code": "LENSES",
"name": "Reembolso de lentes"
},
"costCenter": "OPS-NORTE",
"requestedAt": "2026-09-27T18:20:00-03:00",
"eventDate": null,
"serviceDate": "2026-09-20",
"amount": {
"requested": 45000,
"approved": 45000,
"currency": "CLP"
},
"benefitAmount": {
"requested": 1.0967,
"approved": 1.0967,
"currency": "UF"
},
"onBehalf": false,
"approvedAt": "2026-09-28T09:10:00-03:00",
"rejectedAt": null,
"rejectReason": null,
"payPeriod": null,
"paidAt": null,
"updatedAt": "2026-09-28T09:10:00-03:00"
}
}
¿Prefieres que lo hagamos nosotros?
Qubits realiza la integración con tu ERP como servicio profesional, cotizado aparte: conversemos.