[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"docs-entities\u002Fquotes\u002Fupdate":3,"docs-tabs-entities\u002Fquotes\u002Fupdate":6},{"content":4,"lastmod":5},"\n## Update a quote\n\n`PATCH \u002Fv1\u002Fquotes\u002F:id`\n\nUpdates fields of an existing CRM quote. Pass only the fields you want to change — the rest stay as they are.\n\n## Parameters\n\n| Parameter | Type | Required | Description |\n|----------|-----|:-----:|---------|\n| `id` (path) | number | yes | Quote ID. List: [`GET \u002Fv1\u002Fquotes`](\u002Fdocs\u002Fentities\u002Fquotes\u002Flist) |\n\n## Request fields (body)\n\nAll fields are optional. Frequently changed: `stageId`, `amount` together with `isManualOpportunity`, `assignedById`, `closeDate`.\n\n| Field | Type | Description |\n|------|-----|---------|\n| `title` | string | Title |\n| `quoteNumber` | string | Quote number |\n| `stageId` | string | Status: `DRAFT`, `SENT`, `APPROVED`. List: `GET \u002Fv1\u002Fstatuses?filter[entityId]=QUOTE_STATUS` |\n| `amount` | number | Quote amount. Pass it together with `isManualOpportunity: true` — without this flag the amount is recalculated from the product rows |\n| `isManualOpportunity` | boolean | `true` — manual amount mode |\n| `currency` | string | Currency. List: `GET \u002Fv1\u002Fcurrencies` |\n| `dealId` | number | Deal ID. List: `GET \u002Fv1\u002Fdeals` |\n| `leadId` | number | Lead ID. List: `GET \u002Fv1\u002Fleads` |\n| `contactId` | number | Primary contact ID. List: `GET \u002Fv1\u002Fcontacts` |\n| `contactIds` | array | IDs of all contacts of the quote. The set of bindings is replaced as a whole, so pass the full list |\n| `companyId` | number | Company ID. List: `GET \u002Fv1\u002Fcompanies` |\n| `mycompanyId` | number | Your company's details |\n| `assignedById` | number | Assignee. List: `GET \u002Fv1\u002Fusers` |\n| `opened` | boolean | Available to everyone |\n| `comments` | string | Comment |\n| `content` | string | Content |\n| `terms` | string | Terms |\n| `beginDate` | datetime | Start date |\n| `closeDate` | datetime | Close date |\n| `actualDate` | datetime | Valid until |\n| `locationId` | string | Location |\n| `webformId` | number | CRM form that created the quote |\n| `storageTypeId` | number | File storage type |\n| `storageElementIds` | array | IDs of files in the storage |\n| `lastActivityBy` | number | Author of the last activity. List: `GET \u002Fv1\u002Fusers` |\n| `utmSource` | string | UTM Source |\n| `utmMedium` | string | UTM Medium |\n| `utmCampaign` | string | UTM Campaign |\n| `utmContent` | string | UTM Content |\n| `utmTerm` | string | UTM Term |\n| `ufCrm*` | per field schema | A user field of the Bitrix24 account. The name and type are in the schema [`GET \u002Fv1\u002Fquotes\u002Ffields`](\u002Fdocs\u002Fentities\u002Fquotes\u002Ffields), and the value format for each type is in [User fields (UF)](\u002Fdocs\u002Fentity-api#user-fields-uf) |\n\nFields marked RO on the [Quote fields](\u002Fdocs\u002Fentities\u002Fquotes\u002Ffields) page cannot be changed — a request that includes them is rejected with `400 READONLY_FIELD`.\n\n> **Field names.** In responses, fields are returned in camelCase: `amount`, `currency`, `beginDate`, `closeDate`. On write, both forms are accepted: these camelCase names and the original Bitrix24 names `opportunity`, `currencyId`, `begindate`, `closedate`. The API layer maps them to the names Bitrix24 expects.\n\n## Examples\n\n### curl — personal key\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fquotes\u002F412\" \\\n  -H \"X-Api-Key: YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"stageId\": \"APPROVED\",\n    \"isManualOpportunity\": true,\n    \"opportunity\": 1450\n  }'\n```\n\n### curl — OAuth application\n\n```bash\ncurl -X PATCH \"https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fquotes\u002F412\" \\\n  -H \"X-Api-Key: YOUR_APP_KEY\" \\\n  -H \"Authorization: Bearer USER_SESSION_TOKEN\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"stageId\": \"APPROVED\",\n    \"isManualOpportunity\": true,\n    \"opportunity\": 1450\n  }'\n```\n\n### JavaScript — personal key\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fquotes\u002F412', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    stageId: 'APPROVED',\n    isManualOpportunity: true,\n    opportunity: 1450,\n  }),\n})\n\nconst { success, data } = await res.json()\n```\n\n### JavaScript — OAuth application\n\n```javascript\nconst res = await fetch('https:\u002F\u002Fvibecode.bitrix24.com\u002Fv1\u002Fquotes\u002F412', {\n  method: 'PATCH',\n  headers: {\n    'X-Api-Key': 'YOUR_APP_KEY',\n    'Authorization': 'Bearer USER_SESSION_TOKEN',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    stageId: 'APPROVED',\n    isManualOpportunity: true,\n    opportunity: 1450,\n  }),\n})\n\nconst { success, data } = await res.json()\n```\n\n## Response fields\n\n| Field | Type | Description |\n|------|-----|---------|\n| `success` | boolean | Always `true` on success |\n| `data` | object | The updated quote object with all fields — see [Quote fields](\u002Fdocs\u002Fentities\u002Fquotes\u002Ffields) |\n| `meta.warnings` | array | Present when the body carries fields that are neither in the quote schema nor in the field list of [`GET \u002Fv1\u002Fquotes\u002Ffields`](\u002Fdocs\u002Fentities\u002Fquotes\u002Ffields), for example a misspelled name. The warning code is `UNRECOGNIZED_WRITE_FIELD`: such a field may not have been stored. The response status is `200`. On a route that wraps the field map itself, an object under `fields` is rejected with `400 NESTED_FIELDS_ENVELOPE` when the schema does not declare `fields`; pass fields flat at the JSON root. |\n\n## Response example\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"id\": 412,\n    \"title\": \"Quote for server hardware\",\n    \"amount\": 1450,\n    \"currency\": \"USD\",\n    \"stageId\": \"APPROVED\",\n    \"dealId\": 741,\n    \"assignedById\": 1,\n    \"updatedTime\": \"2026-04-15T15:10:00.000Z\"\n  }\n}\n```\n\n## Error response example\n\n404 — quote not found:\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"ENTITY_NOT_FOUND\",\n    \"message\": \"Item not found\"\n  }\n}\n```\n\n## Errors\n\n| HTTP | Code | Description |\n|------|-----|---------|\n| 404 | `ENTITY_NOT_FOUND` | Quote not found |\n| 403 | `ACCESS_DENIED` | No access to the quote |\n| 400 | `INVALID_REQUEST` | Invalid fields |\n| 400 | `READONLY_FIELD` | The request body contains a read-only field, such as `clientEmail`. Such fields are marked in the RO column of [Quote fields](\u002Fdocs\u002Fentities\u002Fquotes\u002Ffields) |\n| 403 | `SCOPE_DENIED` | The API key lacks the `crm` scope |\n| 401 | `TOKEN_MISSING` | The API key has no configured tokens |\n\nFull list of common API errors — [Errors](\u002Fdocs\u002Ferrors).\n\n## See also\n\n- [Working with files in CRM fields](\u002Fdocs\u002Frecipes\u002Fcrm-files)\n- [Get a quote](\u002Fdocs\u002Fentities\u002Fquotes\u002Fget)\n- [Quote fields](\u002Fdocs\u002Fentities\u002Fquotes\u002Ffields)\n- [Batch](\u002Fdocs\u002Fbatch)\n- [Limits and optimization](\u002Fdocs\u002Foptimization)\n","2026-10-15",{},1794739408055]