Accept a quote on the customer's behalf
POST/v1/quotes/{quoteId}/accept
Records that the customer accepted, as the quote editor's Accept does (acceptedVia: agent). A package quote takes the chosen packageId (absent or null = the base proposal); a per_item quote takes the lineIds the customer bought. Accepting a package quote supersedes any other accepted package quote of the trip, and moves the trip to aceptada from nueva, propuesta_enviada or rechazada. To bring the accepted services into the itinerary, then call POST /trips/{tripId}/itinerary/sync. Undo with POST /quotes/{quoteId}/reopen.
Permissions: quotes:write · Kind: write · Cost: 1 unit · MCP tool accept_quote
Undo with Reopen a quote.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
quoteId |
uuid | yes |
Body
| Field | Type | Required | Description |
|---|---|---|---|
packageId |
string | null | A package quote: the package chosen; absent or null = the base proposal. | |
lineIds |
string[] | A per_item quote: the lines the customer bought. max 200 items |
Response 200
| 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 |
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