VitrinaAPI

Clinic laboratory

The clinic's laboratories, their price list by type of work and the orders sent to them, with each order's status.

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/lab-ordersList lab orders
POST/clinic/lab-ordersSend work to a lab for a treatment
GET/clinic/lab-orders/{id}One lab order
PATCH/clinic/lab-orders/{id}Move a lab order along, or correct it
GET/clinic/lab-work-typesList the labs' price lists
POST/clinic/lab-work-typesAdd a line to a lab's price list
PATCH/clinic/lab-work-types/{id}Re-price or retire a line of a lab's price list
POST/clinic/labsAdd a laboratorio
PATCH/clinic/labs/{id}Edit or deactivate a laboratorio

GET /clinic/lab-orders

List lab orders

Every order with its lab, patient, treatment and professional. Filter by lab_id, status, or open=true (to send + sent — the work still in flight); treatment_plan_item_id, treatment_plan_id and patient_id narrow to one treatment, plan or ficha. Work in flight sorts first, oldest first. counts carries the per-status totals for the same lab/patient filter, ignoring status.

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
lab_idqueryuuidno
statusqueryto_send \sent \received \
openquerytrue \falseno
treatment_plan_item_idqueryuuidno
treatment_plan_idqueryuuidno
patient_idqueryuuidno
pagequeryintegerno≥ 1, por defecto 1
limitqueryintegerno≥ 1, ≤ 200, por defecto 50
curl https://api.vitrinadev.com/api/v1/clinic/lab-orders \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "items": [
      {
        "id": "c0e57121-0000-4000-8000-0000000003ab",
        "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
        "source": "native",
        "external_id": null,
        "treatment_plan_item_id": "b7b7b7b7-0000-4000-8000-000000000011",
        "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
        "work_type_id": "c0e57121-0000-4000-8000-0000000002ab",
        "work_type": "Corona de zirconio",
        "cost_clp": 95000,
        "status": "sent",
        "sent_on": "2026-09-29",
        "received_on": null,
        "notes": "Color A2",
        "created_by": "5e5e5e5e-0000-4000-8000-000000000001",
        "created_at": "2026-09-29T13:05:00.000Z",
        "updated_at": "2026-09-29T15:20:00.000Z",
        "lab_name": "Laboratorio Ejemplo",
        "treatment_plan_id": "b7b7b7b7-0000-4000-8000-000000000001",
        "treatment_plan_name": "Rehabilitación sector posterior",
        "clinic_patient_id": "b1b0b8de-0000-4000-8000-000000000001",
        "patient_name": "María José Fuentes Lagos",
        "service_name": "Corona cerámica",
        "professional_name": "Camila Rojas"
      }
    ],
    "total": 1,
    "page": 1,
    "limit": 50,
    "counts": {
      "to_send": 0,
      "sent": 1,
      "received": 0,
      "cancelled": 0
    }
  }
}

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

POST /clinic/lab-orders

Send work to a lab for a treatment

Created from a treatment-plan item. With work_type_id (a line of the lab's price list) the name and cost default from the list; work_type / cost_clp override them, and are required without it. status defaults to to_send; sent / received without a date are stamped with today in the clinic's calendar. A cancelled treatment or a deactivated lab answers 400.

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
treatment_plan_item_iduuidyes
clinic_lab_iduuidyes
work_type_idstring | null—
work_typestring | null—mín. 1, máx. 160
cost_clpinteger | null—≥ 0, ≤ 1000000000
statusto_send \sent \received \
sent_onstring | null—patrón ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
received_onstring | null—patrón ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
notesstring | null—máx. 1000
curl -X POST https://api.vitrinadev.com/api/v1/clinic/lab-orders \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "treatment_plan_item_id": "b7b7b7b7-0000-4000-8000-000000000011",
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "work_type_id": "c0e57121-0000-4000-8000-0000000002ab",
    "notes": "Color A2"
  }'

Example response (201)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000003ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "treatment_plan_item_id": "b7b7b7b7-0000-4000-8000-000000000011",
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "work_type_id": "c0e57121-0000-4000-8000-0000000002ab",
    "work_type": "Corona de zirconio",
    "cost_clp": 95000,
    "status": "to_send",
    "sent_on": null,
    "received_on": null,
    "notes": "Color A2",
    "created_by": "5e5e5e5e-0000-4000-8000-000000000001",
    "created_at": "2026-09-29T13:05:00.000Z",
    "updated_at": "2026-09-29T15:20:00.000Z",
    "lab_name": "Laboratorio Ejemplo",
    "treatment_plan_id": "b7b7b7b7-0000-4000-8000-000000000001",
    "treatment_plan_name": "Rehabilitación sector posterior",
    "clinic_patient_id": "b1b0b8de-0000-4000-8000-000000000001",
    "patient_name": "María José Fuentes Lagos",
    "service_name": "Corona cerámica",
    "professional_name": "Camila Rojas"
  }
}

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

GET /clinic/lab-orders/{id}

One lab order

The order with the same names the list carries.

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/lab-orders/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000003ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "treatment_plan_item_id": "b7b7b7b7-0000-4000-8000-000000000011",
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "work_type_id": "c0e57121-0000-4000-8000-0000000002ab",
    "work_type": "Corona de zirconio",
    "cost_clp": 95000,
    "status": "sent",
    "sent_on": "2026-09-29",
    "received_on": null,
    "notes": "Color A2",
    "created_by": "5e5e5e5e-0000-4000-8000-000000000001",
    "created_at": "2026-09-29T13:05:00.000Z",
    "updated_at": "2026-09-29T15:20:00.000Z",
    "lab_name": "Laboratorio Ejemplo",
    "treatment_plan_id": "b7b7b7b7-0000-4000-8000-000000000001",
    "treatment_plan_name": "Rehabilitación sector posterior",
    "clinic_patient_id": "b1b0b8de-0000-4000-8000-000000000001",
    "patient_name": "María José Fuentes Lagos",
    "service_name": "Corona cerámica",
    "professional_name": "Camila Rojas"
  }
}

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

PATCH /clinic/lab-orders/{id}

Move a lab order along, or correct it

status: "sent" / "received" stamps today when no date is given; "to_send" clears both dates; "cancelled" keeps them and stops the order counting toward the treatment's lab cost. Choosing another work_type_id re-defaults the name and cost unless the same request sends its own. A received date before the sent date answers 400.

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

Body

FieldTypeRequiredConstraints
clinic_lab_iduuid—
work_type_idstring | null—
work_typestring—mín. 1, máx. 160
cost_clpinteger—≥ 0, ≤ 1000000000
statusto_send \sent \received \
sent_onstring | null—patrón ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
received_onstring | null—patrón ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
notesstring | null—máx. 1000
curl -X PATCH https://api.vitrinadev.com/api/v1/clinic/lab-orders/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "sent"
  }'

Example response (200)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000003ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "treatment_plan_item_id": "b7b7b7b7-0000-4000-8000-000000000011",
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "work_type_id": "c0e57121-0000-4000-8000-0000000002ab",
    "work_type": "Corona de zirconio",
    "cost_clp": 95000,
    "status": "sent",
    "sent_on": "2026-09-29",
    "received_on": null,
    "notes": "Color A2",
    "created_by": "5e5e5e5e-0000-4000-8000-000000000001",
    "created_at": "2026-09-29T13:05:00.000Z",
    "updated_at": "2026-09-29T15:20:00.000Z",
    "lab_name": "Laboratorio Ejemplo",
    "treatment_plan_id": "b7b7b7b7-0000-4000-8000-000000000001",
    "treatment_plan_name": "Rehabilitación sector posterior",
    "clinic_patient_id": "b1b0b8de-0000-4000-8000-000000000001",
    "patient_name": "María José Fuentes Lagos",
    "service_name": "Corona cerámica",
    "professional_name": "Camila Rojas"
  }
}

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

GET /clinic/lab-work-types

List the labs' price lists

What each lab charges per kind of work («Corona de zirconio», $95.000). ?lab_id= narrows to one lab; ?active=true is what the order form offers. The cost here is the DEFAULT a new order copies.

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
lab_idqueryuuidno
activequerytrue \falseno
curl https://api.vitrinadev.com/api/v1/clinic/lab-work-types \
  -H "Authorization: Bearer $VITRINA_KEY"

Example response (200)

{
  "data": [
    {
      "id": "c0e57121-0000-4000-8000-0000000002ab",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
      "source": "native",
      "external_id": null,
      "name": "Corona de zirconio",
      "cost_clp": 95000,
      "active": true,
      "created_at": "2026-09-29T13:01:00.000Z",
      "updated_at": "2026-09-29T13:01:00.000Z"
    }
  ]
}

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

POST /clinic/lab-work-types

Add a line to a lab's price list

One name per lab, case-insensitive — a duplicate answers 409. Requires clinic_admin: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
clinic_lab_iduuidyes
namestringyesmín. 1, máx. 160
cost_clpintegeryes≥ 0, ≤ 1000000000
curl -X POST https://api.vitrinadev.com/api/v1/clinic/lab-work-types \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "name": "Corona de zirconio",
    "cost_clp": 95000
  }'

Example response (201)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000002ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "source": "native",
    "external_id": null,
    "name": "Corona de zirconio",
    "cost_clp": 95000,
    "active": true,
    "created_at": "2026-09-29T13:01:00.000Z",
    "updated_at": "2026-09-29T13:01:00.000Z"
  }
}

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

PATCH /clinic/lab-work-types/{id}

Re-price or retire a line of a lab's price list

Changing cost_clp affects orders created FROM NOW ON; an order already created keeps the cost it was created with.

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

Body

FieldTypeRequiredConstraints
namestring—mín. 1, máx. 160
cost_clpinteger—≥ 0, ≤ 1000000000
activeboolean—
curl -X PATCH https://api.vitrinadev.com/api/v1/clinic/lab-work-types/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cost_clp": 98000
  }'

Example response (200)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000002ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "clinic_lab_id": "c0e57121-0000-4000-8000-0000000001ab",
    "source": "native",
    "external_id": null,
    "name": "Corona de zirconio",
    "cost_clp": 98000,
    "active": true,
    "created_at": "2026-09-29T13:01:00.000Z",
    "updated_at": "2026-09-29T13:01:00.000Z"
  }
}

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

POST /clinic/labs

Add a laboratorio

A lab the clinic works with that did not arrive from the Dentalink import (source: "native"). contact is the lab's address and phone. Requires clinic_admin: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
namestringyesmín. 1, máx. 160
contactobject—
curl -X POST https://api.vitrinadev.com/api/v1/clinic/labs \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Laboratorio Ejemplo",
    "contact": {
      "direccion": "Avenida Ejemplo 456",
      "telefono": "+56 9 0000 0200"
    }
  }'

Example response (201)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000001ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "name": "Laboratorio Ejemplo",
    "contact": {
      "direccion": "Avenida Ejemplo 456",
      "telefono": "+56 9 0000 0200"
    },
    "active": true,
    "created_at": "2026-09-29T13:00:00.000Z",
    "updated_at": "2026-09-29T13:00:00.000Z"
  }
}

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

PATCH /clinic/labs/{id}

Edit or deactivate a laboratorio

Rename it, change its contact, or active: false to hide it from the order form. A lab is deactivated, never deleted: its orders keep naming it.

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

Body

FieldTypeRequiredConstraints
namestring—mín. 1, máx. 160
contactobject—
activeboolean—
curl -X PATCH https://api.vitrinadev.com/api/v1/clinic/labs/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "active": false
  }'

Example response (200)

{
  "data": {
    "id": "c0e57121-0000-4000-8000-0000000001ab",
    "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "name": "Laboratorio Ejemplo",
    "contact": {
      "direccion": "Avenida Ejemplo 456",
      "telefono": "+56 9 0000 0200"
    },
    "active": false,
    "created_at": "2026-09-29T13:00:00.000Z",
    "updated_at": "2026-09-29T13:00:00.000Z"
  }
}

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

On this page