> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.crehana.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.crehana.com/_mcp/server.

## Sesiones en vivo: listar, crear, invitar y marcar asistencia

Nueva sección **Live Sessions** con los cuatro endpoints del ciclo completo de
una sesión en vivo, para que una integración haga por API lo que hoy solo se
puede hacer desde el panel de administración.

```
GET  /org/{slug}/learning/live-sessions/
POST /org/{slug}/learning/live-sessions/
POST /org/{slug}/learning/live-sessions/{live_session_id}/participants/
POST /org/{slug}/learning/live-sessions/{live_session_id}/attendance/
```

### Listar las sesiones

`GET .../live-sessions/` devuelve las sesiones de la organización, de la más
reciente a la más antigua. `status` elige el tramo: `NEXT` (por defecto) las que
todavía no terminaron y `PAST` las que ya terminaron — para recorrer todo el
calendario hay que pedir los dos. La paginación es por página: `first` (de 1 a
100, por defecto 10) y `page` (desde 1). `ids` acota el listado a las sesiones
que le pases.

Los contadores miran todo el calendario, no la página: `total` son todas las
sesiones de la organización, y `next_sessions_count` y `past_sessions_count`
dicen cuántas hay en cada tramo. `results` trae solo la página pedida del
`status` pedido.

```json
{
  "total": 3,
  "next_sessions_count": 2,
  "past_sessions_count": 1,
  "results": [
    {
      "id": "1258",
      "session_title": "Onboarding comercial",
      "instructor_name": "Katherine N.",
      "type_session": "ONLINE",
      "location": "https://meet.google.com/abc-defg-hij",
      "time_zone": "TIME_ZONE_ES_PE",
      "start_date": "2026-10-01T10:00:00",
      "end_date": "2026-10-01T11:00:00",
      "start_date_utc": "2026-10-01T15:00:00+00:00",
      "end_date_utc": "2026-10-01T16:00:00+00:00",
      "timeline": "FUTURE",
      "total_guests": 2,
      "has_qr_available": true,
      "issues_certificate": false
    }
  ]
}
```

Cada sesión trae las fechas dos veces: `start_date` y `end_date` son la hora de
reloj en la zona horaria de la sesión (`time_zone`) y van sin marca de zona, y
`start_date_utc` / `end_date_utc` son el mismo instante en UTC. Usá el par UTC
para ordenar o comparar sesiones de zonas distintas.

En la respuesta del `POST` de creación el par UTC viene en `null`: el servicio
devuelve ahí la misma hora de reloj que le mandaste, sin convertir. Leé la
sesión con el `GET` para obtener los instantes en UTC.

### Crear una sesión

`POST .../live-sessions/` crea la sesión y responde `201` con la sesión creada.
Obligatorios: `session_title`, `description`, `start_date`, `end_date`,
`time_zone` y `type_session` (`ONLINE` o `PRESENCE`). Opcionales:
`instructor_name`, `location` (el link de la reunión si es `ONLINE`, la
dirección si es `PRESENCE`), `cover_file_id`, `resource_file_ids`,
`participant_user_ids`, `has_qr_available` e `issues_certificate`.

Las fechas son hora de reloj en `time_zone` y van **sin** offset
(`2026-10-01T10:00:00`). Mandar un offset responde `422`: el offset se
descartaría y la sesión quedaría a otra hora que la pedida. `end_date` tiene que
ser posterior a `start_date`.

Si la organización ya tiene una sesión con ese título, el título se guarda con
un sufijo numérico — por eso conviene leer el `session_title` de la respuesta en
vez de asumir el que mandaste.

### Invitar participantes

`POST .../live-sessions/{id}/participants/` invita usuarios a la sesión. Los
`user_ids` son los ids de usuario de learning, los que devuelve
`GET /org/{slug}/learning/users/` en `user.id`. Con `send_notification: true` se
manda el correo de invitación, si la organización tiene esa notificación
activa.

La asignación se procesa en segundo plano: la respuesta es `202` y confirma qué
se aceptó, no qué ya está aplicado. Los usuarios que no pertenecen a la
organización vuelven en `invalid_user_ids` y no se asignan; si ninguno de los
pedidos pertenece, la respuesta es `422`.

```json
{
  "message": "Assignment of 2 users in live session 1258 queued",
  "code": "LIVE_SESSION_PARTICIPANTS_QUEUED",
  "datetime": "2026-09-16T10:30:00.000Z",
  "data": {
    "live_session_id": 1258,
    "engagement_id": "907",
    "state": "SUBMITTED",
    "total_users_requested": 3,
    "total_users_accepted": 2,
    "total_users_skipped": 1,
    "invalid_user_ids": [605999],
    "errors": []
  }
}
```

### Marcar asistencia

`POST .../live-sessions/{id}/attendance/` registra la asistencia. Mandá
`user_ids` con los usuarios a marcar, o `all_participants: true` para marcar a
todos los participantes de la sesión — uno u otro, no los dos: mandar ambos
responde `422`, igual que no mandar ninguno.

También se procesa en segundo plano (`202`). `errors` explica cada usuario que
quedó afuera: ya estaba registrado, no se encontró en la organización, o está
inactivo. Si no se pudo registrar a nadie, la respuesta es `422` con esos
mismos motivos.

### Una sola organización

Los cuatro endpoints trabajan sobre la organización de la api-key: pedir el
`slug` de otra organización responde `403`, no datos. Un `401` significa que
las credenciales no llegaron o no son válidas, y un `400` que el pedido tiene
un problema de validación — así el motivo del rechazo se distingue sin leer el
detalle.

## Listar las politicas de tiempo libre de la organizacion

`GET /org/{slug}/timeoff/policies/` devuelve el catálogo de políticas de
ausencia configuradas por la organización: vacaciones, licencias y permisos.
Es la configuración de cada política, no las solicitudes ni los datos de los
colaboradores — para eso sigue estando
`GET /org/{slug}/timeoff/requests/`.

Cada política trae `id`, `name`, `description`, `policy_type` (la categoría,
con su `id` y su `name`), `is_paid`, `is_unlimited`, `quantification` (`DAYS`
u `HOURS`), `needs_approvals` y `status` (`enabled` o `disabled`).

```json
{
  "total": 335,
  "results": [
    {
      "id": "1107",
      "name": "Vacaciones México",
      "description": "15 días por año",
      "policy_type": { "id": 15, "name": "Vacaciones" },
      "is_paid": true,
      "is_unlimited": true,
      "quantification": "DAYS",
      "needs_approvals": false,
      "status": "enabled"
    }
  ]
}
```

El `id` de cada política es el mismo que devuelve `policy_id` en el listado de
solicitudes, así que podés cruzar ambos recursos sin repetir la configuración
en cada fila.

La paginación es la misma del resto de la sección: `limit` (de 1 a 50) y
`offset`. Filtros opcionales: `search` (por nombre, sin distinguir
mayúsculas), `name` (nombre exacto), `policy_type_ids` (repetible) e `is_paid`.
Un `order_by` desconocido responde `422`.

Sólo se listan políticas de la organización de la api-key: pedir el `slug` de
otra organización responde `403`, no datos.