---
title: "Duplicate a quote"
method: POST
path: "/quotes/{id}/duplicate"
tags: ["Quotes"]
---

# Duplicate a quote

`POST /quotes/{id}/duplicate`

## Request

- Base URL: `https://joinways.app/api/v1`
- URL: `https://joinways.app/api/v1/quotes/{id}/duplicate`
- 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.write`)

Copies the quote and all its line items into a new draft on the same event. No body. A platform quote cannot be duplicated. **Role permission:** `quotes.manage`.

## Headers

- `Idempotency-Key` string

## Response `200`

The new draft.

- object
  - `success` boolean
  - `new_quote_id` string, uuid
  - `source_title` string

## 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`).
- `409`: The quote's state refuses the operation (`conflict`); retrying the same call fails the same way until that state changes (except `amendment_in_flight`, transient). `error.details.reason` (see `QuoteErrorReason`): `quote_locked` (signed, invoiced or paid: amend or cancel instead), `quote_signed`, `quote_cancelled`, `quote_not_cancellable`, `quote_has_active_invoice` (credit the invoice first), `quote_has_amendments` (a quote with a live amendment is frozen), `quote_superseded` (a replaced version is history), `amendment_in_flight` (one amendment at a time), `amendment_nested`, `parent_not_active`, `parent_not_signed`, `parent_fully_invoiced`, `quote_changed` (the status changed meanwhile), `invalid_status`, `not_a_platform_version`, `event_closed` (event lost or cancelled), `event_archived`, `platform_quote_read_only` (a platform quote, `source: platform`, is the platform's document: amounts, discounts, currency and lines are read-only, its status only takes `accepted` or `rejected`), `platform_quote_delete_forbidden` (cancel or refuse it instead), `platform_version_signed` (another version is signed), `quote_conflict` (another live contract must be cancelled or refused first).
- `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)
