bymundi API

Update a quote

PATCH/v1/quotes/{quoteId}

Changes the quote's own fields, as the quote editor's header and copy editor do: name, travelers (must equal the trip's headcount), marginPct, finalPriceOverride, validUntil, ctaUrl, templateId, and the template's editable texts and images (textOverrides, imageOverrides: merged key by key, null restores the template's). metadata merges key by key. Lines have their own endpoint. Pass the updatedAt you read as expectedUpdatedAt to refuse a stale write with a 409. With ?dryRun=true, returns a quote_preview with each field's from/to and the new totals.

Permissions: quotes:write · Kind: write · Cost: 1 unit · Dry run: ?dryRun=true · MCP tool update_quote

Undoable: the response carries Bymundi-Change-Id; revert it with POST /v1/changes/{changeId}/revert.

Path parameters

Field Type Required Description
quoteId uuid yes

Body

Field Type Required Description
name string max 200 chars
travelers integer Must equal the trip's headcount. 1–40
marginPct number A % of the SALE price. 0–99
finalPriceOverride string | null The rounded price the customer is asked to pay; null = the computed total.
validUntil string | null
ctaUrl string | null Where the public page's button leads (WhatsApp, email, a URL).
templateId uuid | null A quote template; null = the agency's default.
textOverrides object The template's editable texts, by key; null restores the template's text.
imageOverrides object The template's editable images (URLs), by key; null restores the template's image.
expectedUpdatedAt datetime The quote's updatedAt as you read it; the write is refused (409) if the quote changed since.
metadata object

Response 200

One of:

quote

Field Type Required Description
object "quote" yes
id uuid yes
tripId uuid yes
code string yes
name string yes
mode "package" | "per_item" yes
status "draft" | "sent" | "accepted" | "rejected" | "expired" | "superseded" yes
travelers integer yes
marginPct number yes
finalPriceOverride string | null yes
validUntil string | null yes
ctaUrl string | null yes
templateId string | null yes
packages object[] yes
packages[].id string yes
packages[].name string yes
lines object | object | object[] yes
totals object yes
totals.currency "EUR" yes
totals.net string yes
totals.marginAmount string yes
totals.total string yes
totals.finalPrice string yes
totals.perPax string yes
totals.finalMargin string yes
totals.packages object[] yes
totals.packages[].id string yes
totals.packages[].name string yes
totals.packages[].deltaNet string yes
totals.packages[].deltaPvp string yes
totals.packages[].lineIds string[] yes
textOverrides object yes
imageOverrides object yes
sentAt string | null yes
modifiedSinceSent boolean yes
acceptedAt string | null yes
acceptedVia "prospect_link" | "agent" | null yes
acceptedPackageId string | null yes
acceptedLineIds string[] yes
acceptance object | null yes What the customer typed when accepting on the quote page — personal data: present only for a key holding travelers:read, only on quote reads (a write's response carries null; read the quote), and every such read is audited.
acceptance.name string | null yes
acceptance.email string | null yes
acceptance.phone string | null yes
acceptance.message string | null yes
engagement object yes
engagement.views integer yes
engagement.uniqueSessions integer yes
engagement.activeSeconds integer yes
engagement.ctaClicks integer yes
engagement.maxScrollPct number yes
engagement.sectionsSeen integer yes
engagement.interactions integer yes
engagement.lastSeenAt string | null yes
engagement.lastCtaAt string | null yes
metadata object yes
appUrl string | null yes
publicUrl string | null yes
createdAt string yes
updatedAt string yes

quote_preview

Field Type Required Description
object "quote_preview" yes
quoteId uuid | null yes
changes object[] yes
changes[].field string yes
changes[].from any
changes[].to any
sync object | null yes
sync.added integer yes
sync.updated integer yes
sync.removed integer yes
packages object[] yes
packages[].id string yes
packages[].name string yes
lines object | object | object[] yes
totals object yes
totals.currency "EUR" yes
totals.net string yes
totals.marginAmount string yes
totals.total string yes
totals.finalPrice string yes
totals.perPax string yes
totals.finalMargin string yes
totals.packages object[] yes
totals.packages[].id string yes
totals.packages[].name string yes
totals.packages[].deltaNet string yes
totals.packages[].deltaPvp string yes
totals.packages[].lineIds string[] yes

Errors

Errors are problem details. Besides the refusals described above, any call like this one can return: