# Get a quote

> Returns one quote with everything the quote editor shows: its mode (a package quote with upgrade packages, or a per_item basket), lines, packages, bill totals, status and decision, whether it changed since it was sent, the customer's engagement with the public page, the public link and your metadata.

`GET /v1/quotes/{quoteId}`

Returns one quote with everything the quote editor shows: its mode (a package quote with upgrade packages, or a per_item basket), lines, packages, bill totals, status and decision, whether it changed since it was sent, the customer's engagement with the public page, the public link and your metadata. Money is a decimal string in `totals.currency`.

**Permissions:** `quotes:read` · **Kind:** read · **Cost:** 1 unit · MCP tool [`get_quote`](https://api.bymundi.com/docs/mcp/tools/get_quote.md)



## Path parameters

| Field | Type | Required | Description |
|---|---|---|---|
| `quoteId` | uuid | yes |  |

## Query parameters

_None._

## 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](https://api.bymundi.com/docs/guides/errors.md). Besides the refusals described above, any call like this one can return:

- [`invalid_request`](https://api.bymundi.com/problems/invalid_request.md) — Invalid request
- [`unauthorized`](https://api.bymundi.com/problems/unauthorized.md) — Missing or invalid API key
- [`insufficient_scope`](https://api.bymundi.com/problems/insufficient_scope.md) — Missing permission
- [`rate_limited`](https://api.bymundi.com/problems/rate_limited.md) — Rate limit reached
- [`not_found`](https://api.bymundi.com/problems/not_found.md) — Not found

## Examples

#### curl

```bash
curl https://api.bymundi.com/v1/quotes/$QUOTE_ID \
  -H "Authorization: Bearer $BYMUNDI_KEY"
```

#### JavaScript

```javascript
const res = await fetch(`https://api.bymundi.com/v1/quotes/${quoteId}`, {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.BYMUNDI_KEY}`,
  },
});
if (!res.ok) throw new Error((await res.json()).detail);
const data = await res.json();
```

#### Python

```python
import os, uuid, requests

res = requests.get(
    f"https://api.bymundi.com/v1/quotes/{quoteId}",
    headers={"Authorization": f"Bearer {os.environ['BYMUNDI_KEY']}"},
)
res.raise_for_status()
data = res.json()
```
