# Itineraries

> The block tree, block types, refs, and days that come from a trip's design.

## The tree

A trip's itinerary is a tree of **blocks**. Read it with `GET /v1/trips/{tripId}/itinerary`; change it with `POST /v1/trips/{tripId}/itinerary/ops`, a list of ops applied together or not at all.

Block types are Spanish machine keys — keep them as they are:

| Type | What it is |
|---|---|
| `capitulo` | A section at the root; holds content. |
| `agenda` | The organizer that holds the days. |
| `dia` | A day. |
| `actividad` | A stop or activity in a day. |
| `alojamiento` | A stay. |
| `vuelo`, `transporte`, `tren`, `crucero` | Flights and transfers. |
| `comida` | A meal. |
| `texto` | A note. |

Each type's `data` fields, as the [apply ops](https://api.bymundi.com/docs/reference/itinerary.applyOps.md) operation accepts them:

`data` fields by block type — use exactly these names; an unknown field is refused. Rich-text fields accept plain text.
`catalogRef` takes only an id a tool returned (search_catalog, search_places, suggest_routes), as {"kind":"punto","id":"…"}.
- titulo: text:string
- texto: markdown:rich text
- imagen: assetId:string, url:string, alt:string, caption:string, width:number, height:number
- agenda: title:string, mode:one of(tabs|accordion|timeline), showDates:boolean, showTitleInTabs:boolean, showMap:boolean
- dia: date:string(YYYY-MM-DD), title:string, location:string, description:rich text | set by bymundi, leave out: locationPlace, window
- caja: title:string, body:rich text, color:string
- desplegable: title:string, open:boolean
- seccion: key:one of(transportes|alojamiento|actividades|comidas), title:string, description:rich text
- capitulo: key:one of(bienvenida|hoteles|vuelos|info-practica|contactos|custom), title:string, icon:string
- derivado: kind:one of(hoteles|vuelos)
- actividad: title:string, time:string(HH:MM), durationMin:number, location:string, meetingPoint:string, description:rich text, tips:rich text, warnings:rich text, arrival:rich text, paidEntry:boolean, priceNote:string, bookingUrl:string, catalogCategory:string, hideTips:boolean, confirmationCode:string, optional:boolean, hideSchedule:boolean | set by bymundi, leave out: locationPlace, hours, image
- alojamiento: hotel:string, roomType:string, board:one of(room_only|breakfast|half_board|full_board|all_inclusive), checkIn:string(YYYY-MM-DD), checkOut:string(YYYY-MM-DD), address:string, nights:number, notes:rich text, catalogCategory:string, confirmationCode:string, optional:boolean, hideSchedule:boolean | set by bymundi, leave out: place, image
- vuelo: title:string, from:string, to:string, departAt:string(YYYY-MM-DDTHH:MM), arriveAt:string(YYYY-MM-DDTHH:MM), stopovers:list[place:string, arriveAt:string(YYYY-MM-DDTHH:MM), departAt:string(YYYY-MM-DDTHH:MM)], flight[flightNo:string, airline:string, fromAirport:string, toAirport:string], confirmationCode:string, optional:boolean, hideSchedule:boolean | set by bymundi, leave out: fromPlace, toPlace, image
- transporte: title:string, from:string, to:string, mode:string, travelMode:one of(|walking|transit|driving|bicycling), durationMin:number, provider:string, serviceNo:string, seat:string, departAt:string(YYYY-MM-DDTHH:MM), arriveAt:string(YYYY-MM-DDTHH:MM), stopovers:list[place:string, arriveAt:string(YYYY-MM-DDTHH:MM), departAt:string(YYYY-MM-DDTHH:MM)], description:rich text, catalogCategory:string, confirmationCode:string, optional:boolean, hideSchedule:boolean | set by bymundi, leave out: fromPlace, toPlace, image
- informacion: variant:one of(info|tip|warning|important), title:string, body:rich text
- galeria: columns:one of(2|3|4) | set by bymundi, leave out: items
- video: url:string, caption:string
- mapa: query:string, zoom:number, caption:string | set by bymundi, leave out: place

## Ops

Four ops: `add`, `update`, `move`, `delete`. `add` and `move` place a block with `parentId` and `position` (`start`, `end`, `after`, `before`) plus `anchorId` for `after`/`before`. `update` needs the block's current `version`: if someone changed it since you read it, the op is refused rather than overwrite them. Give each `add` a `clientId` to find its new id in the answer's `created`.

Unknown fields are refused, not ignored, so a typo cannot silently misplace a block.

## Days from a design

A trip can have a **design**: its route, as stops with nights and the transfers between them (`hasDesignedRoute: true`). On such a trip the days **come from the design**: adding or deleting `dia` blocks is refused. Change the design with `PATCH /v1/trips/{tripId}`, then call `POST /v1/trips/{tripId}/itinerary/sync` to rebuild the days.

## Refs (MCP)

Over MCP, `get_itinerary` gives every block a short `ref`, and tools accept refs or full ids, so a model never has to copy long ids. An ambiguous ref answers [`ambiguous_ref`](https://api.bymundi.com/problems/ambiguous_ref.md).

## Operations

- [Get a trip's itinerary](https://api.bymundi.com/docs/reference/itinerary.get.md) — `GET /v1/trips/{tripId}/itinerary`
- [Get one block](https://api.bymundi.com/docs/reference/itinerary.getBlock.md) — `GET /v1/trips/{tripId}/itinerary/blocks/{blockId}`
- [Change the itinerary](https://api.bymundi.com/docs/reference/itinerary.applyOps.md) — `POST /v1/trips/{tripId}/itinerary/ops`
- [Sync the itinerary with the design](https://api.bymundi.com/docs/reference/itinerary.sync.md) — `POST /v1/trips/{tripId}/itinerary/sync`
