{"openapi":"3.1.0","info":{"title":"GeometrAI API","version":"1.0.0","description":"REST API exposing the actions of the GeometrAI product. Authenticate with a Kavaro API key as a bearer token."},"servers":[{"url":"https://kavaro.ai"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","description":"A Kavaro API key (user- or organization-scoped)."}}},"security":[{"ApiKeyAuth":[]}],"paths":{"/api/rest/actions/create_project":{"post":{"operationId":"create_project","summary":"Create project","description":"Create a new project (case) for the current firm.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"description":"The project name"},"status":{"description":"Initial status; defaults to draft","type":"string","enum":["draft","active","on_hold","completed","archived"]},"type":{"description":"Kind of project; defaults to generic","type":"string","enum":["generic","cila","scia","permesso_di_costruire","catastale","perizia"]},"description":{"description":"Optional description of the work","type":"string"},"address":{"description":"Address of the work site","type":"string"},"municipality":{"description":"The municipality (comune) the project belongs to","type":"string"},"clientContactId":{"description":"The id of the client contact for this project","type":"string"}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_project_status":{"post":{"operationId":"update_project_status","summary":"Update project status","description":"Change a project's status.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to update"},"status":{"type":"string","enum":["draft","active","on_hold","completed","archived"],"description":"The new status"}},"required":["projectId","status"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_project":{"post":{"operationId":"update_project","summary":"Update project","description":"Update a project's details: name, type, description, address, municipality or client contact.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to update"},"name":{"description":"New name","type":"string","minLength":1},"type":{"description":"Kind of project","type":"string","enum":["generic","cila","scia","permesso_di_costruire","catastale","perizia"]},"description":{"description":"Description of the work","type":"string"},"address":{"description":"Address of the work site","type":"string"},"municipality":{"description":"The municipality (comune)","type":"string"},"clientContactId":{"description":"The id of the client contact for this project","type":"string"}},"required":["projectId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/connect_contact":{"post":{"operationId":"connect_contact","summary":"Connect contact to project","description":"Connect a contact to a project so it shows on the project (a contact can be connected to many projects). Separate from the project's single primary client.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to connect the contact to"},"contactId":{"type":"string","description":"The contact to connect"}},"required":["projectId","contactId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/disconnect_contact":{"post":{"operationId":"disconnect_contact","summary":"Disconnect contact from project","description":"Remove the connection between a contact and a project (the contact itself is kept).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to disconnect the contact from"},"contactId":{"type":"string","description":"The contact to disconnect"}},"required":["projectId","contactId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_project":{"post":{"operationId":"delete_project","summary":"Delete project","description":"Delete a project (case) and its tasks, bills of quantities and submissions. Linked documents and contacts are kept (unlinked).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:delete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to delete"}},"required":["projectId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_project_stage":{"post":{"operationId":"update_project_stage","summary":"Update project stage","description":"Advance or change the lifecycle stage of a project (e.g. from preparation to submitted after filing with the municipality). Also lets you record the protocol number, submission date, decision deadline and any authority notes.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to update"},"stage":{"type":"string","enum":["preparation","submitted","review","integration","approved","site_survey","drafting","registered","in_progress","closed"],"description":"The new stage"},"protocolNumber":{"description":"Authority protocol / reference number (populated on submission)","type":"string"},"submittedAt":{"description":"Date of formal submission; defaults to now when stage is 'submitted'"},"decisionDeadline":{"description":"Deadline by which the authority must decide"},"authorityNotes":{"description":"Notes from the authority (e.g. integration request text)","type":"string"}},"required":["projectId","stage"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_task":{"post":{"operationId":"create_task","summary":"Create task","description":"Add a task to a project.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["tasks:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project the task belongs to"},"title":{"type":"string","minLength":1,"description":"The task title"},"dueAt":{"description":"Optional due date (ISO 8601)"},"assigneeId":{"description":"Optional id of the org user to assign the task to","type":"string"}},"required":["projectId","title"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_task_status":{"post":{"operationId":"update_task_status","summary":"Update task status","description":"Change a task's status.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["tasks:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"taskId":{"type":"string","description":"The task to update"},"status":{"type":"string","enum":["todo","in_progress","done","cancelled"],"description":"The new status"}},"required":["taskId","status"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/file_thread":{"post":{"operationId":"file_thread","summary":"File conversation","description":"Attach a conversation thread to a project (and optionally a contact), record a short summary and set its status. Use after you've created the relevant tasks/bills-of-quantities/reminders from it.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["inbox:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"threadId":{"type":"string","description":"The thread (conversation) id"},"projectId":{"description":"The project to attach the thread to","type":"string"},"contactId":{"description":"The contact this conversation is with","type":"string"},"summary":{"description":"A short note on what the thread is about / what was done","type":"string"},"status":{"description":"Resulting thread status; defaults to waiting","type":"string","enum":["open","needs_reply","waiting","closed"]}},"required":["threadId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_thread_status":{"post":{"operationId":"set_thread_status","summary":"Set conversation status","description":"Change a conversation thread's status (open, needs_reply, waiting, closed). Use 'closed' to dismiss a thread that needs no action.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["inbox:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"threadId":{"type":"string","description":"The thread to update"},"status":{"type":"string","enum":["open","needs_reply","waiting","closed"],"description":"The new status"}},"required":["threadId","status"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/send_message":{"post":{"operationId":"send_message","summary":"Send message","description":"Send a new outbound message to a contact on a channel, starting a new conversation thread (or adding to one if threadId is given).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["inbox:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"body":{"type":"string","minLength":1,"description":"The message body"},"threadId":{"description":"Existing thread to send within; omit to start a new one","type":"string"},"contactId":{"description":"The contact to send to (used to resolve the address when starting a new thread)","type":"string"},"to":{"description":"Explicit destination address (email), overriding the contact's","type":"string"},"subject":{"description":"Subject for a new email thread","type":"string"},"projectId":{"description":"The project a new thread belongs to","type":"string"},"channel":{"description":"Channel to send on; defaults to email","type":"string","enum":["email","whatsapp","pec","sms"]},"attachmentFileIds":{"description":"Ids of product files to attach to the outgoing message","type":"array","items":{"type":"string"}}},"required":["body"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/reply_to_thread":{"post":{"operationId":"reply_to_thread","summary":"Reply","description":"Reply to an existing conversation thread on its channel.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["inbox:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"threadId":{"type":"string","description":"The thread to reply to"},"body":{"type":"string","minLength":1,"description":"The reply body"},"attachmentFileIds":{"description":"Ids of product files to attach to the reply","type":"array","items":{"type":"string"}}},"required":["threadId","body"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_bill_of_quantities":{"post":{"operationId":"create_bill_of_quantities","summary":"Create bill of quantities","description":"Create a new bill of quantities (computo metrico) for a project.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["bills_of_quantities:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project the bill of quantities belongs to"},"name":{"type":"string","minLength":1,"description":"The bill-of-quantities name"}},"required":["projectId","name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/save_bill_of_quantities_lines":{"post":{"operationId":"save_bill_of_quantities_lines","summary":"Save bill-of-quantities lines","description":"Replace the contents of a bill of quantities. Each node is either a line (desc, unit, qty, price; optionally a prezzario code, regional list price and a measured breakdown) or a section ({type:'section', title, children}) grouping lines into a WBS.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["bills_of_quantities:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"computoId":{"type":"string","description":"The bill of quantities to update"},"lines":{"type":"array","items":{"$ref":"#/$defs/__schema0"},"description":"The full set of nodes (lines and/or sections)"}},"required":["computoId","lines"],"additionalProperties":false,"$defs":{"__schema0":{"type":"object","properties":{"type":{"type":"string","enum":["line","section"]},"desc":{"type":"string"},"unit":{"type":"string"},"qty":{"type":"number"},"price":{"type":"number"},"code":{"type":"string"},"listPrice":{"type":"number"},"priceBook":{"type":"string"},"measurements":{"type":"array","items":{"type":"object","properties":{"desc":{"type":"string"},"count":{"type":"number"},"length":{"type":"number"},"width":{"type":"number"},"height":{"type":"number"}},"additionalProperties":{}}},"title":{"type":"string"},"children":{"type":"array","items":{"$ref":"#/$defs/__schema0"}}},"additionalProperties":{}}}}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_contact":{"post":{"operationId":"create_contact","summary":"Add contact","description":"Add a person or company to the firm's address book (client, contractor, site manager, municipality, notary, …).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["contacts:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Person or company name"},"role":{"description":"Their role; defaults to client","type":"string","enum":["client","contractor","site_manager","municipality","notary","other"]},"company":{"description":"Company name, if the contact is a person at a firm","type":"string"},"email":{"description":"Primary email address","type":"string"},"phone":{"description":"Primary phone number","type":"string"},"emails":{"description":"All email addresses for this contact (the first is the primary)","type":"array","items":{"type":"string"}},"phones":{"description":"All phone numbers for this contact (the first is the primary)","type":"array","items":{"type":"string"}},"pec":{"description":"PEC (certified email) address","type":"string"},"notes":{"description":"Free-form notes","type":"string"}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_contact":{"post":{"operationId":"update_contact","summary":"Update contact","description":"Update an address-book contact's details.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["contacts:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"contactId":{"type":"string","description":"The contact to update"},"name":{"description":"Name","type":"string","minLength":1},"role":{"description":"Role","type":"string","enum":["client","contractor","site_manager","municipality","notary","other"]},"company":{"description":"Company name","type":"string"},"email":{"description":"Primary email address","type":"string"},"phone":{"description":"Primary phone number","type":"string"},"emails":{"description":"All email addresses for this contact (the first is the primary)","type":"array","items":{"type":"string"}},"phones":{"description":"All phone numbers for this contact (the first is the primary)","type":"array","items":{"type":"string"}},"pec":{"description":"PEC (certified email) address","type":"string"},"notes":{"description":"Free-form notes","type":"string"}},"required":["contactId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_contact":{"post":{"operationId":"delete_contact","summary":"Delete contact","description":"Remove a contact from the address book.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["contacts:delete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"contactId":{"type":"string","description":"The contact to delete"}},"required":["contactId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/merge_contacts":{"post":{"operationId":"merge_contacts","summary":"Merge contacts","description":"Merge a duplicate contact into another: all threads, projects and documents are repointed to the surviving contact, empty fields are filled in from the duplicate, and the duplicate is then deleted. Use this to de-duplicate the address book.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["contacts:edit","contacts:delete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"targetId":{"type":"string","description":"The surviving contact (kept)"},"sourceId":{"type":"string","description":"The duplicate contact (merged in and deleted)"}},"required":["targetId","sourceId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_reminder":{"post":{"operationId":"create_reminder","summary":"Add deadline","description":"Add a deadline or follow-up. Use this for legal deadlines, payment due dates, hearings and any date the firm must not miss.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["reminders:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"description":"What is due"},"dueAt":{"description":"When it is due (ISO 8601)"},"kind":{"description":"Kind of deadline; defaults to generic","type":"string","enum":["deadline","follow_up","payment","hearing","generic"]},"projectId":{"description":"The project this deadline belongs to, if any","type":"string"},"notes":{"description":"Free-form notes","type":"string"}},"required":["title","dueAt"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/complete_reminder":{"post":{"operationId":"complete_reminder","summary":"Complete deadline","description":"Mark a deadline as done (or cancelled).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["reminders:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"reminderId":{"type":"string","description":"The reminder to complete"},"status":{"description":"Resulting status; defaults to done","type":"string","enum":["done","cancelled"]}},"required":["reminderId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_document":{"post":{"operationId":"create_document","summary":"Create document","description":"Create a new document (quote, letter, engagement letter, delegation, expert report or generic) for the firm, optionally linked to a project and a contact.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"title":{"type":"string","minLength":1,"description":"Document title"},"kind":{"description":"Document kind; defaults to preventivo","type":"string","enum":["preventivo","letter","engagement_letter","delegation","perizia","report","plan","generic"]},"projectId":{"description":"The project this document belongs to","type":"string"},"contactId":{"description":"The counterparty contact (e.g. the client)","type":"string"},"body":{"description":"Free-text body (for letters/contracts)","type":"string"}},"required":["title"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/draft_quote_from_bill_of_quantities":{"post":{"operationId":"draft_quote_from_bill_of_quantities","summary":"Draft quote from bill of quantities","description":"Create a quote whose line items are seeded from a bill of quantities' lines. The firm then reviews and adjusts prices/discount before issuing.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"computoId":{"type":"string","description":"The bill of quantities to base the quote on"},"title":{"description":"Document title; defaults to the bill-of-quantities name","type":"string"},"contactId":{"description":"The client contact to address it to","type":"string"},"discountPct":{"description":"Whole-document discount %, 0–100","type":"number"},"vatPct":{"description":"VAT (IVA) rate %; defaults to 22","type":"number"}},"required":["computoId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_document":{"post":{"operationId":"update_document","summary":"Update document","description":"Update a document's title, body, line items, discount/VAT, validity or linked contact.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to update"},"title":{"description":"Title","type":"string","minLength":1},"body":{"description":"Free-text body","type":"string"},"lineItems":{"description":"Full replacement set of priced line items","type":"array","items":{"type":"object","properties":{"desc":{"type":"string","description":"Line description"},"unit":{"type":"string","description":"Unit of measure, e.g. m², m³, cad"},"qty":{"type":"number","description":"Quantity"},"price":{"type":"number","description":"Unit price (€)"},"code":{"description":"Official price-list (prezzario) code, if any","type":"string"}},"required":["desc","unit","qty","price"],"additionalProperties":false}},"discountPct":{"description":"Whole-document discount %, 0–100","type":"number"},"vatPct":{"description":"VAT (IVA) rate %","type":"number"},"notes":{"description":"Closing notes / terms","type":"string"},"validUntil":{"description":"Validity date (ISO 8601)"},"contactId":{"description":"The counterparty contact","type":"string"}},"required":["docId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_document":{"post":{"operationId":"delete_document","summary":"Delete document","description":"Delete a document (quote, letter, report, …) and its revisions.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:delete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to delete"}},"required":["docId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/issue_document":{"post":{"operationId":"issue_document","summary":"Issue document","description":"Freeze the current content as an immutable revision and mark the document issued. Do this once the content is final and ready to go to the counterparty.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to issue"}},"required":["docId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_document_status":{"post":{"operationId":"set_document_status","summary":"Set document status","description":"Change a document's status (e.g. mark a quote accepted or declined, send it back to draft, or expire it).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to update"},"status":{"type":"string","enum":["draft","review","issued","accepted","declined","expired"],"description":"The new status"}},"required":["docId","status"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/send_issued_document":{"post":{"operationId":"send_issued_document","summary":"Send issued document","description":"Send an issued document (e.g. a quote) to the contact via the communication hub and create a follow-up reminder.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The issued document to send"},"message":{"description":"Optional cover-note to accompany the document","type":"string"},"followUpDays":{"description":"Days until a follow-up reminder fires; defaults to 14","type":"number"}},"required":["docId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/search_records":{"post":{"operationId":"search_records","summary":"Search records","description":"Full-text search across projects, contacts, threads, and documents. Returns grouped results.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"query":{"type":"string","minLength":1,"description":"The search query"}},"required":["query"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/share_project":{"post":{"operationId":"share_project","summary":"Share project","description":"Share a project with another user (client, engineer, municipality or contractor) by granting them a role on it, so everyone has a shared understanding.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project to share"},"userId":{"type":"string","description":"The id of the user to share with"},"role":{"type":"string","enum":["viewer","editor"],"description":"Access level to grant: viewer or editor"}},"required":["projectId","userId","role"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/save_as_template":{"post":{"operationId":"save_as_template","summary":"Save as template","description":"Save a document (its content and structure) as a reusable template so future documents of the same kind can be created from it.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to save as a template"},"title":{"description":"Template title; defaults to the document title","type":"string","minLength":1}},"required":["docId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_document_from_template":{"post":{"operationId":"create_document_from_template","summary":"Create document from template","description":"Create a new document pre-filled from a saved template.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"templateId":{"type":"string","description":"The template to use"},"title":{"description":"Title for the new document; defaults to the template title","type":"string","minLength":1},"projectId":{"description":"The project this document belongs to","type":"string"},"contactId":{"description":"The counterparty contact","type":"string"}},"required":["templateId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/draft_document_from_instructions":{"post":{"operationId":"draft_document_from_instructions","summary":"Draft document with AI","description":"Use AI to draft or improve a document's body and/or line items from natural-language instructions. The document remains in draft until you review and issue it.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to draft/update"},"instructions":{"type":"string","minLength":1,"description":"Natural-language instructions for the draft (what to write, items to include, tone, etc.)"}},"required":["docId","instructions"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/review_document":{"post":{"operationId":"review_document","summary":"Review document","description":"Run an AI pre-issuance consistency check on a document: flag unclear prices, missing details, legal / formal issues and readability problems. Returns a structured review report.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["documents:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"docId":{"type":"string","description":"The document to review"}},"required":["docId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_task_checklist":{"post":{"operationId":"update_task_checklist","summary":"Update task checklist","description":"Set the checklist items for a task (each item is a text description + done flag).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["tasks:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"taskId":{"type":"string","description":"The task to update"},"checklist":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string","description":"Checklist item description"},"done":{"description":"Whether the item is done; defaults to false","type":"boolean"}},"required":["text"],"additionalProperties":false},"description":"The complete checklist (replaces any existing one)"}},"required":["taskId","checklist"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/create_price_book":{"post":{"operationId":"create_price_book","summary":"Create price book","description":"Create a custom price book the firm can use to price bill-of-quantities line items.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["price_books:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Price book name, e.g. 'Regione Toscana 2025' or 'Listino interno'"},"description":{"description":"Optional description","type":"string"},"source":{"description":"Source, e.g. 'DEI', 'CNR', 'regionale', 'custom'","type":"string"},"year":{"description":"Reference year","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"projectId":{"description":"Optionally scope this price book to a project (id)","type":"string"}},"required":["name"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/add_price_book_entries":{"post":{"operationId":"add_price_book_entries","summary":"Add price book entries","description":"Bulk-add entries to a price book (code, description, unit, price, optional category).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["price_books:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"bookId":{"type":"string","description":"The price book to add entries to"},"entries":{"type":"array","items":{"type":"object","properties":{"code":{"description":"Official code, e.g. 'B.01.001.01'","type":"string"},"category":{"description":"Category, e.g. 'Strutture', 'Impianti'","type":"string"},"description":{"type":"string","minLength":1,"description":"Work item description"},"unit":{"type":"string","minLength":1,"description":"Unit of measure"},"price":{"type":"number","description":"Unit price (€)"},"notes":{"description":"Notes or spec reference","type":"string"}},"required":["description","unit","price"],"additionalProperties":false},"description":"Entries to add"}},"required":["bookId","entries"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/update_price_book":{"post":{"operationId":"update_price_book","summary":"Update price book","description":"Update a price book's name, description, source or reference year.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["price_books:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"bookId":{"type":"string","description":"The price book to update"},"name":{"description":"New name","type":"string","minLength":1},"description":{"description":"New description","type":"string"},"source":{"description":"New source","type":"string"},"year":{"description":"New reference year, or null to clear it","anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"projectId":{"description":"Project id to scope this price book to, or null to make it org-wide","anyOf":[{"type":"string"},{"type":"null"}]}},"required":["bookId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/delete_price_book":{"post":{"operationId":"delete_price_book","summary":"Delete price book","description":"Delete a price book and all of its entries.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["price_books:delete"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"bookId":{"type":"string","description":"The price book to delete"}},"required":["bookId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/search_price_book":{"post":{"operationId":"search_price_book","summary":"Search price book","description":"Search the firm's price books for items matching a description or category — use this to find standard prices when building a bill of quantities.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["price_books:view"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"query":{"type":"string","minLength":1,"description":"What to search for, e.g. 'solaio latero-cemento' or 'impianto idraulico'"},"category":{"description":"Filter by category if known","type":"string"},"limit":{"description":"Max results to return; defaults to 10","type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["query"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/record_submission":{"post":{"operationId":"record_submission","summary":"Record submission","description":"Record a formal submission to an authority on a project (the initial submission, an integration of extra documents, a reminder chase, or the outcome). Captures the protocol number and decision deadline, and adds to the submission history. A decision deadline automatically creates a deadline.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"projectId":{"type":"string","description":"The project the submission belongs to"},"kind":{"description":"Submission kind; defaults to submission","type":"string","enum":["submission","integration","reminder","outcome"]},"protocolNumber":{"description":"Authority protocol / reference number","type":"string"},"submittedAt":{"description":"When it was submitted; defaults to now"},"decisionDeadline":{"description":"Deadline by which the authority must respond"},"notes":{"description":"Free-form notes (e.g. what was filed)","type":"string"},"advanceStage":{"description":"Optionally move the project to this stage (e.g. submitted, integration)","type":"string","enum":["preparation","submitted","review","integration","approved","site_survey","drafting","registered","in_progress","closed"]}},"required":["projectId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/set_submission_outcome":{"post":{"operationId":"set_submission_outcome","summary":"Set submission outcome","description":"Record the authority's decision on a submission (approved, rejected or suspended) and optionally a note.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["projects:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"submissionId":{"type":"string","description":"The submission to update"},"outcome":{"type":"string","enum":["approved","rejected","suspended"],"description":"The decision outcome"},"notes":{"description":"Optional note on the decision","type":"string"}},"required":["submissionId","outcome"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/add_bill_of_quantities_section":{"post":{"operationId":"add_bill_of_quantities_section","summary":"Add bill-of-quantities section","description":"Add a section heading to a bill of quantities so line items can be grouped into a work breakdown structure (WBS). Returns the updated nodes list.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["bills_of_quantities:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"computoId":{"type":"string","description":"The bill of quantities to add the section to"},"title":{"type":"string","minLength":1,"description":"Section title, e.g. 'Strutture' or 'Impianti'"},"lines":{"description":"Initial line items inside the section","type":"array","items":{"type":"object","properties":{"desc":{"type":"string"},"unit":{"type":"string"},"qty":{"type":"number"},"price":{"type":"number"}},"required":["desc","unit","qty","price"],"additionalProperties":false}}},"required":["computoId","title"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/link_quote_line":{"post":{"operationId":"link_quote_line","summary":"Link a quote line to a computo line","description":"Record that a preventivo (quote) line covers a computo metrico line, so the two can be compared. A whole-computo or whole-quote lump sum is expressed with a null line index. The same quote line may be linked to several computo lines (one squashed quote line covering many computo lines), and the same computo line may be linked to several quote lines (competing quotes).","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["bills_of_quantities:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"computoId":{"type":"string","description":"The bill of quantities (computo metrico)"},"docId":{"type":"string","description":"The preventivo (quote) document"},"computoLineIndex":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Flattened index of the computo line; null means the link covers the whole computo as a lump sum"},"docLineIndex":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"Index of the quote line item; null means the quote's total is a single lump sum"}},"required":["computoId","docId","computoLineIndex","docLineIndex"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}},"/api/rest/actions/unlink_quote_line":{"post":{"operationId":"unlink_quote_line","summary":"Remove a quote↔computo link","description":"Delete a previously recorded link between a preventivo line and a computo metrico line.","tags":["actions"],"security":[{"ApiKeyAuth":[]}],"x-required-permissions":["bills_of_quantities:edit"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"linkId":{"type":"string","description":"The id of the link to remove"}},"required":["linkId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Action result","content":{"application/json":{"schema":{"type":"object","properties":{"result":{}}}}}},"400":{"description":"Invalid input"},"401":{"description":"Missing or invalid API key"},"403":{"description":"The key may not invoke this action"},"404":{"description":"Unknown action"}}}}}}