{"openapi": "3.0.3", "info": {"title": "ManufactIQ API", "version": "1", "description": "One company's CRM, read and written by its own systems. Every call carries an API key made under Administration > API keys, acts as the person the key names, and is checked as the screens check it: the same validation, the same roles, the same audit trail. The reference is at https://manufactiq.co.uk/api.", "contact": {"name": "ManufactIQ", "url": "https://manufactiq.co.uk", "email": "support@manufactiq.co.uk"}}, "servers": [{"url": "https://manufactiq.co.uk/api/v1", "description": "Replace the host with your own installation's."}], "security": [{"bearerAuth": []}, {"apiKeyHeader": []}], "tags": [{"name": "Getting started", "description": "Where the API is, the key, and who it acts as."}, {"name": "Companies", "description": "Customers, prospects, contractors, architects and suppliers, and everything filed against them."}, {"name": "Contacts", "description": "The people at those companies."}, {"name": "Enquiries", "description": "Every opportunity from the first call to won or lost, its lines and its stage, and the website's queue."}, {"name": "Quotations", "description": "Priced, revised, sent as a PDF, won or lost."}, {"name": "Orders", "description": "The job once it is placed, through the workshop to delivery."}, {"name": "Invoices", "description": "Raised against an order, in parts, and sent with your bank details."}, {"name": "Products", "description": "The price book a line is built from."}, {"name": "Tasks", "description": "Who is doing what, by when."}, {"name": "Activity", "description": "Calls, emails, meetings, site visits and notes, logged against a record."}, {"name": "Documents", "description": "The files held against a record, uploaded and downloaded."}, {"name": "Your own tabs", "description": "Records on the tabs the company designed itself."}, {"name": "Calendar", "description": "Every date in the CRM, between two days."}, {"name": "Reports", "description": "The figures the Reports tab shows, and the report builder."}, {"name": "Queues", "description": "Saved, named filters over a list, and the records in them."}, {"name": "Captured email", "description": "The correspondence filed against a record."}, {"name": "Automations", "description": "What the company has set up, whether it is on, and what it did."}, {"name": "Search", "description": "One box across everything."}, {"name": "Audit trail", "description": "Who changed which record, and to what."}, {"name": "Reference data", "description": "People, roles, pipelines, sources, categories, fields, tabs and settings."}], "paths": {"/api/v1/activities": {"get": {"operationId": "activities_list_activities", "tags": ["Activity"], "summary": "List activity", "description": "Newest first.\n\nNeeds: Any key, Activity tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the subject, detail and company."}, {"name": "type", "in": "query", "required": false, "schema": {"type": "string", "enum": ["call", "email", "meeting", "site_visit", "note", "other"]}, "description": "One activity type."}, {"name": "user", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "Who logged it: a user id."}, {"name": "days", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "Only the last so many days."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List activity", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Activity"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "activities_create", "tags": ["Activity"], "summary": "Log an activity", "description": "Logged in the key's own user's name. The company is filled in from the enquiry or contact when only those are given, so it shows on the customer's timeline.\n\nNeeds: Write key, Activity tab.", "parameters": [], "responses": {"201": {"description": "Log an activity", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Activity"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"activity_type": {"type": "string", "description": "call, email, meeting, site_visit, note (the default) or other.", "nullable": true, "enum": ["call", "email", "meeting", "site_visit", "note", "other"]}, "subject": {"type": "string", "description": "What it was, in a line.", "nullable": true}, "body": {"type": "string", "description": "The detail, up to 20,000 characters. @Name tells a colleague, as on the form.", "nullable": true}, "occurred_at": {"type": "string", "format": "date-time", "description": "When; now if left out.", "nullable": true}, "company_id": {"type": "integer", "description": "The company. At least one of company, contact or enquiry is needed."}, "contact_id": {"type": "integer", "description": "The contact."}, "enquiry_id": {"type": "integer", "description": "The enquiry."}}, "required": ["subject"]}}}}}}, "/api/v1/activities/{activity_id}": {"get": {"operationId": "activities_get", "tags": ["Activity"], "summary": "One activity", "description": "One activity\n\nNeeds: Any key, Activity tab.", "parameters": [{"name": "activity_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The activity id."}], "responses": {"200": {"description": "One activity", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Activity"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "delete": {"operationId": "activities_delete", "tags": ["Activity"], "summary": "Delete an activity", "description": "The key's own user's entries, or any entry for an administrator.\n\nNeeds: Write key, Activity tab.", "parameters": [{"name": "activity_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The activity id."}], "responses": {"200": {"description": "Delete an activity", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/audit": {"get": {"operationId": "audit_audit", "tags": ["Audit trail"], "summary": "The audit trail", "description": "With entity and record_id, one record's history - for a kind in the key's role. Without a record, the whole company's trail, newest first: administrators only.\n\nNeeds: Any key.", "parameters": [{"name": "entity", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A kind of record: company, contact, enquiry, quote, order, invoice, product, task, api_key or tenant_settings."}, {"name": "record_id", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "One record of that kind: its history."}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "At most so many, newest first; 100 if left out, 500 at most."}], "responses": {"200": {"description": "The audit trail", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/AuditEntry"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/automations": {"get": {"operationId": "automations_list_automations", "tags": ["Automations"], "summary": "List automations", "description": "Every automation, switched-on ones first, each with what it does in a line and what, if anything, stops it being switched on.\n\nNeeds: Any key, Administrator.", "parameters": [], "responses": {"200": {"description": "List automations", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Automation"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/automations/runs": {"get": {"operationId": "automations_runs", "tags": ["Automations"], "summary": "What automations did lately", "description": "The log across every automation: the record, the cause, the outcome and what each step did.\n\nNeeds: Any key, Administrator.", "parameters": [{"name": "limit", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "At most so many, newest first; 50 if left out."}], "responses": {"200": {"description": "What automations did lately", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/AutomationRun"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/automations/{automation_id}": {"get": {"operationId": "automations_get", "tags": ["Automations"], "summary": "One automation", "description": "With its own recent runs under runs.\n\nNeeds: Any key, Administrator.", "parameters": [{"name": "automation_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The automation id."}], "responses": {"200": {"description": "One automation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Automation"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/automations/{automation_id}/switch": {"post": {"operationId": "automations_switch", "tags": ["Automations"], "summary": "Switch an automation on or off", "description": "On only once it is complete; the answer says what is missing otherwise (422). Switched on, it acts on what happens from now on.\n\nNeeds: Write key, Administrator, Automations on the plan.", "parameters": [{"name": "automation_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The automation id."}], "responses": {"200": {"description": "Switch an automation on or off", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Automation"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"on": {"type": "boolean", "description": "true to switch it on, false to switch it off."}}, "required": ["on"]}}}}}}, "/api/v1/calendar": {"get": {"operationId": "calendar_events", "tags": ["Calendar"], "summary": "What is in the diary", "description": "Calls and meetings, tasks due, enquiries expected to close, quotations expiring and orders promised, in date order, with a count of each kind.\n\nNeeds: Any key, Calendar tab.", "parameters": [{"name": "from", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "The first day; today if left out."}, {"name": "to", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "The last day, inclusive; 30 days on if left out. At most a year."}, {"name": "kinds", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Which to include, comma-separated: meeting, task, enquiry, quote, order, note. Everything but notes if left out; only kinds from tabs in the key's role are drawn."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "Whose diary: a user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's diary."}, {"name": "done", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include what is already done, delivered or decided."}], "responses": {"200": {"description": "What is in the diary", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/CalendarEvent"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies": {"get": {"operationId": "companies_list_companies", "tags": ["Companies"], "summary": "List companies", "description": "The company list, with the same filters as the Companies tab.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the name, town, postcode, email and phone."}, {"name": "type", "in": "query", "required": false, "schema": {"type": "string", "enum": ["prospect", "customer", "main_contractor", "architect", "supplier", "other"]}, "description": "One company type."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An owner's user id."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include archived companies."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["name", "name_desc", "type", "recent", "created"]}, "description": "name (the default), name_desc, type, recent or created."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields: x_<field>=value, or x_<field>.from and x_<field>.to for a number, money or date field."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List companies", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Company"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "companies_create", "tags": ["Companies"], "summary": "Add a company", "description": "The same checks as the form, and the same duplicate check: a company that looks like one you already have is refused with 409 unless you say to add it anyway.\n\nNeeds: Write key, Companies tab.", "parameters": [], "responses": {"201": {"description": "Add a company", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Company"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "The company's name.", "nullable": true}, "company_type": {"type": "string", "description": "prospect (the default), customer, main_contractor, architect, supplier or other.", "nullable": true, "enum": ["prospect", "customer", "main_contractor", "architect", "supplier", "other"]}, "sector": {"type": "string", "description": "What they do.", "nullable": true}, "phone": {"type": "string", "description": "Telephone.", "nullable": true}, "email": {"type": "string", "description": "General address.", "nullable": true}, "website": {"type": "string", "description": "Website.", "nullable": true}, "address_line1": {"type": "string", "description": "Address, first line.", "nullable": true}, "address_line2": {"type": "string", "description": "Address, second line.", "nullable": true}, "city": {"type": "string", "description": "Town or city.", "nullable": true}, "county": {"type": "string", "description": "County.", "nullable": true}, "postcode": {"type": "string", "description": "Postcode.", "nullable": true}, "country": {"type": "string", "description": "Country; United Kingdom if left out.", "nullable": true}, "currency": {"type": "string", "description": "The currency they are usually quoted in (ISO code), or null for yours.", "nullable": true}, "notes": {"type": "string", "description": "Free notes, up to 10,000 characters.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "The account owner's user id (see GET /users); the key's own user if left out of a new company."}, "fields": {"type": "object", "additionalProperties": true, "description": "The company's extra fields, by name - see GET /fields."}, "confirm_duplicate": {"type": "boolean", "description": "true to save even though a similar company exists; without it a likely duplicate is refused with 409 and the matches."}}, "required": ["name"]}}}}}}, "/api/v1/companies/{company_id}": {"get": {"operationId": "companies_get", "tags": ["Companies"], "summary": "One company", "description": "The company, with the headline figures its page shows under summary: open enquiries and their value, enquiries won, quotes, open tasks.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "One company", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Company"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "companies_update", "tags": ["Companies"], "summary": "Change a company", "description": "Send only the fields to change; the rest keep their values.\n\nNeeds: Write key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Change a company", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Company"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "The company's name.", "nullable": true}, "company_type": {"type": "string", "description": "prospect (the default), customer, main_contractor, architect, supplier or other.", "nullable": true, "enum": ["prospect", "customer", "main_contractor", "architect", "supplier", "other"]}, "sector": {"type": "string", "description": "What they do.", "nullable": true}, "phone": {"type": "string", "description": "Telephone.", "nullable": true}, "email": {"type": "string", "description": "General address.", "nullable": true}, "website": {"type": "string", "description": "Website.", "nullable": true}, "address_line1": {"type": "string", "description": "Address, first line.", "nullable": true}, "address_line2": {"type": "string", "description": "Address, second line.", "nullable": true}, "city": {"type": "string", "description": "Town or city.", "nullable": true}, "county": {"type": "string", "description": "County.", "nullable": true}, "postcode": {"type": "string", "description": "Postcode.", "nullable": true}, "country": {"type": "string", "description": "Country; United Kingdom if left out.", "nullable": true}, "currency": {"type": "string", "description": "The currency they are usually quoted in (ISO code), or null for yours.", "nullable": true}, "notes": {"type": "string", "description": "Free notes, up to 10,000 characters.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "The account owner's user id (see GET /users); the key's own user if left out of a new company."}, "fields": {"type": "object", "additionalProperties": true, "description": "The company's extra fields, by name - see GET /fields."}, "confirm_duplicate": {"type": "boolean", "description": "true to save even though a similar company exists; without it a likely duplicate is refused with 409 and the matches."}}, "required": ["name"]}}}}}, "delete": {"operationId": "companies_delete", "tags": ["Companies"], "summary": "Delete a company permanently", "description": "Administrators only, and refused with 409 while enquiries, quotations or records on your own tabs still point at it. Contacts are detached; activities, tasks and documents go with it. Archive instead to keep the history.\n\nNeeds: Write key, Administrator, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Delete a company permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/archive": {"post": {"operationId": "companies_archive", "tags": ["Companies"], "summary": "Archive a company", "description": "The ordinary way to dispose of one: it keeps its history and leaves the lists.\n\nNeeds: Write key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Archive a company", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Company"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/restore": {"post": {"operationId": "companies_restore", "tags": ["Companies"], "summary": "Restore an archived company", "description": "Restore an archived company\n\nNeeds: Write key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Restore an archived company", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Company"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/contacts": {"get": {"operationId": "companies_contacts", "tags": ["Companies"], "summary": "Its contacts", "description": "What the company's page shows under its contacts. Needs the contacts tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its contacts", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Contact"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/enquiries": {"get": {"operationId": "companies_enquiries", "tags": ["Companies"], "summary": "Its enquiries", "description": "What the company's page shows under its enquiries. Needs the enquiries tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its enquiries", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Enquiry"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/quotes": {"get": {"operationId": "companies_quotes", "tags": ["Companies"], "summary": "Its quotations", "description": "What the company's page shows under its quotations. Needs the quotes tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its quotations", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Quote"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/orders": {"get": {"operationId": "companies_orders", "tags": ["Companies"], "summary": "Its orders", "description": "What the company's page shows under its orders. Needs the orders tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its orders", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Order"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/invoices": {"get": {"operationId": "companies_invoices", "tags": ["Companies"], "summary": "Its invoices", "description": "What the company's page shows under its invoices. Needs the invoices tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its invoices", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Invoice"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/tasks": {"get": {"operationId": "companies_tasks", "tags": ["Companies"], "summary": "Its open tasks", "description": "What the company's page shows under its open tasks. Needs the tasks tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its open tasks", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/activities": {"get": {"operationId": "companies_activities", "tags": ["Companies"], "summary": "Its activity", "description": "What the company's page shows under its activity. Needs the activities tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its activity", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Activity"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/documents": {"get": {"operationId": "companies_documents", "tags": ["Companies"], "summary": "Its documents", "description": "What the company's page shows under its documents. Needs the documents tab in the key's role.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its documents", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Document"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/emails": {"get": {"operationId": "companies_emails", "tags": ["Companies"], "summary": "Its captured emails", "description": "What the company's page shows under its captured emails. \n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Its captured emails", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Email"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/companies/{company_id}/records": {"get": {"operationId": "companies_records", "tags": ["Companies"], "summary": "Records on your own tabs linked to it", "description": "Live records from the company's own tabs - an NCR raised against them, a survey done for them - with the tab each is on.\n\nNeeds: Any key, Companies tab.", "parameters": [{"name": "company_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The company id."}], "responses": {"200": {"description": "Records on your own tabs linked to it", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/LinkedRecord"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/contacts": {"get": {"operationId": "contacts_list_contacts", "tags": ["Contacts"], "summary": "List contacts", "description": "List contacts\n\nNeeds: Any key, Contacts tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the name, email, phone and company."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include archived contacts."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["name", "name_desc", "company", "recent"]}, "description": "name (the default), name_desc, company or recent."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields, as for companies."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List contacts", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Contact"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "contacts_create", "tags": ["Contacts"], "summary": "Add a contact", "description": "A contact that looks like one you already have is refused with 409 and the matches, unless confirm_duplicate is true.\n\nNeeds: Write key, Contacts tab.", "parameters": [], "responses": {"201": {"description": "Add a contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Contact"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The company they are at (see GET /companies)."}, "first_name": {"type": "string", "description": "First name.", "nullable": true}, "last_name": {"type": "string", "description": "Surname.", "nullable": true}, "job_title": {"type": "string", "description": "Job title.", "nullable": true}, "email": {"type": "string", "description": "Email address.", "nullable": true}, "phone": {"type": "string", "description": "Telephone.", "nullable": true}, "mobile": {"type": "string", "description": "Mobile.", "nullable": true}, "is_primary": {"type": "boolean", "description": "true to make them the main contact at their company; the previous main contact stops being it."}, "notes": {"type": "string", "description": "Free notes, up to 10,000 characters.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The contact's extra fields, by name - see GET /fields."}, "confirm_duplicate": {"type": "boolean", "description": "true to save even though a similar contact exists."}}, "required": ["first_name", "last_name"]}}}}}}, "/api/v1/contacts/{contact_id}": {"get": {"operationId": "contacts_get", "tags": ["Contacts"], "summary": "One contact", "description": "One contact\n\nNeeds: Any key, Contacts tab.", "parameters": [{"name": "contact_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The contact id."}], "responses": {"200": {"description": "One contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Contact"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "contacts_update", "tags": ["Contacts"], "summary": "Change a contact", "description": "Send only the fields to change.\n\nNeeds: Write key, Contacts tab.", "parameters": [{"name": "contact_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The contact id."}], "responses": {"200": {"description": "Change a contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Contact"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The company they are at (see GET /companies)."}, "first_name": {"type": "string", "description": "First name.", "nullable": true}, "last_name": {"type": "string", "description": "Surname.", "nullable": true}, "job_title": {"type": "string", "description": "Job title.", "nullable": true}, "email": {"type": "string", "description": "Email address.", "nullable": true}, "phone": {"type": "string", "description": "Telephone.", "nullable": true}, "mobile": {"type": "string", "description": "Mobile.", "nullable": true}, "is_primary": {"type": "boolean", "description": "true to make them the main contact at their company; the previous main contact stops being it."}, "notes": {"type": "string", "description": "Free notes, up to 10,000 characters.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The contact's extra fields, by name - see GET /fields."}, "confirm_duplicate": {"type": "boolean", "description": "true to save even though a similar contact exists."}}, "required": ["first_name", "last_name"]}}}}}, "delete": {"operationId": "contacts_delete", "tags": ["Contacts"], "summary": "Delete a contact permanently", "description": "Administrators only. Their documents go with them.\n\nNeeds: Write key, Administrator, Contacts tab.", "parameters": [{"name": "contact_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The contact id."}], "responses": {"200": {"description": "Delete a contact permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/contacts/{contact_id}/archive": {"post": {"operationId": "contacts_archive", "tags": ["Contacts"], "summary": "Archive a contact", "description": "Archive a contact\n\nNeeds: Write key, Contacts tab.", "parameters": [{"name": "contact_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The contact id."}], "responses": {"200": {"description": "Archive a contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Contact"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/contacts/{contact_id}/restore": {"post": {"operationId": "contacts_restore", "tags": ["Contacts"], "summary": "Restore an archived contact", "description": "Restore an archived contact\n\nNeeds: Write key, Contacts tab.", "parameters": [{"name": "contact_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The contact id."}], "responses": {"200": {"description": "Restore an archived contact", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Contact"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/documents": {"get": {"operationId": "documents_list_documents", "tags": ["Documents"], "summary": "List documents", "description": "Every document the company holds that the key's role may see, newest first, with how much storage is in use.\n\nNeeds: Any key, Documents tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the file name, description, company and references."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "user", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "Who uploaded it: a user id."}, {"name": "days", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "Only the last so many days."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["recent", "oldest", "name", "name_desc", "size", "size_asc"]}, "description": "recent (the default), oldest, name, name_desc, size or size_asc."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List documents", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Document"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "documents_upload", "tags": ["Documents"], "summary": "Upload documents", "description": "A multipart form, not JSON. Each file is dealt with on its own: one refused does not lose the others, and every refusal is named under refused. The storage allowance is checked for the whole batch first.\n\nNeeds: Write key, Documents tab.", "parameters": [], "responses": {"201": {"description": "Upload documents", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Document"}}}}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"multipart/form-data": {"schema": {"type": "object", "properties": {"files": {"type": "string", "format": "binary", "description": "One or more files, as multipart form parts named files (or file). The name, type and size rules are the upload box's: documents, spreadsheets, drawings, photographs and archives; never programs or scripts.", "nullable": true}, "company_id": {"type": "integer", "description": "The record to file them against: at least one of these."}, "contact_id": {"type": "integer", "description": "A contact."}, "enquiry_id": {"type": "integer", "description": "An enquiry."}, "quote_id": {"type": "integer", "description": "A quotation."}, "order_id": {"type": "integer", "description": "An order."}, "record_id": {"type": "integer", "description": "A record on one of your own tabs."}, "description": {"type": "string", "description": "What the files are.", "nullable": true}}, "required": ["files"]}}}}}}, "/api/v1/documents/{attachment_id}": {"get": {"operationId": "documents_get", "tags": ["Documents"], "summary": "One document", "description": "The record of the file; the bytes are at .../file.\n\nNeeds: Any key, Documents tab.", "parameters": [{"name": "attachment_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The attachment id."}], "responses": {"200": {"description": "One document", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Document"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "documents_update", "tags": ["Documents"], "summary": "Change a document's description", "description": "Change a document's description\n\nNeeds: Write key, Documents tab.", "parameters": [{"name": "attachment_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The attachment id."}], "responses": {"200": {"description": "Change a document's description", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Document"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"description": {"type": "string", "description": "What the file is.", "nullable": true}}, "required": ["description"]}}}}}, "delete": {"operationId": "documents_delete", "tags": ["Documents"], "summary": "Delete a document", "description": "The key's own user's uploads, or any document for an administrator.\n\nNeeds: Write key, Documents tab.", "parameters": [{"name": "attachment_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The attachment id."}], "responses": {"200": {"description": "Delete a document", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/documents/{attachment_id}/file": {"get": {"operationId": "documents_file", "tags": ["Documents"], "summary": "Download a document", "description": "The bytes, as an attachment - or, where files are held in object storage, a redirect to a link that works for a few minutes. Follow redirects.\n\nNeeds: Any key, Documents tab.", "parameters": [{"name": "attachment_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The attachment id."}, {"name": "inline", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to ask for it inline, for a PDF or photograph."}], "responses": {"200": {"description": "the file's own type", "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/emails": {"get": {"operationId": "emails_list_emails", "tags": ["Captured email"], "summary": "Captured emails on a record", "description": "One of the record arguments is needed. For an enquiry, quotation, order or invoice the answer is the whole job's correspondence, as the pages show it. Messages a colleague captured privately are left out; the record must be on a tab in the key's role.\n\nNeeds: Any key.", "parameters": [{"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "Filed against a company: its id."}, {"name": "contact", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A contact's id."}, {"name": "enquiry", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An enquiry's id - which answers for the whole job."}, {"name": "quote", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A quotation's id."}, {"name": "order", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An order's id."}, {"name": "invoice", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An invoice's id."}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "At most so many, newest first; 100 if left out."}], "responses": {"200": {"description": "Captured emails on a record", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Email"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/emails/{email_id}": {"get": {"operationId": "emails_get", "tags": ["Captured email"], "summary": "One captured email", "description": "With its plain-text body (quoted history trimmed), who was on it and what was attached. A colleague's private message answers 404.\n\nNeeds: Any key.", "parameters": [{"name": "email_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The email id."}], "responses": {"200": {"description": "One captured email", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Email"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/emails/{email_id}/files/{attachment_id}": {"get": {"operationId": "emails_file", "tags": ["Captured email"], "summary": "Download an email's attachment", "description": "Always as an attachment, never inline: these bytes came from outside.\n\nNeeds: Any key.", "parameters": [{"name": "email_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The email id."}, {"name": "attachment_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The attachment id."}], "responses": {"200": {"description": "the file's own type", "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries": {"get": {"operationId": "enquiries_list_enquiries", "tags": ["Enquiries"], "summary": "List enquiries", "description": "List enquiries\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the reference, title, company, description and site postcode."}, {"name": "stage", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A stage id."}, {"name": "pipeline", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A pipeline id."}, {"name": "outcome", "in": "query", "required": false, "schema": {"type": "string", "enum": ["open", "won", "lost"]}, "description": "open, won or lost."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An owner's user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's enquiries."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "category", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A product category."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include archived enquiries."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["recent", "created", "reference", "value", "value_asc", "close", "company", "stage"]}, "description": "recent (the default), created, reference, value, value_asc, close, company or stage."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List enquiries", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Enquiry"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "enquiries_create", "tags": ["Enquiries"], "summary": "Raise an enquiry", "description": "Takes the next reference in the company's format. The owner is emailed and Microsoft Teams told, as from the form.\n\nNeeds: Write key, Enquiries tab.", "parameters": [], "responses": {"201": {"description": "Raise an enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"title": {"type": "string", "description": "What it is for, in a line.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer (see GET /companies)."}, "contact_id": {"type": "integer", "description": "The contact at that company."}, "pipeline_id": {"type": "integer", "description": "Which enquiry pipeline it starts on; the default one if left out. On a PATCH, move it with POST .../stage instead."}, "stage_id": {"type": "integer", "description": "The stage; the pipeline's first open stage if left out."}, "source_id": {"type": "integer", "description": "Where it came from (see GET /sources)."}, "product_category": {"type": "string", "description": "What it is for: one of GET /product-categories; the company's default if left out.", "nullable": true}, "estimated_value": {"type": "string", "format": "decimal", "description": "What it is worth, in your currency.", "nullable": true}, "probability": {"type": "integer", "description": "The odds, 0 to 100; the stage's own figure if left out."}, "expected_close_date": {"type": "string", "format": "date", "description": "When a decision is expected.", "nullable": true}, "site_postcode": {"type": "string", "description": "Where the work would be.", "nullable": true}, "description": {"type": "string", "description": "The long description, up to 20,000 characters.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out. A new owner is emailed."}, "lines": {"type": "array", "items": {}, "description": "What is being asked for, as a list of lines (see PUT .../lines). On a POST only; change them afterwards with PUT .../lines."}, "fields": {"type": "object", "additionalProperties": true, "description": "The enquiry's extra fields, by name."}}, "required": ["title", "company_id"]}}}}}}, "/api/v1/enquiries/{enquiry_id}": {"get": {"operationId": "enquiries_get", "tags": ["Enquiries"], "summary": "One enquiry", "description": "With its lines, the quotations, orders and invoices behind it (those the key's role may see), and the stages of its pipeline with the odds it would take on each.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "One enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "enquiries_update", "tags": ["Enquiries"], "summary": "Change an enquiry", "description": "Send only the fields to change. A changed stage carries the odds with it unless a probability is sent too; a new owner is emailed.\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Change an enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"title": {"type": "string", "description": "What it is for, in a line.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer (see GET /companies)."}, "contact_id": {"type": "integer", "description": "The contact at that company."}, "pipeline_id": {"type": "integer", "description": "Which enquiry pipeline it starts on; the default one if left out. On a PATCH, move it with POST .../stage instead."}, "stage_id": {"type": "integer", "description": "The stage; the pipeline's first open stage if left out."}, "source_id": {"type": "integer", "description": "Where it came from (see GET /sources)."}, "product_category": {"type": "string", "description": "What it is for: one of GET /product-categories; the company's default if left out.", "nullable": true}, "estimated_value": {"type": "string", "format": "decimal", "description": "What it is worth, in your currency.", "nullable": true}, "probability": {"type": "integer", "description": "The odds, 0 to 100; the stage's own figure if left out."}, "expected_close_date": {"type": "string", "format": "date", "description": "When a decision is expected.", "nullable": true}, "site_postcode": {"type": "string", "description": "Where the work would be.", "nullable": true}, "description": {"type": "string", "description": "The long description, up to 20,000 characters.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out. A new owner is emailed."}, "lines": {"type": "array", "items": {}, "description": "What is being asked for, as a list of lines (see PUT .../lines). On a POST only; change them afterwards with PUT .../lines."}, "fields": {"type": "object", "additionalProperties": true, "description": "The enquiry's extra fields, by name."}}, "required": ["title", "company_id"]}}}}}, "delete": {"operationId": "enquiries_delete", "tags": ["Enquiries"], "summary": "Delete an enquiry permanently", "description": "Administrators only. Its documents go with it.\n\nNeeds: Write key, Administrator, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Delete an enquiry permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/stage": {"post": {"operationId": "enquiries_change_stage", "tags": ["Enquiries"], "summary": "Move an enquiry to a stage", "description": "What dragging the card does: the odds travel with it, a note is logged, and a won stage wins the chosen quotation and raises the order. The answer carries messages - what the page would have said.\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Move an enquiry to a stage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"stage_id": {"type": "integer", "description": "The stage to move to - on any of the company's enquiry pipelines."}, "outcome_reason": {"type": "string", "description": "Why, where the stage is won or lost.", "nullable": true}, "winning_quote_id": {"type": "integer", "description": "When moving to a won stage: which quotation won it. Marks that quotation won and raises its order, as the page does."}, "customer_po": {"type": "string", "description": "The customer's order number, for the order raised.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "What the customer was promised, for the order raised.", "nullable": true}}, "required": ["stage_id"]}}}}}}, "/api/v1/enquiries/{enquiry_id}/pipeline": {"post": {"operationId": "enquiries_change_pipeline", "tags": ["Enquiries"], "summary": "Move an enquiry to another pipeline", "description": "It lands at the start of the new route - or, if won or lost, on that route's stage for the outcome.\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Move an enquiry to another pipeline", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"pipeline_id": {"type": "integer", "description": "One of the company's enquiry pipelines."}}, "required": ["pipeline_id"]}}}}}}, "/api/v1/enquiries/{enquiry_id}/lines": {"get": {"operationId": "enquiries_lines", "tags": ["Enquiries"], "summary": "What an enquiry asks for", "description": "What an enquiry asks for\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "What an enquiry asks for", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/EnquiryLine"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "put": {"operationId": "enquiries_put_lines", "tags": ["Enquiries"], "summary": "Replace what an enquiry asks for", "description": "The whole set, as the page saves it. An unpriced line is allowed; the enquiry's estimated value is re-totalled from the priced ones.\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Replace what an enquiry asks for", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"lines": {"type": "array", "items": {}, "description": "The whole set of lines, each as below; an empty list removes them all."}, "product_id": {"type": "integer", "description": "A product from the price book; its wording, unit, price and cost fill whatever the line leaves blank."}, "description": {"type": "string", "description": "What is asked for. Needed unless a product supplies it.", "nullable": true}, "quantity": {"type": "string", "format": "decimal", "description": "How many.", "nullable": true}, "unit": {"type": "string", "description": "each, bay, m and so on; the product's, or each.", "nullable": true}, "unit_price": {"type": "string", "format": "decimal", "description": "Price each. Leave out while it is not yet priced.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost each, if known.", "nullable": true}, "notes": {"type": "string", "description": "A note on the line.", "nullable": true}, "dim_length": {"type": "integer", "description": "Length in mm, for a product sold at a size."}, "dim_width": {"type": "integer", "description": "Width in mm."}, "dim_height": {"type": "integer", "description": "Height in mm."}}, "required": ["lines", "quantity"]}}}}}}, "/api/v1/enquiries/{enquiry_id}/archive": {"post": {"operationId": "enquiries_archive", "tags": ["Enquiries"], "summary": "Archive an enquiry", "description": "Archive an enquiry\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Archive an enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/restore": {"post": {"operationId": "enquiries_restore", "tags": ["Enquiries"], "summary": "Restore an archived enquiry", "description": "Restore an archived enquiry\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Restore an archived enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/quotes": {"get": {"operationId": "enquiries_quotes", "tags": ["Enquiries"], "summary": "Its quotations", "description": "What the enquiry's page shows under its quotations. Needs the quotes tab in the key's role.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Its quotations", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Quote"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/orders": {"get": {"operationId": "enquiries_orders", "tags": ["Enquiries"], "summary": "Its orders", "description": "What the enquiry's page shows under its orders. Needs the orders tab in the key's role.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Its orders", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Order"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/invoices": {"get": {"operationId": "enquiries_invoices", "tags": ["Enquiries"], "summary": "Its invoices", "description": "What the enquiry's page shows under its invoices. Needs the invoices tab in the key's role.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Its invoices", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Invoice"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/tasks": {"get": {"operationId": "enquiries_tasks", "tags": ["Enquiries"], "summary": "Its tasks", "description": "What the enquiry's page shows under its tasks. Needs the tasks tab in the key's role.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Its tasks", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/activities": {"get": {"operationId": "enquiries_activities", "tags": ["Enquiries"], "summary": "Its activity", "description": "What the enquiry's page shows under its activity. Needs the activities tab in the key's role.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Its activity", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Activity"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/documents": {"get": {"operationId": "enquiries_documents", "tags": ["Enquiries"], "summary": "Its documents", "description": "What the enquiry's page shows under its documents. Needs the documents tab in the key's role.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "Its documents", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Document"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/{enquiry_id}/emails": {"get": {"operationId": "enquiries_emails", "tags": ["Enquiries"], "summary": "The job's captured emails", "description": "What the enquiry's page shows under the job's captured emails.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "enquiry_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The enquiry id."}], "responses": {"200": {"description": "The job's captured emails", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Email"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/waiting": {"get": {"operationId": "enquiries_waiting", "tags": ["Enquiries"], "summary": "Website enquiries waiting to be approved", "description": "What the form on the company's website sent, newest first, until somebody approves or rejects each one.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "Website enquiries waiting to be approved", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/WebSubmission"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/waiting/{submission_id}": {"get": {"operationId": "enquiries_waiting_one", "tags": ["Enquiries"], "summary": "One website enquiry", "description": "With what the CRM already knows under matches - the contact by email, their company, or a company by name or domain - and the values the approval would start from under suggested.\n\nNeeds: Any key, Enquiries tab.", "parameters": [{"name": "submission_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The submission id."}], "responses": {"200": {"description": "One website enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebSubmission"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/enquiries/waiting/{submission_id}/approve": {"post": {"operationId": "enquiries_approve", "tags": ["Enquiries"], "summary": "Approve a website enquiry", "description": "What approving on the page does: the company and contact are found or made, the enquiry raised with the next reference and a note holding everything as sent, the owner emailed and Teams told. Every value starts from what GET .../waiting/{id} suggests; send only what differs.\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "submission_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The submission id."}], "responses": {"201": {"description": "Approve a website enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Enquiry"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_choice": {"type": "string", "description": "existing or new.", "nullable": true, "enum": ["existing", "new"]}, "company_id": {"type": "integer", "description": "With existing: the company."}, "new_company_name": {"type": "string", "description": "With new: the company's name, and new_company_phone, new_company_email, new_company_address_line1, new_company_address_line2, new_company_city, new_company_county, new_company_postcode as wanted.", "nullable": true}, "contact_choice": {"type": "string", "description": "existing, new or none.", "nullable": true, "enum": ["existing", "new", "none"]}, "contact_id": {"type": "integer", "description": "With existing: the contact, at that company."}, "new_contact_first_name": {"type": "string", "description": "With new: their first name, and new_contact_last_name, new_contact_job_title, new_contact_email, new_contact_phone, new_contact_mobile.", "nullable": true}, "title": {"type": "string", "description": "The enquiry's title.", "nullable": true}, "stage_id": {"type": "integer", "description": "The stage; the default pipeline's first if left out."}, "owner_user_id": {"type": "integer", "description": "Who looks after it; the key's own user if left out."}, "source_id": {"type": "integer", "description": "The enquiry source; the one called Website if there is one."}, "product_category": {"type": "string", "description": "What it is for.", "nullable": true}, "estimated_value": {"type": "string", "format": "decimal", "description": "What it is worth.", "nullable": true}, "probability": {"type": "integer", "description": "The odds; the stage's figure if left out."}, "expected_close_date": {"type": "string", "format": "date", "description": "When a decision is expected.", "nullable": true}, "site_postcode": {"type": "string", "description": "Where the work would be.", "nullable": true}, "description": {"type": "string", "description": "The description; the message and their answers if left out.", "nullable": true}, "email_customer": {"type": "boolean", "description": "Whether to send the sender the 'in progress' email, where the company has it switched on. Defaults to the company's setting."}, "fields": {"type": "object", "additionalProperties": true, "description": "The enquiry's extra fields, by name."}}, "required": ["title"]}}}}}}, "/api/v1/enquiries/waiting/{submission_id}/reject": {"post": {"operationId": "enquiries_reject", "tags": ["Enquiries"], "summary": "Reject a website enquiry", "description": "Nothing is created and nobody is emailed. It can be put back for 30 days.\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "submission_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The submission id."}], "responses": {"200": {"description": "Reject a website enquiry", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebSubmission"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"review_note": {"type": "string", "description": "Why, for the record.", "nullable": true}}}}}}}}, "/api/v1/enquiries/waiting/{submission_id}/restore": {"post": {"operationId": "enquiries_restore_waiting", "tags": ["Enquiries"], "summary": "Put a rejected website enquiry back in the queue", "description": "Put a rejected website enquiry back in the queue\n\nNeeds: Write key, Enquiries tab.", "parameters": [{"name": "submission_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The submission id."}], "responses": {"200": {"description": "Put a rejected website enquiry back in the queue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebSubmission"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/invoices": {"get": {"operationId": "invoices_list_invoices", "tags": ["Invoices"], "summary": "List invoices", "description": "Newest first. The answer carries the invoice book's figures too: drafts, outstanding, overdue and billed this month.\n\nNeeds: Any key, Invoices tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the reference, PO number, company, quotation and order references."}, {"name": "status", "in": "query", "required": false, "schema": {"type": "string", "enum": ["draft", "sent", "paid", "cancelled"]}, "description": "draft, sent, paid or cancelled."}, {"name": "pipeline", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A pipeline id."}, {"name": "open", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for draft and sent invoices."}, {"name": "overdue", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for sent invoices past their due date."}, {"name": "billing", "in": "query", "required": false, "schema": {"type": "string", "enum": ["part", "full", "none"]}, "description": "part, full or none: how much of the invoice's order is billed."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An owner's user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's invoices."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include archived invoices."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["recent", "reference", "due", "value", "customer", "status"]}, "description": "recent (the default), reference, due, value, customer or status."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List invoices", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Invoice"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "invoices_create", "tags": ["Invoices"], "summary": "Raise an invoice", "description": "An invoice typed in whole. Against an order (order_id) its lines may be anchored to the order's lines, and a quantity beyond what is left to bill is refused (422); a line with no anchor is deliberately uncapped. It takes the order's reference, with -2, -3 for further invoices on the job.\n\nNeeds: Write key, Invoices tab.", "parameters": [], "responses": {"201": {"description": "Raise an invoice", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The customer."}, "contact_id": {"type": "integer", "description": "The contact."}, "order_id": {"type": "integer", "description": "The order it bills. To bill some of an order's lines, use POST /orders/{order_id}/invoice instead, which does the picking."}, "quote_id": {"type": "integer", "description": "The quotation."}, "enquiry_id": {"type": "integer", "description": "The enquiry."}, "customer_po": {"type": "string", "description": "The customer's order number.", "nullable": true}, "invoice_date": {"type": "string", "format": "date", "description": "Dated; today if left out.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "Payment due; the company's payment days on if left out.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms, as written.", "nullable": true}, "discount_pct": {"type": "string", "format": "decimal", "description": "Whole-invoice discount, per cent; usually nil.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate; the company's default if left out.", "nullable": true}, "currency": {"type": "string", "description": "ISO code; yours if left out.", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours.", "nullable": true}, "notes": {"type": "string", "description": "Notes printed on it.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out."}, "pipeline_id": {"type": "integer", "description": "Which invoice pipeline it travels; the default if left out."}, "lines": {"type": "array", "items": {}, "description": "The lines, each as below. At least one."}, "fields": {"type": "object", "additionalProperties": true, "description": "The invoice's extra fields, by name."}}, "required": ["company_id", "lines"]}}}}}}, "/api/v1/orders/{order_id}/invoice": {"post": {"operationId": "invoices_from_order", "tags": ["Invoices"], "summary": "Invoice some or all of an order", "description": "The part-invoicing screen: the lines are read off the order, never from the request, so only the quantity and price of each can be chosen. What is not picked stays on the order for the next invoice. An order with no lines, or a cancelled one, is refused (409). Needs the orders tab in the key's role.\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"201": {"description": "Invoice some or all of an order", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"lines": {"type": "array", "items": {}, "description": "Which order lines to bill, each {order_line_id, quantity, unit_price}: quantity defaults to what is left, unit_price to the price agreed. Leave the whole list out to bill everything left on the order."}, "invoice_date": {"type": "string", "format": "date", "description": "Dated; today if left out.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "Payment due.", "nullable": true}, "customer_po": {"type": "string", "description": "The customer's order number; the order's if left out.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms; the quotation's if left out.", "nullable": true}, "notes": {"type": "string", "description": "Notes printed on it.", "nullable": true}}}}}}}}, "/api/v1/invoices/{invoice_id}": {"get": {"operationId": "invoices_get", "tags": ["Invoices"], "summary": "One invoice", "description": "With its lines, how much of its order is billed, the other invoices on the same order and the stages of its pipeline.\n\nNeeds: Any key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "One invoice", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "invoices_update", "tags": ["Invoices"], "summary": "Change an invoice", "description": "Send only the fields to change; lines sent replace the set. A paid or cancelled invoice cannot be changed (409).\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Change an invoice", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The customer."}, "contact_id": {"type": "integer", "description": "The contact."}, "order_id": {"type": "integer", "description": "The order it bills. To bill some of an order's lines, use POST /orders/{order_id}/invoice instead, which does the picking."}, "quote_id": {"type": "integer", "description": "The quotation."}, "enquiry_id": {"type": "integer", "description": "The enquiry."}, "customer_po": {"type": "string", "description": "The customer's order number.", "nullable": true}, "invoice_date": {"type": "string", "format": "date", "description": "Dated; today if left out.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "Payment due; the company's payment days on if left out.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms, as written.", "nullable": true}, "discount_pct": {"type": "string", "format": "decimal", "description": "Whole-invoice discount, per cent; usually nil.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate; the company's default if left out.", "nullable": true}, "currency": {"type": "string", "description": "ISO code; yours if left out.", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours.", "nullable": true}, "notes": {"type": "string", "description": "Notes printed on it.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out."}, "pipeline_id": {"type": "integer", "description": "Which invoice pipeline it travels; the default if left out."}, "lines": {"type": "array", "items": {}, "description": "The lines, each as below. At least one."}, "fields": {"type": "object", "additionalProperties": true, "description": "The invoice's extra fields, by name."}}, "required": ["company_id", "lines"]}}}}}, "delete": {"operationId": "invoices_delete", "tags": ["Invoices"], "summary": "Delete an invoice permanently", "description": "Administrators only. What it billed goes back on the order.\n\nNeeds: Write key, Administrator, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Delete an invoice permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/invoices/{invoice_id}/status": {"post": {"operationId": "invoices_set_status", "tags": ["Invoices"], "summary": "Mark an invoice sent, paid or cancelled", "description": "Sent and paid stamp their dates and tell the enquiry's and the order's pipelines. Cancelling puts what was on it back on the order to be invoiced again. Paid tells Teams. A note is logged.\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Mark an invoice sent, paid or cancelled", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string", "description": "draft, sent, paid or cancelled.", "nullable": true, "enum": ["draft", "sent", "paid", "cancelled"]}, "outcome_reason": {"type": "string", "description": "A note, kept with the change.", "nullable": true}}, "required": ["status"]}}}}}}, "/api/v1/invoices/{invoice_id}/stage": {"post": {"operationId": "invoices_set_stage", "tags": ["Invoices"], "summary": "Move an invoice to a stage", "description": "Onto a stage recording sent marks it sent, onto paid marks it paid, with everything that follows. A cancelled invoice is not moved (409).\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Move an invoice to a stage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"stage_id": {"type": "integer", "description": "A stage on one of the company's invoice pipelines."}, "outcome_reason": {"type": "string", "description": "A note, kept with the change.", "nullable": true}}, "required": ["stage_id"]}}}}}}, "/api/v1/invoices/{invoice_id}/pipeline": {"post": {"operationId": "invoices_change_pipeline", "tags": ["Invoices"], "summary": "Move an invoice to another pipeline", "description": "Move an invoice to another pipeline\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Move an invoice to another pipeline", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"pipeline_id": {"type": "integer", "description": "One of the company's invoice pipelines."}}, "required": ["pipeline_id"]}}}}}}, "/api/v1/invoices/{invoice_id}/send": {"post": {"operationId": "invoices_send", "tags": ["Invoices"], "summary": "Email an invoice, or a reminder", "description": "A draft goes as the invoice and becomes sent; one already sent goes again as a payment reminder. Your bank details and terms from Administration > Documents are on it. Paid and cancelled invoices are refused (409).\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Email an invoice, or a reminder", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"to_email": {"type": "string", "description": "Who to; the contact's address if left out.", "nullable": true}, "message": {"type": "string", "description": "A note above the document, up to 2,000 characters.", "nullable": true}, "attach_pdf": {"type": "boolean", "description": "Whether the PDF goes with it. Default true."}}}}}}}}, "/api/v1/invoices/{invoice_id}/pdf": {"get": {"operationId": "invoices_pdf", "tags": ["Invoices"], "summary": "The invoice as a PDF", "description": "The customer's copy, with the letterhead, VAT number and bank details.\n\nNeeds: Any key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "application/pdf", "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/invoices/{invoice_id}/archive": {"post": {"operationId": "invoices_archive", "tags": ["Invoices"], "summary": "Archive an invoice", "description": "Archive an invoice\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Archive an invoice", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/invoices/{invoice_id}/restore": {"post": {"operationId": "invoices_restore", "tags": ["Invoices"], "summary": "Restore an archived invoice", "description": "Restore an archived invoice\n\nNeeds: Write key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "Restore an archived invoice", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Invoice"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/invoices/{invoice_id}/emails": {"get": {"operationId": "invoices_emails_of", "tags": ["Invoices"], "summary": "The job's captured emails", "description": "The job's captured emails\n\nNeeds: Any key, Invoices tab.", "parameters": [{"name": "invoice_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The invoice id."}], "responses": {"200": {"description": "The job's captured emails", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Email"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1": {"get": {"operationId": "meta_index", "tags": ["Getting started"], "summary": "Where the API is", "description": "Answers without a key: the version, where the reference is and how to authenticate. A good first call when setting a client up.", "parameters": [], "responses": {"200": {"description": "Where the API is", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Index"}}}}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "security": []}}, "/api/v1/openapi.json": {"get": {"operationId": "meta_openapi", "tags": ["Getting started"], "summary": "The OpenAPI document", "description": "Every route, parameter and schema as an OpenAPI 3.0 document, for Postman, Insomnia, a code generator or a browser-based explorer.", "parameters": [], "responses": {"200": {"description": "The OpenAPI document", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OpenAPI"}}}}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "security": []}}, "/api/v1/me": {"get": {"operationId": "meta_me", "tags": ["Getting started"], "summary": "Who this key is", "description": "The key, the person it acts as, the company and the rate limit. The call to make to check a key works.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "Who this key is", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Me"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/keys": {"get": {"operationId": "meta_keys", "tags": ["Getting started"], "summary": "The company's API keys", "description": "Every key the company has made, live ones first, without the keys themselves - those were shown once. Administrators only; keys are made and revoked under Administration > API keys.\n\nNeeds: Any key, Administrator.", "parameters": [], "responses": {"200": {"description": "The company's API keys", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/ApiKey"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders": {"get": {"operationId": "orders_list_orders", "tags": ["Orders"], "summary": "List orders", "description": "Soonest promised first. The answer carries the order book's summary too.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the reference, PO number, company, site and invoice reference."}, {"name": "status", "in": "query", "required": false, "schema": {"type": "string", "enum": ["confirmed", "drawings", "manufacturing", "ready", "delivered", "installed", "complete", "cancelled"]}, "description": "One workshop status."}, {"name": "pipeline", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A pipeline id."}, {"name": "open", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for orders still in hand."}, {"name": "late", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for orders past their promised date and not delivered."}, {"name": "uninvoiced", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for delivered orders with no invoice recorded."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An owner's user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's orders."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include archived orders."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["promised", "promised_desc", "reference", "created", "value", "customer", "status"]}, "description": "promised (the default), promised_desc, reference, created, value, customer or status."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List orders", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Order"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "orders_create", "tags": ["Orders"], "summary": "Raise an order by hand", "description": "For a job placed without a quotation. It takes the enquiry's reference where it has one, else a fresh one, and the enquiry's pipeline hears that an order was raised.\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [], "responses": {"201": {"description": "Raise an order by hand", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The customer."}, "contact_id": {"type": "integer", "description": "The contact."}, "enquiry_id": {"type": "integer", "description": "The enquiry it came from; the customer, contact and site postcode are taken from it when left out."}, "quote_id": {"type": "integer", "description": "The quotation it came from. To raise an order from a won quotation with its lines, use POST /quotes/{quote_id}/order instead."}, "customer_po": {"type": "string", "description": "The customer's own order number.", "nullable": true}, "order_date": {"type": "string", "format": "date", "description": "Placed on; today if left out.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "What the customer was promised.", "nullable": true}, "site_name": {"type": "string", "description": "The site.", "nullable": true}, "site_address": {"type": "string", "description": "The site's address.", "nullable": true}, "site_postcode": {"type": "string", "description": "The site's postcode.", "nullable": true}, "access_notes": {"type": "string", "description": "How to get in.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate; the company's default if left out.", "nullable": true}, "currency": {"type": "string", "description": "ISO code; yours if left out.", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours.", "nullable": true}, "lead_time": {"type": "string", "description": "Lead time.", "nullable": true}, "notes": {"type": "string", "description": "Notes.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out."}, "pipeline_id": {"type": "integer", "description": "Which order pipeline it travels; the default if left out."}, "lines": {"type": "array", "items": {}, "description": "The lines, each as below. At least one."}, "fields": {"type": "object", "additionalProperties": true, "description": "The order's extra fields, by name."}}, "required": ["company_id", "lines"]}}}}}}, "/api/v1/quotes/{quote_id}/order": {"post": {"operationId": "orders_from_quote", "tags": ["Orders"], "summary": "Raise the order for a won quotation", "description": "Winning a quotation raises its order by itself; this is for one that was won before that, or whose order was deleted. The lines come across with both discounts folded into the prices. A quotation that already has an order, or is not won, is refused with 409.\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"201": {"description": "Raise the order for a won quotation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"customer_po": {"type": "string", "description": "The customer's order number.", "nullable": true}, "order_date": {"type": "string", "format": "date", "description": "Placed on; today if left out.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "What the customer was promised.", "nullable": true}}}}}}}}, "/api/v1/orders/{order_id}": {"get": {"operationId": "orders_get", "tags": ["Orders"], "summary": "One order", "description": "With its lines, how much of it is billed (coverage), its invoices, the stages of its pipeline and the next workshop step.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "One order", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "orders_update", "tags": ["Orders"], "summary": "Change an order", "description": "Send only the fields to change. Lines sent replace the set, matched by id so invoices keep their anchors; a line an invoice has billed cannot be removed or cut below what was billed (422).\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Change an order", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The customer."}, "contact_id": {"type": "integer", "description": "The contact."}, "enquiry_id": {"type": "integer", "description": "The enquiry it came from; the customer, contact and site postcode are taken from it when left out."}, "quote_id": {"type": "integer", "description": "The quotation it came from. To raise an order from a won quotation with its lines, use POST /quotes/{quote_id}/order instead."}, "customer_po": {"type": "string", "description": "The customer's own order number.", "nullable": true}, "order_date": {"type": "string", "format": "date", "description": "Placed on; today if left out.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "What the customer was promised.", "nullable": true}, "site_name": {"type": "string", "description": "The site.", "nullable": true}, "site_address": {"type": "string", "description": "The site's address.", "nullable": true}, "site_postcode": {"type": "string", "description": "The site's postcode.", "nullable": true}, "access_notes": {"type": "string", "description": "How to get in.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate; the company's default if left out.", "nullable": true}, "currency": {"type": "string", "description": "ISO code; yours if left out.", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours.", "nullable": true}, "lead_time": {"type": "string", "description": "Lead time.", "nullable": true}, "notes": {"type": "string", "description": "Notes.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out."}, "pipeline_id": {"type": "integer", "description": "Which order pipeline it travels; the default if left out."}, "lines": {"type": "array", "items": {}, "description": "The lines, each as below. At least one."}, "fields": {"type": "object", "additionalProperties": true, "description": "The order's extra fields, by name."}}, "required": ["company_id", "lines"]}}}}}, "delete": {"operationId": "orders_delete", "tags": ["Orders"], "summary": "Delete an order permanently", "description": "Administrators only.\n\nNeeds: Write key, Administrator, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Delete an order permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/status": {"post": {"operationId": "orders_set_status", "tags": ["Orders"], "summary": "Move an order along the workshop", "description": "Delivered and installed stamp their dates; complete and cancelled stamp when. The enquiry's pipeline hears each step, and a note is logged.\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Move an order along the workshop", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string", "description": "confirmed, drawings, manufacturing, ready, delivered, installed, complete or cancelled.", "nullable": true, "enum": ["confirmed", "drawings", "manufacturing", "ready", "delivered", "installed", "complete", "cancelled"]}, "outcome_reason": {"type": "string", "description": "A note, kept with the change.", "nullable": true}}, "required": ["status"]}}}}}}, "/api/v1/orders/{order_id}/stage": {"post": {"operationId": "orders_set_stage", "tags": ["Orders"], "summary": "Move an order to a stage", "description": "A stage stands for a workshop status, so landing on one that records a different status is that status change, date stamp and all.\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Move an order to a stage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"stage_id": {"type": "integer", "description": "A stage on one of the company's order pipelines."}, "outcome_reason": {"type": "string", "description": "A note, kept with the change.", "nullable": true}}, "required": ["stage_id"]}}}}}}, "/api/v1/orders/{order_id}/pipeline": {"post": {"operationId": "orders_change_pipeline", "tags": ["Orders"], "summary": "Move an order to another pipeline", "description": "Move an order to another pipeline\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Move an order to another pipeline", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"pipeline_id": {"type": "integer", "description": "One of the company's order pipelines."}}, "required": ["pipeline_id"]}}}}}}, "/api/v1/orders/{order_id}/invoiced": {"post": {"operationId": "orders_set_invoiced", "tags": ["Orders"], "summary": "Record an invoice raised elsewhere", "description": "For an order billed outside the CRM. An invoice raised in the CRM fills these in by itself.\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Record an invoice raised elsewhere", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"invoice_ref": {"type": "string", "description": "The invoice number from your accounts package.", "nullable": true}, "invoiced_at": {"type": "string", "format": "date", "description": "When; today if left out.", "nullable": true}}}}}}}}, "/api/v1/orders/{order_id}/billable": {"get": {"operationId": "orders_billable", "tags": ["Orders"], "summary": "What is left to invoice on an order", "description": "Every line with how much is already on an invoice and how much is left, and the price agreed - what the invoice picker shows. Needs the invoices tab in the key's role.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "What is left to invoice on an order", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/BillableLine"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/archive": {"post": {"operationId": "orders_archive", "tags": ["Orders"], "summary": "Archive an order", "description": "Archive an order\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Archive an order", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/restore": {"post": {"operationId": "orders_restore", "tags": ["Orders"], "summary": "Restore an archived order", "description": "Restore an archived order\n\nNeeds: Write key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Restore an archived order", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Order"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/invoices": {"get": {"operationId": "orders_invoices", "tags": ["Orders"], "summary": "Its invoices", "description": "What the order's page shows under its invoices. Needs the invoices tab in the key's role.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Its invoices", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Invoice"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/tasks": {"get": {"operationId": "orders_tasks", "tags": ["Orders"], "summary": "Its tasks", "description": "What the order's page shows under its tasks. Needs the tasks tab in the key's role.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Its tasks", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/documents": {"get": {"operationId": "orders_documents", "tags": ["Orders"], "summary": "Its documents", "description": "What the order's page shows under its documents. Needs the documents tab in the key's role.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "Its documents", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Document"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/orders/{order_id}/emails": {"get": {"operationId": "orders_emails", "tags": ["Orders"], "summary": "The job's captured emails", "description": "What the order's page shows under the job's captured emails.\n\nNeeds: Any key, Orders tab, Order book on the plan.", "parameters": [{"name": "order_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The order id."}], "responses": {"200": {"description": "The job's captured emails", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Email"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/products": {"get": {"operationId": "products_list_products", "tags": ["Products"], "summary": "List products", "description": "Products on sale unless archived says otherwise.\n\nNeeds: Any key, Products tab, Price book on the plan.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the name, code, description and category."}, {"name": "category", "in": "query", "required": false, "schema": {"type": "string"}, "description": "One category."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include withdrawn products."}, {"name": "uncosted", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for products with no cost recorded."}, {"name": "unpriced", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for products priced per job."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["name", "name_desc", "code", "price", "price_asc", "category", "recent", "used"]}, "description": "name (the default), name_desc, code, price, price_asc, category, recent or used."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List products", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Product"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "products_create", "tags": ["Products"], "summary": "Add a product", "description": "Administrators only, as on the Products tab. A code already in use is refused with 409.\n\nNeeds: Write key, Administrator, Products tab, Price book on the plan.", "parameters": [], "responses": {"201": {"description": "Add a product", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Product"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"code": {"type": "string", "description": "Its code, unique in the price book.", "nullable": true}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "description": {"type": "string", "description": "The wording a line starts with.", "nullable": true}, "unit": {"type": "string", "description": "What it is sold by: each (the default), bay, m, m², linear m, hour, day, set, pair, or anything you like.", "nullable": true}, "unit_price": {"type": "string", "format": "decimal", "description": "Sell price in your currency; leave out for a product priced per job.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost; leave out if unknown. Zero means free, not unknown.", "nullable": true}, "category": {"type": "string", "description": "Its category - what an enquiry can be filed under.", "nullable": true}, "dimensions": {"type": "array", "items": {}, "description": "Which of length, width and height a line asks for, for a product sold in different sizes. An empty list for one size."}, "notes": {"type": "string", "description": "Notes, up to 1,000 characters.", "nullable": true}, "is_active": {"type": "boolean", "description": "On sale (the default); false withdraws it."}, "fields": {"type": "object", "additionalProperties": true, "description": "The product's extra fields, by name."}}, "required": ["name"]}}}}}}, "/api/v1/products/{product_id}": {"get": {"operationId": "products_get", "tags": ["Products"], "summary": "One product", "description": "One product\n\nNeeds: Any key, Products tab, Price book on the plan.", "parameters": [{"name": "product_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The product id."}], "responses": {"200": {"description": "One product", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Product"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "products_update", "tags": ["Products"], "summary": "Change a product", "description": "Send only the fields to change. Lines already quoted keep the price they were quoted at.\n\nNeeds: Write key, Administrator, Products tab, Price book on the plan.", "parameters": [{"name": "product_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The product id."}], "responses": {"200": {"description": "Change a product", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Product"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"code": {"type": "string", "description": "Its code, unique in the price book.", "nullable": true}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "description": {"type": "string", "description": "The wording a line starts with.", "nullable": true}, "unit": {"type": "string", "description": "What it is sold by: each (the default), bay, m, m², linear m, hour, day, set, pair, or anything you like.", "nullable": true}, "unit_price": {"type": "string", "format": "decimal", "description": "Sell price in your currency; leave out for a product priced per job.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost; leave out if unknown. Zero means free, not unknown.", "nullable": true}, "category": {"type": "string", "description": "Its category - what an enquiry can be filed under.", "nullable": true}, "dimensions": {"type": "array", "items": {}, "description": "Which of length, width and height a line asks for, for a product sold in different sizes. An empty list for one size."}, "notes": {"type": "string", "description": "Notes, up to 1,000 characters.", "nullable": true}, "is_active": {"type": "boolean", "description": "On sale (the default); false withdraws it."}, "fields": {"type": "object", "additionalProperties": true, "description": "The product's extra fields, by name."}}, "required": ["name"]}}}}}, "delete": {"operationId": "products_delete", "tags": ["Products"], "summary": "Delete a product permanently", "description": "For the one typed in by mistake. Lines keep their copied wording and price and lose the link; the answer says how many.\n\nNeeds: Write key, Administrator, Products tab, Price book on the plan.", "parameters": [{"name": "product_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The product id."}], "responses": {"200": {"description": "Delete a product permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/products/{product_id}/archive": {"post": {"operationId": "products_archive", "tags": ["Products"], "summary": "Withdraw a product from sale", "description": "Lines that used it are untouched; it is no longer offered for new ones.\n\nNeeds: Write key, Administrator, Products tab, Price book on the plan.", "parameters": [{"name": "product_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The product id."}], "responses": {"200": {"description": "Withdraw a product from sale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Product"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/products/{product_id}/restore": {"post": {"operationId": "products_restore", "tags": ["Products"], "summary": "Put a withdrawn product back on sale", "description": "Put a withdrawn product back on sale\n\nNeeds: Write key, Administrator, Products tab, Price book on the plan.", "parameters": [{"name": "product_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The product id."}], "responses": {"200": {"description": "Put a withdrawn product back on sale", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Product"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/queues": {"get": {"operationId": "queues_list_queues", "tags": ["Queues"], "summary": "List queues", "description": "Every queue the key's own user may see - shared ones, and their own private ones - over lists their role includes, each with its live count.\n\nNeeds: Any key, Queues tab.", "parameters": [], "responses": {"200": {"description": "List queues", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Queue"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "queues_create", "tags": ["Queues"], "summary": "Save a queue", "description": "Save a queue\n\nNeeds: Write key, Queues tab.", "parameters": [], "responses": {"201": {"description": "Save a queue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Queue"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "Its name, unique in the company.", "nullable": true}, "dataset": {"type": "string", "description": "The list it is over: enquiries, quotes, orders, invoices, tasks, companies, contacts, or records:<tab id>. Fixed once made.", "nullable": true}, "filters": {"type": "object", "additionalProperties": true, "description": "The list's own arguments, as GET /queues/{queue_id}/records and the list routes take them: status, owner, mine, overdue, q, sort, x_<field>... Anything the list does not take is dropped."}, "columns": {"type": "array", "items": {}, "description": "The column keys to show, in order, or null for the list's own."}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "visibility": {"type": "string", "description": "shared (the default) or private to the key's own user.", "nullable": true, "enum": ["shared", "private"]}}, "required": ["name", "dataset"]}}}}}}, "/api/v1/queues/{queue_id}": {"get": {"operationId": "queues_get", "tags": ["Queues"], "summary": "One queue", "description": "One queue\n\nNeeds: Any key, Queues tab.", "parameters": [{"name": "queue_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The queue id."}], "responses": {"200": {"description": "One queue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Queue"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "queues_update", "tags": ["Queues"], "summary": "Change a queue", "description": "Its owner, or an administrator for a shared queue. The list it is over cannot change.\n\nNeeds: Write key, Queues tab.", "parameters": [{"name": "queue_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The queue id."}], "responses": {"200": {"description": "Change a queue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Queue"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "Its name, unique in the company.", "nullable": true}, "dataset": {"type": "string", "description": "The list it is over: enquiries, quotes, orders, invoices, tasks, companies, contacts, or records:<tab id>. Fixed once made.", "nullable": true}, "filters": {"type": "object", "additionalProperties": true, "description": "The list's own arguments, as GET /queues/{queue_id}/records and the list routes take them: status, owner, mine, overdue, q, sort, x_<field>... Anything the list does not take is dropped."}, "columns": {"type": "array", "items": {}, "description": "The column keys to show, in order, or null for the list's own."}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "visibility": {"type": "string", "description": "shared (the default) or private to the key's own user.", "nullable": true, "enum": ["shared", "private"]}}, "required": ["name", "dataset"]}}}}}, "delete": {"operationId": "queues_delete", "tags": ["Queues"], "summary": "Delete a queue", "description": "Delete a queue\n\nNeeds: Write key, Queues tab.", "parameters": [{"name": "queue_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The queue id."}], "responses": {"200": {"description": "Delete a queue", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/queues/{queue_id}/records": {"get": {"operationId": "queues_records", "tags": ["Queues"], "summary": "The records in a queue", "description": "A page of whatever the queue is over - enquiries, quotations, orders, invoices, tasks, companies, contacts or a tab of your own - each answered as its own route would answer it. 'Mine' in a queue means the key's own user.\n\nNeeds: Any key, Queues tab.", "parameters": [{"name": "queue_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The queue id."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string"}, "description": "An ordering the list offers, overriding the queue's."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "The records in a queue", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Record"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tabs/{slug}/records": {"get": {"operationId": "records_list_records", "tags": ["Your own tabs"], "summary": "List a tab's records", "description": "The tab is named by its slug (GET /tabs). The key's role must include it.\n\nNeeds: Any key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}, {"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the record's values, reference, company and enquiry."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A user id, for a tab with a link to a person."}, {"name": "archived", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include archived records."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["recent", "created", "oldest", "reference", "title", "company"]}, "description": "recent (the default), created, oldest, reference, title or company."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of the tab's own fields: x_<field>=value, or x_<field>.from and x_<field>.to."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List a tab's records", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Record"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "records_create", "tags": ["Your own tabs"], "summary": "Add a record to a tab", "description": "Checked field by field as the tab's form checks it: a required field missing, an option not on the list or a link to another company's record is refused (422). A numbered tab gives it the next reference.\n\nNeeds: Write key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}], "responses": {"201": {"description": "Add a record to a tab", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Record"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"fields": {"type": "object", "additionalProperties": true, "description": "The record's values, by field name - see GET /tabs/{slug}. A link field takes an id: a company's, a contact's, an enquiry's or a user's."}}, "required": ["fields"]}}}}}}, "/api/v1/tabs/{slug}/records/{record_id}": {"get": {"operationId": "records_get", "tags": ["Your own tabs"], "summary": "One record", "description": "With its documents under documents.\n\nNeeds: Any key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}, {"name": "record_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The record id."}], "responses": {"200": {"description": "One record", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Record"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "records_update", "tags": ["Your own tabs"], "summary": "Change a record", "description": "Send only the fields to change.\n\nNeeds: Write key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}, {"name": "record_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The record id."}], "responses": {"200": {"description": "Change a record", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Record"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"fields": {"type": "object", "additionalProperties": true, "description": "The record's values, by field name - see GET /tabs/{slug}. A link field takes an id: a company's, a contact's, an enquiry's or a user's."}}, "required": ["fields"]}}}}}, "delete": {"operationId": "records_delete", "tags": ["Your own tabs"], "summary": "Delete a record permanently", "description": "Administrators only. Its documents go with it.\n\nNeeds: Write key, Administrator.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}, {"name": "record_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The record id."}], "responses": {"200": {"description": "Delete a record permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tabs/{slug}/records/{record_id}/archive": {"post": {"operationId": "records_archive", "tags": ["Your own tabs"], "summary": "Archive a record", "description": "Archive a record\n\nNeeds: Write key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}, {"name": "record_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The record id."}], "responses": {"200": {"description": "Archive a record", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Record"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tabs/{slug}/records/{record_id}/restore": {"post": {"operationId": "records_restore", "tags": ["Your own tabs"], "summary": "Restore an archived record", "description": "Restore an archived record\n\nNeeds: Write key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}, {"name": "record_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The record id."}], "responses": {"200": {"description": "Restore an archived record", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Record"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/users": {"get": {"operationId": "reference_users", "tags": ["Reference data"], "summary": "The company's people", "description": "Everybody at the company, active ones first: the ids that owner and assignee fields take. Email addresses are answered only to an administrator's key.\n\nNeeds: Any key.", "parameters": [{"name": "inactive", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true to include disabled accounts."}], "responses": {"200": {"description": "The company's people", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/User"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/roles": {"get": {"operationId": "reference_roles", "tags": ["Reference data"], "summary": "The roles people hold", "description": "The two built-in roles and the company's own, each with the tab keys it includes. A built-in role has no id.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "The roles people hold", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Role"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/pipelines": {"get": {"operationId": "reference_pipelines", "tags": ["Reference data"], "summary": "The pipelines and their stages", "description": "Every route of every kind the key's role includes, default first, with its stages in order - the stage ids the stage routes take, and what each stands for - and its rules.\n\nNeeds: Any key.", "parameters": [{"name": "entity", "in": "query", "required": false, "schema": {"type": "string", "enum": ["enquiry", "quote", "order", "invoice"]}, "description": "enquiry, quote, order or invoice; all four if left out."}], "responses": {"200": {"description": "The pipelines and their stages", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Pipeline"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/pipelines/{pipeline_id}": {"get": {"operationId": "reference_pipeline", "tags": ["Reference data"], "summary": "One pipeline", "description": "One pipeline\n\nNeeds: Any key.", "parameters": [{"name": "pipeline_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The pipeline id."}], "responses": {"200": {"description": "One pipeline", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Pipeline"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/sources": {"get": {"operationId": "reference_sources", "tags": ["Reference data"], "summary": "The enquiry sources", "description": "Where enquiries come from, as Administration lists them, retired ones included and marked.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "The enquiry sources", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Source"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/product-categories": {"get": {"operationId": "reference_categories", "tags": ["Reference data"], "summary": "The product categories", "description": "What an enquiry can be filed under: the categories that ship and the ones on the price book, grouped as the form groups them, and the default.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "The product categories", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProductCategories"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/fields": {"get": {"operationId": "reference_fields", "tags": ["Reference data"], "summary": "The extra fields on each tab", "description": "The fields the company added to the tabs that ship (Administration > Extra fields), by tab, for the tabs in the key's role: what a record's 'fields' object may carry, and what the x_<field> list filters take.\n\nNeeds: Any key.", "parameters": [{"name": "entity", "in": "query", "required": false, "schema": {"type": "string", "enum": ["company", "contact", "enquiry", "quote", "order", "invoice", "product", "task"]}, "description": "One tab: company, contact, enquiry, quote, order, invoice, product or task."}], "responses": {"200": {"description": "The extra fields on each tab", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/FieldDefinition"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tabs": {"get": {"operationId": "reference_tabs", "tags": ["Reference data"], "summary": "The company's own tabs", "description": "Every tab the company designed itself that the key's role includes, with its fields - and its slug, which the records routes take.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "The company's own tabs", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Tab"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tabs/{slug}": {"get": {"operationId": "reference_tab", "tags": ["Reference data"], "summary": "One of the company's own tabs", "description": "One of the company's own tabs\n\nNeeds: Any key.", "parameters": [{"name": "slug", "in": "path", "required": true, "schema": {"type": "string"}, "description": "The slug."}], "responses": {"200": {"description": "One of the company's own tabs", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Tab"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/vocabulary": {"get": {"operationId": "reference_vocabulary", "tags": ["Reference data"], "summary": "The fixed vocabularies", "description": "Every fixed list of values a route takes or answers, with what each is called - statuses, types, outcomes - and the company's own words for its record types.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "The fixed vocabularies", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Vocabulary"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/settings": {"get": {"operationId": "reference_settings", "tags": ["Reference data"], "summary": "The company's settings", "description": "What the company has set up: its letterhead, its currency and rates, its wording and workshop steps, its reference format, the defaults a new document starts with, what its paperwork carries, its plan's allowances and which features are in force. The bank details are answered only to a key whose role includes invoices.\n\nNeeds: Any key.", "parameters": [], "responses": {"200": {"description": "The company's settings", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Settings"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/sales": {"get": {"operationId": "reports_sales", "tags": ["Reports"], "summary": "The sales report", "description": "Every table the sales report prints: performance by month, the forecast by expected close, by owner, by product category, by source, the top customers, quotation conversion and margin (for a role with quotes), lost reasons and the won-by-month series. Needs the enquiries tab in the key's role.\n\nNeeds: Any key, Reports tab.", "parameters": [{"name": "months", "in": "query", "required": false, "schema": {"type": "integer", "enum": ["3", "6", "12", "24", "36"]}, "description": "3, 6, 12, 24 or 36; 12 if left out."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "One person's share: a user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's share."}], "responses": {"200": {"description": "The sales report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SalesReport"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/kpis": {"get": {"operationId": "reports_kpis", "tags": ["Reports"], "summary": "The Reports page's figures", "description": "Sales, workshop, cash, customers, people and your own tabs: each section's tiles (value, the comparison and the change), its snapshots of right now and its tables, for the period asked for. A section is null where the key's role leaves its tab out. The charts are left out; the figures behind them are in the tiles.\n\nNeeds: Any key, Reports tab.", "parameters": [{"name": "range", "in": "query", "required": false, "schema": {"type": "string", "enum": ["this_month", "last_month", "this_quarter", "last_quarter", "this_year", "last_year", "this_fy", "last_fy", "last_3m", "last_6m", "last_12m", "last_24m", "custom"]}, "description": "The period: this_month, last_month, this_quarter, last_quarter, this_year, last_year, this_fy, last_fy, last_3m, last_6m, last_12m, last_24m, custom. last_12m if left out."}, {"name": "from", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "With range=custom: the first day."}, {"name": "to", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "With range=custom: the last day."}, {"name": "compare", "in": "query", "required": false, "schema": {"type": "string", "enum": ["previous", "year", "none"]}, "description": "What to set it against: previous, year, none."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "One person's share: a user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's share."}], "responses": {"200": {"description": "The Reports page's figures", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/KpiHub"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/dashboard": {"get": {"operationId": "reports_dashboard_figures", "tags": ["Reports"], "summary": "The dashboard's figures", "description": "The headline (open pipeline, weighted forecast, won this month and the rest), the twelve-month conversion, the order book and the invoice book, and what needs a person today - overdue invoices, late orders, overdue tasks, quotations about to expire, enquiries gone quiet - each with the record's page. Only the parts in the key's role.\n\nNeeds: Any key, Reports tab.", "parameters": [{"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "One person's share: a user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's share."}], "responses": {"200": {"description": "The dashboard's figures", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Dashboard"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/datasets": {"get": {"operationId": "reports_datasets", "tags": ["Reports"], "summary": "What can be reported on", "description": "Every dataset the key's role may report on, with its dimensions, figures, date fields, filters and list columns - the vocabulary the totals and list routes take.\n\nNeeds: Any key, Reports tab.", "parameters": [], "responses": {"200": {"description": "What can be reported on", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Dataset"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/totals": {"get": {"operationId": "reports_totals", "tags": ["Reports"], "summary": "Run a totals report", "description": "The report builder: figures grouped by a dimension over a period, against the period before, with the totals. The same words as the report's own address, so one built on screen runs here from its URL. A word the dataset does not offer is replaced by the dataset's default.\n\nNeeds: Any key, Reports tab.", "parameters": [{"name": "dataset", "in": "query", "required": true, "schema": {"type": "string", "default": "enquiries"}, "description": "What it is about: a key from GET /reports/datasets."}, {"name": "dim", "in": "query", "required": false, "schema": {"type": "string", "default": "stage"}, "description": "What to group by: a dimension of the dataset."}, {"name": "measure", "in": "query", "required": false, "schema": {"type": "string", "default": "count"}, "description": "Which figures, repeated for more than one, up to four."}, {"name": "date", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Which date the period applies to: a date field of the dataset."}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "enum": ["this_month", "last_month", "this_quarter", "last_quarter", "this_year", "last_year", "this_fy", "last_fy", "last_3m", "last_6m", "last_12m", "last_24m", "custom"]}, "description": "The period: this_month, last_month, this_quarter, last_quarter, this_year, last_year, this_fy, last_fy, last_3m, last_6m, last_12m, last_24m, custom. last_12m if left out."}, {"name": "from", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "With range=custom: the first day."}, {"name": "to", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "With range=custom: the last day."}, {"name": "compare", "in": "query", "required": false, "schema": {"type": "string", "enum": ["previous", "year", "none"]}, "description": "What to set it against: previous, year, none."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "string", "default": ""}, "description": "A user id, or mine."}, {"name": "status", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A status the dataset offers."}], "responses": {"200": {"description": "Run a totals report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TotalsReport"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/list": {"get": {"operationId": "reports_listing", "tags": ["Reports"], "summary": "Run a list report", "description": "Every record on its own row with the columns chosen, over a period or any date, sorted and searched - what the list report page shows and exports.\n\nNeeds: Any key, Reports tab.", "parameters": [{"name": "dataset", "in": "query", "required": true, "schema": {"type": "string"}, "description": "What it lists: a key from GET /reports/datasets."}, {"name": "col", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Which columns, repeated, up to 16; the dataset's own if left out."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A column key to sort by."}, {"name": "dir", "in": "query", "required": false, "schema": {"type": "string", "enum": ["asc", "desc"]}, "description": "asc or desc."}, {"name": "date", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Which date the period applies to."}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "enum": ["all", "this_month", "last_month", "this_quarter", "last_quarter", "this_year", "last_year", "this_fy", "last_fy", "last_3m", "last_6m", "last_12m", "last_24m", "custom"]}, "description": "A period, or all for any date."}, {"name": "from", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "With range=custom: the first day."}, {"name": "to", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "With range=custom: the last day."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A user id, or mine."}, {"name": "status", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A status the dataset offers."}, {"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "A search within the rows."}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "At most so many rows; 500 if left out, 10,000 at most."}], "responses": {"200": {"description": "Run a list report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ListReport"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/reports/saved": {"get": {"operationId": "reports_saved", "tags": ["Reports"], "summary": "The saved reports", "description": "Every saved report the key's own user may see: shared ones, and their own private ones, over data in their role.\n\nNeeds: Any key, Reports tab.", "parameters": [], "responses": {"200": {"description": "The saved reports", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/SavedReport"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "reports_save", "tags": ["Reports"], "summary": "Save a report", "description": "Save a report\n\nNeeds: Write key, Reports tab.", "parameters": [], "responses": {"201": {"description": "Save a report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SavedReport"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "Its name, unique in the company.", "nullable": true}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "visibility": {"type": "string", "description": "shared (the default) or private to the key's own user.", "nullable": true, "enum": ["shared", "private"]}, "spec": {"type": "object", "additionalProperties": true, "description": "The report: the same keys GET /reports/totals or GET /reports/list take (kind: list for a list), as an object. Checked word by word; anything the dataset does not offer is replaced by its default."}}, "required": ["name", "spec"]}}}}}}, "/api/v1/reports/saved/{report_id}": {"get": {"operationId": "reports_run_saved", "tags": ["Reports"], "summary": "Run a saved report", "description": "The saved report, run now: a TotalsReport or a ListReport by its kind, with the saved report itself under saved.\n\nNeeds: Any key, Reports tab.", "parameters": [{"name": "report_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The report id."}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "enum": ["this_month", "last_month", "this_quarter", "last_quarter", "this_year", "last_year", "this_fy", "last_fy", "last_3m", "last_6m", "last_12m", "last_24m", "custom"]}, "description": "A period to run it over instead of its own."}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "For a list: at most so many rows."}], "responses": {"200": {"description": "Run a saved report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TotalsReport"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "reports_update_saved", "tags": ["Reports"], "summary": "Change a saved report", "description": "Its owner, or an administrator. Send only what changes.\n\nNeeds: Write key, Reports tab.", "parameters": [{"name": "report_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The report id."}], "responses": {"200": {"description": "Change a saved report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SavedReport"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "Its name, unique in the company.", "nullable": true}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "visibility": {"type": "string", "description": "shared (the default) or private to the key's own user.", "nullable": true, "enum": ["shared", "private"]}, "spec": {"type": "object", "additionalProperties": true, "description": "The report: the same keys GET /reports/totals or GET /reports/list take (kind: list for a list), as an object. Checked word by word; anything the dataset does not offer is replaced by its default."}}, "required": ["name", "spec"]}}}}}, "delete": {"operationId": "reports_delete_saved", "tags": ["Reports"], "summary": "Delete a saved report", "description": "Delete a saved report\n\nNeeds: Write key, Reports tab.", "parameters": [{"name": "report_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The report id."}], "responses": {"200": {"description": "Delete a saved report", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/search": {"get": {"operationId": "search_search", "tags": ["Search"], "summary": "Search everything", "description": "Companies, contacts, enquiries, quotations, orders, invoices and documents, a few of each, grouped - only the kinds in the key's role. Each hit carries its id, a title, a line of detail and the record's page.\n\nNeeds: Any key.", "parameters": [{"name": "q", "in": "query", "required": true, "schema": {"type": "string"}, "description": "What to look for; at least two characters."}, {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "At most so many of each kind; 5 if left out, 25 at most."}], "responses": {"200": {"description": "Search everything", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SearchResult"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tasks": {"get": {"operationId": "tasks_list_tasks", "tags": ["Tasks"], "summary": "List tasks", "description": "Open tasks unless status says otherwise, soonest due first.\n\nNeeds: Any key, Tasks tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the title, details and company."}, {"name": "status", "in": "query", "required": false, "schema": {"type": "string", "enum": ["open", "done", "cancelled", "all"]}, "description": "open (the default), done or cancelled; all for every status."}, {"name": "assignee", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A user id."}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for the key's own user's tasks."}, {"name": "due", "in": "query", "required": false, "schema": {"type": "string", "enum": ["overdue", "today", "week", "none"]}, "description": "overdue, today, week or none."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["due", "due_desc", "priority", "created"]}, "description": "due (the default), due_desc, priority or created."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List tasks", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "tasks_create", "tags": ["Tasks"], "summary": "Add a task", "description": "The assignee is emailed that a task has been put in their name, as they would be from the form - unless they are the key's own user.\n\nNeeds: Write key, Tasks tab.", "parameters": [], "responses": {"201": {"description": "Add a task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"title": {"type": "string", "description": "What has to be done.", "nullable": true}, "details": {"type": "string", "description": "More detail, up to 10,000 characters.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "When by.", "nullable": true}, "priority": {"type": "string", "description": "low, normal (the default) or high.", "nullable": true, "enum": ["low", "normal", "high"]}, "assigned_to_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out. They are emailed, unless it is the key's own user."}, "company_id": {"type": "integer", "description": "The company it is about."}, "contact_id": {"type": "integer", "description": "The contact."}, "enquiry_id": {"type": "integer", "description": "The enquiry."}, "order_id": {"type": "integer", "description": "The order."}, "fields": {"type": "object", "additionalProperties": true, "description": "The task's extra fields, by name."}}, "required": ["title"]}}}}}}, "/api/v1/tasks/{task_id}": {"get": {"operationId": "tasks_get", "tags": ["Tasks"], "summary": "One task", "description": "One task\n\nNeeds: Any key, Tasks tab.", "parameters": [{"name": "task_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The task id."}], "responses": {"200": {"description": "One task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "tasks_update", "tags": ["Tasks"], "summary": "Change a task", "description": "Send only the fields to change. A new assignee is emailed.\n\nNeeds: Write key, Tasks tab.", "parameters": [{"name": "task_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The task id."}], "responses": {"200": {"description": "Change a task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"title": {"type": "string", "description": "What has to be done.", "nullable": true}, "details": {"type": "string", "description": "More detail, up to 10,000 characters.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "When by.", "nullable": true}, "priority": {"type": "string", "description": "low, normal (the default) or high.", "nullable": true, "enum": ["low", "normal", "high"]}, "assigned_to_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out. They are emailed, unless it is the key's own user."}, "company_id": {"type": "integer", "description": "The company it is about."}, "contact_id": {"type": "integer", "description": "The contact."}, "enquiry_id": {"type": "integer", "description": "The enquiry."}, "order_id": {"type": "integer", "description": "The order."}, "fields": {"type": "object", "additionalProperties": true, "description": "The task's extra fields, by name."}}, "required": ["title"]}}}}}, "delete": {"operationId": "tasks_delete", "tags": ["Tasks"], "summary": "Delete a task", "description": "The key's own user's tasks, or any task for an administrator.\n\nNeeds: Write key, Tasks tab.", "parameters": [{"name": "task_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The task id."}], "responses": {"200": {"description": "Delete a task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/tasks/{task_id}/status": {"post": {"operationId": "tasks_set_status", "tags": ["Tasks"], "summary": "Complete or reopen a task", "description": "Complete or reopen a task\n\nNeeds: Write key, Tasks tab.", "parameters": [{"name": "task_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The task id."}], "responses": {"200": {"description": "Complete or reopen a task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string", "description": "open, done or cancelled.", "nullable": true, "enum": ["open", "done", "cancelled"]}}, "required": ["status"]}}}}}}, "/api/v1/quotes": {"get": {"operationId": "quotes_list_quotes", "tags": ["Quotations"], "summary": "List quotations", "description": "The latest revision of each number, unless all=true.\n\nNeeds: Any key, Quotations tab.", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Search the number, company, enquiry reference and title."}, {"name": "status", "in": "query", "required": false, "schema": {"type": "string", "enum": ["draft", "sent", "accepted", "rejected", "superseded", "expired"]}, "description": "draft, sent, accepted, rejected, superseded or expired."}, {"name": "pipeline", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A pipeline id."}, {"name": "company", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "A company id."}, {"name": "enquiry", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An enquiry id."}, {"name": "owner", "in": "query", "required": false, "schema": {"type": "integer"}, "description": "An owner's user id."}, {"name": "all", "in": "query", "required": false, "schema": {"type": "boolean"}, "description": "true for every revision; otherwise only the latest of each number."}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "enum": ["recent", "number", "date", "value", "company", "status"]}, "description": "recent (the default), number, date, value, company or status."}, {"name": "x_<field>", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Filter on one of your own fields."}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "default": "1"}, "description": "Which page, counting from 1."}, {"name": "per_page", "in": "query", "required": false, "schema": {"type": "integer", "default": "25"}, "description": "Rows per page, 5 to 200."}], "responses": {"200": {"description": "List quotations", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Quote"}}, "paging": {"$ref": "#/components/schemas/Paging"}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "post": {"operationId": "quotes_create", "tags": ["Quotations"], "summary": "Raise a quotation", "description": "Revision 1 of a new number - or, for an enquiry that already has a quotation, the next revision of it, superseding the earlier one unless it was won or lost. Lines left out are carried from the enquiry. The enquiry's pipeline hears that a quote was drafted.\n\nNeeds: Write key, Quotations tab.", "parameters": [], "responses": {"201": {"description": "Raise a quotation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The customer."}, "enquiry_id": {"type": "integer", "description": "The enquiry it is for. The quotation then takes the enquiry's reference (as the next revision under it), and its lines if none are sent."}, "contact_id": {"type": "integer", "description": "The contact; the enquiry's if left out."}, "quote_date": {"type": "string", "format": "date", "description": "Dated; today if left out.", "nullable": true}, "valid_until": {"type": "string", "format": "date", "description": "Valid until; 30 days on if left out.", "nullable": true}, "discount_pct": {"type": "string", "format": "decimal", "description": "Whole-quote discount, per cent.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate; the company's default if left out.", "nullable": true}, "currency": {"type": "string", "description": "ISO code; the customer's usual currency, else yours.", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours; the company's rate table if left out.", "nullable": true}, "lead_time": {"type": "string", "description": "Lead time, as written.", "nullable": true}, "delivery_terms": {"type": "string", "description": "Delivery terms.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms; the company's default if left out.", "nullable": true}, "notes": {"type": "string", "description": "Notes printed on it; the enquiry's title if left out.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out."}, "pipeline_id": {"type": "integer", "description": "Which quote pipeline it travels; the default if left out."}, "lines": {"type": "array", "items": {}, "description": "The lines, each as below. At least one, unless the enquiry supplies them."}, "fields": {"type": "object", "additionalProperties": true, "description": "The quotation's extra fields, by name."}}, "required": ["company_id"]}}}}}}, "/api/v1/quotes/{quote_id}": {"get": {"operationId": "quotes_get", "tags": ["Quotations"], "summary": "One quotation", "description": "With its lines, every revision of its number, and the orders and invoices that followed it (those the key's role may see).\n\nNeeds: Any key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "One quotation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}, "patch": {"operationId": "quotes_update", "tags": ["Quotations"], "summary": "Change a quotation", "description": "Send only the fields to change; lines sent replace the whole set, lines left out stay as they are. A won, lost or superseded revision cannot be changed (409): revise it instead.\n\nNeeds: Write key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Change a quotation", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"company_id": {"type": "integer", "description": "The customer."}, "enquiry_id": {"type": "integer", "description": "The enquiry it is for. The quotation then takes the enquiry's reference (as the next revision under it), and its lines if none are sent."}, "contact_id": {"type": "integer", "description": "The contact; the enquiry's if left out."}, "quote_date": {"type": "string", "format": "date", "description": "Dated; today if left out.", "nullable": true}, "valid_until": {"type": "string", "format": "date", "description": "Valid until; 30 days on if left out.", "nullable": true}, "discount_pct": {"type": "string", "format": "decimal", "description": "Whole-quote discount, per cent.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate; the company's default if left out.", "nullable": true}, "currency": {"type": "string", "description": "ISO code; the customer's usual currency, else yours.", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours; the company's rate table if left out.", "nullable": true}, "lead_time": {"type": "string", "description": "Lead time, as written.", "nullable": true}, "delivery_terms": {"type": "string", "description": "Delivery terms.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms; the company's default if left out.", "nullable": true}, "notes": {"type": "string", "description": "Notes printed on it; the enquiry's title if left out.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is; the key's own user if left out."}, "pipeline_id": {"type": "integer", "description": "Which quote pipeline it travels; the default if left out."}, "lines": {"type": "array", "items": {}, "description": "The lines, each as below. At least one, unless the enquiry supplies them."}, "fields": {"type": "object", "additionalProperties": true, "description": "The quotation's extra fields, by name."}}, "required": ["company_id"]}}}}}, "delete": {"operationId": "quotes_delete", "tags": ["Quotations"], "summary": "Delete a revision permanently", "description": "Administrators only. Its documents go with it.\n\nNeeds: Write key, Administrator, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Delete a revision permanently", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Deleted"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/quotes/{quote_id}/status": {"post": {"operationId": "quotes_set_status", "tags": ["Quotations"], "summary": "Mark a quotation sent, won, lost or expired", "description": "What the page's status control does. Won is one event: the quotation is decided, the enquiry moves to its won stage and the order is raised. Sent and lost tell the enquiry's pipeline rules. The owner is emailed about a decision and Teams told. The answer carries messages.\n\nNeeds: Write key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Mark a quotation sent, won, lost or expired", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"status": {"type": "string", "description": "draft, sent, accepted (won), rejected (lost) or expired.", "nullable": true, "enum": ["draft", "sent", "accepted", "rejected", "expired"]}, "outcome_reason": {"type": "string", "description": "Why, for won or lost.", "nullable": true}, "customer_po": {"type": "string", "description": "For won: the customer's order number, carried onto the order.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "For won: what the customer was promised.", "nullable": true}}, "required": ["status"]}}}}}}, "/api/v1/quotes/{quote_id}/stage": {"post": {"operationId": "quotes_set_stage", "tags": ["Quotations"], "summary": "Move a quotation to a stage", "description": "A stage stands for a status, so onto a stage recording won wins it and raises the order, as dragging the card does.\n\nNeeds: Write key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Move a quotation to a stage", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"stage_id": {"type": "integer", "description": "A stage on one of the company's quote pipelines."}, "outcome_reason": {"type": "string", "description": "Why, where the stage records won or lost.", "nullable": true}, "customer_po": {"type": "string", "description": "For a won stage: the customer's order number.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "For a won stage: what was promised.", "nullable": true}}, "required": ["stage_id"]}}}}}}, "/api/v1/quotes/{quote_id}/pipeline": {"post": {"operationId": "quotes_change_pipeline", "tags": ["Quotations"], "summary": "Move a quotation to another pipeline", "description": "Move a quotation to another pipeline\n\nNeeds: Write key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Move a quotation to another pipeline", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"pipeline_id": {"type": "integer", "description": "One of the company's quote pipelines."}}, "required": ["pipeline_id"]}}}}}}, "/api/v1/quotes/{quote_id}/revise": {"post": {"operationId": "quotes_revise", "tags": ["Quotations"], "summary": "Raise the next revision", "description": "Copies the header and every line to the next revision as a draft and supersedes the earlier revisions, except any that recorded a win or a loss. The enquiry's pipeline hears that the quote was revised. The answer is the new revision.\n\nNeeds: Write key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"201": {"description": "Raise the next revision", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/quotes/{quote_id}/send": {"post": {"operationId": "quotes_send", "tags": ["Quotations"], "summary": "Email a quotation to the customer", "description": "Queued like every message the CRM sends, in the key's own user's name with replies to their address; the PDF is filed under the quotation's documents. A draft becomes sent and the enquiry's pipeline hears of it. Refused for a superseded revision (409).\n\nNeeds: Write key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Email a quotation to the customer", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Quote"}}}}, "400": {"$ref": "#/components/responses/Error400"}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "422": {"$ref": "#/components/responses/Error422"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}, "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "properties": {"to_email": {"type": "string", "description": "Who to; the contact's address if left out.", "nullable": true}, "subject": {"type": "string", "description": "The subject; the company's own wording if left out.", "nullable": true}, "message": {"type": "string", "description": "A note above the document, up to 4,000 characters.", "nullable": true}, "attach_pdf": {"type": "boolean", "description": "Whether the PDF goes with it. Default true."}, "include_lines": {"type": "boolean", "description": "Whether the lines and totals go in the body. Default true."}}}}}}}}, "/api/v1/quotes/{quote_id}/pdf": {"get": {"operationId": "quotes_pdf", "tags": ["Quotations"], "summary": "The quotation as a PDF", "description": "The customer's copy, exactly as the page downloads it and the email attaches it.\n\nNeeds: Any key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "application/pdf", "content": {"application/octet-stream": {"schema": {"type": "string", "format": "binary"}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/quotes/{quote_id}/documents": {"get": {"operationId": "quotes_documents_of", "tags": ["Quotations"], "summary": "Its documents", "description": "Its documents\n\nNeeds: Any key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "Its documents", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Document"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}, "/api/v1/quotes/{quote_id}/emails": {"get": {"operationId": "quotes_emails_of", "tags": ["Quotations"], "summary": "The job's captured emails", "description": "The job's captured emails\n\nNeeds: Any key, Quotations tab.", "parameters": [{"name": "quote_id", "in": "path", "required": true, "schema": {"type": "integer"}, "description": "The quote id."}], "responses": {"200": {"description": "The job's captured emails", "content": {"application/json": {"schema": {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/Email"}}}}}}}, "401": {"$ref": "#/components/responses/Error401"}, "403": {"$ref": "#/components/responses/Error403"}, "404": {"$ref": "#/components/responses/Error404"}, "409": {"$ref": "#/components/responses/Error409"}, "429": {"$ref": "#/components/responses/Error429"}, "503": {"$ref": "#/components/responses/Error503"}}}}}, "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "mq_<company>_<secret>"}, "apiKeyHeader": {"type": "apiKey", "in": "header", "name": "X-API-Key"}}, "schemas": {"Error": {"type": "object", "properties": {"error": {"type": "object", "properties": {"code": {"type": "string"}, "message": {"type": "string"}, "details": {"type": "array", "items": {"type": "string"}}}, "required": ["code", "message"]}}, "required": ["error"]}, "Paging": {"type": "object", "properties": {"page": {"type": "integer"}, "per_page": {"type": "integer"}, "total": {"type": "integer"}, "pages": {"type": "integer"}}}, "Company": {"type": "object", "properties": {"id": {"type": "integer", "description": "The company's id."}, "name": {"type": "string", "description": "The company's name.", "nullable": true}, "company_type": {"type": "string", "description": "prospect, customer, main_contractor, architect, supplier or other.", "nullable": true}, "sector": {"type": "string", "description": "Free text: what they do.", "nullable": true}, "phone": {"type": "string", "description": "Switchboard number.", "nullable": true}, "email": {"type": "string", "description": "General address.", "nullable": true}, "website": {"type": "string", "description": "Website.", "nullable": true}, "address_line1": {"type": "string", "description": "Address, first line.", "nullable": true}, "address_line2": {"type": "string", "description": "Address, second line.", "nullable": true}, "city": {"type": "string", "description": "Town or city.", "nullable": true}, "county": {"type": "string", "description": "County.", "nullable": true}, "postcode": {"type": "string", "description": "Postcode, tidied to UK form where it is one.", "nullable": true}, "country": {"type": "string", "description": "Country; United Kingdom unless said.", "nullable": true}, "currency": {"type": "string", "description": "The currency they are usually quoted in (ISO code), or null for yours.", "nullable": true}, "notes": {"type": "string", "description": "Free notes.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "The account owner's user id."}, "owner_name": {"type": "string", "description": "The account owner's name.", "nullable": true}, "contact_count": {"type": "integer", "description": "Live contacts at the company."}, "open_enquiry_count": {"type": "integer", "description": "Enquiries still open."}, "is_archived": {"type": "boolean", "description": "Archived rather than deleted."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Contact": {"type": "object", "properties": {"id": {"type": "integer", "description": "The contact's id."}, "company_id": {"type": "integer", "description": "The company they are at, or null."}, "company_name": {"type": "string", "description": "That company's name.", "nullable": true}, "first_name": {"type": "string", "description": "First name.", "nullable": true}, "last_name": {"type": "string", "description": "Surname.", "nullable": true}, "full_name": {"type": "string", "description": "Both together.", "nullable": true}, "job_title": {"type": "string", "description": "Job title.", "nullable": true}, "email": {"type": "string", "description": "Email address.", "nullable": true}, "phone": {"type": "string", "description": "Telephone.", "nullable": true}, "mobile": {"type": "string", "description": "Mobile.", "nullable": true}, "is_primary": {"type": "boolean", "description": "The main contact at their company; one per company."}, "notes": {"type": "string", "description": "Free notes.", "nullable": true}, "is_archived": {"type": "boolean", "description": "Archived rather than deleted."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Enquiry": {"type": "object", "properties": {"id": {"type": "integer", "description": "The enquiry's id."}, "reference": {"type": "string", "description": "Its reference, in the company's own format - carried by its quote, order and invoices.", "nullable": true}, "title": {"type": "string", "description": "What it is for, in a line.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer."}, "company_name": {"type": "string", "description": "The customer's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "The contact's name.", "nullable": true}, "contact_email": {"type": "string", "description": "The contact's address.", "nullable": true}, "pipeline_id": {"type": "integer", "description": "The pipeline it is on."}, "pipeline_name": {"type": "string", "description": "That pipeline's name.", "nullable": true}, "stage_id": {"type": "integer", "description": "The stage it is at."}, "stage_name": {"type": "string", "description": "That stage's name.", "nullable": true}, "stage_outcome": {"type": "string", "description": "open, won or lost - what the stage means.", "nullable": true}, "source_id": {"type": "integer", "description": "Where it came from (an enquiry source), or null."}, "source_name": {"type": "string", "description": "That source's name.", "nullable": true}, "product_category": {"type": "string", "description": "What it is for: a category from the price book.", "nullable": true}, "estimated_value": {"type": "string", "format": "decimal", "description": "What it is worth, in your currency.", "nullable": true}, "probability": {"type": "integer", "description": "The odds, 0 to 100."}, "expected_close_date": {"type": "string", "format": "date", "description": "When a decision is expected.", "nullable": true}, "site_postcode": {"type": "string", "description": "Where the work would be.", "nullable": true}, "description": {"type": "string", "description": "The long description.", "nullable": true}, "lines_total": {"type": "string", "format": "decimal", "description": "The total of its priced lines.", "nullable": true}, "lines_cost": {"type": "string", "format": "decimal", "description": "The total cost of its costed lines.", "nullable": true}, "unpriced_lines": {"type": "integer", "description": "Lines still without a price."}, "outcome_reason": {"type": "string", "description": "Why it was won or lost.", "nullable": true}, "closed_at": {"type": "string", "format": "date-time", "description": "When it was won or lost, or null while open.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "quote_count": {"type": "integer", "description": "Quotations raised for it, every revision counted."}, "is_archived": {"type": "boolean", "description": "Archived rather than deleted."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "EnquiryLine": {"type": "object", "properties": {"id": {"type": "integer", "description": "The line's id."}, "line_no": {"type": "integer", "description": "Its position."}, "product_id": {"type": "integer", "description": "The product it came from, or null for free text."}, "product_code": {"type": "string", "description": "That product's code.", "nullable": true}, "product_name": {"type": "string", "description": "That product's name.", "nullable": true}, "description": {"type": "string", "description": "What is being asked for.", "nullable": true}, "quantity": {"type": "string", "format": "decimal", "description": "How many.", "nullable": true}, "unit": {"type": "string", "description": "each, bay, m and so on.", "nullable": true}, "dim_length": {"type": "integer", "description": "Length in mm, where asked for at a size."}, "dim_width": {"type": "integer", "description": "Width in mm."}, "dim_height": {"type": "integer", "description": "Height in mm."}, "unit_price": {"type": "string", "format": "decimal", "description": "Price each, or null while unpriced.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost each, or null if unknown.", "nullable": true}, "line_total": {"type": "string", "format": "decimal", "description": "quantity × unit_price.", "nullable": true}, "line_cost": {"type": "string", "format": "decimal", "description": "quantity × unit_cost, or null.", "nullable": true}, "notes": {"type": "string", "description": "A note on the line.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Quote": {"type": "object", "properties": {"id": {"type": "integer", "description": "This revision's id."}, "quote_number": {"type": "string", "description": "The quotation's number - its enquiry's reference.", "nullable": true}, "revision": {"type": "integer", "description": "Which revision this is, from 1."}, "latest_revision": {"type": "integer", "description": "The newest revision of the number."}, "status": {"type": "string", "description": "draft, sent, accepted (won), rejected (lost), superseded or expired.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry it is for, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "enquiry_title": {"type": "string", "description": "That enquiry's title.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer."}, "company_name": {"type": "string", "description": "The customer's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "The contact's name.", "nullable": true}, "contact_email": {"type": "string", "description": "The contact's address.", "nullable": true}, "pipeline_id": {"type": "integer", "description": "The quote pipeline it is on."}, "pipeline_name": {"type": "string", "description": "That pipeline's name.", "nullable": true}, "stage_id": {"type": "integer", "description": "The stage it is at."}, "stage_name": {"type": "string", "description": "That stage's name.", "nullable": true}, "quote_date": {"type": "string", "format": "date", "description": "Dated.", "nullable": true}, "valid_until": {"type": "string", "format": "date", "description": "Valid until.", "nullable": true}, "discount_pct": {"type": "string", "format": "decimal", "description": "Whole-quote discount, per cent.", "nullable": true}, "currency": {"type": "string", "description": "The document's currency (ISO code).", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours, fixed when it was raised.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate applied, per cent.", "nullable": true}, "net_subtotal": {"type": "string", "format": "decimal", "description": "The lines added up, after their own discounts.", "nullable": true}, "discount_amount": {"type": "string", "format": "decimal", "description": "The whole-document discount taken off.", "nullable": true}, "net_total": {"type": "string", "format": "decimal", "description": "Net of VAT, after discount.", "nullable": true}, "vat_amount": {"type": "string", "format": "decimal", "description": "VAT.", "nullable": true}, "gross_total": {"type": "string", "format": "decimal", "description": "Total payable.", "nullable": true}, "total_cost": {"type": "string", "format": "decimal", "description": "Cost of the costed lines.", "nullable": true}, "uncosted_lines": {"type": "integer", "description": "Lines with no cost recorded, so the margin is incomplete."}, "lead_time": {"type": "string", "description": "Lead time, as written.", "nullable": true}, "delivery_terms": {"type": "string", "description": "Delivery terms.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms.", "nullable": true}, "notes": {"type": "string", "description": "Notes printed on it.", "nullable": true}, "outcome_reason": {"type": "string", "description": "Why it was won or lost.", "nullable": true}, "sent_at": {"type": "string", "format": "date-time", "description": "When it was first sent.", "nullable": true}, "decided_at": {"type": "string", "format": "date-time", "description": "When it was won or lost.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "line_count": {"type": "integer", "description": "How many lines."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "QuoteLine": {"type": "object", "properties": {"id": {"type": "integer", "description": "The line's id."}, "line_no": {"type": "integer", "description": "Its position."}, "product_id": {"type": "integer", "description": "The product it came from, or null."}, "product_code": {"type": "string", "description": "The code printed.", "nullable": true}, "description": {"type": "string", "description": "The wording printed.", "nullable": true}, "quantity": {"type": "string", "format": "decimal", "description": "How many.", "nullable": true}, "unit": {"type": "string", "description": "each, bay, m and so on.", "nullable": true}, "dim_length": {"type": "integer", "description": "Length in mm, where sold at a size."}, "dim_width": {"type": "integer", "description": "Width in mm."}, "dim_height": {"type": "integer", "description": "Height in mm."}, "unit_price": {"type": "string", "format": "decimal", "description": "Price each.", "nullable": true}, "line_discount_pct": {"type": "string", "format": "decimal", "description": "Discount on this line, per cent.", "nullable": true}, "line_total": {"type": "string", "format": "decimal", "description": "After the line's own discount.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost each, or null.", "nullable": true}, "line_cost": {"type": "string", "format": "decimal", "description": "quantity × unit_cost, or null.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Order": {"type": "object", "properties": {"id": {"type": "integer", "description": "The order's id."}, "reference": {"type": "string", "description": "Its reference - the enquiry's, with -2 for a second order on the same job.", "nullable": true}, "status": {"type": "string", "description": "confirmed, drawings, manufacturing, ready, delivered, installed, complete or cancelled.", "nullable": true}, "status_label": {"type": "string", "description": "What the company calls that step.", "nullable": true}, "quote_id": {"type": "integer", "description": "The quotation it came from, or null."}, "quote_number": {"type": "string", "description": "That quotation's number.", "nullable": true}, "quote_revision": {"type": "integer", "description": "That quotation's revision."}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "enquiry_title": {"type": "string", "description": "That enquiry's title.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer."}, "company_name": {"type": "string", "description": "The customer's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "The contact's name.", "nullable": true}, "pipeline_id": {"type": "integer", "description": "The order pipeline it is on."}, "pipeline_name": {"type": "string", "description": "That pipeline's name.", "nullable": true}, "stage_id": {"type": "integer", "description": "The stage it is at."}, "stage_name": {"type": "string", "description": "That stage's name.", "nullable": true}, "customer_po": {"type": "string", "description": "The customer's own order number.", "nullable": true}, "order_date": {"type": "string", "format": "date", "description": "Placed on.", "nullable": true}, "promised_date": {"type": "string", "format": "date", "description": "What the customer was promised.", "nullable": true}, "delivered_date": {"type": "string", "format": "date", "description": "When it was delivered.", "nullable": true}, "installed_date": {"type": "string", "format": "date", "description": "When it was installed.", "nullable": true}, "site_name": {"type": "string", "description": "The site.", "nullable": true}, "site_address": {"type": "string", "description": "The site's address.", "nullable": true}, "site_postcode": {"type": "string", "description": "The site's postcode.", "nullable": true}, "access_notes": {"type": "string", "description": "How to get in.", "nullable": true}, "currency": {"type": "string", "description": "The document's currency (ISO code).", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours, fixed when it was raised.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate applied, per cent.", "nullable": true}, "net_subtotal": {"type": "string", "format": "decimal", "description": "The lines added up, after their own discounts.", "nullable": true}, "discount_amount": {"type": "string", "format": "decimal", "description": "The whole-document discount taken off.", "nullable": true}, "net_total": {"type": "string", "format": "decimal", "description": "Net of VAT, after discount.", "nullable": true}, "vat_amount": {"type": "string", "format": "decimal", "description": "VAT.", "nullable": true}, "gross_total": {"type": "string", "format": "decimal", "description": "Total payable.", "nullable": true}, "total_cost": {"type": "string", "format": "decimal", "description": "Cost of the costed lines.", "nullable": true}, "uncosted_lines": {"type": "integer", "description": "Lines with no cost recorded, so the margin is incomplete."}, "invoiced_at": {"type": "string", "format": "date", "description": "When it was fully billed, or null.", "nullable": true}, "invoice_ref": {"type": "string", "description": "The invoice that billed it, or one typed from your accounts package.", "nullable": true}, "lead_time": {"type": "string", "description": "Lead time, as written.", "nullable": true}, "notes": {"type": "string", "description": "Notes.", "nullable": true}, "outcome_reason": {"type": "string", "description": "The note on its last status change.", "nullable": true}, "completed_at": {"type": "string", "format": "date-time", "description": "When it was completed or cancelled.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "is_late": {"type": "boolean", "description": "Past its promised date and not yet delivered."}, "days_late": {"type": "integer", "description": "Days past the promised date (negative while there is time)."}, "is_archived": {"type": "boolean", "description": "Archived rather than deleted."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "OrderLine": {"type": "object", "properties": {"id": {"type": "integer", "description": "The line's id - kept for life, because invoices point at it."}, "line_no": {"type": "integer", "description": "Its position."}, "quote_line_id": {"type": "integer", "description": "The quote line it was copied from, or null."}, "product_id": {"type": "integer", "description": "The product, or null."}, "product_code": {"type": "string", "description": "The code.", "nullable": true}, "description": {"type": "string", "description": "The wording.", "nullable": true}, "quantity": {"type": "string", "format": "decimal", "description": "How many ordered.", "nullable": true}, "quantity_delivered": {"type": "string", "format": "decimal", "description": "How many have gone out.", "nullable": true}, "unit": {"type": "string", "description": "each, bay, m and so on.", "nullable": true}, "dim_length": {"type": "integer", "description": "Length in mm, where sold at a size."}, "dim_width": {"type": "integer", "description": "Width in mm."}, "dim_height": {"type": "integer", "description": "Height in mm."}, "unit_price": {"type": "string", "format": "decimal", "description": "Price each, discounts already folded in.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost each, or null.", "nullable": true}, "line_total": {"type": "string", "format": "decimal", "description": "quantity × unit_price.", "nullable": true}, "line_cost": {"type": "string", "format": "decimal", "description": "quantity × unit_cost, or null.", "nullable": true}, "notes": {"type": "string", "description": "A note on the line.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Invoice": {"type": "object", "properties": {"id": {"type": "integer", "description": "The invoice's id."}, "reference": {"type": "string", "description": "Its reference - the order's, with -2, -3 for further invoices on the job.", "nullable": true}, "status": {"type": "string", "description": "draft, sent, paid or cancelled.", "nullable": true}, "quote_id": {"type": "integer", "description": "The quotation, or null."}, "quote_number": {"type": "string", "description": "That quotation's number.", "nullable": true}, "order_id": {"type": "integer", "description": "The order it bills, or null for one raised on its own."}, "order_reference": {"type": "string", "description": "That order's reference.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer."}, "company_name": {"type": "string", "description": "The customer's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "The contact's name.", "nullable": true}, "contact_email": {"type": "string", "description": "The contact's address.", "nullable": true}, "pipeline_id": {"type": "integer", "description": "The invoice pipeline it is on."}, "pipeline_name": {"type": "string", "description": "That pipeline's name.", "nullable": true}, "stage_id": {"type": "integer", "description": "The stage it is at."}, "stage_name": {"type": "string", "description": "That stage's name.", "nullable": true}, "customer_po": {"type": "string", "description": "The customer's own order number.", "nullable": true}, "invoice_date": {"type": "string", "format": "date", "description": "Dated.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "Payment due.", "nullable": true}, "payment_terms": {"type": "string", "description": "Payment terms, as written.", "nullable": true}, "discount_pct": {"type": "string", "format": "decimal", "description": "Whole-invoice discount, per cent; usually nil.", "nullable": true}, "currency": {"type": "string", "description": "The document's currency (ISO code).", "nullable": true}, "fx_rate": {"type": "string", "format": "decimal", "description": "Units of that currency per one of yours, fixed when it was raised.", "nullable": true}, "vat_rate": {"type": "string", "format": "decimal", "description": "VAT rate applied, per cent.", "nullable": true}, "net_subtotal": {"type": "string", "format": "decimal", "description": "The lines added up, after their own discounts.", "nullable": true}, "discount_amount": {"type": "string", "format": "decimal", "description": "The whole-document discount taken off.", "nullable": true}, "net_total": {"type": "string", "format": "decimal", "description": "Net of VAT, after discount.", "nullable": true}, "vat_amount": {"type": "string", "format": "decimal", "description": "VAT.", "nullable": true}, "gross_total": {"type": "string", "format": "decimal", "description": "Total payable.", "nullable": true}, "total_cost": {"type": "string", "format": "decimal", "description": "Cost of the costed lines.", "nullable": true}, "uncosted_lines": {"type": "integer", "description": "Lines with no cost recorded, so the margin is incomplete."}, "notes": {"type": "string", "description": "Notes printed on it.", "nullable": true}, "outcome_reason": {"type": "string", "description": "The note on its last status change.", "nullable": true}, "sent_at": {"type": "string", "format": "date-time", "description": "When it was sent.", "nullable": true}, "paid_at": {"type": "string", "format": "date", "description": "When it was paid.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Whose it is."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "is_overdue": {"type": "boolean", "description": "Sent and past its due date."}, "days_overdue": {"type": "integer", "description": "Days past the due date (negative while there is time)."}, "order_net_total": {"type": "string", "format": "decimal", "description": "The order's net value, where it bills one.", "nullable": true}, "order_remaining_net": {"type": "string", "format": "decimal", "description": "What is still to bill on that order, by value.", "nullable": true}, "order_is_settled": {"type": "boolean", "description": "Whether that order is now fully billed."}, "is_archived": {"type": "boolean", "description": "Archived rather than deleted."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "InvoiceLine": {"type": "object", "properties": {"id": {"type": "integer", "description": "The line's id."}, "line_no": {"type": "integer", "description": "Its position."}, "order_line_id": {"type": "integer", "description": "The order line it bills, or null for a line not on the order."}, "product_id": {"type": "integer", "description": "The product, or null."}, "product_code": {"type": "string", "description": "The code.", "nullable": true}, "description": {"type": "string", "description": "The wording.", "nullable": true}, "quantity": {"type": "string", "format": "decimal", "description": "How many are billed on this invoice.", "nullable": true}, "unit": {"type": "string", "description": "each, bay, m and so on.", "nullable": true}, "unit_price": {"type": "string", "format": "decimal", "description": "Price each.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost each, or null.", "nullable": true}, "line_total": {"type": "string", "format": "decimal", "description": "quantity × unit_price.", "nullable": true}, "line_cost": {"type": "string", "format": "decimal", "description": "quantity × unit_cost, or null.", "nullable": true}, "notes": {"type": "string", "description": "A note on the line.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "BillableLine": {"type": "object", "properties": {"order_line_id": {"type": "integer", "description": "The order line."}, "line_no": {"type": "integer", "description": "Its position on the order."}, "product_id": {"type": "integer", "description": "The product, or null."}, "product_code": {"type": "string", "description": "The code.", "nullable": true}, "description": {"type": "string", "description": "The wording.", "nullable": true}, "quantity": {"type": "string", "format": "decimal", "description": "Ordered.", "nullable": true}, "quantity_invoiced": {"type": "string", "format": "decimal", "description": "Already on an invoice that is not cancelled.", "nullable": true}, "quantity_remaining": {"type": "string", "format": "decimal", "description": "Left to invoice.", "nullable": true}, "is_fully_invoiced": {"type": "boolean", "description": "Nothing left on it."}, "unit": {"type": "string", "description": "each, bay, m and so on.", "nullable": true}, "bill_price": {"type": "string", "format": "decimal", "description": "The price agreed: the line total spread over the quantity.", "nullable": true}, "unit_price": {"type": "string", "format": "decimal", "description": "The order line's price each.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Coverage": {"type": "object", "properties": {"net_total": {"type": "string", "format": "decimal", "description": "The order's net value.", "nullable": true}, "billed_net": {"type": "string", "format": "decimal", "description": "Invoiced so far, net, not counting cancelled invoices.", "nullable": true}, "remaining_net": {"type": "string", "format": "decimal", "description": "Still to bill, never below zero.", "nullable": true}, "invoice_count": {"type": "integer", "description": "Invoices raised against it that are not cancelled."}, "is_settled": {"type": "boolean", "description": "Fully billed, within a penny."}, "percent": {"type": "integer", "description": "How much of it is billed, 0 to 100."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Product": {"type": "object", "properties": {"id": {"type": "integer", "description": "The product's id."}, "code": {"type": "string", "description": "Its code, unique in your price book, or null.", "nullable": true}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "description": {"type": "string", "description": "The wording a line starts with.", "nullable": true}, "unit": {"type": "string", "description": "What it is sold by: each, bay, m and so on.", "nullable": true}, "dimensions": {"type": "array", "items": {}, "description": "Which of length, width, height a line asks for; empty for one size."}, "unit_price": {"type": "string", "format": "decimal", "description": "Sell price in your currency, or null when priced per job.", "nullable": true}, "unit_cost": {"type": "string", "format": "decimal", "description": "Cost, or null when unknown - which is what switches margin reporting off for it.", "nullable": true}, "category": {"type": "string", "description": "Its category - what an enquiry can be filed under.", "nullable": true}, "notes": {"type": "string", "description": "Notes.", "nullable": true}, "is_active": {"type": "boolean", "description": "On sale; false once withdrawn."}, "times_quoted": {"type": "integer", "description": "Quote lines that came from it."}, "times_enquired": {"type": "integer", "description": "Enquiry lines that came from it."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Task": {"type": "object", "properties": {"id": {"type": "integer", "description": "The task's id."}, "title": {"type": "string", "description": "What has to be done.", "nullable": true}, "details": {"type": "string", "description": "More detail.", "nullable": true}, "due_date": {"type": "string", "format": "date", "description": "When by.", "nullable": true}, "priority": {"type": "string", "description": "low, normal or high.", "nullable": true}, "status": {"type": "string", "description": "open, done or cancelled.", "nullable": true}, "assigned_to_user_id": {"type": "integer", "description": "Whose it is."}, "assignee_name": {"type": "string", "description": "Their name.", "nullable": true}, "company_id": {"type": "integer", "description": "The company it is about, or null."}, "company_name": {"type": "string", "description": "That company's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "That contact's name.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "order_id": {"type": "integer", "description": "The order, or null."}, "order_reference": {"type": "string", "description": "That order's reference.", "nullable": true}, "completed_at": {"type": "string", "format": "date-time", "description": "When it was done.", "nullable": true}, "is_overdue": {"type": "boolean", "description": "Open and past its due date."}, "created_by": {"type": "integer", "description": "Who made it."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Activity": {"type": "object", "properties": {"id": {"type": "integer", "description": "The entry's id."}, "activity_type": {"type": "string", "description": "call, email, meeting, site_visit, note or other.", "nullable": true}, "subject": {"type": "string", "description": "What it was.", "nullable": true}, "body": {"type": "string", "description": "The detail.", "nullable": true}, "occurred_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "user_id": {"type": "integer", "description": "Who logged it."}, "logged_by": {"type": "string", "description": "Their name.", "nullable": true}, "company_id": {"type": "integer", "description": "The company, or null."}, "company_name": {"type": "string", "description": "That company's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "That contact's name.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "created_at": {"type": "string", "format": "date-time", "description": "When it was logged.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Document": {"type": "object", "properties": {"id": {"type": "integer", "description": "The document's id."}, "filename": {"type": "string", "description": "The name it was uploaded with, and downloads as.", "nullable": true}, "content_type": {"type": "string", "description": "Its media type, from the extension.", "nullable": true}, "byte_size": {"type": "integer", "description": "Size in bytes."}, "checksum": {"type": "string", "description": "SHA-256 of the file.", "nullable": true}, "description": {"type": "string", "description": "What it is.", "nullable": true}, "company_id": {"type": "integer", "description": "The customer it is held for."}, "company_name": {"type": "string", "description": "That company's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact it was filed against, or null."}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "quote_id": {"type": "integer", "description": "The quotation, or null."}, "quote_number": {"type": "string", "description": "That quotation's number.", "nullable": true}, "order_id": {"type": "integer", "description": "The order, or null."}, "order_reference": {"type": "string", "description": "That order's reference.", "nullable": true}, "record_id": {"type": "integer", "description": "The record on one of your own tabs, or null."}, "record_reference": {"type": "string", "description": "That record's reference.", "nullable": true}, "uploaded_by": {"type": "integer", "description": "Who uploaded it."}, "uploaded_by_name": {"type": "string", "description": "Their name.", "nullable": true}, "created_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Record": {"type": "object", "properties": {"id": {"type": "integer", "description": "The record's id."}, "module_id": {"type": "integer", "description": "The tab it is on."}, "reference": {"type": "string", "description": "Its reference, where the tab numbers its records.", "nullable": true}, "title": {"type": "string", "description": "Its name.", "nullable": true}, "company_id": {"type": "integer", "description": "The company it is linked to, or null."}, "company_name": {"type": "string", "description": "That company's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "contact_name": {"type": "string", "description": "That contact's name.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "The person it is linked to, or null."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "is_archived": {"type": "boolean", "description": "Archived rather than deleted."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Email": {"type": "object", "properties": {"id": {"type": "integer", "description": "The message's id."}, "subject": {"type": "string", "description": "Subject line.", "nullable": true}, "from_address": {"type": "string", "description": "Who sent it.", "nullable": true}, "from_name": {"type": "string", "description": "Their name as sent.", "nullable": true}, "sent_at": {"type": "string", "format": "date-time", "description": "When it was sent.", "nullable": true}, "received_at": {"type": "string", "format": "date-time", "description": "When it was captured.", "nullable": true}, "visibility": {"type": "string", "description": "shared, or private to whoever captured it.", "nullable": true}, "match_rule": {"type": "string", "description": "How it was filed: job, thread, token, contact, domain or none.", "nullable": true}, "company_id": {"type": "integer", "description": "The company it is filed against, or null."}, "company_name": {"type": "string", "description": "That company's name.", "nullable": true}, "contact_id": {"type": "integer", "description": "The contact, or null."}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "quote_id": {"type": "integer", "description": "The quotation, or null."}, "order_id": {"type": "integer", "description": "The order, or null."}, "invoice_id": {"type": "integer", "description": "The invoice, or null."}, "captured_by": {"type": "string", "description": "Whose capture address caught it.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "EmailAttachment": {"type": "object", "properties": {"id": {"type": "integer", "description": "The attachment's id."}, "filename": {"type": "string", "description": "Its name.", "nullable": true}, "content_type": {"type": "string", "description": "Its media type.", "nullable": true}, "byte_size": {"type": "integer", "description": "Size in bytes."}, "is_inline": {"type": "boolean", "description": "Part of the message's own layout (a signature image) rather than a file sent."}, "refused_reason": {"type": "string", "description": "Why the file was not kept, or null.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "User": {"type": "object", "properties": {"id": {"type": "integer", "description": "The user's id - what owner and assignee fields take."}, "full_name": {"type": "string", "description": "Their name.", "nullable": true}, "email": {"type": "string", "description": "Their address.", "nullable": true}, "role": {"type": "string", "description": "tenant_admin or standard.", "nullable": true}, "role_name": {"type": "string", "description": "Administrator, Standard, or the company's own role.", "nullable": true}, "is_active": {"type": "boolean", "description": "Whether they can sign in."}, "last_login_at": {"type": "string", "format": "date-time", "description": "When they last signed in.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Pipeline": {"type": "object", "properties": {"id": {"type": "integer", "description": "The pipeline's id."}, "entity": {"type": "string", "description": "enquiry, quote, order or invoice.", "nullable": true}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "is_default": {"type": "boolean", "description": "Where a new record of its kind starts."}, "is_active": {"type": "boolean", "description": "Offered on forms and boards."}, "sort_order": {"type": "integer", "description": "Its position."}, "stages": {"type": "array", "items": {}, "description": "Its stages, in order: id, name, sort_order, outcome, maps_to, default_probability, is_active."}, "rules": {"type": "array", "items": {}, "description": "What moves records along it: trigger_key, after_days, target_stage_id, target_name, is_active."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Stage": {"type": "object", "properties": {"id": {"type": "integer", "description": "The stage's id."}, "pipeline_id": {"type": "integer", "description": "Its pipeline."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "sort_order": {"type": "integer", "description": "Its position."}, "outcome": {"type": "string", "description": "open, won or lost.", "nullable": true}, "maps_to": {"type": "string", "description": "The fixed status a quote, order or invoice stage records; null on an enquiry stage.", "nullable": true}, "default_probability": {"type": "integer", "description": "The odds a typical enquiry has here."}, "is_active": {"type": "boolean", "description": "Still offered."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Source": {"type": "object", "properties": {"id": {"type": "integer", "description": "The source's id."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "sort_order": {"type": "integer", "description": "Its position."}, "is_active": {"type": "boolean", "description": "Still offered."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Role": {"type": "object", "properties": {"id": {"type": "integer", "description": "The role's id."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "tabs": {"type": "array", "items": {}, "description": "The tab keys it includes."}, "people": {"type": "integer", "description": "How many hold it."}, "active_people": {"type": "integer", "description": "How many of them are active."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "ApiKey": {"type": "object", "properties": {"id": {"type": "integer", "description": "The key's id."}, "name": {"type": "string", "description": "What it was called.", "nullable": true}, "key_prefix": {"type": "string", "description": "The start of the key, to tell it apart.", "nullable": true}, "scope": {"type": "string", "description": "read or write.", "nullable": true}, "user_id": {"type": "integer", "description": "The account it acts as."}, "user_name": {"type": "string", "description": "Their name.", "nullable": true}, "expires_at": {"type": "string", "format": "date-time", "description": "When it stops, or null.", "nullable": true}, "last_used_at": {"type": "string", "format": "date-time", "description": "When it was last used.", "nullable": true}, "use_count": {"type": "integer", "description": "How many requests it has made."}, "revoked_at": {"type": "string", "format": "date-time", "description": "When it was revoked, or null.", "nullable": true}, "created_at": {"type": "string", "format": "date-time", "description": "When it was made.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "FieldDefinition": {"type": "object", "properties": {"id": {"type": "integer", "description": "The field's id."}, "name": {"type": "string", "description": "Its key - how it is sent and answered under 'fields'.", "nullable": true}, "label": {"type": "string", "description": "What the form calls it.", "nullable": true}, "field_type": {"type": "string", "description": "text, textarea, number, money, date, datetime, select, checkbox, or a link type on a tab of your own.", "nullable": true}, "options": {"type": "array", "items": {}, "description": "The choices of a select field."}, "hint": {"type": "string", "description": "The help under the box.", "nullable": true}, "is_required": {"type": "boolean", "description": "Must be filled in."}, "sort_order": {"type": "integer", "description": "Its position."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Tab": {"type": "object", "properties": {"id": {"type": "integer", "description": "The tab's id."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "slug": {"type": "string", "description": "Its address segment - what the records routes take.", "nullable": true}, "item_name": {"type": "string", "description": "What one record is called.", "nullable": true}, "reference_prefix": {"type": "string", "description": "The prefix its references take, or null if not numbered.", "nullable": true}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "is_active": {"type": "boolean", "description": "Shown in the menu."}, "fields": {"type": "array", "items": {}, "description": "Its fields, each as a FieldDefinition with is_title and show_in_list as well."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}}}, "Queue": {"type": "object", "properties": {"id": {"type": "integer", "description": "The queue's id."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "dataset": {"type": "string", "description": "The list it is over: enquiries, quotes, orders, invoices, tasks, companies, contacts, or records:<tab id>.", "nullable": true}, "filters": {"type": "object", "additionalProperties": true, "description": "The list page's arguments it carries."}, "filter_text": {"type": "array", "items": {}, "description": "The same, in words."}, "columns": {"type": "array", "items": {}, "description": "Its column keys, or null for the list's own."}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "visibility": {"type": "string", "description": "shared or private.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Who made it."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "count": {"type": "integer", "description": "How many records are in it now."}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "SavedReport": {"type": "object", "properties": {"id": {"type": "integer", "description": "The report's id."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "description": {"type": "string", "description": "What it is for.", "nullable": true}, "kind": {"type": "string", "description": "totals or list.", "nullable": true}, "spec": {"type": "object", "additionalProperties": true, "description": "Its specification: the same keys the report routes take."}, "visibility": {"type": "string", "description": "shared or private.", "nullable": true}, "owner_user_id": {"type": "integer", "description": "Who made it."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Automation": {"type": "object", "properties": {"id": {"type": "integer", "description": "The automation's id."}, "name": {"type": "string", "description": "Its name.", "nullable": true}, "sentence": {"type": "string", "description": "What it does, in a line.", "nullable": true}, "entity": {"type": "string", "description": "The tab it watches.", "nullable": true}, "event": {"type": "string", "description": "created, updated, archived or date.", "nullable": true}, "is_active": {"type": "boolean", "description": "Switched on."}, "problems": {"type": "array", "items": {}, "description": "What stops it being switched on."}, "run_count": {"type": "integer", "description": "How many times it has acted."}, "last_run_at": {"type": "string", "format": "date-time", "description": "When it last acted.", "nullable": true}, "failure_streak": {"type": "integer", "description": "Failures in a row."}, "off_reason": {"type": "string", "description": "Why it switched itself off, if it did.", "nullable": true}, "definition": {"type": "object", "additionalProperties": true, "description": "The trigger, conditions and steps, as the builder stores them."}, "created_at": {"type": "string", "format": "date-time", "description": "When the record was made.", "nullable": true}, "updated_at": {"type": "string", "format": "date-time", "description": "When it last changed.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "AutomationRun": {"type": "object", "properties": {"id": {"type": "integer", "description": "The run's id."}, "automation_id": {"type": "integer", "description": "Which automation."}, "automation_name": {"type": "string", "description": "Its name.", "nullable": true}, "entity": {"type": "string", "description": "The tab of the record it acted on.", "nullable": true}, "record_id": {"type": "integer", "description": "The record."}, "record_label": {"type": "string", "description": "The record's reference or name.", "nullable": true}, "cause": {"type": "string", "description": "What set it off.", "nullable": true}, "outcome": {"type": "string", "description": "done, partly, failed or nothing.", "nullable": true}, "summary": {"type": "string", "description": "What happened, in a line.", "nullable": true}, "detail": {"type": "array", "items": {}, "description": "What each step did."}, "actor_name": {"type": "string", "description": "Who made the change that set it off.", "nullable": true}, "created_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "AuditEntry": {"type": "object", "properties": {"id": {"type": "integer", "description": "The entry's id."}, "entity": {"type": "string", "description": "The kind of record: company, enquiry, quote, order, invoice, product, task, contact, api_key, tenant_settings.", "nullable": true}, "record_id": {"type": "integer", "description": "Which record."}, "record_label": {"type": "string", "description": "Its reference or name at the time.", "nullable": true}, "action": {"type": "string", "description": "created, updated, archived, restored, deleted or status_changed.", "nullable": true}, "actor_user_id": {"type": "integer", "description": "Who, or null for the system."}, "actor_name": {"type": "string", "description": "Their name - with the API key's name when it was a program.", "nullable": true}, "changes": {"type": "object", "additionalProperties": true, "description": "Field name to {from, to}."}, "summary": {"type": "string", "description": "The change in a line.", "nullable": true}, "created_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "CalendarEvent": {"type": "object", "properties": {"kind": {"type": "string", "description": "meeting, note, task, enquiry, quote or order.", "nullable": true}, "id": {"type": "integer", "description": "The record's id."}, "on": {"type": "string", "format": "date", "description": "The day.", "nullable": true}, "at": {"type": "string", "format": "date-time", "description": "The time, for a call or meeting; null for an all-day item.", "nullable": true}, "ends_at": {"type": "string", "format": "date-time", "description": "Half an hour on, for a call or meeting.", "nullable": true}, "title": {"type": "string", "description": "What it is.", "nullable": true}, "ref": {"type": "string", "description": "The record's reference, where it has one.", "nullable": true}, "state": {"type": "string", "description": "Its status or stage.", "nullable": true}, "done": {"type": "boolean", "description": "Already happened or completed."}, "value": {"type": "string", "format": "decimal", "description": "What it is worth, where it is worth something.", "nullable": true}, "company_id": {"type": "integer", "description": "The company, or null."}, "company_name": {"type": "string", "description": "Its name.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry, or null."}, "owner_user_id": {"type": "integer", "description": "Whose it is."}, "owner_name": {"type": "string", "description": "Their name.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "WebSubmission": {"type": "object", "properties": {"id": {"type": "integer", "description": "The submission's id."}, "status": {"type": "string", "description": "pending, approved or rejected.", "nullable": true}, "received_at": {"type": "string", "format": "date-time", "description": "When the website sent it.", "nullable": true}, "name": {"type": "string", "description": "The sender's name.", "nullable": true}, "email": {"type": "string", "description": "The sender's address.", "nullable": true}, "company": {"type": "string", "description": "The company they gave.", "nullable": true}, "job_title": {"type": "string", "description": "Their job title.", "nullable": true}, "phone": {"type": "string", "description": "Telephone.", "nullable": true}, "mobile": {"type": "string", "description": "Mobile.", "nullable": true}, "address_line1": {"type": "string", "description": "Address.", "nullable": true}, "address_line2": {"type": "string", "description": "Address, second line.", "nullable": true}, "city": {"type": "string", "description": "Town or city.", "nullable": true}, "county": {"type": "string", "description": "County.", "nullable": true}, "postcode": {"type": "string", "description": "Postcode.", "nullable": true}, "site_postcode": {"type": "string", "description": "Where the work would be.", "nullable": true}, "product": {"type": "string", "description": "What it is for.", "nullable": true}, "budget": {"type": "string", "description": "The budget band.", "nullable": true}, "timescale": {"type": "string", "description": "When it is needed.", "nullable": true}, "heard_about": {"type": "string", "description": "How they heard of you.", "nullable": true}, "subject": {"type": "string", "description": "Subject.", "nullable": true}, "message": {"type": "string", "description": "What they wrote.", "nullable": true}, "page": {"type": "string", "description": "The page of your site the form was on.", "nullable": true}, "enquiry_id": {"type": "integer", "description": "The enquiry it became, once approved."}, "enquiry_reference": {"type": "string", "description": "That enquiry's reference.", "nullable": true}, "reviewer_name": {"type": "string", "description": "Who approved or rejected it.", "nullable": true}, "reviewed_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "review_note": {"type": "string", "description": "Why it was rejected.", "nullable": true}, "web_url": {"type": "string", "description": "The record's own page in the CRM.", "nullable": true}, "fields": {"type": "object", "additionalProperties": true, "description": "The record's extra fields, by name, where the tab takes them."}}}, "Index": {"type": "object", "properties": {"name": {"type": "string", "description": "ManufactIQ API.", "nullable": true}, "version": {"type": "string", "description": "The API version in every address.", "nullable": true}, "application": {"type": "string", "description": "The CRM's own version.", "nullable": true}, "docs_url": {"type": "string", "description": "The reference.", "nullable": true}, "openapi_url": {"type": "string", "description": "The OpenAPI document.", "nullable": true}, "authenticate": {"type": "string", "description": "How to send a key.", "nullable": true}}}, "Me": {"type": "object", "properties": {"key": {"type": "object", "additionalProperties": true, "description": "The key, as an ApiKey."}, "user": {"type": "object", "additionalProperties": true, "description": "The person the key acts as, as a User."}, "company": {"type": "object", "additionalProperties": true, "description": "id, name, slug and plan."}, "scope": {"type": "string", "description": "read or write.", "nullable": true}, "rate_limit": {"type": "object", "additionalProperties": true, "description": "per_minute, and remaining in this minute."}, "server_time": {"type": "string", "format": "date-time", "description": "The server's clock, in its own time.", "nullable": true}, "version": {"type": "string", "description": "The API version.", "nullable": true}}}, "OpenAPI": {"type": "object", "properties": {"openapi": {"type": "string", "description": "3.0.3.", "nullable": true}, "paths": {"type": "object", "additionalProperties": true, "description": "Every route."}, "components": {"type": "object", "additionalProperties": true, "description": "Every schema."}}}, "Deleted": {"type": "object", "properties": {"deleted": {"type": "boolean", "description": "true."}, "id": {"type": "integer", "description": "What was deleted."}, "name": {"type": "string", "description": "What it was called.", "nullable": true}}}, "Action": {"type": "object", "properties": {"ok": {"type": "boolean", "description": "true."}, "messages": {"type": "array", "items": {}, "description": "What the CRM would have said to a person doing the same thing on screen."}}}, "LinkedRecord": {"type": "object", "properties": {"id": {"type": "integer", "description": "The record's id."}, "reference": {"type": "string", "description": "Its reference.", "nullable": true}, "title": {"type": "string", "description": "Its name.", "nullable": true}, "created_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "module_id": {"type": "integer", "description": "The tab it is on."}, "module_name": {"type": "string", "description": "That tab's name.", "nullable": true}, "slug": {"type": "string", "description": "That tab's address segment.", "nullable": true}, "item_name": {"type": "string", "description": "What one record on that tab is called.", "nullable": true}}}, "SearchResult": {"type": "object", "properties": {"groups": {"type": "array", "items": {}, "description": "One group per kind with hits: key, label, and items of {id, title, sub, web_url}."}}}, "SalesReport": {"type": "object", "properties": {"months": {"type": "integer", "description": "The period, in months."}, "owner_id": {"type": "integer", "description": "Whose share, or null for everybody."}, "generated_at": {"type": "string", "format": "date-time", "description": "When.", "nullable": true}, "performance": {"type": "object", "additionalProperties": true, "description": "Won, lost and open by month, with win rate, average deal and the sales cycle."}, "forecast": {"type": "array", "items": {}, "description": "The open pipeline by expected close month, with weighted values."}, "by_owner": {"type": "array", "items": {}, "description": "Won and lost by person."}, "by_category": {"type": "array", "items": {}, "description": "Won and lost by product category."}, "by_source": {"type": "array", "items": {}, "description": "Won and lost by enquiry source."}, "top_customers": {"type": "array", "items": {}, "description": "The customers who bought most."}, "quotes": {"type": "object", "additionalProperties": true, "description": "Quotation conversion, or null for a role without quotes."}, "lost_reasons": {"type": "array", "items": {}, "description": "Why work was lost, by reason."}, "lost_total": {"type": "integer", "description": "How many were lost."}, "margin": {"type": "object", "additionalProperties": true, "description": "The margin quoted, or null for a role without quotes."}, "monthly": {"type": "array", "items": {}, "description": "Won value by month."}}}, "KpiHub": {"type": "object", "properties": {"period": {"type": "object", "additionalProperties": true, "description": "from, to and label."}, "comparison": {"type": "object", "additionalProperties": true, "description": "The period it is set against, or null."}, "compare_label": {"type": "string", "description": "What the comparison is called.", "nullable": true}, "sales": {"type": "object", "additionalProperties": true, "description": "kpis, snapshots, stage_rows, by_product, by_source - or null."}, "workshop": {"type": "object", "additionalProperties": true, "description": "kpis, snapshots, load, by_area - or null."}, "cash": {"type": "object", "additionalProperties": true, "description": "kpis, snapshots, aged, aged_total - or null."}, "customers": {"type": "object", "additionalProperties": true, "description": "kpis and the tables about customers - or null."}, "people": {"type": "object", "additionalProperties": true, "description": "Each person's figures - or null."}, "tabs": {"type": "array", "items": {}, "description": "A block per tab of your own that carries dates."}, "fields": {"type": "array", "items": {}, "description": "A block per extra field worth grouping by."}, "overview": {"type": "object", "additionalProperties": true, "description": "The lead tiles and snapshots from every section."}}}, "Dashboard": {"type": "object", "properties": {"headline": {"type": "object", "additionalProperties": true, "description": "Open pipeline, weighted forecast, won and lost this month and more."}, "conversion": {"type": "object", "additionalProperties": true, "description": "Won, lost and the rate over twelve months."}, "pipeline_by_stage": {"type": "array", "items": {}, "description": "Open enquiries and their value at each stage."}, "order_book": {"type": "object", "additionalProperties": true, "description": "Open orders, their value, late ones, due this week, delivered but not invoiced."}, "invoice_book": {"type": "object", "additionalProperties": true, "description": "Drafts, outstanding, overdue and billed this month."}, "attention": {"type": "array", "items": {}, "description": "What needs a person today: tone, kind, title, detail, web_url."}}}, "Dataset": {"type": "object", "properties": {"key": {"type": "string", "description": "What the report routes take as dataset.", "nullable": true}, "label": {"type": "string", "description": "What it is called.", "nullable": true}, "dimensions": {"type": "array", "items": {}, "description": "What it can be grouped by: key and label."}, "measures": {"type": "array", "items": {}, "description": "Its figures: key, label, format (count, money, pct, days, number) and hint."}, "dates": {"type": "array", "items": {}, "description": "The date fields a period can apply to."}, "filters": {"type": "array", "items": {}, "description": "The filter arguments it takes (owner, status...)."}, "columns": {"type": "array", "items": {}, "description": "The columns a list of it can show."}, "defaults": {"type": "object", "additionalProperties": true, "description": "dim, measures, date and columns when none is sent."}}}, "TotalsReport": {"type": "object", "properties": {"spec": {"type": "object", "additionalProperties": true, "description": "The report, every word checked."}, "args": {"type": "object", "additionalProperties": true, "description": "The same as query-string arguments."}, "title": {"type": "string", "description": "The report in a sentence.", "nullable": true}, "period": {"type": "object", "additionalProperties": true, "description": "from, to and label."}, "comparison": {"type": "object", "additionalProperties": true, "description": "The period it is set against, or null."}, "measures": {"type": "array", "items": {}, "description": "The figures: key, label and format."}, "dimension": {"type": "object", "additionalProperties": true, "description": "What it is grouped by."}, "rows": {"type": "array", "items": {}, "description": "One per group: key, label, each measure's value, its previous value and the change."}, "totals": {"type": "object", "additionalProperties": true, "description": "The same, added up."}, "other": {"type": "object", "additionalProperties": true, "description": "Groups beyond the first sixty, folded together, or null."}, "web_url": {"type": "string", "description": "The report's own page.", "nullable": true}}}, "ListReport": {"type": "object", "properties": {"spec": {"type": "object", "additionalProperties": true, "description": "The list, every word checked."}, "args": {"type": "object", "additionalProperties": true, "description": "The same as query-string arguments."}, "title": {"type": "string", "description": "What it lists.", "nullable": true}, "period": {"type": "object", "additionalProperties": true, "description": "from, to and label, or null for any date."}, "columns": {"type": "array", "items": {}, "description": "The columns: key, label and format."}, "rows": {"type": "array", "items": {}, "description": "One per record, keyed by column."}, "total": {"type": "integer", "description": "How many rows matched."}, "truncated": {"type": "boolean", "description": "Whether the limit cut the rows short."}, "web_url": {"type": "string", "description": "The list's own page.", "nullable": true}}}, "ProductCategories": {"type": "object", "properties": {"groups": {"type": "array", "items": {}, "description": "Each group's name and its items of {value, label}."}, "default": {"type": "string", "description": "The category a new enquiry starts on.", "nullable": true}}}, "Vocabulary": {"type": "object", "properties": {"terms": {"type": "object", "additionalProperties": true, "description": "The company's words for each record type: singular and plural."}, "company_types": {"type": "array", "items": {}, "description": "key and label."}, "activity_types": {"type": "array", "items": {}, "description": "key and label."}, "task_priorities": {"type": "array", "items": {}, "description": "key and label."}, "task_statuses": {"type": "array", "items": {}, "description": "key and label."}, "quote_statuses": {"type": "array", "items": {}, "description": "key and label."}, "order_statuses": {"type": "array", "items": {}, "description": "key, the company's label, and whether the step is hidden."}, "invoice_statuses": {"type": "array", "items": {}, "description": "key and label."}, "stage_outcomes": {"type": "array", "items": {}, "description": "open, won, lost."}, "pipeline_entities": {"type": "array", "items": {}, "description": "enquiry, quote, order, invoice."}, "submission_statuses": {"type": "array", "items": {}, "description": "pending, approved, rejected."}, "field_types": {"type": "array", "items": {}, "description": "The types a field on a tab of your own may have."}, "extra_field_types": {"type": "array", "items": {}, "description": "The types an extra field on a shipped tab may have."}, "key_scopes": {"type": "array", "items": {}, "description": "read and write."}}}, "Settings": {"type": "object", "properties": {"letterhead": {"type": "object", "additionalProperties": true, "description": "name, address, phone, email, website, vat_number, company_number."}, "settings": {"type": "object", "additionalProperties": true, "description": "currency, currency_symbol, default_vat_rate, financial_year_start_month, timezone, date_format, quote_validity_days, quote_footer, order_footer."}, "currency": {"type": "object", "additionalProperties": true, "description": "base, symbol, and rates by ISO code."}, "terms": {"type": "object", "additionalProperties": true, "description": "The company's words for each record type."}, "modules": {"type": "object", "additionalProperties": true, "description": "Which tabs are switched on, by key."}, "order_steps": {"type": "array", "items": {}, "description": "The workshop steps in order: key, label, hidden, fixed."}, "numbering": {"type": "object", "additionalProperties": true, "description": "The reference format."}, "example_reference": {"type": "string", "description": "What the next reference would look like.", "nullable": true}, "defaults": {"type": "object", "additionalProperties": true, "description": "payment_days, payment_terms, lead_time, delivery_terms, quote_notes, product_category."}, "documents": {"type": "object", "additionalProperties": true, "description": "What the quotation and invoice carry; the bank details for a role with invoices."}, "plan": {"type": "object", "additionalProperties": true, "description": "key, label, trial_ends_on, max_users, used_users, max_storage_mb, used_mb."}, "features": {"type": "object", "additionalProperties": true, "description": "Each plan feature and whether it is in force."}, "api": {"type": "object", "additionalProperties": true, "description": "version, rate_limit_per_minute, docs_url."}}}}, "responses": {"Error400": {"description": "invalid_json: The body is not a JSON object.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error401": {"description": "unauthenticated: No key was sent, or the key is not recognised, revoked, expired or acting as a disabled account. Which of those it was is not said.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error403": {"description": "plan_required: The company's plan does not include the API, or the part of the CRM the route needs. read_only_key: A read-only key called a route that writes. administrator_required: The route is for company administrators and the key's user is not one. not_in_role: The tab the route belongs to is not in the key's user's role. forbidden: Something only the record's owner, or an administrator, may do.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error404": {"description": "not_found: No such record in this company, or no such address.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error405": {"description": "method_not_allowed: A real address called with a method it does not take; Allow lists the ones it does.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error409": {"description": "duplicate, in_use, quote_decided, order_exists, quote_not_won, invoice_locked, no_lines, order_cancelled, already_decided, storage_full, list_gone, tab_not_ready: The request is well formed but the record's state refuses it; the code says which, and the message says what to do instead.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error413": {"description": "too_large: The request is bigger than the installation accepts.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error415": {"description": "unsupported_media_type: Send JSON, with Content-Type: application/json.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error422": {"description": "validation_failed: A value the form would refuse, in the form's own words; details carries every message.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error429": {"description": "rate_limited: The key has made its allowance of requests this minute; Retry-After says how many seconds to wait.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error500": {"description": "server_error: Something went wrong on the server and has been logged.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "Error503": {"description": "not_ready: The installation's database has not been brought up to date for the API yet, or the PDF engine is not installed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}
