VitrinaAPI

Clinic commissions

Each professional's commission history: the months Vitrina settles next to the liquidaciones Dentalink issued, imported read-only, and the Dentalink exports the clinic uploads.

Beta
This may change at any time, with a changelog entry and a notice to recent callers — see versioning.

Download the full API pública projection: openapi.json.

MethodPathWhat it does
GET/clinic/commissions/historyA professional’s commission history, Vitrina and Dentalink
POST/clinic/commissions/imported-exportsUpload Dentalink’s own export of a liquidación
GET/clinic/commissions/imported-exports/{id}/fileDownload an uploaded Dentalink liquidación export
GET/clinic/commissions/imported/{id}One liquidación imported from Dentalink, with its lines

GET /clinic/commissions/history

A professional’s commission history, Vitrina and Dentalink

One professional’s months, newest first, so the whole history is in one place: for each month settled_by (vitrina from «primer mes que liquida Vitrina» on, dentalink before it), Vitrina’s own lines (native: counts and Σ, read_only: false), the liquidaciones Dentalink settled and the migration imported (imported, labelled «Importada de Dentalink», read_only: true, Dentalink’s own total) and the Dentalink exports the clinic uploaded for pages the reader could not reach (exports, read_only: true). Imported months are never recomputed, approved or exported and never count as months Vitrina computed. 404 unknown professional. Requires 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.

ParameterInTypeRequiredConstraints
professional_idqueryuuidyes
curl https://api.vitrinadev.com/api/v1/clinic/commissions/history \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "professional_id": "0192f0c4-0000-7000-8000-000000000001",
    "first_native_money_month": "2026-11",
    "months": [
      {
        "period": "2026-11",
        "settled_by": "vitrina",
        "native": {
          "source": "vitrina",
          "read_only": false,
          "lines": 42,
          "amount_clp": 1260000,
          "computed": 0,
          "approved": 42,
          "exported": 0
        },
        "imported": [],
        "exports": []
      },
      {
        "period": "2026-10",
        "settled_by": "dentalink",
        "native": null,
        "imported": [
          {
            "id": "0192f0c4-0000-7000-8000-000000000002",
            "source": "dentalink_import",
            "label": "Importada de Dentalink",
            "read_only": true,
            "external_id": "9001",
            "location_id": null,
            "location_name": "Central",
            "period_from": "2026-10-01",
            "period_to": "2026-10-31",
            "total_clp": 1180000,
            "lines_total_clp": 1180000,
            "deductions_clp": -80000,
            "line_count": 38,
            "imported_at": "2026-11-05T14:00:00.000Z"
          }
        ],
        "exports": []
      }
    ]
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /clinic/commissions/imported-exports

Upload Dentalink’s own export of a liquidación

The manual fallback for a liquidación the migration reader could not reach (gap liquidacion_unreachable / liquidacion_unparseable, whose detail names the professional, sucursal and month): Dentalink’s export (PDF, Excel, CSV or an image; content as base64 or a data: URL; at most 20 MB), stored against that professional, month and sucursal and shown in the professional’s history in place of the imported liquidación. A new upload for the same slot replaces the previous. Only a month Dentalink settled: 409 month_owned_by_vitrina otherwise. 400 liquidacion_export_type / _encoding / _empty / _too_large; 404 unknown professional. Requires clinic_money:write.

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

FieldTypeRequiredConstraints
professional_iduuidyes
periodstringyespatrón ^\d{4}-(0[1-9]|1[0-2])$
location_idstring | null—
external_idstring | null—patrón ^\d{1,20}$
file_namestringyesmín. 1, máx. 200
mime_typestring—máx. 120
contentstringyesmín. 1
curl -X POST https://api.vitrinadev.com/api/v1/clinic/commissions/imported-exports \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "professional_id": "0192f0c4-0000-7000-8000-000000000001",
    "period": "2026-09",
    "location_id": "0192f0c4-0000-7000-8000-000000000003",
    "external_id": "9000",
    "file_name": "liquidacion-septiembre.pdf",
    "content": "data:application/pdf;base64,JVBERi0xLjQK"
  }'

Example response (201)

{
  "data": {
    "id": "0192f0c4-0000-7000-8000-000000000005",
    "source": "dentalink_export",
    "label": "Exportación de Dentalink",
    "read_only": true,
    "location_id": "0192f0c4-0000-7000-8000-000000000003",
    "location_name": "Central",
    "external_id": "9000",
    "file_name": "liquidacion-septiembre.pdf",
    "mime_type": "application/pdf",
    "size_bytes": 48213,
    "uploaded_at": "2026-11-06T13:10:00.000Z"
  }
}

Answers: 201 · 400 · 401 · 403 · 404 · 409 · 429

GET /clinic/commissions/imported-exports/{id}/file

Download an uploaded Dentalink liquidación export

The file the clinic uploaded, as uploaded (its own content type). 404 unknown id. Requires 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.

ParameterInTypeRequiredConstraints
idpathuuidyes
curl https://api.vitrinadev.com/api/v1/clinic/commissions/imported-exports/<id>/file \
  -H "Authorization: Bearer $VITRINA_KEY"

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

GET /clinic/commissions/imported/{id}

One liquidación imported from Dentalink, with its lines

A liquidación as Dentalink settled it (read-only, «Importada de Dentalink»): dentist, sucursal, period, Dentalink’s total, the page’s own total and deductions, and its lines (day, prestación, base, rate in basis points, deductions, amount). The paciente is the migrated ficha’s id when resolvable and the INITIALS — never a name, like the native liquidación PDF. 404 unknown id. Requires 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.

ParameterInTypeRequiredConstraints
idpathuuidyes
curl https://api.vitrinadev.com/api/v1/clinic/commissions/imported/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "id": "0192f0c4-0000-7000-8000-000000000002",
    "source": "dentalink_import",
    "label": "Importada de Dentalink",
    "read_only": true,
    "professional_id": "0192f0c4-0000-7000-8000-000000000001",
    "external_id": "9001",
    "location_id": "0192f0c4-0000-7000-8000-000000000003",
    "location_name": "Central",
    "period": "2026-10",
    "period_from": "2026-10-01",
    "period_to": "2026-10-31",
    "total_clp": 152000,
    "lines_total_clp": 152000,
    "deductions_clp": -80000,
    "line_count": 2,
    "imported_at": "2026-11-05T14:00:00.000Z",
    "lines": [
      {
        "position": 0,
        "performed_on": "2026-10-02",
        "treatment": "Obturación resina",
        "patient": {
          "id": "0192f0c4-0000-7000-8000-000000000004",
          "initials": "APE"
        },
        "base_clp": 60000,
        "rate_bps": 4000,
        "deductions_clp": 0,
        "amount_clp": 24000
      },
      {
        "position": 1,
        "performed_on": "2026-10-15",
        "treatment": "Corona metal porcelana",
        "patient": {
          "id": null,
          "initials": "BFD"
        },
        "base_clp": 400000,
        "rate_bps": 4000,
        "deductions_clp": -80000,
        "amount_clp": 128000
      }
    ]
  }
}

Answers: 200 · 400 · 401 · 403 · 404 · 409 · 429

On this page