Authenticate using a Zoho OAuth access token with ZohoCRM.modules.quotes.CREATE scope and the correct data center domain (e.g. accounts.zoho.eu for EU)
Construct a JSON body for the Quotes module insert with top-level fields (Subject, Account_Name, etc.) and a 'Product_Details' key containing an array of subform objects, each with 'product', 'quantity', 'unit_price', and 'discount' fields
POST to /crm/v8/Quotes with the JSON body and inspect the response 'data' array for per-record status; each entry includes 'code': 'SUCCESS' or an error code with details
Retrieve the created quote via GET /crm/v8/Quotes/{id}?fields=Product_Details to verify subform line items were persisted correctly
Handle the 'MANDATORY_NOT_FOUND' error code which fires when a required subform field (like 'product') is missing from any line item
Known gotchas
Zoho CRM subform fields use internal API names that differ from display labels; the correct API name for the product lookup in Quotes subform is typically 'product' not 'Product_Name' — always verify via GET /crm/v8/settings/fields?module=Quotes
The number of subform rows per record is limited by the Zoho CRM plan tier; exceeding the row limit causes the entire record insert to fail, not just the excess rows
Tax and discount calculations in subform line items are not automatically recalculated server-side when inserted via API — the caller must send pre-calculated 'total' values or trigger a recalculation by updating the record afterward
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp