---
title: "Catálogo"
description: "Los servicios, las ofertas, los recursos, las sedes y las reglas de horario de Agenda, qué es cada uno y cómo leerlos y cambiarlos a través de la API."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.getarbol.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Catálogo

El catálogo de Agenda es cómo está configurada la clínica: los servicios que ofrece, las ofertas que hacen que cada uno se pueda agendar, los recursos que los prestan, las sedes donde están y el horario en que trabaja cada recurso. La disponibilidad se calcula a partir de él, así que un cambio aquí cambia los horarios que los pacientes pueden agendar.

## Quién puede leerlo y cambiarlo

Leer el catálogo está abierto a personas y máquinas que tengan el permiso (scope) `:read` de lo que listan, como `agenda:services:read`; una lista no acepta ningún otro scope. Cambiarlo acepta solo personas: un miembro con sesión iniciada cuyos roles le otorgan el scope `:write`, como `agenda:services:write`, normalmente a través de una herramienta del personal. Las API keys y los tokens de máquina no pueden cambiar el catálogo.

| Operación | Solicitud | Quién llama | Efecto |
| --- | --- | --- | --- |
| [`agenda.services.list`](/api/agenda/services/list/) | `GET /v1/agenda/services` | Personas y máquinas | Lee |
| [`agenda.services.create`](/api/agenda/services/create/) | `POST /v1/agenda/services` | Solo personas | Escribe; no idempotente |
| [`agenda.services.update`](/api/agenda/services/update/) | `PATCH /v1/agenda/services/{serviceId}` | Solo personas | Escribe; idempotente |
| [`agenda.offerings.list`](/api/agenda/offerings/list/) | `GET /v1/agenda/offerings` | Personas y máquinas | Lee |
| [`agenda.offerings.create`](/api/agenda/offerings/create/) | `POST /v1/agenda/offerings` | Solo personas | Escribe; no idempotente |
| [`agenda.offerings.update`](/api/agenda/offerings/update/) | `PATCH /v1/agenda/offerings/{offeringId}` | Solo personas | Escribe; idempotente |
| [`agenda.resources.list`](/api/agenda/resources/list/) | `GET /v1/agenda/resources` | Personas y máquinas | Lee |
| [`agenda.resources.create`](/api/agenda/resources/create/) | `POST /v1/agenda/resources` | Solo personas | Escribe; no idempotente |
| [`agenda.resources.update`](/api/agenda/resources/update/) | `PATCH /v1/agenda/resources/{resourceId}` | Solo personas | Escribe; idempotente |
| [`agenda.scheduleRules.list`](/api/agenda/schedule-rules/list/) | `GET /v1/agenda/schedule-rules` | Personas y máquinas | Lee |
| [`agenda.scheduleRules.create`](/api/agenda/schedule-rules/create/) | `POST /v1/agenda/schedule-rules` | Solo personas | Escribe; no idempotente |
| [`agenda.scheduleRules.update`](/api/agenda/schedule-rules/update/) | `PATCH /v1/agenda/schedule-rules/{scheduleRuleId}` | Solo personas | Escribe; no idempotente |
| [`agenda.resourceSchedules.update`](/api/agenda/resource-schedules/update/) | `PATCH /v1/agenda/resource-schedules/{resourceId}` | Solo personas | Escribe; idempotente |
| [`agenda.locations.list`](/api/agenda/locations/list/) | `GET /v1/agenda/locations` | Personas y máquinas | Lee |

Las listas de servicios, ofertas, recursos y sedes responden una página a la vez, 25 elementos por defecto y hasta 100: consulta [Paginación](/developers/concepts/pagination/). Crear no es idempotente, así que después de una creación cuyo resultado se desconoce, lista antes de volver a crear. No hay ninguna operación para eliminar: pon el `status` de un registro en `inactive` para dejar de usarlo. Las operaciones de agendamiento solo ofrecen ofertas activas.

## Servicios

Un servicio es lo que pide un paciente, con el nombre que le da la clínica, como una consulta de neurología. [`agenda.services.list`](/api/agenda/services/list/) filtra por `status`.

| Campo | Significado |
| --- | --- |
| `name` | Obligatorio. |
| `defaultDurationMinutes` | Obligatorio, de 1 a 1440. La duración por defecto de sus citas; cada oferta puede fijar la suya. |
| `status` | `active` (el valor por defecto) o `inactive`. |

## Ofertas

Una oferta vincula un servicio a una agenda, con lo que se necesita para agendarlo. [`agenda.offerings.list`](/api/agenda/offerings/list/) filtra por `serviceId` y `status`.

| Campo | Por defecto | Significado |
| --- | --- | --- |
| `serviceId`, `name` | Obligatorios | El servicio que ofrece, y el nombre de la oferta. |
| `durationMinutes` | Obligatorio | La duración de la cita visible, de 1 a 1440 minutos. |
| `slotIntervalMinutes` | `15` | Minutos entre las posibles horas de inicio, de 5 a 240. |
| `bufferBeforeMinutes`, `bufferAfterMinutes` | `0` | Minutos que los recursos quedan ocupados antes y después de la cita visible. |
| `minNoticeMinutes` | `0` | La antelación mínima que necesita un agendamiento. |
| `bookingHorizonDays` | `90` | Con cuántos días de anticipación se puede agendar, hasta 730. |
| `resourceRequirements` | `[]` | Hasta 30 requisitos: los recursos que necesita cada agendamiento. |
| `status` | `active` | `active` o `inactive`. |

Cada requisito nombra un `kind` de recurso y una `quantity`, 1 por defecto. `alternatives` lista los recursos que pueden cumplirlo; cuando está vacío, puede cumplirlo cualquier recurso de ese tipo. `required`, true por defecto, dice si el requisito debe cumplirse para que el agendamiento siga adelante. En una actualización, `resourceRequirements` reemplaza toda la lista para los agendamientos futuros; las citas existentes conservan sus recursos.

Un cuerpo de ejemplo para [`agenda.offerings.create`](/api/agenda/offerings/create/), una consulta de 30 minutos con un profesional determinado y cualquier sala:

```json
{
  "serviceId": "svc_00000000-0000-4000-8000-000000000001",
  "name": "Consulta de neurología, Dr. Example",
  "durationMinutes": 30,
  "slotIntervalMinutes": 30,
  "minNoticeMinutes": 120,
  "resourceRequirements": [
    { "kind": "practitioner", "alternatives": ["srs_00000000-0000-4000-8000-000000000003"] },
    { "kind": "room" }
  ]
}
```

## Recursos

Un recurso es cualquier cosa con su propio calendario que usa un agendamiento. [`agenda.resources.list`](/api/agenda/resources/list/) filtra por `kind` y `status`.

| Campo | Significado |
| --- | --- |
| `kind` | Obligatorio: `practitioner`, `assistant`, `room`, `chair`, `equipment`, `location`, `team` o `generic`. Los requisitos de las ofertas se comparan con él. |
| `name` | Obligatorio. |
| `timezone` | Obligatorio. La zona horaria IANA de su horario de trabajo, de las fechas de sus citas y de las reglas de edad. |
| `locationId` | La sede a la que pertenece. `null`, el valor por defecto, no lo vincula a ninguna sede, así que cubre todas las sedes. |
| `capacity` | Cuántas unidades puede atender a la vez, 1 por defecto; cada agendamiento usa su parte. |
| `status` | `active` (el valor por defecto) o `inactive`. |

## Sedes

Las sedes (locations) de la clínica tienen cada una su `name`, `address`, `city`, `timezone` y `status`. La API las lee con [`agenda.locations.list`](/api/agenda/locations/list/) (`agenda:locations:read`), o con [`agenda.bookingLocations.list`](/api/agenda/booking-locations/list/) cuando agendas (`agenda:bookings:read`). No tiene ninguna operación que cree o cambie una sede.

## Reglas de horario

Las reglas de horario dicen cuándo trabaja un recurso. Cada regla es una franja de hora local, de `from` a `to` en formato `HH:MM`, leída en la zona horaria del recurso:

| Campo | Significado |
| --- | --- |
| `kind` | `weekly`, `date_override`, `time_off` o `block`. |
| `weekdays` | En una franja semanal, los días en que aplica, del domingo `0` al sábado `6`. |
| `effectiveFrom`, `effectiveTo` | En una franja semanal, la primera y la última fecha en que aplica; `null` sin límite. |
| `date` | En una franja o un cierre con fecha, su fecha local; `null` en una franja semanal. |

- [`agenda.scheduleRules.list`](/api/agenda/schedule-rules/list/) filtra por `resourceId` y responde con la lista completa, sin páginas. Cada regla tiene su `id`, su `resourceId` y su `version`.
- [`agenda.scheduleRules.create`](/api/agenda/schedule-rules/create/) añade una regla con `resourceId`, `kind`, `timezone`, `from` y `to`.
- [`agenda.scheduleRules.update`](/api/agenda/schedule-rules/update/) cambia la regla identificada por `scheduleRuleId`; envía su `expectedVersion`. Sin ella se rechaza con `SCHEDULE_RULE_EXPECTED_VERSION_REQUIRED`.
- [`agenda.resourceSchedules.update`](/api/agenda/resource-schedules/update/) reemplaza de una vez todo el horario del recurso: `rules` es el conjunto nuevo, de hasta 400 reglas, y `expectedRules` contiene el `id` y la `version` de cada regla que cargaste. Si el horario cambió desde entonces, el reemplazo se rechaza y nada cambia.

Un cuerpo de ejemplo para `agenda.resourceSchedules.update`: de lunes a viernes, de 07:00 a 12:00 y de 14:00 a 17:00, reemplazando una regla cargada en la versión 3:

```json
{
  "expectedRules": [{ "id": "sch_00000000-0000-4000-8000-000000000006", "version": 3 }],
  "rules": [
    { "kind": "weekly", "weekdays": [1, 2, 3, 4, 5], "from": "07:00", "to": "12:00" },
    { "kind": "weekly", "weekdays": [1, 2, 3, 4, 5], "from": "14:00", "to": "17:00" }
  ]
}
```

## Versiones

Cada registro del catálogo tiene una `version`. Una actualización requiere como `expectedVersion` la versión que leíste, y se rechaza con `409` cuando alguien cambió el registro desde entonces:

| Registro | `error.code` |
| --- | --- |
| Servicio | `SERVICE_VERSION_MISMATCH` |
| Oferta | `OFFERING_VERSION_MISMATCH` |
| Recurso | `RESOURCE_VERSION_MISMATCH` |
| Regla de horario | `SCHEDULE_RULE_VERSION_MISMATCH` |
| El horario de un recurso, al reemplazarlo | `SCHEDULE_RULES_CHANGED` |

Vuelve a leer el registro, aplica tu cambio sobre lo que leíste y envíalo con la nueva versión. Consulta [Manejar errores y reintentos](/developers/guides/handle-errors-and-retries/#un-conflicto-de-versión-al-actualizar).

Source: https://docs.getarbol.com/developers/agenda/catalog/index.mdx
