VitrinaAPI

Prestaciones de la clínica

Qué hace la clínica: duración, precio de lista, requisitos de consentimiento y quién puede ejecutar cada prestación.

Beta
Puede cambiar en cualquier momento, con una entrada en el changelog y aviso a quienes la llamaron recientemente — ver versionado.

Descarga la proyección completa de la API pública: openapi.json.

Definir prestaciones y precios explica este recurso en prosa, con ejemplos ejecutables.

MétodoRutaQué hace
GET/clinic/service-categoriesList the clinic's service categories
POST/clinic/service-categoriesCreate a service category (find-or-create, native only)
DELETE/clinic/service-categories/{id}Delete a service category
PATCH/clinic/service-categories/{id}Enable/disable a service category
GET/clinic/servicesList the clinic's services
POST/clinic/servicesCreate a native service
DELETE/clinic/services/{id}Delete a native service
PATCH/clinic/services/{id}Edit a native service (or activar/desactivar)
GET/clinic/services/{id}/professionalsWho may perform a prestación
PUT/clinic/services/{id}/professionalsSet who may perform a prestación

GET /clinic/service-categories

List the clinic's service categories

List the clinic's service categories

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.

ParámetroEnTipoObligatorioRestricciones
enabledquerytrue \falseno
curl https://api.vitrinadev.com/api/v1/clinic/service-categories \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": [
    {
      "id": "795cf9e4-0000-4000-8000-000000000001",
      "source": "native",
      "nombre": "Ortodoncia",
      "enabled": true,
      "created_at": "2026-09-22T22:21:14.461Z",
      "updated_at": "2026-09-22T22:21:14.461Z"
    }
  ]
}

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

POST /clinic/service-categories

Create a service category (find-or-create, native only)

Create a service category (find-or-create, native only)

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.

Cuerpo

CampoTipoObligatorioRestricciones
nombrestringmín. 1, máx. 120
curl -X POST https://api.vitrinadev.com/api/v1/clinic/service-categories \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Ortodoncia"
  }'

Ejemplo de respuesta (201)

{
  "data": {
    "id": "795cf9e4-0000-4000-8000-000000000001",
    "source": "native",
    "nombre": "Ortodoncia",
    "enabled": true,
    "created_at": "2026-09-22T22:21:14.461Z",
    "updated_at": "2026-09-22T22:21:14.461Z"
  }
}

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

DELETE /clinic/service-categories/{id}

Delete a service category

Delete a service category

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.

ParámetroEnTipoObligatorioRestricciones
idpathuuid
curl -X DELETE https://api.vitrinadev.com/api/v1/clinic/service-categories/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Responde: 204 · 400 · 401 · 403 · 404 · 409 · 429

PATCH /clinic/service-categories/{id}

Enable/disable a service category

Enable/disable a service category

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.

ParámetroEnTipoObligatorioRestricciones
idpathuuid

Cuerpo

CampoTipoObligatorioRestricciones
enabledboolean
curl -X PATCH https://api.vitrinadev.com/api/v1/clinic/service-categories/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "id": "795cf9e4-0000-4000-8000-000000000001",
    "source": "native",
    "nombre": "Ortodoncia",
    "enabled": true,
    "created_at": "2026-09-22T22:21:14.461Z",
    "updated_at": "2026-09-22T22:21:14.476Z"
  }
}

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

GET /clinic/services

List the clinic's services

The clinic's price list. search (min 2 chars) matches nombre, código or categoría accent-insensitively. active is OPTIONAL and omitting it returns every row. precio is the vendor LIST price before previsión/convenio — it is deliberately never shown to the AI agent. is_entry filters entry prestaciones, tri-state: true = entry (evaluación / diagnóstico), false = CONFIRMED treatment rows only, unclassified = nobody has said yet (is_entry IS NULL); omitted = every row.

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.

ParámetroEnTipoObligatorioRestricciones
searchquerystringnomín. 2, máx. 120
activequerytrue \falseno
review_statequerypending \stale \draft \
is_entryquerytrue \false \unclassified
sortquerynombre \codigo \categoria \
dirqueryasc \descno
pagequeryintegerno≥ 1, por defecto 1
limitqueryintegerno≥ 1, ≤ 200, por defecto 50
curl https://api.vitrinadev.com/api/v1/clinic/services \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "data": [
      {
        "id": "4cf5bc59-0000-4000-8000-000000000001",
        "source": "native",
        "external_id": null,
        "nombre": "Control de ortodoncia",
        "codigo": "ORT-CTRL",
        "categoria": "Ortodoncia",
        "tipo": null,
        "precio": 25000,
        "arancel": null,
        "duration_minutes": 30,
        "vendor_duration_minutes": null,
        "review_state": "draft",
        "reviewed_at": null,
        "reviewed_by": null,
        "is_telehealth": false,
        "online_bookable": true,
        "requires_consent_template_id": null,
        "eligibility_min_age_years": null,
        "eligibility_max_age_years": null,
        "eligibility_sexo": null,
        "eligibility_previsiones": null,
        "active": true,
        "synced_at": null
      },
      {
        "id": "4cf5bc59-0000-4000-8000-000000000002",
        "source": "native",
        "external_id": null,
        "nombre": "Limpieza dental",
        "codigo": null,
        "categoria": "Ortodoncia",
        "tipo": null,
        "precio": 35000,
        "arancel": null,
        "duration_minutes": 45,
        "vendor_duration_minutes": null,
        "review_state": "draft",
        "reviewed_at": null,
        "reviewed_by": null,
        "is_telehealth": false,
        "online_bookable": false,
        "requires_consent_template_id": null,
        "eligibility_min_age_years": null,
        "eligibility_max_age_years": null,
        "eligibility_sexo": null,
        "eligibility_previsiones": null,
        "active": true,
        "synced_at": null
      }
    ],
    "total": 2,
    "page": 1,
    "limit": 50
  }
}

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

POST /clinic/services

Create a native service

Create a native service

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.

Cuerpo

CampoTipoObligatorioRestricciones
nombrestringmín. 1, máx. 200
codigostring | nullmáx. 60
categoriastring | nullmáx. 120
tipostring | nullmáx. 120
preciointeger | null≥ 0, ≤ 1000000000
duration_minutesinteger | null≥ 1, ≤ 1440
activeboolean
is_telehealthboolean
online_bookableboolean
is_entryboolean | null
requires_consent_template_idstring | null
eligibility_min_age_yearsinteger | null≥ 0, ≤ 120
eligibility_max_age_yearsinteger | null≥ 0, ≤ 120
eligibility_sexoF \M \otro
eligibility_previsionesarray | null
curl -X POST https://api.vitrinadev.com/api/v1/clinic/services \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Control de ortodoncia",
    "codigo": "ORT-CTRL",
    "categoria": "Ortodoncia",
    "precio": 25000,
    "duration_minutes": 30,
    "online_bookable": true
  }'

Ejemplo de respuesta (201)

{
  "data": {
    "id": "4cf5bc59-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "nombre": "Control de ortodoncia",
    "codigo": "ORT-CTRL",
    "categoria": "Ortodoncia",
    "tipo": null,
    "precio": 25000,
    "arancel": null,
    "duration_minutes": 30,
    "vendor_duration_minutes": null,
    "review_state": "draft",
    "reviewed_at": null,
    "reviewed_by": null,
    "is_telehealth": false,
    "online_bookable": true,
    "requires_consent_template_id": null,
    "eligibility_min_age_years": null,
    "eligibility_max_age_years": null,
    "eligibility_sexo": null,
    "eligibility_previsiones": null,
    "active": true,
    "synced_at": null
  }
}

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

DELETE /clinic/services/{id}

Delete a native service

Delete a native service

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.

ParámetroEnTipoObligatorioRestricciones
idpathuuid
curl -X DELETE https://api.vitrinadev.com/api/v1/clinic/services/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Responde: 204 · 400 · 401 · 403 · 404 · 409 · 429

PATCH /clinic/services/{id}

Edit a native service (or activar/desactivar)

Edit a native service (or activar/desactivar)

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.

ParámetroEnTipoObligatorioRestricciones
idpathuuid

Cuerpo

CampoTipoObligatorioRestricciones
nombrestringmín. 1, máx. 200
codigostring | nullmáx. 60
categoriastring | nullmáx. 120
tipostring | nullmáx. 120
preciointeger | null≥ 0, ≤ 1000000000
duration_minutesinteger | null≥ 1, ≤ 1440
activeboolean
is_telehealthboolean
online_bookableboolean
is_entryboolean | null
requires_consent_template_idstring | null
eligibility_min_age_yearsinteger | null≥ 0, ≤ 120
eligibility_max_age_yearsinteger | null≥ 0, ≤ 120
eligibility_sexoF \M \otro
eligibility_previsionesarray | null
curl -X PATCH https://api.vitrinadev.com/api/v1/clinic/services/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "precio": 28000
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "id": "4cf5bc59-0000-4000-8000-000000000001",
    "source": "native",
    "external_id": null,
    "nombre": "Control de ortodoncia",
    "codigo": "ORT-CTRL",
    "categoria": "Ortodoncia",
    "tipo": null,
    "precio": 28000,
    "arancel": null,
    "duration_minutes": 30,
    "vendor_duration_minutes": null,
    "review_state": "draft",
    "reviewed_at": null,
    "reviewed_by": null,
    "is_telehealth": false,
    "online_bookable": true,
    "requires_consent_template_id": null,
    "eligibility_min_age_years": null,
    "eligibility_max_age_years": null,
    "eligibility_sexo": null,
    "eligibility_previsiones": null,
    "active": true,
    "synced_at": null
  }
}

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

GET /clinic/services/{id}/professionals

Who may perform a prestación

The eligibility set, with each professional’s optional duration and price override. NO ROWS means "anyone may" — never "nobody may".

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

Ejemplo de respuesta (200)

{
  "data": [
    {
      "id": "18342d1b-0000-4000-8000-000000000002",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "clinic_service_id": "4cf5bc59-0000-4000-8000-000000000001",
      "professional_id": "18342d1b-0000-4000-8000-000000000001",
      "duration_minutes": 30,
      "precio_clp": 28000,
      "active": true,
      "created_at": "2026-09-22T22:21:14.591Z",
      "updated_at": "2026-09-22T22:21:14.591Z",
      "professional_nombre": "Ana"
    }
  ]
}

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

PUT /clinic/services/{id}/professionals

Set who may perform a prestación

Replaces the WHOLE set in one transaction. An empty array clears it, which means "anyone may". 409 duplicate_professional when the body names the same professional twice.

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.

Cuerpo

CampoTipoObligatorioRestricciones
professionalsobject[]
curl -X PUT https://api.vitrinadev.com/api/v1/clinic/services/<id>/professionals \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "professionals": [
      {
        "professional_id": "18342d1b-0000-4000-8000-000000000001",
        "duration_minutes": 30,
        "precio_clp": 28000
      }
    ]
  }'

Ejemplo de respuesta (200)

{
  "data": [
    {
      "id": "18342d1b-0000-4000-8000-000000000002",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "clinic_service_id": "4cf5bc59-0000-4000-8000-000000000001",
      "professional_id": "18342d1b-0000-4000-8000-000000000001",
      "duration_minutes": 30,
      "precio_clp": 28000,
      "active": true,
      "created_at": "2026-09-22T22:21:14.591Z",
      "updated_at": "2026-09-22T22:21:14.591Z",
      "professional_nombre": "Ana"
    }
  ]
}

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

En esta página