---
title: "Get a quote"
method: GET
path: "/quotes/{id}"
tags: ["Quotes"]
---

# Get a quote

`GET /quotes/{id}`

## Request

- Base URL: `https://joinways.app/api/v1`
- URL: `https://joinways.app/api/v1/quotes/{id}`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://joinways.app/oauth/authorize`, token URL `https://joinways.app/api/oauth/token`, scopes: `mcp.read`)

The quote header (`quote`) and its line items (`items`, by day then `sort_order`). A package is one item, its articles under `package` (see Packages). **Role permission:** `reports.view` or `quotes.manage`.

## Response `200`

The quote and its items.

- object
  - `quote` Quote, required: A quote as listed (`GET /quotes`).
    - `id` string, uuid
    - `event_id` string, uuid
    - `quote_number` string, nullable
    - `title` string
    - `status` 'draft' | 'pending' | 'accepted' | 'signed' | 'rejected' | 'invoiced' | 'paid' | 'cancelled': `draft` = not sent yet; `pending` = sent, awaiting the client; `accepted` / `signed` = client agreement (signed = signature recorded); `rejected` = refused; `invoiced` = at least one invoice issued (a deposit included); `paid` = fully settled; `cancelled` = withdrawn. accepted, signed, invoiced and paid are live contracts counted in the event's confirmed amount (unless replaced, see `superseded_by_quote_id`).
    - `currency` string
    - `total_excl_tax` number
    - `total_tax` number
    - `total_incl_tax` number
    - `is_signed` boolean, nullable
    - `signed_at` string, date-time, nullable
    - `signature_mode` 'manual' | 'public' | 'null', nullable
    - `signer_name` string, nullable
    - `signer_email` string, nullable
    - `is_invoiced` boolean, nullable
    - `invoice_number` string, nullable
    - `invoice_date` string, date-time, nullable
    - `due_date` string, date-time, nullable
    - `payment_date` string, date-time, nullable
    - `is_reverse_charge` boolean, nullable
    - `sent_at` string, date-time, nullable: When the quote was sent (for a platform quote, when the platform transmitted it).
    - `viewed_at` string, date-time, nullable
    - `last_viewed_at` string, date-time, nullable
    - `view_count` integer
    - `expires_at` string, date-time, nullable: Validity end of the offer.
    - `created_at` string, date-time
    - `author_id` string, uuid
    - `billing_profile_id` string, uuid, nullable
    - `source` 'joinways' | 'platform': `joinways` = written in Joinways. `platform` = a booking platform's own document recorded in Joinways, mostly read from the platform's emails (quote transmitted, with its PDF), or imported once signed. A platform quote is read-only: its amounts, discounts, currency and lines are never edited, it is never deleted nor duplicated, and its status only takes `accepted` or `rejected` through the API; its PDF is the platform's.
    - `source_platform` string, nullable: Booking platform the document comes from (platform quote), or the one a Joinways quote was deposited to (e.g. Kactus).
    - `external_reference` string, nullable: The platform's own quote number (a platform that renumbers each revision gives each version its own). Unique per event.
    - `platform_pushed_at` string, date-time, nullable: When a Joinways quote was deposited on the platform (first deposit only).
    - `superseded_by_quote_id` string, uuid, nullable: Set when this quote was replaced: by a later version the booking platform sent, or by a signed amendment. A replaced quote keeps its status but never counts in the event's confirmed amount; only quotes where this is null are live. Set by Joinways only.
    - `superseded_at` string, date-time, nullable: When the quote was replaced (null while it is live).
    - `account_id` string, uuid
    - `totals_updated_at` string, date-time, nullable
    - `discount_percent` number, nullable
    - `discount_amount` number, nullable
    - `invoiced_at` string, date-time, nullable
    - `invoiced_by` string, uuid, nullable
    - `invoice_pdf_path` string, nullable
    - `invoice_snapshot` object, nullable
    - `payment_terms` string, nullable
    - `cancellation_terms` string, nullable
    - `postponement_terms` string, nullable
    - `purchase_order` string, nullable
    - `client_first_name` string, nullable
    - `client_last_name` string, nullable
    - `client_email` string, nullable
    - `client_phone` string, nullable
    - `client_is_individual` boolean, nullable
    - `client_company_name` string, nullable
    - `client_address` string, nullable
    - `client_postal_code` string, nullable
    - `client_city` string, nullable
    - `client_state` string, nullable
    - `client_country` string, nullable
    - `client_vat_number` string, nullable
    - `client_registration_number` string, nullable
    - `client_purchase_order` string, nullable
    - `parent_quote_id` string, uuid, nullable: The quote this one amends (amendment).
    - `amendment_sequence` integer
    - `platform_request_token` string, nullable
    - `translations` object
    - `space_plan_snapshot` object, nullable
    - `space_plan_snapshot_at` string, date-time, nullable
    - `ai_generated` boolean
    - `ai_source_lead_id` string, uuid, nullable
    - `ai_model` string, nullable
    - `ai_confidence` number, nullable
    - `ai_reasoning` string, nullable
    - `ai_warnings` string[]
    - `ai_generated_at` string, date-time, nullable
    - `document_lines` QuoteDocumentLine[], nullable: Platform quotes only: the lines read out of the PDF the platform sent, read-only. They never count in the totals (the quote keeps one line carrying the printed amount). Null on a Joinways quote; empty until read (see `document_lines_status`).
      - `id` string, uuid
      - `title` string
      - `description` string, nullable
      - `section` string, nullable: Heading printed above the line on the document.
      - `quantity` number, nullable
      - `unit` string, nullable
      - `day` string, date, nullable: Event day the line belongs to, when the document says.
      - `amount_excl_tax` number, nullable
      - `amount_incl_tax` number, nullable
      - `is_option` boolean
      - `is_discount` boolean
    - `document_lines_status` 'pending' | 'done' | 'failed' | 'no_pdf' | 'skipped' | 'null', nullable: Where the reading of the platform PDF stands. Null = not asked (only won platform quotes are read automatically).
    - `document_lines_extracted_at` string, date-time, nullable
    - `rejected_with_event` boolean
    - `is_demo` boolean
  - `items` QuoteItem[], required
    - `id` string, uuid
    - `quote_id` string, uuid
    - `account_id` string, uuid, nullable
    - `title` string
    - `description` string
    - `quantity` number
    - `unit_price` number: Price per unit, excluding tax. On a package: the price of one package unit (`package.unit_price`).
    - `vat` number, nullable: Tax rate as a percentage (e.g. 20 for 20 %). A package mixes rates: this is only the lowest of them, read `package.tax_rates` and never compute its tax from `vat`.
    - `total` number, nullable: Computed line total, excluding tax, after the line discount. On a package: the sum of its articles (`package.total_excl_tax`).
    - `is_package` boolean: The line is a package; `package` is then present.
    - `parent_item_id` string, uuid, nullable: The package line an article belongs to. `null` on the items returned: the articles of a package are under its `package.articles`, not items of their own.
    - `package` QuoteItemPackage: Only on a package line. Amounts are summed article by article, like the quote totals, so they can differ by a cent from `unit_price × quantity`.
      - `unit_price` number, required: Price of one package unit, excluding tax, before discount.
      - `total_excl_tax` number, required: Sum of the articles, after the package's discount.
      - `total_tax` number, required
      - `total_incl_tax` number, required
      - `tax_rates` number[], required: Distinct tax rates of the articles, ascending, in %.
      - `articles` QuoteItemPackageArticle[], required: What the package is made of, in the order of its composition. Read-only: written by Joinways from the package line. Their ids are refused by every write (`package_article`).
        - `id` string, uuid
        - `location_item_id` string, uuid, nullable: Catalog item of the article.
        - `title` string
        - `description` string, nullable
        - `quantity` number: Package quantity × `package_unit_quantity`.
        - `package_unit_quantity` number: Quantity of the article in one package unit.
        - `unit_price` number: Unit price of the article inside the package, excluding tax.
        - `vat` number: Tax rate of the article, in %.
        - `total` number: Amount of the article, excluding tax, after the package's discount.
    - `location_item_id` string, uuid, nullable: The catalog item this line was priced from, if any.
    - `min_price_applied` number, nullable: Catalog minimum price the line was checked against.
    - `is_option` boolean, nullable
    - `is_discount` boolean, nullable
    - `is_offered` boolean, nullable: Offered (free) line; bypasses the catalog minimum-price check.
    - `discount_amount` number, nullable
    - `discount_percent` number, nullable
    - `event_day` integer: 1-based day this line belongs to (multi-day events).
    - `event_day_date` string, date, nullable
    - `sort_order` integer: Display order within the day.
    - `client_selected_at` string, date-time, nullable: When the client ticked this option on the public quote.
    - `inherited_from_item_id` string, uuid, nullable
    - `ai_rationale` string, nullable
    - `created_at` string, date-time

## Other responses

- `401`: Missing, invalid, expired or revoked bearer token (`unauthorized`).
- `403`: `forbidden`: the token lacks the scope, its owner's role lacks the permission named by the operation, or the workspace has neither the Pro plan nor a trial (`details.reason` `plan_not_eligible`).
- `404`: Not found in this workspace, or the id of the path is not a UUID (`not_found`).
- `429`: Too many requests (`rate_limited`). `details.reason`: `per-ip`, `per-account-minute`, `per-account-day`, or `email_rate_limited` (email budget). Always carries `Retry-After`: wait that many seconds.

---

[API](https://skmtc.dev/joinways/apis/joinways-public-api.md) · [All operations](https://skmtc.dev/joinways/apis/joinways-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/joinways/apis/joinways-public-api/revisions/39e84309953e?raw)
