Clinic HR
The read-only Buk connection and the month's payroll cost, summed from the closed settlements without storing the per-person detail.
Download the full API pública projection: openapi.json.
| Method | Path | What it does |
|---|---|---|
POST | /clinic/hr/buk/connect | Connect (or rotate) the tenant’s Buk API token |
POST | /clinic/hr/buk/disconnect | Disconnect and wipe the stored Buk token |
GET | /clinic/hr/buk/status | Buk payroll connection status |
POST | /clinic/hr/buk/sync | Sincronizar ahora — pull last month’s payroll cost from Buk |
POST /clinic/hr/buk/connect
Connect (or rotate) the tenant’s Buk API token
One Buk (buk.cl) connection per tenant: the company subdomain plus a read-only auth_token API key a human mints inside Buk (Configuración → Accesos API). Every sync reads ONLY the payroll_detail/month operation (Buk has no company-wide aggregate endpoint) and sums the CLOSED settlements in memory — the raw per-employee response (which carries rut) never leaves the provider client. Upserts BY TENANT — a second call with a new token rotates the stored credential rather than creating a second connection. The token is AES-GCM enveloped under the tenant’s own DEK before it is written; only a masked preview is ever returned.
Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.
Body
| Field | Type | Required | Constraints |
|---|---|---|---|
subdomain | string | yes | mín. 2, máx. 63, patrón ^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$ |
auth_token | string | yes | mín. 8, máx. 500 |
country | chile | — |
curl -X POST https://api.vitrinadev.com/api/v1/clinic/hr/buk/connect \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"subdomain": "clinicaodm",
"auth_token": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"country": "chile"
}'Example response (200)
{
"data": {
"connected": true,
"id": "b6b6b6b6-0000-4000-8000-000000000001",
"subdomain": "clinicaodm",
"country": "chile",
"has_credentials": true,
"auth_token_preview": "a1b2••••d6",
"enabled": true,
"last_sync_at": "2026-09-22T09:05:11.000Z",
"last_sync_status": "ok",
"last_sync_error": null,
"created_at": "2026-08-01T13:00:00.000Z",
"updated_at": "2026-09-22T09:05:11.000Z"
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /clinic/hr/buk/disconnect
Disconnect and wipe the stored Buk token
Disables the connection and erases the stored token — never leaves an encrypted secret behind with no way to use it. Reconnecting is POST .../connect again with a fresh token.
Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.
curl -X POST https://api.vitrinadev.com/api/v1/clinic/hr/buk/disconnect \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": {
"connected": false,
"disconnected": true
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
GET /clinic/hr/buk/status
Buk payroll connection status
One Buk (buk.cl) connection per tenant: the company subdomain plus a read-only auth_token API key a human mints inside Buk (Configuración → Accesos API). Every sync reads ONLY the payroll_detail/month operation (Buk has no company-wide aggregate endpoint) and sums the CLOSED settlements in memory — the raw per-employee response (which carries rut) never leaves the provider client. Readable with clinic_money:read.
Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.
curl https://api.vitrinadev.com/api/v1/clinic/hr/buk/status \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": {
"connected": true,
"id": "b6b6b6b6-0000-4000-8000-000000000001",
"subdomain": "clinicaodm",
"country": "chile",
"has_credentials": true,
"auth_token_preview": "a1b2••••d6",
"enabled": true,
"last_sync_at": "2026-09-22T09:05:11.000Z",
"last_sync_status": "ok",
"last_sync_error": null,
"created_at": "2026-08-01T13:00:00.000Z",
"updated_at": "2026-09-22T09:05:11.000Z"
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /clinic/hr/buk/sync
Sincronizar ahora — pull last month’s payroll cost from Buk
Runs the same aggregate pull the daily tick runs, synchronously, for the caller’s tenant. Targets the LAST FULLY-CLOSED calendar month — a liquidación Buk has not closed yet is skipped, not zeroed, and picked up by a later sync. reason explains a 200 that wrote nothing (no_enabled_connection / no_closed_settlements).
Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.
curl -X POST https://api.vitrinadev.com/api/v1/clinic/hr/buk/sync \
-H "Authorization: Bearer $VITRINA_KEY"Example response (200)
{
"data": {
"tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
"period": "2026-08",
"wrote": true,
"inserted": false,
"amount_clp": 5430000,
"settlement_count": 6,
"skipped_open_count": 0,
"skipped_unparsable_count": 0
}
}Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429