Update a trip template
PATCH/v1/trip-templates/{templateId}
Edits a template's title, description or tags, and/or REPLACES its content with a trip's (fromTripId: the same capture as saving; needs trips:read) — the API's Save changes. A refresh is refused with 409 being_edited while the template is open in the builder. Pass the updatedAt you read as expectedUpdatedAt to refuse a stale write with a 409. Undo with POST /changes/{changeId}/revert.
Permissions: catalog:write · Kind: write · Cost: 2 units · MCP tool update_trip_template
Undoable: the response carries Bymundi-Change-Id; revert it with POST /v1/changes/{changeId}/revert.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
templateId |
uuid | yes |
Body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | max 200 chars | |
description |
string | max 2000 chars | |
tags |
string[] | Replaces the tags; lowercased. max 20 items | |
fromTripId |
uuid | Replace the template's content with this trip's (design, blocks, proposals, pax, presentation, start date). | |
expectedUpdatedAt |
datetime |
Response 200
| Field | Type | Required | Description |
|---|---|---|---|
object |
"trip_template" | yes | |
id |
uuid | yes | |
title |
string | yes | |
description |
string | yes | |
tags |
string[] | yes | |
coverUrl |
string | null | yes | |
stopCount |
integer | yes | |
updatedAt |
string | yes | |
design |
object | yes | |
design.version |
1 | yes | |
design.originCity |
string | yes | |
design.stops |
object[] | yes | max 60 items |
design.stops[].id |
string | yes | |
design.stops[].city |
string | yes | |
design.stops[].nights |
integer | yes | 0–365 |
design.stops[].transferBefore |
object | null | yes | |
design.stops[].escala |
boolean | default false | |
design.stops[].place |
object | default {"placeId":"","lat":null,"lng":null,"formattedAddress":""} | |
design.returnCity |
string | null | yes | |
design.returnTransfer |
object | null | yes | |
design.returnTransfer.id |
string | yes | |
design.returnTransfer.departDate |
string | null | yes | |
design.returnTransfer.arriveDate |
string | null | yes | |
design.returnTransfer.days |
integer | 0–30, default 0 | |
design.returnTransfer.departTime |
string | default "" | |
design.returnTransfer.arriveTime |
string | default "" | |
design.returnTransfer.flight |
object | default {"flightNo":"","airline":"","fromAirport":"","toAirport":"","source":"","fetchedAt":"","scheduleValidFor":""} | |
design.originPlace |
object | default {"placeId":"","lat":null,"lng":null,"formattedAddress":""} | |
design.originPlace.placeId |
string | default "" | |
design.originPlace.lat |
number | null | default null | |
design.originPlace.lng |
number | null | default null | |
design.originPlace.formattedAddress |
string | default "" | |
design.returnPlace |
object | default {"placeId":"","lat":null,"lng":null,"formattedAddress":""} | |
design.returnPlace.placeId |
string | default "" | |
design.returnPlace.lat |
number | null | default null | |
design.returnPlace.lng |
number | null | default null | |
design.returnPlace.formattedAddress |
string | default "" | |
blocks |
object[] | yes | |
proposals |
object[] | null | yes | The quotes a trip made from it starts with, as drafts; null on a template saved before proposals were kept. |
proposals[].name |
string | yes | |
proposals[].mode |
string | yes | package (one price, upgrade packages) or per_item (the customer picks lines). |
proposals[].marginPct |
number | yes | |
proposals[].lineCount |
integer | yes | |
proposals[].wasAccepted |
boolean | yes | Accepted in the trip the template was saved from. |
travelers |
integer | null | yes | The headcount a trip made from it starts with. |
presentation |
object | null | yes | The branding a trip made from it starts with. |
baseStartDate |
string | null | yes | The start date of the trip it was saved from; a new trip's dates shift relative to it. |
Errors
Errors are problem details. Besides the refusals described above, any call like this one can return:
invalid_request— Invalid requestunauthorized— Missing or invalid API keyinsufficient_scope— Missing permissionrate_limited— Rate limit reachednot_found— Not foundidempotency_key_reused— Idempotency-Key reusedrequest_in_progress— Request in progress