{
  "openapi": "3.1.0",
  "info": {
    "title": "Konverge API",
    "version": "1.0.0",
    "summary": "Read and write your Konverge construction data: projects, tasks, site records, drawings, documents, contacts and money.",
    "description": "Every request is authenticated with an API key (`Authorization: Bearer kvg_live_…`) and acts as that key's own account, with the role, projects and scopes chosen when the key was made. Everything a person with that role could not do, the key cannot do either.\n\n- **Records**: fields are the database column names (snake_case). ids are UUIDs, timestamps RFC 3339 (UTC), dates `YYYY-MM-DD`, amounts JSON numbers with at most 2 decimal places.\n- **Lists**: `{ \"data\": [...], \"has_more\": true, \"next_cursor\": \"…\" }`. Pass `cursor=<next_cursor>` for the next page; `limit` is 1-100 (default 25). Filters: `?status=open,in_progress` (comma = any of), `?due_date[gte]=2026-10-01`, `?updated_since=…`, `?q=…`. An unknown parameter is an error, never ignored.\n- **Writes**: send `Idempotency-Key` on every POST, PATCH and DELETE, and retry safely with the same key.\n- **Rate limits**: two token buckets per request: the key's own (reads 5 × and writes 1 × its per-minute limit, default 600 / 120) and the company's plan bucket, shared by all its keys (`GET /v1/me` shows both). Every response carries `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` (seconds) and the same as `X-RateLimit-*` (`X-RateLimit-Reset` is a Unix time), for the tighter bucket; `Konverge-RateLimit-Scope` says which. A 429 also carries `Retry-After`.\n- **Webhooks**: `POST /v1/webhook_subscriptions` subscribes an https address to events; each delivery is signed (`Konverge-Signature`). See the Webhooks section.\n- **Errors**: `{ \"error\": { \"code\", \"message\", \"request_id\", \"details\"? } }`, with a stable `code` and a plain-words `message`.\n- **Versioning**: `/v1` only changes additively (new resources, fields, filters, values). A breaking change becomes `/v2`; anything retired in v1 is announced with `Deprecation` and `Sunset` headers first.",
    "contact": {
      "name": "Konverge support",
      "email": "support@getkonverge.com",
      "url": "https://getkonverge.com/developers"
    }
  },
  "servers": [
    {
      "url": "https://api.getkonverge.com",
      "description": "Konverge API"
    },
    {
      "url": "https://mzjojszpepzkvcvfblzs.supabase.co/functions/v1/api",
      "description": "The same API at its direct address, for networks that cannot reach api.getkonverge.com."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The API key itself and this document."
    },
    {
      "name": "Webhooks",
      "description": "Subscribe an https address to events (REST hooks, as Zapier, Make and n8n use them), list and delete subscriptions, and what each delivery looks like."
    },
    {
      "name": "Tasks",
      "description": "A task on a project: what needs doing, its status and priority, who it is assigned to and when it is due."
    },
    {
      "name": "Projects",
      "description": "A construction project. Its team is managed with the add_member, set_member_role and remove_member actions."
    },
    {
      "name": "Milestones",
      "description": "A dated milestone on a project's programme."
    },
    {
      "name": "Schedule baselines",
      "description": "A captured copy of a project's programme: every task's start and finish at the moment it was captured, kept unchanged so the programme's slippage (variance) can be measured against it. Numbered per project; one baseline per project is the current one. Baselines are captured in the Konverge apps by owners, admins and managers and are never edited afterwards."
    },
    {
      "name": "Task links",
      "description": "A link between two tasks on the same project's programme: the successor waits for the predecessor. type is FS (finish-to-start: it starts when the other finishes), SS (start-to-start), FF (finish-to-finish) or SF (start-to-finish); lag_days (-365 to 365) adds days, or overlaps when negative. Links never form a loop. Links are made in the Konverge apps or by importing a programme."
    },
    {
      "name": "Incidents",
      "description": "A safety or site incident report: an injury, near miss, damage, environmental or security event."
    },
    {
      "name": "Inspections",
      "description": "A site inspection run from one of the company's inspection templates (pass or fail checks). A new inspection starts from the template you name, or else the company's active template that matches its type."
    },
    {
      "name": "Punch lists",
      "description": "A named list of snags (punch-list items) for an area or trade."
    },
    {
      "name": "Daily logs",
      "description": "A daily site log: what was done on a project that day, the crew and the weather. One per project per day. A new log is a draft until it is submitted for approval; an approver then approves or rejects it."
    },
    {
      "name": "Field notes",
      "description": "A note from site: an observation, an issue, a question or something that needs action. It is acknowledged, then resolved, or turned into a follow-up task."
    },
    {
      "name": "Snags",
      "description": "A snag (punch-list item): a defect to put right, where it is and which trade owns it. A new snag goes on its project's punch list (one is started when the project has none). It is signed off as completed, rejected back to open, or turned into a follow-up task."
    },
    {
      "name": "Contacts",
      "description": "A party the company works with: a client, supplier, subcontractor or employee."
    },
    {
      "name": "Equipment",
      "description": "Plant, tools and vehicles, optionally assigned to a project."
    },
    {
      "name": "Transactions",
      "description": "A money record: an invoice, a payment in or out, an expense, a credit or debit note, or a material purchase, return or transfer. Every type can be created here."
    },
    {
      "name": "Cost codes",
      "description": "A cost code for sorting spend (for example 03-300 Concrete)."
    },
    {
      "name": "Estimates",
      "description": "A quotation or estimate for a client. Its lines are the estimate_items resource; the totals are worked out again whenever a line changes."
    },
    {
      "name": "Estimate line items",
      "description": "One line on an estimate. The estimate's totals are worked out again after every change."
    },
    {
      "name": "Documents",
      "description": "A project document (a specification, submittal, report and so on). Files are uploaded in the Konverge app; here you can rename documents, edit their description, delete them, send them for review, approve or reject them and comment on them."
    },
    {
      "name": "Folders",
      "description": "A document folder within a project."
    },
    {
      "name": "Drawing sheets",
      "description": "A drawing sheet. New drawings and revisions are uploaded in the Konverge app; here you can read sheets, change a sheet's number or title, or delete one."
    },
    {
      "name": "Drawing pins",
      "description": "An issue or note pinned to a spot on a drawing. Pins are placed on the drawing in the Konverge app; here you can change a pin's status, comment on it, turn it into a task or delete it."
    },
    {
      "name": "Approval workflows",
      "description": "A document review or approval workflow in progress. Workflows start in the Konverge app (each needs a template); here you can decide the current step, resubmit one that is on hold, or cancel it."
    },
    {
      "name": "RFIs",
      "description": "A request for information: `title` is its subject, `description` the question and `workflow_number` its number. Here you can raise one (from a workflow template: template_id, or the company's only active RFI template), record the answer, comment, decide the current review step (one RFI, or up to 20 at once), resubmit or cancel."
    },
    {
      "name": "Conversations",
      "description": "A chat conversation: a direct chat or a named group. Post to it with the send action; add or remove people in a group with add_member and remove_member. Groups are started in the Konverge app."
    },
    {
      "name": "Invites",
      "description": "An invite code a new person uses to join the company with the role it carries. The code, its expiry and how many times it can be used come back in the response."
    },
    {
      "name": "Team members",
      "description": "A person's membership of the company and their role. Change someone's role, remove them from the company or change one of their permissions with the set_role, remove and set_permission actions, which take the person's user id."
    },
    {
      "name": "Folder access rules",
      "description": "Who may open a restricted document folder. Give one person access with grant and take it away with revoke."
    },
    {
      "name": "Companies",
      "description": "Your company's details: name, contact details, address and currency. update_details changes them."
    },
    {
      "name": "Locations",
      "description": "A place on a project: a site, building or block, level, zone, unit or plot, room or area, arranged as a tree (for example Block B > Level 3 > Flat 12). Snags, inspections, photos, field notes, incidents and tasks are filed under a location through their location_id. Each location's printed QR label opens https://getkonverge.com/l/{id}. Locations are set up in the Konverge apps."
    },
    {
      "name": "Site inductions",
      "description": "A record that someone was inducted on a project: a team member (user_id), a contact such as a subcontractor's operative (contact_id), or a visitor (visitor_name); exactly one of the three is set. Inductions are made when the Site Induction form is signed in the Konverge apps (inspection_id is that form), or recorded by a manager. A person has at most one valid induction per project; it counts until expires_on (null = it does not expire) unless it is revoked. Read only."
    },
    {
      "name": "Permits to work",
      "description": "A permit to work, numbered PTW-0001 per project: who may do which high-risk work (hot works, confined space, work at height, excavation, an electrical or mechanical isolation, a lifting operation, roof access, demolition or general), where, and between which times (at most 7 days). Its status moves draft → requested → issued, may be suspended and resumed, and ends handed back and closed, cancelled (before issue) or expired (when its time runs out). The API raises draft permits and sends them to be issued; a permit is issued, suspended, extended and closed with a signature in the Konverge apps."
    },
    {
      "name": "Deliveries",
      "description": "A delivery to a project's site, numbered DEL-0001 per project: the supplier, the purchase order it is against, the booked day, time window, gate and location, the vehicle, and, once it arrives, when it was received, by whom, its condition and the outcome (received in full, part received or rejected). Receiving a delivery in the Konverge apps records the proof of delivery and posts the purchase order's receipts."
    },
    {
      "name": "Material requests",
      "description": "A request from site for materials, numbered MR-0001 per project: a title, the day it is needed by and its items. It is submitted for approval, approved or rejected (with a reason), and an approved request becomes a draft purchase order (purchase_order_id); it then follows that order's deliveries to delivered."
    },
    {
      "name": "Meetings",
      "description": "A project meeting and its minutes: when (scheduled_start, scheduled_end) and where, who chairs it and who takes the minutes, and where it stands (status): scheduled, in progress, minutes written but not issued, minutes issued, or cancelled. Meetings in a series (series_id) are numbered from 1. Each time the minutes are issued, issued_version goes up by one and every open action owned by a team member becomes a task assigned to them. The API schedules meetings; they are minuted and issued in the Konverge apps."
    },
    {
      "name": "Submittals",
      "description": "A submittal under review: `title` says what is submitted, `workflow_number` is its number, `status` where it stands (active, on_hold when changes were asked for, completed, cancelled) and `outcome` how it ended (approved, approved_with_comments, rejected, for_information, cancelled). `ball_in_court` is the person it is waiting on; a parallel review (engine_version 2) has several places, listed as workflow_step records. Here you can start one (from a workflow template: template_id, or the company's only active submittal template), decide the review (one submittal, or up to 20 at once), resubmit or cancel."
    },
    {
      "name": "Workflow places",
      "description": "One place on a parallel workflow review (engine 2): `instance_id` is the workflow (an rfi, submittal or workflow record), `step_number` and `group_no` the step and the group of steps that open together, `round` goes up each time the workflow is resubmitted or routed back. `state` is waiting, open, decided, skipped, superseded (the group finished without it) or cancelled. The holder is `holder_user_id`, or anyone with `holder_role` or in the project organisation `holder_organisation_id`. Read only."
    },
    {
      "name": "Contracts",
      "description": "A contract on a project: its form (NEC4 ECC, ECS or PSC; JCT Design and Build, Standard, Intermediate or Minor Works; AIA A201; or other), which side your company is on, the organisation notices go to, the starting and completion dates, and the contract data the notice clocks read (the period for reply, the notification period, the reply and quotation periods and deemed acceptance). Konverge tracks the periods in the contract data; it is not legal advice."
    },
    {
      "name": "Contract notices",
      "description": "A contract notice on a project, run as a workflow: a technical query, an early warning, a compensation event, an instruction or a non-conformance report (filter by workflow_type). It carries the contract data and the clocks Konverge computes from the contract (the notification period, the reply and quotation periods and deemed acceptance, with the clause number) and the clock state. Amounts are never included. Konverge tracks the periods in the contract data; it is not legal advice."
    },
    {
      "name": "Received email",
      "description": "An email that arrived for a project: a reply by email to an RFI, submittal, approval or meeting action (route reply, added to that item as a comment) or a message sent to the project's own inbox address (route project). Lists who sent it, when, its subject, how many files came with it and where it was filed; the message text is not included. Mail from an unknown or unverified sender is held for a person to check and is visible only to owners, admins and managers. Received email is managed in the Konverge apps."
    },
    {
      "name": "Bid packages",
      "description": "A package of work put out to subcontractors for prices. `status` is the package's own state (open, closed, awarded); `tender_status` is its tender's: draft until issued to the bidders through private links, then issued, closed at the return deadline (late returns are refused), awarded, or withdrawn. Prices are not included. Tenders are issued and awarded in the Konverge apps."
    },
    {
      "name": "Bids",
      "description": "One subcontractor invited to price a bid package: their answer to the invitation (`intent`), the bid's status (invited, received, declined, awarded), when the price came in, whether through their tender link or recorded by your team, and how many times they sent it. Prices are not included."
    },
    {
      "name": "Service requests",
      "description": "A defect reported after handover (aftercare): where it is (location_id or unit_text), what kind of problem it is (category), how urgent (priority) and when it is due under the company's service levels (due_at). warranty_state says whether it was reported within the defects period. status moves from new through triaged, assigned and scheduled to resolved and closed, or rejected when it isn't covered. When it is assigned, one warranty snag is created for the contractor (punch_item_id). The reporter's contact details and photos are never included. Requests are reported, triaged and assigned in the Konverge apps."
    },
    {
      "name": "Handover packs",
      "description": "One issue of a project's handover pack: the certificates, manuals and drawings a client receives at handover, in sections by system or trade, with an index first. version counts the issues on the project (1, 2 …). status is draft while it is being put together, issued once sent, and superseded when a newer version is issued. An issued pack is a locked, frozen document package (frozen_package_id) sent with a transmittal (transmittal_id). Packs are built and issued in the Konverge apps."
    },
    {
      "name": "Site sign-ins",
      "description": "One visit in a project's site sign-in book: who signed in (a contact, or a team member; a visitor has neither, and their name and details are never part of the API), on which site, when they signed in and out, how (at the kiosk, by staff or in the app) and their trade. Status on_site, signed_out or auto_signed_out (signed out by Konverge at the site's end-of-day time). Fire roll calls read the same book in the Konverge apps."
    },
    {
      "name": "Working calendars",
      "description": "A working calendar: the company's default (project_id null) or one project's own, which replaces the default for that project. It says which days of the week are worked (ISO weekday numbers, 1 = Monday), the hours in a working day, the bank-holiday list it was filled from (England and Wales, Scotland, Northern Ireland or US federal) and whether the project programme counts durations and lags in working days on it."
    },
    {
      "name": "Estimate sections",
      "description": "A section of an estimate, such as Groundworks or Kitchen. Sections go two levels deep: a section with a parent_id sits under a top-level section. Estimate lines point at their section through section_id. cost_code is the default cost code for new lines in the section. Created, renamed and deleted by people with edit rights on the estimate (deleting a section keeps its lines, with no section)."
    },
    {
      "name": "Estimate options",
      "description": "An option or an alternate on an estimate. An option (kind option) is an add-on the client may take; alternates (kind alternate) share a group_key and are offered instead of each other, so at most one per group is selected. is_selected is the offer's default and, once the estimate is accepted, the client's choice. Lines in an option count towards the estimate's totals only while it is selected. Created and renamed by people with edit rights on the estimate; `select` (de)selects one and the totals are worked out again."
    },
    {
      "name": "Takeoff items",
      "description": "A quantity measured on a drawing for an estimate: a length, area, perimeter, wall area, volume or count taken off a markup, in metric or imperial units. Konverge works the quantity out from the markup and the drawing's scale (or the confirmed scale of the view the markup sits in). While the estimate is a draft, the line it feeds is kept equal to its measured quantities; once the estimate is sent, a drawing change marks the item stale instead. Takeoff items are made by people in the Konverge apps and through the assistant, never by an API key."
    },
    {
      "name": "Proposal templates",
      "description": "A company's proposal wording, used to start each estimate's proposal: cover letter, scope introduction, inclusions and exclusions, terms, payment schedule, validity and price display. Text is plain text with merge fields in double braces ({{client_name}}, {{company_name}}, {{project_name}}, {{estimate_number}}, {{estimate_title}}, {{valid_until}}, {{total}}), filled in when the proposal is printed or shown. One template can be the company default. Templates are written in the Konverge apps."
    },
    {
      "name": "Estimate acceptances",
      "description": "The record of an estimate's acceptance, written once and never changed. accepted_via says how: portal (the client accepted in the client portal), esign (by electronic signature) or staff (recorded by the team on the client's behalf, with a note saying how). chosen_option_ids are the options and alternates the client chose; accepted_subtotal, accepted_tax and accepted_total are the totals for that choice. offer_hash is the sha256 of the whole offer (every line, option and section) when it was accepted. Estimates are accepted in the Konverge apps, the client portal or by e-signature, never through the API."
    },
    {
      "name": "Selections",
      "description": "Something the client chooses on a project, such as a kitchen worktop or a front door. allowance_id is the allowance it is measured against, chosen_option_id the option chosen (by the client in the portal, or by the builder on the client's behalf: chosen_via). Status: draft (not shown to the client yet), open (waiting for the client), chosen, approved (confirmed by the builder), ordered, installed or cancelled. Prices live on the options. Read only."
    },
    {
      "name": "Takeoff suggestions",
      "description": "A quantity Konverge's drawing intelligence read off a drawing sheet for an estimate: a room area exactly as it is printed on a plan, or the number of doors or windows of one type in a schedule. It is a suggestion for a person to check: someone with edit rights accepts it onto a draft estimate (the line's rate always comes from the company's own catalog, never from the suggestion) or dismisses it. A newer reading of the same drawing replaces the suggestions still open. Suggestions carry quantities and labels only, never a rate, a cost or a price. They are made, accepted and dismissed by people in the Konverge apps, never by an API key."
    },
    {
      "name": "Client updates",
      "description": "A weekly update for a project's client. Konverge drafts it from the period's approved site records (with AI, or as a plain list of facts), a project manager checks and edits it, and only then is it published to the client's portal and emailed (status published). A draft nobody publishes within 7 days expires and is never sent. What a draft was built from, the settings and who received it are not included. Updates are approved and published in the Konverge apps."
    }
  ],
  "paths": {
    "/v1/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Account"
        ],
        "summary": "The API key, its company, role, scopes and rate limits",
        "description": "Works with any valid key (no scope needed). A good first call to check a key.",
        "responses": {
          "200": {
            "description": "The key and its company.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/openapi.json": {
      "get": {
        "operationId": "getOpenApi",
        "tags": [
          "Account"
        ],
        "summary": "This OpenAPI 3.1 document",
        "description": "Public (no key): generated from the same definitions the API runs on.",
        "security": [],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook_subscriptions": {
      "get": {
        "operationId": "listWebhookSubscriptions",
        "tags": [
          "Webhooks"
        ],
        "summary": "List this key's webhook subscriptions",
        "description": "The webhooks that run as this API key (the ones it made, and any an owner pointed at it). Needs the `webhooks:manage` scope.",
        "x-konverge-scope": "webhooks:manage",
        "responses": {
          "200": {
            "description": "This key's webhooks.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscriptionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createWebhookSubscription",
        "tags": [
          "Webhooks"
        ],
        "summary": "Subscribe an address to events (REST hook)",
        "description": "Konverge sends every matching event of this key's company to `target_url`, signed with the secret in the response, which is shown once. Needs the `webhooks:manage` scope. It also needs `records:read`: each event carries its record, read as this key, and events about records this key cannot read are never sent. A company can have at most 25 webhooks. If a delivery is answered with HTTP 410 Gone, a webhook made through the API is deleted (the REST-hook convention Zapier uses).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSubscriptionCreate"
              }
            }
          }
        },
        "x-konverge-scope": "webhooks:manage",
        "responses": {
          "201": {
            "description": "The webhook, with its signing secret (shown this once).",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscriptionCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/webhook_subscriptions/{id}": {
      "get": {
        "operationId": "getWebhookSubscription",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a webhook subscription",
        "description": "Needs the `webhooks:manage` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "webhooks:manage",
        "responses": {
          "200": {
            "description": "The webhook (never its secret).",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscriptionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhookSubscription",
        "tags": [
          "Webhooks"
        ],
        "summary": "Unsubscribe (delete a webhook subscription)",
        "description": "Stops the deliveries and deletes the signing secret. Another key's or another company's webhook answers 404, like one that does not exist. Needs the `webhooks:manage` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-scope": "webhooks:manage",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/tasks": {
      "get": {
        "operationId": "listTasks",
        "tags": [
          "Tasks"
        ],
        "summary": "List tasks",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: pending, in_progress, completed, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(pending|in_progress|completed|cancelled)(,(pending|in_progress|completed|cancelled))*$|^null$"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "description": "Filter on priority. Comma-separated values (any of them matches); `null` for records without one. Values: low, medium, high, urgent.",
            "schema": {
              "type": "string",
              "pattern": "^(low|medium|high|urgent)(,(low|medium|high|urgent))*$|^null$"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assigned_to",
            "in": "query",
            "description": "Filter on assigned to. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "Filter on start date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gte]",
            "in": "query",
            "description": "Only records whose start date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lte]",
            "in": "query",
            "description": "Only records whose start date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gt]",
            "in": "query",
            "description": "Only records whose start date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lt]",
            "in": "query",
            "description": "Only records whose start date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "progress",
            "in": "query",
            "description": "Filter on progress. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "progress[gte]",
            "in": "query",
            "description": "Only records whose progress is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "progress[lte]",
            "in": "query",
            "description": "Only records whose progress is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "progress[gt]",
            "in": "query",
            "description": "Only records whose progress is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "progress[lt]",
            "in": "query",
            "description": "Only records whose progress is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_milestone",
            "in": "query",
            "description": "Filter on milestone. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parent_id",
            "in": "query",
            "description": "Only records with these parent ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of tasks.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Create a task",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new task.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/tasks/{id}": {
      "get": {
        "operationId": "getTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Get a task",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The task.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Update a task",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteTask",
        "tags": [
          "Tasks"
        ],
        "summary": "Delete a task (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/tasks/{id}/actions/set_status": {
      "post": {
        "operationId": "taskSetStatus",
        "tags": [
          "Tasks"
        ],
        "summary": "Change the task's status",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.set_status",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskSetStatusParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/tasks/{id}/actions/assign": {
      "post": {
        "operationId": "taskAssign",
        "tags": [
          "Tasks"
        ],
        "summary": "Assign the task to a team member",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.assign",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskAssignParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/tasks/actions/set_status": {
      "post": {
        "operationId": "taskSetStatusBatch",
        "tags": [
          "Tasks"
        ],
        "summary": "Change the task's status, for up to 20 at once",
        "description": "Change the task's status. Needs the `records:write` scope. All ids must be records this key can see, or nothing is changed. At most 20.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.batch_set_status",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskSetStatusBatchParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The records as they are now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskRecords"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/tasks/actions/assign": {
      "post": {
        "operationId": "taskAssignBatch",
        "tags": [
          "Tasks"
        ],
        "summary": "Assign the task to a team member, for up to 20 at once",
        "description": "Assign the task to a team member. Needs the `records:write` scope. All ids must be records this key can see, or nothing is changed. At most 20.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "task.batch_assign",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskAssignBatchParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The records as they are now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskRecords"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/projects": {
      "get": {
        "operationId": "listProjects",
        "tags": [
          "Projects"
        ],
        "summary": "List projects",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: planning, in_progress, on_hold, completed, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(planning|in_progress|on_hold|completed|cancelled)(,(planning|in_progress|on_hold|completed|cancelled))*$|^null$"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "Filter on start date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gte]",
            "in": "query",
            "description": "Only records whose start date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lte]",
            "in": "query",
            "description": "Only records whose start date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gt]",
            "in": "query",
            "description": "Only records whose start date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lt]",
            "in": "query",
            "description": "Only records whose start date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "description": "Filter on end date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end_date[gte]",
            "in": "query",
            "description": "Only records whose end date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end_date[lte]",
            "in": "query",
            "description": "Only records whose end date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end_date[gt]",
            "in": "query",
            "description": "Only records whose end date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "end_date[lt]",
            "in": "query",
            "description": "Only records whose end date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "budget",
            "in": "query",
            "description": "Filter on budget. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "budget[gte]",
            "in": "query",
            "description": "Only records whose budget is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "budget[lte]",
            "in": "query",
            "description": "Only records whose budget is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "budget[gt]",
            "in": "query",
            "description": "Only records whose budget is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "budget[lt]",
            "in": "query",
            "description": "Only records whose budget is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of projects.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createProject",
        "tags": [
          "Projects"
        ],
        "summary": "Create a project",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "project.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new project.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/projects/{id}": {
      "get": {
        "operationId": "getProject",
        "tags": [
          "Projects"
        ],
        "summary": "Get a project",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The project.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateProject",
        "tags": [
          "Projects"
        ],
        "summary": "Update a project",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "project.update",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteProject",
        "tags": [
          "Projects"
        ],
        "summary": "Delete a project (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "project.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/projects/{id}/actions/add_member": {
      "post": {
        "operationId": "projectAddMember",
        "tags": [
          "Projects"
        ],
        "summary": "Add a team member to the project",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "project.add_member",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectAddMemberParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/projects/{id}/actions/set_member_role": {
      "post": {
        "operationId": "projectSetMemberRole",
        "tags": [
          "Projects"
        ],
        "summary": "Change a member's role on the project",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "project.set_member_role",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectSetMemberRoleParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/projects/{id}/actions/remove_member": {
      "post": {
        "operationId": "projectRemoveMember",
        "tags": [
          "Projects"
        ],
        "summary": "Remove a member from the project",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "project.remove_member",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectRemoveMemberParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/milestones": {
      "get": {
        "operationId": "listMilestones",
        "tags": [
          "Milestones"
        ],
        "summary": "List milestones",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "due_date",
                "due_date.desc",
                "due_date.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: upcoming, in_progress, completed, missed.",
            "schema": {
              "type": "string",
              "pattern": "^(upcoming|in_progress|completed|missed)(,(upcoming|in_progress|completed|missed))*$"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "Filter on start date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gte]",
            "in": "query",
            "description": "Only records whose start date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lte]",
            "in": "query",
            "description": "Only records whose start date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gt]",
            "in": "query",
            "description": "Only records whose start date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lt]",
            "in": "query",
            "description": "Only records whose start date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of milestones.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MilestoneList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createMilestone",
        "tags": [
          "Milestones"
        ],
        "summary": "Create a milestone",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "milestone.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MilestoneCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new milestone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MilestoneResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/milestones/{id}": {
      "get": {
        "operationId": "getMilestone",
        "tags": [
          "Milestones"
        ],
        "summary": "Get a milestone",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The milestone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MilestoneResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateMilestone",
        "tags": [
          "Milestones"
        ],
        "summary": "Update a milestone",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "milestone.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MilestoneUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MilestoneResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteMilestone",
        "tags": [
          "Milestones"
        ],
        "summary": "Delete a milestone (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "milestone.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/schedule_baselines": {
      "get": {
        "operationId": "listScheduleBaselines",
        "tags": [
          "Schedule baselines"
        ],
        "summary": "List schedule baselines",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "captured_at",
                "captured_at.desc",
                "captured_at.asc"
              ],
              "default": "captured_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number",
            "in": "query",
            "description": "Filter on number. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[gte]",
            "in": "query",
            "description": "Only records whose number is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[lte]",
            "in": "query",
            "description": "Only records whose number is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[gt]",
            "in": "query",
            "description": "Only records whose number is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[lt]",
            "in": "query",
            "description": "Only records whose number is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_current",
            "in": "query",
            "description": "Filter on current. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "task_count",
            "in": "query",
            "description": "Filter on tasks. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "task_count[gte]",
            "in": "query",
            "description": "Only records whose task count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "task_count[lte]",
            "in": "query",
            "description": "Only records whose task count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "task_count[gt]",
            "in": "query",
            "description": "Only records whose task count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "task_count[lt]",
            "in": "query",
            "description": "Only records whose task count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "milestone_count",
            "in": "query",
            "description": "Filter on milestones. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "milestone_count[gte]",
            "in": "query",
            "description": "Only records whose milestone count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "milestone_count[lte]",
            "in": "query",
            "description": "Only records whose milestone count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "milestone_count[gt]",
            "in": "query",
            "description": "Only records whose milestone count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "milestone_count[lt]",
            "in": "query",
            "description": "Only records whose milestone count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date",
            "in": "query",
            "description": "Filter on starts. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gte]",
            "in": "query",
            "description": "Only records whose start date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lte]",
            "in": "query",
            "description": "Only records whose start date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[gt]",
            "in": "query",
            "description": "Only records whose start date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "start_date[lt]",
            "in": "query",
            "description": "Only records whose start date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "finish_date",
            "in": "query",
            "description": "Filter on finishes. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "finish_date[gte]",
            "in": "query",
            "description": "Only records whose finish date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "finish_date[lte]",
            "in": "query",
            "description": "Only records whose finish date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "finish_date[gt]",
            "in": "query",
            "description": "Only records whose finish date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "finish_date[lt]",
            "in": "query",
            "description": "Only records whose finish date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of schedule baselines.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleBaselineList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/schedule_baselines/{id}": {
      "get": {
        "operationId": "getScheduleBaseline",
        "tags": [
          "Schedule baselines"
        ],
        "summary": "Get a schedule baseline",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The schedule baseline.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleBaselineResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/task_dependencies": {
      "get": {
        "operationId": "listTaskDependencies",
        "tags": [
          "Task links"
        ],
        "summary": "List task links",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches). Values: FS, SS, FF, SF.",
            "schema": {
              "type": "string",
              "pattern": "^(FS|SS|FF|SF)(,(FS|SS|FF|SF))*$"
            }
          },
          {
            "name": "lag_days",
            "in": "query",
            "description": "Filter on lag (days). Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lag_days[gte]",
            "in": "query",
            "description": "Only records whose lag days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lag_days[lte]",
            "in": "query",
            "description": "Only records whose lag days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lag_days[gt]",
            "in": "query",
            "description": "Only records whose lag days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lag_days[lt]",
            "in": "query",
            "description": "Only records whose lag days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "predecessor_id",
            "in": "query",
            "description": "Only records with these predecessor ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "successor_id",
            "in": "query",
            "description": "Only records with these successor ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of task links.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDependencyList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/task_dependencies/{id}": {
      "get": {
        "operationId": "getTaskDependency",
        "tags": [
          "Task links"
        ],
        "summary": "Get a task link",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The task link.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskDependencyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/incidents": {
      "get": {
        "operationId": "listIncidents",
        "tags": [
          "Incidents"
        ],
        "summary": "List incidents",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: open, investigating, resolved, closed.",
            "schema": {
              "type": "string",
              "pattern": "^(open|investigating|resolved|closed)(,(open|investigating|resolved|closed))*$|^null$"
            }
          },
          {
            "name": "incident_type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches); `null` for records without one. Values: injury, near_miss, property_damage, environmental, security, other.",
            "schema": {
              "type": "string",
              "pattern": "^(injury|near_miss|property_damage|environmental|security|other)(,(injury|near_miss|property_damage|environmental|security|other))*$|^null$"
            }
          },
          {
            "name": "incident_date",
            "in": "query",
            "description": "Filter on date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "incident_date[gte]",
            "in": "query",
            "description": "Only records whose incident date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "incident_date[lte]",
            "in": "query",
            "description": "Only records whose incident date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "incident_date[gt]",
            "in": "query",
            "description": "Only records whose incident date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "incident_date[lt]",
            "in": "query",
            "description": "Only records whose incident date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lost_time_incident",
            "in": "query",
            "description": "Filter on lost time. Comma-separated true or false (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days_lost",
            "in": "query",
            "description": "Filter on days lost. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days_lost[gte]",
            "in": "query",
            "description": "Only records whose days lost is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days_lost[lte]",
            "in": "query",
            "description": "Only records whose days lost is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days_lost[gt]",
            "in": "query",
            "description": "Only records whose days lost is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days_lost[lt]",
            "in": "query",
            "description": "Only records whose days lost is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of incidents.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IncidentList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createIncident",
        "tags": [
          "Incidents"
        ],
        "summary": "Create an incident",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "incident.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IncidentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new incident.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IncidentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/incidents/{id}": {
      "get": {
        "operationId": "getIncident",
        "tags": [
          "Incidents"
        ],
        "summary": "Get an incident",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The incident.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IncidentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/incidents/{id}/actions/set_status": {
      "post": {
        "operationId": "incidentSetStatus",
        "tags": [
          "Incidents"
        ],
        "summary": "Change the incident's status",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "incident.set_status",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IncidentSetStatusParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IncidentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/inspections": {
      "get": {
        "operationId": "listInspections",
        "tags": [
          "Inspections"
        ],
        "summary": "List inspections",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "template_id",
            "in": "query",
            "description": "Only records with these template ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "score_percentage",
            "in": "query",
            "description": "Filter on score percentage. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "score_percentage[gte]",
            "in": "query",
            "description": "Only records whose score percentage is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "score_percentage[lte]",
            "in": "query",
            "description": "Only records whose score percentage is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "score_percentage[gt]",
            "in": "query",
            "description": "Only records whose score percentage is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "score_percentage[lt]",
            "in": "query",
            "description": "Only records whose score percentage is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pass_count",
            "in": "query",
            "description": "Filter on pass count. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pass_count[gte]",
            "in": "query",
            "description": "Only records whose pass count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pass_count[lte]",
            "in": "query",
            "description": "Only records whose pass count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pass_count[gt]",
            "in": "query",
            "description": "Only records whose pass count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pass_count[lt]",
            "in": "query",
            "description": "Only records whose pass count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fail_count",
            "in": "query",
            "description": "Filter on fail count. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fail_count[gte]",
            "in": "query",
            "description": "Only records whose fail count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fail_count[lte]",
            "in": "query",
            "description": "Only records whose fail count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fail_count[gt]",
            "in": "query",
            "description": "Only records whose fail count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fail_count[lt]",
            "in": "query",
            "description": "Only records whose fail count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of inspections.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InspectionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createInspection",
        "tags": [
          "Inspections"
        ],
        "summary": "Create an inspection",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "inspection.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InspectionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new inspection.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InspectionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/inspections/{id}": {
      "get": {
        "operationId": "getInspection",
        "tags": [
          "Inspections"
        ],
        "summary": "Get an inspection",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The inspection.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InspectionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_lists": {
      "get": {
        "operationId": "listPunchLists",
        "tags": [
          "Punch lists"
        ],
        "summary": "List punch lists",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: open, in_progress, completed, verified.",
            "schema": {
              "type": "string",
              "pattern": "^(open|in_progress|completed|verified)(,(open|in_progress|completed|verified))*$|^null$"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "description": "Filter on priority. Comma-separated values (any of them matches); `null` for records without one. Values: low, medium, high, critical.",
            "schema": {
              "type": "string",
              "pattern": "^(low|medium|high|critical)(,(low|medium|high|critical))*$|^null$"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_items",
            "in": "query",
            "description": "Filter on total items. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_items[gte]",
            "in": "query",
            "description": "Only records whose total items is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_items[lte]",
            "in": "query",
            "description": "Only records whose total items is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_items[gt]",
            "in": "query",
            "description": "Only records whose total items is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_items[lt]",
            "in": "query",
            "description": "Only records whose total items is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completed_items",
            "in": "query",
            "description": "Filter on completed items. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completed_items[gte]",
            "in": "query",
            "description": "Only records whose completed items is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completed_items[lte]",
            "in": "query",
            "description": "Only records whose completed items is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completed_items[gt]",
            "in": "query",
            "description": "Only records whose completed items is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completed_items[lt]",
            "in": "query",
            "description": "Only records whose completed items is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of punch lists.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchListList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createPunchList",
        "tags": [
          "Punch lists"
        ],
        "summary": "Create a punch list",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "punch_list.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PunchListCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new punch list.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_lists/{id}": {
      "get": {
        "operationId": "getPunchList",
        "tags": [
          "Punch lists"
        ],
        "summary": "Get a punch list",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The punch list.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/daily_logs": {
      "get": {
        "operationId": "listDailyLogs",
        "tags": [
          "Daily logs"
        ],
        "summary": "List daily logs",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "log_date",
            "in": "query",
            "description": "Filter on date. Comma-separated dates (YYYY-MM-DD) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "log_date[gte]",
            "in": "query",
            "description": "Only records whose log date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "log_date[lte]",
            "in": "query",
            "description": "Only records whose log date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "log_date[gt]",
            "in": "query",
            "description": "Only records whose log date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "log_date[lt]",
            "in": "query",
            "description": "Only records whose log date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crew_count",
            "in": "query",
            "description": "Filter on crew count. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crew_count[gte]",
            "in": "query",
            "description": "Only records whose crew count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crew_count[lte]",
            "in": "query",
            "description": "Only records whose crew count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crew_count[gt]",
            "in": "query",
            "description": "Only records whose crew count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "crew_count[lt]",
            "in": "query",
            "description": "Only records whose crew count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "weather_condition",
            "in": "query",
            "description": "Filter on weather. Comma-separated values (any of them matches); `null` for records without one. Values: sunny, cloudy, rainy, snowy, windy, mixed.",
            "schema": {
              "type": "string",
              "pattern": "^(sunny|cloudy|rainy|snowy|windy|mixed)(,(sunny|cloudy|rainy|snowy|windy|mixed))*$|^null$"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of daily logs.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createDailyLog",
        "tags": [
          "Daily logs"
        ],
        "summary": "Create a daily log",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "daily_log",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DailyLogCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new daily log.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/daily_logs/{id}": {
      "get": {
        "operationId": "getDailyLog",
        "tags": [
          "Daily logs"
        ],
        "summary": "Get a daily log",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The daily log.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateDailyLog",
        "tags": [
          "Daily logs"
        ],
        "summary": "Update a daily log",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "daily_log.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DailyLogUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/daily_logs/{id}/actions/submit": {
      "post": {
        "operationId": "dailyLogSubmit",
        "tags": [
          "Daily logs"
        ],
        "summary": "Submit the daily log for approval",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "daily_log.submit",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/daily_logs/{id}/actions/approve": {
      "post": {
        "operationId": "dailyLogApprove",
        "tags": [
          "Daily logs"
        ],
        "summary": "Approve the submitted daily log",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "daily_log.approve",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/daily_logs/{id}/actions/reject": {
      "post": {
        "operationId": "dailyLogReject",
        "tags": [
          "Daily logs"
        ],
        "summary": "Reject the submitted daily log",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "daily_log.reject",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DailyLogRejectParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DailyLogResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/field_notes": {
      "get": {
        "operationId": "listFieldNotes",
        "tags": [
          "Field notes"
        ],
        "summary": "List field notes",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "note_type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches). Values: observation, issue, question, action_required.",
            "schema": {
              "type": "string",
              "pattern": "^(observation|issue|question|action_required)(,(observation|issue|question|action_required))*$"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "description": "Filter on priority. Comma-separated values (any of them matches); `null` for records without one. Values: low, medium, high.",
            "schema": {
              "type": "string",
              "pattern": "^(low|medium|high)(,(low|medium|high))*$|^null$"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of field notes.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldNoteList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createFieldNote",
        "tags": [
          "Field notes"
        ],
        "summary": "Create a field note",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "field_note",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldNoteCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new field note.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldNoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/field_notes/{id}": {
      "get": {
        "operationId": "getFieldNote",
        "tags": [
          "Field notes"
        ],
        "summary": "Get a field note",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The field note.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldNoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateFieldNote",
        "tags": [
          "Field notes"
        ],
        "summary": "Update a field note",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "field_note.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldNoteUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldNoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/field_notes/{id}/actions/acknowledge": {
      "post": {
        "operationId": "fieldNoteAcknowledge",
        "tags": [
          "Field notes"
        ],
        "summary": "Acknowledge the field note",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "field_note.acknowledge",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldNoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/field_notes/{id}/actions/resolve": {
      "post": {
        "operationId": "fieldNoteResolve",
        "tags": [
          "Field notes"
        ],
        "summary": "Resolve the field note",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "field_note.resolve",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FieldNoteResolveParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FieldNoteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/field_notes/{id}/actions/to_task": {
      "post": {
        "operationId": "fieldNoteToTask",
        "tags": [
          "Field notes"
        ],
        "summary": "Create a follow-up task from the field note",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "field_note.to_task",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "responses": {
          "201": {
            "description": "The new task.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_items": {
      "get": {
        "operationId": "listPunchItems",
        "tags": [
          "Snags"
        ],
        "summary": "List snags",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (through their punch list). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "description": "Filter on priority. Comma-separated values (any of them matches); `null` for records without one. Values: low, medium, high, critical.",
            "schema": {
              "type": "string",
              "pattern": "^(low|medium|high|critical)(,(low|medium|high|critical))*$|^null$"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "punch_list_id",
            "in": "query",
            "description": "Only records with these punch list ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of snags.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createPunchItem",
        "tags": [
          "Snags"
        ],
        "summary": "Create a snag",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "punch_item",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PunchItemCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new snag.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_items/{id}": {
      "get": {
        "operationId": "getPunchItem",
        "tags": [
          "Snags"
        ],
        "summary": "Get a snag",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The snag.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_items/{id}/actions/complete": {
      "post": {
        "operationId": "punchItemComplete",
        "tags": [
          "Snags"
        ],
        "summary": "Mark the snag completed (sign-off)",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "punch_item.complete",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PunchItemCompleteParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_items/{id}/actions/reject": {
      "post": {
        "operationId": "punchItemReject",
        "tags": [
          "Snags"
        ],
        "summary": "Reject the completed snag back to open",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "punch_item.reject",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PunchItemRejectParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_items/{id}/actions/to_task": {
      "post": {
        "operationId": "punchItemToTask",
        "tags": [
          "Snags"
        ],
        "summary": "Create a follow-up task from the snag",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "punch_item.to_task",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "responses": {
          "201": {
            "description": "The new task.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/punch_items/actions/complete": {
      "post": {
        "operationId": "punchItemCompleteBatch",
        "tags": [
          "Snags"
        ],
        "summary": "Mark the snag completed (sign-off), for up to 20 at once",
        "description": "Mark the snag completed (sign-off). Needs the `records:write` scope. All ids must be records this key can see, or nothing is changed. At most 20.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "punch_item.batch_complete",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PunchItemCompleteBatchParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The records as they are now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PunchItemRecords"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/contacts": {
      "get": {
        "operationId": "listContacts",
        "tags": [
          "Contacts"
        ],
        "summary": "List contacts",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "is_active",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated true or false (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches). Values: client, supplier, subcontractor, employee.",
            "schema": {
              "type": "string",
              "pattern": "^(client|supplier|subcontractor|employee)(,(client|supplier|subcontractor|employee))*$"
            }
          },
          {
            "name": "opening_balance",
            "in": "query",
            "description": "Filter on opening balance. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "opening_balance[gte]",
            "in": "query",
            "description": "Only records whose opening balance is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "opening_balance[lte]",
            "in": "query",
            "description": "Only records whose opening balance is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "opening_balance[gt]",
            "in": "query",
            "description": "Only records whose opening balance is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "opening_balance[lt]",
            "in": "query",
            "description": "Only records whose opening balance is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_balance",
            "in": "query",
            "description": "Filter on current balance. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_balance[gte]",
            "in": "query",
            "description": "Only records whose current balance is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_balance[lte]",
            "in": "query",
            "description": "Only records whose current balance is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_balance[gt]",
            "in": "query",
            "description": "Only records whose current balance is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_balance[lt]",
            "in": "query",
            "description": "Only records whose current balance is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of contacts.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Create a contact",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "contact.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new contact.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/contacts/{id}": {
      "get": {
        "operationId": "getContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Get a contact",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The contact.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Update a contact",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "contact.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteContact",
        "tags": [
          "Contacts"
        ],
        "summary": "Delete a contact (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "contact.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/contacts/{id}/actions/toggle_status": {
      "post": {
        "operationId": "contactToggleStatus",
        "tags": [
          "Contacts"
        ],
        "summary": "Activate or deactivate the contact",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "contact.toggle_status",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactToggleStatusParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/equipment": {
      "get": {
        "operationId": "listEquipment",
        "tags": [
          "Equipment"
        ],
        "summary": "List equipment",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: available, in_use, maintenance, retired.",
            "schema": {
              "type": "string",
              "pattern": "^(available|in_use|maintenance|retired)(,(available|in_use|maintenance|retired))*$|^null$"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches); `null` for records without one. Values: plant, tool, vehicle, access, other.",
            "schema": {
              "type": "string",
              "pattern": "^(plant|tool|vehicle|access|other)(,(plant|tool|vehicle|access|other))*$|^null$"
            }
          },
          {
            "name": "purchase_date",
            "in": "query",
            "description": "Filter on purchase date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "purchase_date[gte]",
            "in": "query",
            "description": "Only records whose purchase date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "purchase_date[lte]",
            "in": "query",
            "description": "Only records whose purchase date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "purchase_date[gt]",
            "in": "query",
            "description": "Only records whose purchase date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "purchase_date[lt]",
            "in": "query",
            "description": "Only records whose purchase date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_maintenance_date",
            "in": "query",
            "description": "Filter on next maintenance. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_maintenance_date[gte]",
            "in": "query",
            "description": "Only records whose next maintenance date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_maintenance_date[lte]",
            "in": "query",
            "description": "Only records whose next maintenance date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_maintenance_date[gt]",
            "in": "query",
            "description": "Only records whose next maintenance date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_maintenance_date[lt]",
            "in": "query",
            "description": "Only records whose next maintenance date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of equipment.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EquipmentList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createEquipment",
        "tags": [
          "Equipment"
        ],
        "summary": "Create equipment",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "equipment.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EquipmentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new equipment.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EquipmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/equipment/{id}": {
      "get": {
        "operationId": "getEquipment",
        "tags": [
          "Equipment"
        ],
        "summary": "Get equipment",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The equipment.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EquipmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateEquipment",
        "tags": [
          "Equipment"
        ],
        "summary": "Update equipment",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "equipment.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EquipmentUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EquipmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteEquipment",
        "tags": [
          "Equipment"
        ],
        "summary": "Delete equipment (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "equipment.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/transactions": {
      "get": {
        "operationId": "listTransactions",
        "tags": [
          "Transactions"
        ],
        "summary": "List transactions",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "transaction_date",
                "transaction_date.desc",
                "transaction_date.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches). Values: payment_in, payment_out, expense, invoice, credit_note, debit_note, material_purchase, material_return, material_transfer, party_to_party.",
            "schema": {
              "type": "string",
              "pattern": "^(payment_in|payment_out|expense|invoice|credit_note|debit_note|material_purchase|material_return|material_transfer|party_to_party)(,(payment_in|payment_out|expense|invoice|credit_note|debit_note|material_purchase|material_return|material_transfer|party_to_party))*$"
            }
          },
          {
            "name": "amount",
            "in": "query",
            "description": "Filter on amount. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[gte]",
            "in": "query",
            "description": "Only records whose amount is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[lte]",
            "in": "query",
            "description": "Only records whose amount is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[gt]",
            "in": "query",
            "description": "Only records whose amount is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[lt]",
            "in": "query",
            "description": "Only records whose amount is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_date",
            "in": "query",
            "description": "Filter on date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_date[gte]",
            "in": "query",
            "description": "Only records whose transaction date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_date[lte]",
            "in": "query",
            "description": "Only records whose transaction date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_date[gt]",
            "in": "query",
            "description": "Only records whose transaction date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transaction_date[lt]",
            "in": "query",
            "description": "Only records whose transaction date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from_party_id",
            "in": "query",
            "description": "Filter on from party. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to_party_id",
            "in": "query",
            "description": "Filter on to party. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "payment_method",
            "in": "query",
            "description": "Filter on payment method. Comma-separated values (any of them matches); `null` for records without one. Values: cash, cheque, bank_transfer, card, other.",
            "schema": {
              "type": "string",
              "pattern": "^(cash|cheque|bank_transfer|card|other)(,(cash|cheque|bank_transfer|card|other))*$|^null$"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of transactions.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createTransaction",
        "tags": [
          "Transactions"
        ],
        "summary": "Create a transaction",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "transaction.create",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new transaction.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/transactions/{id}": {
      "get": {
        "operationId": "getTransaction",
        "tags": [
          "Transactions"
        ],
        "summary": "Get a transaction",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The transaction.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateTransaction",
        "tags": [
          "Transactions"
        ],
        "summary": "Update a transaction",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "transaction.update",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransactionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteTransaction",
        "tags": [
          "Transactions"
        ],
        "summary": "Delete a transaction (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "transaction.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/cost_codes": {
      "get": {
        "operationId": "listCostCodes",
        "tags": [
          "Cost codes"
        ],
        "summary": "List cost codes",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "is_active",
            "in": "query",
            "description": "Filter on is active. Comma-separated true or false (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of cost codes.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostCodeList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createCostCode",
        "tags": [
          "Cost codes"
        ],
        "summary": "Create a cost code",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "cost_code.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CostCodeCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new cost code.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostCodeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/cost_codes/{id}": {
      "get": {
        "operationId": "getCostCode",
        "tags": [
          "Cost codes"
        ],
        "summary": "Get a cost code",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The cost code.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostCodeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateCostCode",
        "tags": [
          "Cost codes"
        ],
        "summary": "Update a cost code",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "cost_code.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CostCodeUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostCodeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteCostCode",
        "tags": [
          "Cost codes"
        ],
        "summary": "Delete a cost code (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "cost_code.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates": {
      "get": {
        "operationId": "listEstimates",
        "tags": [
          "Estimates"
        ],
        "summary": "List estimates",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: draft, sent, viewed, accepted, rejected, expired.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|sent|viewed|accepted|rejected|expired)(,(draft|sent|viewed|accepted|rejected|expired))*$|^null$"
            }
          },
          {
            "name": "party_id",
            "in": "query",
            "description": "Filter on client. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number",
            "in": "query",
            "description": "Filter on revision. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[gte]",
            "in": "query",
            "description": "Only records whose revision number is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[lte]",
            "in": "query",
            "description": "Only records whose revision number is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[gt]",
            "in": "query",
            "description": "Only records whose revision number is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[lt]",
            "in": "query",
            "description": "Only records whose revision number is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "subtotal",
            "in": "query",
            "description": "Filter on subtotal. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "subtotal[gte]",
            "in": "query",
            "description": "Only records whose subtotal is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "subtotal[lte]",
            "in": "query",
            "description": "Only records whose subtotal is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "subtotal[gt]",
            "in": "query",
            "description": "Only records whose subtotal is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "subtotal[lt]",
            "in": "query",
            "description": "Only records whose subtotal is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_amount",
            "in": "query",
            "description": "Filter on tax amount. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_amount[gte]",
            "in": "query",
            "description": "Only records whose tax amount is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_amount[lte]",
            "in": "query",
            "description": "Only records whose tax amount is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_amount[gt]",
            "in": "query",
            "description": "Only records whose tax amount is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_amount[lt]",
            "in": "query",
            "description": "Only records whose tax amount is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_amount",
            "in": "query",
            "description": "Filter on total amount. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_amount[gte]",
            "in": "query",
            "description": "Only records whose total amount is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_amount[lte]",
            "in": "query",
            "description": "Only records whose total amount is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_amount[gt]",
            "in": "query",
            "description": "Only records whose total amount is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_amount[lt]",
            "in": "query",
            "description": "Only records whose total amount is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of estimates.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createEstimate",
        "tags": [
          "Estimates"
        ],
        "summary": "Create an estimate",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.create",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new estimate.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates/{id}": {
      "get": {
        "operationId": "getEstimate",
        "tags": [
          "Estimates"
        ],
        "summary": "Get an estimate",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The estimate.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateEstimate",
        "tags": [
          "Estimates"
        ],
        "summary": "Update an estimate",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.update",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteEstimate",
        "tags": [
          "Estimates"
        ],
        "summary": "Delete an estimate (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates/{id}/actions/set_status": {
      "post": {
        "operationId": "estimateSetStatus",
        "tags": [
          "Estimates"
        ],
        "summary": "Change the estimate's status (e.g. mark sent or accepted)",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.set_status",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateSetStatusParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates/{id}/actions/duplicate": {
      "post": {
        "operationId": "estimateDuplicate",
        "tags": [
          "Estimates"
        ],
        "summary": "Duplicate the estimate as a new draft",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.duplicate",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "responses": {
          "201": {
            "description": "The new estimate.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates/{id}/actions/revise": {
      "post": {
        "operationId": "estimateRevise",
        "tags": [
          "Estimates"
        ],
        "summary": "Revise the estimate: a new draft revision (R1, R2, ...) replaces it, and this one becomes superseded",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.revise",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateReviseParams"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new estimate.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates/{id}/actions/save_as_template": {
      "post": {
        "operationId": "estimateSaveAsTemplate",
        "tags": [
          "Estimates"
        ],
        "summary": "Save a copy of the estimate as a reusable template",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.save_as_template",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateSaveAsTemplateParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The id of the record the action created or changed.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimates/actions/from_template": {
      "post": {
        "operationId": "estimateFromTemplate",
        "tags": [
          "Estimates"
        ],
        "summary": "Start a new draft estimate from one of the company's estimate templates",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate.from_template",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateFromTemplateParams"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new estimate.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_items": {
      "get": {
        "operationId": "listEstimateItems",
        "tags": [
          "Estimate line items"
        ],
        "summary": "List estimate line items",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "estimate_id",
            "in": "query",
            "description": "Filter on estimate. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity",
            "in": "query",
            "description": "Filter on quantity. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gte]",
            "in": "query",
            "description": "Only records whose quantity is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lte]",
            "in": "query",
            "description": "Only records whose quantity is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gt]",
            "in": "query",
            "description": "Only records whose quantity is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lt]",
            "in": "query",
            "description": "Only records whose quantity is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rate",
            "in": "query",
            "description": "Filter on rate. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rate[gte]",
            "in": "query",
            "description": "Only records whose rate is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rate[lte]",
            "in": "query",
            "description": "Only records whose rate is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rate[gt]",
            "in": "query",
            "description": "Only records whose rate is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rate[lt]",
            "in": "query",
            "description": "Only records whose rate is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_rate",
            "in": "query",
            "description": "Filter on tax %. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_rate[gte]",
            "in": "query",
            "description": "Only records whose tax rate is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_rate[lte]",
            "in": "query",
            "description": "Only records whose tax rate is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_rate[gt]",
            "in": "query",
            "description": "Only records whose tax rate is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tax_rate[lt]",
            "in": "query",
            "description": "Only records whose tax rate is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discount_percentage",
            "in": "query",
            "description": "Filter on discount %. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discount_percentage[gte]",
            "in": "query",
            "description": "Only records whose discount percentage is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discount_percentage[lte]",
            "in": "query",
            "description": "Only records whose discount percentage is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discount_percentage[gt]",
            "in": "query",
            "description": "Only records whose discount percentage is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discount_percentage[lt]",
            "in": "query",
            "description": "Only records whose discount percentage is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "line_kind",
            "in": "query",
            "description": "Filter on kind. Comma-separated values (any of them matches). Values: item, allowance, contingency, note.",
            "schema": {
              "type": "string",
              "pattern": "^(item|allowance|contingency|note)(,(item|allowance|contingency|note))*$"
            }
          },
          {
            "name": "quantity_source",
            "in": "query",
            "description": "Filter on quantity from. Comma-separated values (any of them matches). Values: manual, takeoff, assembly.",
            "schema": {
              "type": "string",
              "pattern": "^(manual|takeoff|assembly)(,(manual|takeoff|assembly))*$"
            }
          },
          {
            "name": "section_id",
            "in": "query",
            "description": "Only records with these section ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "option_id",
            "in": "query",
            "description": "Only records with these option ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cost_item_id",
            "in": "query",
            "description": "Only records with these cost item ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount",
            "in": "query",
            "description": "Filter on amount. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[gte]",
            "in": "query",
            "description": "Only records whose amount is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[lte]",
            "in": "query",
            "description": "Only records whose amount is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[gt]",
            "in": "query",
            "description": "Only records whose amount is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amount[lt]",
            "in": "query",
            "description": "Only records whose amount is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of estimate line items.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createEstimateItem",
        "tags": [
          "Estimate line items"
        ],
        "summary": "Create an estimate line item",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_item.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateItemCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new estimate line item.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_items/{id}": {
      "get": {
        "operationId": "getEstimateItem",
        "tags": [
          "Estimate line items"
        ],
        "summary": "Get an estimate line item",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The estimate line item.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateEstimateItem",
        "tags": [
          "Estimate line items"
        ],
        "summary": "Update an estimate line item",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_item.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateItemUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteEstimateItem",
        "tags": [
          "Estimate line items"
        ],
        "summary": "Delete an estimate line item (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_item.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/documents": {
      "get": {
        "operationId": "listDocuments",
        "tags": [
          "Documents"
        ],
        "summary": "List documents",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "folder_id",
            "in": "query",
            "description": "Only records with these folder ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of documents.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/documents/{id}": {
      "get": {
        "operationId": "getDocument",
        "tags": [
          "Documents"
        ],
        "summary": "Get a document",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The document.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateDocument",
        "tags": [
          "Documents"
        ],
        "summary": "Update a document",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "document.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteDocument",
        "tags": [
          "Documents"
        ],
        "summary": "Delete a document (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "document.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/documents/{id}/actions/submit_review": {
      "post": {
        "operationId": "documentSubmitReview",
        "tags": [
          "Documents"
        ],
        "summary": "Submit the document for review",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "document.submit_review",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentSubmitReviewParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/documents/{id}/actions/approve": {
      "post": {
        "operationId": "documentApprove",
        "tags": [
          "Documents"
        ],
        "summary": "Approve the document",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "document.approve",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentApproveParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/documents/{id}/actions/reject": {
      "post": {
        "operationId": "documentReject",
        "tags": [
          "Documents"
        ],
        "summary": "Reject the document",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "document.reject",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentRejectParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/documents/{id}/actions/comment": {
      "post": {
        "operationId": "documentComment",
        "tags": [
          "Documents"
        ],
        "summary": "Add a comment to the document",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "document.comment",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentCommentParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/folders": {
      "get": {
        "operationId": "listFolders",
        "tags": [
          "Folders"
        ],
        "summary": "List folders",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parent_folder_id",
            "in": "query",
            "description": "Only records with these parent folder ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of folders.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createFolder",
        "tags": [
          "Folders"
        ],
        "summary": "Create a folder",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "folder.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FolderCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new folder.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/folders/{id}": {
      "get": {
        "operationId": "getFolder",
        "tags": [
          "Folders"
        ],
        "summary": "Get a folder",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The folder.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateFolder",
        "tags": [
          "Folders"
        ],
        "summary": "Update a folder",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "folder.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FolderUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteFolder",
        "tags": [
          "Folders"
        ],
        "summary": "Delete a folder (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "folder.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/drawing_sheets": {
      "get": {
        "operationId": "listDrawingSheets",
        "tags": [
          "Drawing sheets"
        ],
        "summary": "List drawing sheets",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_current",
            "in": "query",
            "description": "Filter on is current. Comma-separated true or false (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of drawing sheets.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrawingSheetList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/drawing_sheets/{id}": {
      "get": {
        "operationId": "getDrawingSheet",
        "tags": [
          "Drawing sheets"
        ],
        "summary": "Get a drawing sheet",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The drawing sheet.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrawingSheetResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateDrawingSheet",
        "tags": [
          "Drawing sheets"
        ],
        "summary": "Update a drawing sheet",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "drawing_sheet.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DrawingSheetUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DrawingSheetResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteDrawingSheet",
        "tags": [
          "Drawing sheets"
        ],
        "summary": "Delete a drawing sheet (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "drawing_sheet.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/pins": {
      "get": {
        "operationId": "listPins",
        "tags": [
          "Drawing pins"
        ],
        "summary": "List drawing pins",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one. Values: open, in_progress, completed, verified, rejected.",
            "schema": {
              "type": "string",
              "pattern": "^(open|in_progress|completed|verified|rejected)(,(open|in_progress|completed|verified|rejected))*$|^null$"
            }
          },
          {
            "name": "sheet_id",
            "in": "query",
            "description": "Only records with these sheet ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pin_number",
            "in": "query",
            "description": "Filter on pin number. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pin_number[gte]",
            "in": "query",
            "description": "Only records whose pin number is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pin_number[lte]",
            "in": "query",
            "description": "Only records whose pin number is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pin_number[gt]",
            "in": "query",
            "description": "Only records whose pin number is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pin_number[lt]",
            "in": "query",
            "description": "Only records whose pin number is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of drawing pins.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PinList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/pins/{id}": {
      "get": {
        "operationId": "getPin",
        "tags": [
          "Drawing pins"
        ],
        "summary": "Get a drawing pin",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The drawing pin.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PinResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deletePin",
        "tags": [
          "Drawing pins"
        ],
        "summary": "Delete a drawing pin (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "pin.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/pins/{id}/actions/set_status": {
      "post": {
        "operationId": "pinSetStatus",
        "tags": [
          "Drawing pins"
        ],
        "summary": "Change the pin's status",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "pin.set_status",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PinSetStatusParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PinResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/pins/{id}/actions/comment": {
      "post": {
        "operationId": "pinComment",
        "tags": [
          "Drawing pins"
        ],
        "summary": "Add a comment to the pin",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "pin.comment",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PinCommentParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PinResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/pins/{id}/actions/to_task": {
      "post": {
        "operationId": "pinToTask",
        "tags": [
          "Drawing pins"
        ],
        "summary": "Create a linked task from the pin",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "pin.to_task",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "responses": {
          "201": {
            "description": "The new task.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflows": {
      "get": {
        "operationId": "listWorkflows",
        "tags": [
          "Approval workflows"
        ],
        "summary": "List approval workflows",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "document_id",
            "in": "query",
            "description": "Only records with these document ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step",
            "in": "query",
            "description": "Filter on current step. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gte]",
            "in": "query",
            "description": "Only records whose current step is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lte]",
            "in": "query",
            "description": "Only records whose current step is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gt]",
            "in": "query",
            "description": "Only records whose current step is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lt]",
            "in": "query",
            "description": "Only records whose current step is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of approval workflows.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflows/{id}": {
      "get": {
        "operationId": "getWorkflow",
        "tags": [
          "Approval workflows"
        ],
        "summary": "Get an approval workflow",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The approval workflow.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflows/{id}/actions/take_action": {
      "post": {
        "operationId": "workflowTakeAction",
        "tags": [
          "Approval workflows"
        ],
        "summary": "Approve / reject / request changes on the current step",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "workflow.take_action",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowTakeActionParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflows/{id}/actions/resubmit": {
      "post": {
        "operationId": "workflowResubmit",
        "tags": [
          "Approval workflows"
        ],
        "summary": "Resubmit an on-hold workflow",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "workflow.resubmit",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowResubmitParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflows/{id}/actions/cancel": {
      "post": {
        "operationId": "workflowCancel",
        "tags": [
          "Approval workflows"
        ],
        "summary": "Cancel the workflow",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "workflow.cancel",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowCancelParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflows/actions/take_action": {
      "post": {
        "operationId": "workflowTakeActionBatch",
        "tags": [
          "Approval workflows"
        ],
        "summary": "Approve / reject / request changes on the current step, for up to 20 at once",
        "description": "Approve / reject / request changes on the current step. Needs the `records:write` scope. All ids must be records this key can see, or nothing is changed. At most 20.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "workflow.batch_take_action",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowTakeActionBatchParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The records as they are now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRecords"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis": {
      "get": {
        "operationId": "listRfis",
        "tags": [
          "RFIs"
        ],
        "summary": "List rfis",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_due_date",
            "in": "query",
            "description": "Filter on response due. Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_due_date[gte]",
            "in": "query",
            "description": "Only records whose response due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_due_date[lte]",
            "in": "query",
            "description": "Only records whose response due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_due_date[gt]",
            "in": "query",
            "description": "Only records whose response due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "response_due_date[lt]",
            "in": "query",
            "description": "Only records whose response due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "document_id",
            "in": "query",
            "description": "Only records with these document ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sheet_id",
            "in": "query",
            "description": "Only records with these sheet ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "template_id",
            "in": "query",
            "description": "Only records with these template ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step",
            "in": "query",
            "description": "Filter on current step. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gte]",
            "in": "query",
            "description": "Only records whose current step is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lte]",
            "in": "query",
            "description": "Only records whose current step is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gt]",
            "in": "query",
            "description": "Only records whose current step is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lt]",
            "in": "query",
            "description": "Only records whose current step is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of rfis.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createRfi",
        "tags": [
          "RFIs"
        ],
        "summary": "Create a rfi",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.create",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new rfi.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/{id}": {
      "get": {
        "operationId": "getRfi",
        "tags": [
          "RFIs"
        ],
        "summary": "Get a rfi",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The rfi.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/{id}/actions/answer": {
      "post": {
        "operationId": "rfiAnswer",
        "tags": [
          "RFIs"
        ],
        "summary": "Record the official answer/resolution for the RFI",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.answer",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiAnswerParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/{id}/actions/comment": {
      "post": {
        "operationId": "rfiComment",
        "tags": [
          "RFIs"
        ],
        "summary": "Add a comment to the RFI thread",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.comment",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiCommentParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/{id}/actions/take_action": {
      "post": {
        "operationId": "rfiTakeAction",
        "tags": [
          "RFIs"
        ],
        "summary": "Approve / reject / request changes on the current review step",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.take_action",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiTakeActionParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/{id}/actions/resubmit": {
      "post": {
        "operationId": "rfiResubmit",
        "tags": [
          "RFIs"
        ],
        "summary": "Resubmit an on-hold RFI",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.resubmit",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiResubmitParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/{id}/actions/cancel": {
      "post": {
        "operationId": "rfiCancel",
        "tags": [
          "RFIs"
        ],
        "summary": "Cancel the RFI",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.cancel",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiCancelParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/rfis/actions/take_action": {
      "post": {
        "operationId": "rfiTakeActionBatch",
        "tags": [
          "RFIs"
        ],
        "summary": "Approve / reject / request changes on the current review step, for up to 20 at once",
        "description": "Approve / reject / request changes on the current review step. Needs the `records:write` scope. All ids must be records this key can see, or nothing is changed. At most 20.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "rfi.batch_take_action",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RfiTakeActionBatchParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The records as they are now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RfiRecords"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/conversations": {
      "get": {
        "operationId": "listConversations",
        "tags": [
          "Conversations"
        ],
        "summary": "List conversations",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "is_group",
            "in": "query",
            "description": "Filter on is group. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of conversations.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/conversations/{id}": {
      "get": {
        "operationId": "getConversation",
        "tags": [
          "Conversations"
        ],
        "summary": "Get a conversation",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The conversation.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/conversations/{id}/actions/send": {
      "post": {
        "operationId": "conversationSend",
        "tags": [
          "Conversations"
        ],
        "summary": "Send a message to the conversation",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "conversation.send",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversationSendParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The id of the record the action created or changed.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/conversations/{id}/actions/add_member": {
      "post": {
        "operationId": "conversationAddMember",
        "tags": [
          "Conversations"
        ],
        "summary": "Add a member to the group",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "conversation.add_member",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversationAddMemberParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/conversations/{id}/actions/remove_member": {
      "post": {
        "operationId": "conversationRemoveMember",
        "tags": [
          "Conversations"
        ],
        "summary": "Remove a member from the group",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "conversation.remove_member",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConversationRemoveMemberParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/invites": {
      "post": {
        "operationId": "createInvite",
        "tags": [
          "Invites"
        ],
        "summary": "Create an invite",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "invite.create",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new invite.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/company_members/actions/set_role": {
      "post": {
        "operationId": "companyMemberSetRole",
        "tags": [
          "Team members"
        ],
        "summary": "Change a team member's company role",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "company_member.set_role",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyMemberSetRoleParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyMemberResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/company_members/actions/remove": {
      "post": {
        "operationId": "companyMemberRemove",
        "tags": [
          "Team members"
        ],
        "summary": "Remove a member from the company",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "company_member.remove",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyMemberRemoveParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The id of the record the action created or changed.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/company_members/actions/set_permission": {
      "post": {
        "operationId": "companyMemberSetPermission",
        "tags": [
          "Team members"
        ],
        "summary": "Toggle one permission for a team member",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "company_member.set_permission",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyMemberSetPermissionParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyMemberResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/folder_access/actions/grant": {
      "post": {
        "operationId": "folderAccessGrant",
        "tags": [
          "Folder access rules"
        ],
        "summary": "Grant a member access to a folder",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "folder_access.grant",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FolderAccessGrantParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/folder_access/actions/revoke": {
      "post": {
        "operationId": "folderAccessRevoke",
        "tags": [
          "Folder access rules"
        ],
        "summary": "Revoke a member's access to a folder",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "folder_access.revoke",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FolderAccessRevokeParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FolderResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/company/actions/update_details": {
      "post": {
        "operationId": "companyUpdateDetails",
        "tags": [
          "Companies"
        ],
        "summary": "Update the company's details",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "company.update_details",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompanyUpdateDetailsParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompanyResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/locations": {
      "get": {
        "operationId": "listLocations",
        "tags": [
          "Locations"
        ],
        "summary": "List locations",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "full_name",
                "full_name.desc",
                "full_name.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "Filter on kind. Comma-separated values (any of them matches). Values: site, building, block, level, zone, unit, plot, room, area, external, other.",
            "schema": {
              "type": "string",
              "pattern": "^(site|building|block|level|zone|unit|plot|room|area|external|other)(,(site|building|block|level|zone|unit|plot|room|area|external|other))*$"
            }
          },
          {
            "name": "depth",
            "in": "query",
            "description": "Filter on depth. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth[gte]",
            "in": "query",
            "description": "Only records whose depth is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth[lte]",
            "in": "query",
            "description": "Only records whose depth is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth[gt]",
            "in": "query",
            "description": "Only records whose depth is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth[lt]",
            "in": "query",
            "description": "Only records whose depth is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parent_id",
            "in": "query",
            "description": "Only records with these parent ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "site_id",
            "in": "query",
            "description": "Only records with these site ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sheet_lineage_id",
            "in": "query",
            "description": "Only records with these sheet lineage ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "description": "Filter on sort order. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order[gte]",
            "in": "query",
            "description": "Only records whose sort order is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order[lte]",
            "in": "query",
            "description": "Only records whose sort order is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order[gt]",
            "in": "query",
            "description": "Only records whose sort order is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_order[lt]",
            "in": "query",
            "description": "Only records whose sort order is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of locations.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/locations/{id}": {
      "get": {
        "operationId": "getLocation",
        "tags": [
          "Locations"
        ],
        "summary": "Get a location",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The location.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/site_inductions": {
      "get": {
        "operationId": "listSiteInductions",
        "tags": [
          "Site inductions"
        ],
        "summary": "List site inductions",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: valid, revoked.",
            "schema": {
              "type": "string",
              "pattern": "^(valid|revoked)(,(valid|revoked))*$"
            }
          },
          {
            "name": "inducted_on",
            "in": "query",
            "description": "Filter on inducted on. Comma-separated dates (YYYY-MM-DD) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inducted_on[gte]",
            "in": "query",
            "description": "Only records whose inducted on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inducted_on[lte]",
            "in": "query",
            "description": "Only records whose inducted on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inducted_on[gt]",
            "in": "query",
            "description": "Only records whose inducted on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inducted_on[lt]",
            "in": "query",
            "description": "Only records whose inducted on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_on",
            "in": "query",
            "description": "Filter on expires on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_on[gte]",
            "in": "query",
            "description": "Only records whose expires on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_on[lte]",
            "in": "query",
            "description": "Only records whose expires on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_on[gt]",
            "in": "query",
            "description": "Only records whose expires on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_on[lt]",
            "in": "query",
            "description": "Only records whose expires on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "description": "Only records with these user ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "description": "Only records with these contact ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inspection_id",
            "in": "query",
            "description": "Only records with these inspection ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of site inductions.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteInductionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/site_inductions/{id}": {
      "get": {
        "operationId": "getSiteInduction",
        "tags": [
          "Site inductions"
        ],
        "summary": "Get a site induction",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The site induction.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteInductionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/permits": {
      "get": {
        "operationId": "listPermits",
        "tags": [
          "Permits to work"
        ],
        "summary": "List permits to work",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: draft, requested, issued, suspended, expired, closed, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|requested|issued|suspended|expired|closed|cancelled)(,(draft|requested|issued|suspended|expired|closed|cancelled))*$"
            }
          },
          {
            "name": "permit_type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches). Values: hot_works, confined_space, work_at_height, excavation, electrical_isolation, mechanical_isolation, lifting, roof_access, demolition, general, other.",
            "schema": {
              "type": "string",
              "pattern": "^(hot_works|confined_space|work_at_height|excavation|electrical_isolation|mechanical_isolation|lifting|roof_access|demolition|general|other)(,(hot_works|confined_space|work_at_height|excavation|electrical_isolation|mechanical_isolation|lifting|roof_access|demolition|general|other))*$"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "issuer_id",
            "in": "query",
            "description": "Only records with these issuer ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "receiver_user_id",
            "in": "query",
            "description": "Only records with these receiver user ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "receiver_contact_id",
            "in": "query",
            "description": "Only records with these receiver contact ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inspection_id",
            "in": "query",
            "description": "Only records with these inspection ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of permits to work.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermitList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createPermit",
        "tags": [
          "Permits to work"
        ],
        "summary": "Create a permit to work",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "permit.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PermitCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new permit to work.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermitResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/permits/{id}": {
      "get": {
        "operationId": "getPermit",
        "tags": [
          "Permits to work"
        ],
        "summary": "Get a permit to work",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The permit to work.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermitResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/permits/{id}/actions/request": {
      "post": {
        "operationId": "permitRequest",
        "tags": [
          "Permits to work"
        ],
        "summary": "Send a draft permit to an Authorised Person to issue (a permit request)",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "permit.request",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PermitResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/deliveries": {
      "get": {
        "operationId": "listDeliveries",
        "tags": [
          "Deliveries"
        ],
        "summary": "List deliveries",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: booked, arrived, received, part_received, rejected, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(booked|arrived|received|part_received|rejected|cancelled)(,(booked|arrived|received|part_received|rejected|cancelled))*$"
            }
          },
          {
            "name": "supplier_contact_id",
            "in": "query",
            "description": "Filter on supplier. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expected_on",
            "in": "query",
            "description": "Filter on expected on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expected_on[gte]",
            "in": "query",
            "description": "Only records whose expected on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expected_on[lte]",
            "in": "query",
            "description": "Only records whose expected on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expected_on[gt]",
            "in": "query",
            "description": "Only records whose expected on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expected_on[lt]",
            "in": "query",
            "description": "Only records whose expected on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "condition",
            "in": "query",
            "description": "Filter on condition. Comma-separated values (any of them matches); `null` for records without one. Values: good, damaged, short, mixed.",
            "schema": {
              "type": "string",
              "pattern": "^(good|damaged|short|mixed)(,(good|damaged|short|mixed))*$|^null$"
            }
          },
          {
            "name": "purchase_order_id",
            "in": "query",
            "description": "Only records with these purchase order ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of deliveries.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createDelivery",
        "tags": [
          "Deliveries"
        ],
        "summary": "Create a delivery",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "delivery.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeliveryCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new delivery.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/deliveries/{id}": {
      "get": {
        "operationId": "getDelivery",
        "tags": [
          "Deliveries"
        ],
        "summary": "Get a delivery",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The delivery.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/material_requests": {
      "get": {
        "operationId": "listMaterialRequests",
        "tags": [
          "Material requests"
        ],
        "summary": "List material requests",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: draft, submitted, approved, rejected, ordered, part_delivered, delivered, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|submitted|approved|rejected|ordered|part_delivered|delivered|cancelled)(,(draft|submitted|approved|rejected|ordered|part_delivered|delivered|cancelled))*$"
            }
          },
          {
            "name": "needed_by",
            "in": "query",
            "description": "Filter on needed by. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "needed_by[gte]",
            "in": "query",
            "description": "Only records whose needed by is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "needed_by[lte]",
            "in": "query",
            "description": "Only records whose needed by is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "needed_by[gt]",
            "in": "query",
            "description": "Only records whose needed by is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "needed_by[lt]",
            "in": "query",
            "description": "Only records whose needed by is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "purchase_order_id",
            "in": "query",
            "description": "Only records with these purchase order ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of material requests.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaterialRequestList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createMaterialRequest",
        "tags": [
          "Material requests"
        ],
        "summary": "Create a material request",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "material_request.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaterialRequestCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new material request.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaterialRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/material_requests/{id}": {
      "get": {
        "operationId": "getMaterialRequest",
        "tags": [
          "Material requests"
        ],
        "summary": "Get a material request",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The material request.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaterialRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/material_requests/{id}/actions/submit": {
      "post": {
        "operationId": "materialRequestSubmit",
        "tags": [
          "Material requests"
        ],
        "summary": "Send a material request for approval, adding its items first when they are given",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "material_request.submit",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MaterialRequestSubmitParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MaterialRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/meetings": {
      "get": {
        "operationId": "listMeetings",
        "tags": [
          "Meetings"
        ],
        "summary": "List meetings",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "scheduled_start",
                "scheduled_start.desc",
                "scheduled_start.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: scheduled, in_progress, draft_minutes, issued, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(scheduled|in_progress|draft_minutes|issued|cancelled)(,(scheduled|in_progress|draft_minutes|issued|cancelled))*$"
            }
          },
          {
            "name": "number",
            "in": "query",
            "description": "Filter on number. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[gte]",
            "in": "query",
            "description": "Only records whose number is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[lte]",
            "in": "query",
            "description": "Only records whose number is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[gt]",
            "in": "query",
            "description": "Only records whose number is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "number[lt]",
            "in": "query",
            "description": "Only records whose number is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "meeting_type",
            "in": "query",
            "description": "Filter on type. Comma-separated values (any of them matches). Values: progress, site, design, pre_start, safety, client, subcontractor, other.",
            "schema": {
              "type": "string",
              "pattern": "^(progress|site|design|pre_start|safety|client|subcontractor|other)(,(progress|site|design|pre_start|safety|client|subcontractor|other))*$"
            }
          },
          {
            "name": "issued_version",
            "in": "query",
            "description": "Filter on issued version. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "issued_version[gte]",
            "in": "query",
            "description": "Only records whose issued version is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "issued_version[lte]",
            "in": "query",
            "description": "Only records whose issued version is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "issued_version[gt]",
            "in": "query",
            "description": "Only records whose issued version is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "issued_version[lt]",
            "in": "query",
            "description": "Only records whose issued version is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "series_id",
            "in": "query",
            "description": "Only records with these series ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chair_id",
            "in": "query",
            "description": "Only records with these chair ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "minute_taker_id",
            "in": "query",
            "description": "Only records with these minute taker ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of meetings.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeetingList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createMeeting",
        "tags": [
          "Meetings"
        ],
        "summary": "Create a meeting",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "meeting.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MeetingCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new meeting.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeetingResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/meetings/{id}": {
      "get": {
        "operationId": "getMeeting",
        "tags": [
          "Meetings"
        ],
        "summary": "Get a meeting",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The meeting.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeetingResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/submittals": {
      "get": {
        "operationId": "listSubmittals",
        "tags": [
          "Submittals"
        ],
        "summary": "List submittals",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "document_id",
            "in": "query",
            "description": "Only records with these document ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "template_id",
            "in": "query",
            "description": "Only records with these template ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step",
            "in": "query",
            "description": "Filter on current step. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gte]",
            "in": "query",
            "description": "Only records whose current step is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lte]",
            "in": "query",
            "description": "Only records whose current step is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gt]",
            "in": "query",
            "description": "Only records whose current step is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lt]",
            "in": "query",
            "description": "Only records whose current step is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round",
            "in": "query",
            "description": "Filter on round. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[gte]",
            "in": "query",
            "description": "Only records whose round is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[lte]",
            "in": "query",
            "description": "Only records whose round is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[gt]",
            "in": "query",
            "description": "Only records whose round is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[lt]",
            "in": "query",
            "description": "Only records whose round is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "engine_version",
            "in": "query",
            "description": "Filter on engine version. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "engine_version[gte]",
            "in": "query",
            "description": "Only records whose engine version is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "engine_version[lte]",
            "in": "query",
            "description": "Only records whose engine version is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "engine_version[gt]",
            "in": "query",
            "description": "Only records whose engine version is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "engine_version[lt]",
            "in": "query",
            "description": "Only records whose engine version is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of submittals.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createSubmittal",
        "tags": [
          "Submittals"
        ],
        "summary": "Create a submittal",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "submittal.create",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmittalCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new submittal.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/submittals/{id}": {
      "get": {
        "operationId": "getSubmittal",
        "tags": [
          "Submittals"
        ],
        "summary": "Get a submittal",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The submittal.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/submittals/{id}/actions/take_action": {
      "post": {
        "operationId": "submittalTakeAction",
        "tags": [
          "Submittals"
        ],
        "summary": "Approve / reject / request changes on the current review step",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "submittal.take_action",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmittalTakeActionParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/submittals/{id}/actions/resubmit": {
      "post": {
        "operationId": "submittalResubmit",
        "tags": [
          "Submittals"
        ],
        "summary": "Resubmit a submittal sent back for changes",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "submittal.resubmit",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmittalResubmitParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/submittals/{id}/actions/cancel": {
      "post": {
        "operationId": "submittalCancel",
        "tags": [
          "Submittals"
        ],
        "summary": "Cancel the submittal",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "submittal.cancel",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmittalCancelParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/submittals/actions/take_action": {
      "post": {
        "operationId": "submittalTakeActionBatch",
        "tags": [
          "Submittals"
        ],
        "summary": "Approve / reject / request changes on the current review step, for up to 20 at once",
        "description": "Approve / reject / request changes on the current review step. Needs the `records:write` scope. All ids must be records this key can see, or nothing is changed. At most 20.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "submittal.batch_take_action",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmittalTakeActionBatchParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The records as they are now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubmittalRecords"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflow_steps": {
      "get": {
        "operationId": "listWorkflowSteps",
        "tags": [
          "Workflow places"
        ],
        "summary": "List workflow places",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "instance_id",
            "in": "query",
            "description": "Only records with these instance ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "holder_user_id",
            "in": "query",
            "description": "Only records with these holder user ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "holder_organisation_id",
            "in": "query",
            "description": "Only records with these holder organisation ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round",
            "in": "query",
            "description": "Filter on round. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[gte]",
            "in": "query",
            "description": "Only records whose round is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[lte]",
            "in": "query",
            "description": "Only records whose round is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[gt]",
            "in": "query",
            "description": "Only records whose round is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[lt]",
            "in": "query",
            "description": "Only records whose round is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "step_number",
            "in": "query",
            "description": "Filter on step number. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "step_number[gte]",
            "in": "query",
            "description": "Only records whose step number is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "step_number[lte]",
            "in": "query",
            "description": "Only records whose step number is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "step_number[gt]",
            "in": "query",
            "description": "Only records whose step number is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "step_number[lt]",
            "in": "query",
            "description": "Only records whose step number is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "group_no",
            "in": "query",
            "description": "Filter on group no. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "group_no[gte]",
            "in": "query",
            "description": "Only records whose group no is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "group_no[lte]",
            "in": "query",
            "description": "Only records whose group no is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "group_no[gt]",
            "in": "query",
            "description": "Only records whose group no is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "group_no[lt]",
            "in": "query",
            "description": "Only records whose group no is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seat",
            "in": "query",
            "description": "Filter on seat. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seat[gte]",
            "in": "query",
            "description": "Only records whose seat is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seat[lte]",
            "in": "query",
            "description": "Only records whose seat is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seat[gt]",
            "in": "query",
            "description": "Only records whose seat is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "seat[lt]",
            "in": "query",
            "description": "Only records whose seat is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of workflow places.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowStepList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/workflow_steps/{id}": {
      "get": {
        "operationId": "getWorkflowStep",
        "tags": [
          "Workflow places"
        ],
        "summary": "Get a workflow place",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The workflow place.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowStepResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/project_contracts": {
      "get": {
        "operationId": "listProjectContracts",
        "tags": [
          "Contracts"
        ],
        "summary": "List contracts",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "form",
            "in": "query",
            "description": "Filter on form. Comma-separated values (any of them matches). Values: nec4_ecc, nec4_ecs, nec4_psc, jct_db, jct_sbc, jct_ic, jct_mw, aia_a201, other.",
            "schema": {
              "type": "string",
              "pattern": "^(nec4_ecc|nec4_ecs|nec4_psc|jct_db|jct_sbc|jct_ic|jct_mw|aia_a201|other)(,(nec4_ecc|nec4_ecs|nec4_psc|jct_db|jct_sbc|jct_ic|jct_mw|aia_a201|other))*$"
            }
          },
          {
            "name": "our_role",
            "in": "query",
            "description": "Filter on our side. Comma-separated values (any of them matches). Values: contractor, employer, subcontractor, consultant.",
            "schema": {
              "type": "string",
              "pattern": "^(contractor|employer|subcontractor|consultant)(,(contractor|employer|subcontractor|consultant))*$"
            }
          },
          {
            "name": "is_primary",
            "in": "query",
            "description": "Filter on primary. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "starting_date",
            "in": "query",
            "description": "Filter on starting date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "starting_date[gte]",
            "in": "query",
            "description": "Only records whose starting date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "starting_date[lte]",
            "in": "query",
            "description": "Only records whose starting date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "starting_date[gt]",
            "in": "query",
            "description": "Only records whose starting date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "starting_date[lt]",
            "in": "query",
            "description": "Only records whose starting date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completion_date",
            "in": "query",
            "description": "Filter on completion date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completion_date[gte]",
            "in": "query",
            "description": "Only records whose completion date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completion_date[lte]",
            "in": "query",
            "description": "Only records whose completion date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completion_date[gt]",
            "in": "query",
            "description": "Only records whose completion date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "completion_date[lt]",
            "in": "query",
            "description": "Only records whose completion date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_for_reply_days",
            "in": "query",
            "description": "Filter on period for reply (days). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_for_reply_days[gte]",
            "in": "query",
            "description": "Only records whose period for reply days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_for_reply_days[lte]",
            "in": "query",
            "description": "Only records whose period for reply days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_for_reply_days[gt]",
            "in": "query",
            "description": "Only records whose period for reply days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_for_reply_days[lt]",
            "in": "query",
            "description": "Only records whose period for reply days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notification_bar_weeks",
            "in": "query",
            "description": "Filter on notification period (weeks). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notification_bar_weeks[gte]",
            "in": "query",
            "description": "Only records whose notification bar weeks is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notification_bar_weeks[lte]",
            "in": "query",
            "description": "Only records whose notification bar weeks is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notification_bar_weeks[gt]",
            "in": "query",
            "description": "Only records whose notification bar weeks is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notification_bar_weeks[lt]",
            "in": "query",
            "description": "Only records whose notification bar weeks is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_notification_days",
            "in": "query",
            "description": "Filter on reply to a notification (days). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_notification_days[gte]",
            "in": "query",
            "description": "Only records whose reply to notification days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_notification_days[lte]",
            "in": "query",
            "description": "Only records whose reply to notification days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_notification_days[gt]",
            "in": "query",
            "description": "Only records whose reply to notification days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_notification_days[lt]",
            "in": "query",
            "description": "Only records whose reply to notification days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_days",
            "in": "query",
            "description": "Filter on quotation (days). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_days[gte]",
            "in": "query",
            "description": "Only records whose quotation days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_days[lte]",
            "in": "query",
            "description": "Only records whose quotation days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_days[gt]",
            "in": "query",
            "description": "Only records whose quotation days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_days[lt]",
            "in": "query",
            "description": "Only records whose quotation days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_quotation_days",
            "in": "query",
            "description": "Filter on reply to a quotation (days). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_quotation_days[gte]",
            "in": "query",
            "description": "Only records whose reply to quotation days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_quotation_days[lte]",
            "in": "query",
            "description": "Only records whose reply to quotation days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_quotation_days[gt]",
            "in": "query",
            "description": "Only records whose reply to quotation days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_to_quotation_days[lt]",
            "in": "query",
            "description": "Only records whose reply to quotation days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_acceptance",
            "in": "query",
            "description": "Filter on deemed acceptance. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_acceptance_notice_days",
            "in": "query",
            "description": "Filter on deemed acceptance (days). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_acceptance_notice_days[gte]",
            "in": "query",
            "description": "Only records whose deemed acceptance notice days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_acceptance_notice_days[lte]",
            "in": "query",
            "description": "Only records whose deemed acceptance notice days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_acceptance_notice_days[gt]",
            "in": "query",
            "description": "Only records whose deemed acceptance notice days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_acceptance_notice_days[lt]",
            "in": "query",
            "description": "Only records whose deemed acceptance notice days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "clocks_on",
            "in": "query",
            "description": "Filter on clocks on. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "counterparty_organisation_id",
            "in": "query",
            "description": "Only records with these counterparty organisation ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of contracts.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectContractList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/project_contracts/{id}": {
      "get": {
        "operationId": "getProjectContract",
        "tags": [
          "Contracts"
        ],
        "summary": "Get a contract",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The contract.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectContractResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/contract_events": {
      "get": {
        "operationId": "listContractEvents",
        "tags": [
          "Contract notices"
        ],
        "summary": "List contract notices",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "updated_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "workflow_type",
            "in": "query",
            "description": "Filter on register. Comma-separated values (any of them matches); `null` for records without one. Values: technical_query, early_warning, compensation_event, instruction, ncr.",
            "schema": {
              "type": "string",
              "pattern": "^(technical_query|early_warning|compensation_event|instruction|ncr)(,(technical_query|early_warning|compensation_event|instruction|ncr))*$|^null$"
            }
          },
          {
            "name": "current_step",
            "in": "query",
            "description": "Filter on current step. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gte]",
            "in": "query",
            "description": "Only records whose current step is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lte]",
            "in": "query",
            "description": "Only records whose current step is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[gt]",
            "in": "query",
            "description": "Only records whose current step is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "current_step[lt]",
            "in": "query",
            "description": "Only records whose current step is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round",
            "in": "query",
            "description": "Filter on round. Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[gte]",
            "in": "query",
            "description": "Only records whose round is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[lte]",
            "in": "query",
            "description": "Only records whose round is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[gt]",
            "in": "query",
            "description": "Only records whose round is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "round[lt]",
            "in": "query",
            "description": "Only records whose round is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aware_on",
            "in": "query",
            "description": "Filter on aware on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aware_on[gte]",
            "in": "query",
            "description": "Only records whose aware on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aware_on[lte]",
            "in": "query",
            "description": "Only records whose aware on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aware_on[gt]",
            "in": "query",
            "description": "Only records whose aware on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "aware_on[lt]",
            "in": "query",
            "description": "Only records whose aware on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_date",
            "in": "query",
            "description": "Filter on event date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_date[gte]",
            "in": "query",
            "description": "Only records whose event date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_date[lte]",
            "in": "query",
            "description": "Only records whose event date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_date[gt]",
            "in": "query",
            "description": "Only records whose event date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_date[lt]",
            "in": "query",
            "description": "Only records whose event date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notified_on",
            "in": "query",
            "description": "Filter on notified on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notified_on[gte]",
            "in": "query",
            "description": "Only records whose notified on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notified_on[lte]",
            "in": "query",
            "description": "Only records whose notified on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notified_on[gt]",
            "in": "query",
            "description": "Only records whose notified on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "notified_on[lt]",
            "in": "query",
            "description": "Only records whose notified on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "replied_on",
            "in": "query",
            "description": "Filter on replied on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "replied_on[gte]",
            "in": "query",
            "description": "Only records whose replied on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "replied_on[lte]",
            "in": "query",
            "description": "Only records whose replied on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "replied_on[gt]",
            "in": "query",
            "description": "Only records whose replied on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "replied_on[lt]",
            "in": "query",
            "description": "Only records whose replied on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_due_on",
            "in": "query",
            "description": "Filter on reply due. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_due_on[gte]",
            "in": "query",
            "description": "Only records whose reply due on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_due_on[lte]",
            "in": "query",
            "description": "Only records whose reply due on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_due_on[gt]",
            "in": "query",
            "description": "Only records whose reply due on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reply_due_on[lt]",
            "in": "query",
            "description": "Only records whose reply due on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_due_on",
            "in": "query",
            "description": "Filter on quotation due. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_due_on[gte]",
            "in": "query",
            "description": "Only records whose quotation due on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_due_on[lte]",
            "in": "query",
            "description": "Only records whose quotation due on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_due_on[gt]",
            "in": "query",
            "description": "Only records whose quotation due on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quotation_due_on[lt]",
            "in": "query",
            "description": "Only records whose quotation due on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assessment_due_on",
            "in": "query",
            "description": "Filter on reply to quotation due. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assessment_due_on[gte]",
            "in": "query",
            "description": "Only records whose assessment due on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assessment_due_on[lte]",
            "in": "query",
            "description": "Only records whose assessment due on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assessment_due_on[gt]",
            "in": "query",
            "description": "Only records whose assessment due on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assessment_due_on[lt]",
            "in": "query",
            "description": "Only records whose assessment due on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_accepted_on",
            "in": "query",
            "description": "Filter on deemed accepted on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_accepted_on[gte]",
            "in": "query",
            "description": "Only records whose deemed accepted on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_accepted_on[lte]",
            "in": "query",
            "description": "Only records whose deemed accepted on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_accepted_on[gt]",
            "in": "query",
            "description": "Only records whose deemed accepted on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deemed_accepted_on[lt]",
            "in": "query",
            "description": "Only records whose deemed accepted on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "time_bar_on",
            "in": "query",
            "description": "Filter on notify by. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "time_bar_on[gte]",
            "in": "query",
            "description": "Only records whose time bar on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "time_bar_on[lte]",
            "in": "query",
            "description": "Only records whose time bar on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "time_bar_on[gt]",
            "in": "query",
            "description": "Only records whose time bar on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "time_bar_on[lt]",
            "in": "query",
            "description": "Only records whose time bar on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_due_on",
            "in": "query",
            "description": "Filter on next due. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_due_on[gte]",
            "in": "query",
            "description": "Only records whose next due on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_due_on[lte]",
            "in": "query",
            "description": "Only records whose next due on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_due_on[gt]",
            "in": "query",
            "description": "Only records whose next due on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "next_due_on[lt]",
            "in": "query",
            "description": "Only records whose next due on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "clock_state",
            "in": "query",
            "description": "Filter on clock state. Comma-separated values (any of them matches); `null` for records without one. Values: none, running, warning, overdue, deemed_accepted, time_barred, closed.",
            "schema": {
              "type": "string",
              "pattern": "^(none|running|warning|overdue|deemed_accepted|time_barred|closed)(,(none|running|warning|overdue|deemed_accepted|time_barred|closed))*$|^null$"
            }
          },
          {
            "name": "closed_on",
            "in": "query",
            "description": "Filter on closed on. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "closed_on[gte]",
            "in": "query",
            "description": "Only records whose closed on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "closed_on[lte]",
            "in": "query",
            "description": "Only records whose closed on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "closed_on[gt]",
            "in": "query",
            "description": "Only records whose closed on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "closed_on[lt]",
            "in": "query",
            "description": "Only records whose closed on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contract_id",
            "in": "query",
            "description": "Only records with these contract ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of contract notices.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContractEventList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/contract_events/{id}": {
      "get": {
        "operationId": "getContractEvent",
        "tags": [
          "Contract notices"
        ],
        "summary": "Get a contract notice",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The contract notice.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContractEventResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/inbound_emails": {
      "get": {
        "operationId": "listInboundEmails",
        "tags": [
          "Received email"
        ],
        "summary": "List received email",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "received_at",
                "received_at.desc",
                "received_at.asc"
              ],
              "default": "received_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: received, filed, held, refused, dropped, released.",
            "schema": {
              "type": "string",
              "pattern": "^(received|filed|held|refused|dropped|released)(,(received|filed|held|refused|dropped|released))*$"
            }
          },
          {
            "name": "route",
            "in": "query",
            "description": "Filter on arrived as. Comma-separated values (any of them matches). Values: reply, project, unknown.",
            "schema": {
              "type": "string",
              "pattern": "^(reply|project|unknown)(,(reply|project|unknown))*$"
            }
          },
          {
            "name": "sender_status",
            "in": "query",
            "description": "Filter on sender. Comma-separated values (any of them matches). Values: token_match, member, contact, org_domain, unknown, mismatch.",
            "schema": {
              "type": "string",
              "pattern": "^(token_match|member|contact|org_domain|unknown|mismatch)(,(token_match|member|contact|org_domain|unknown|mismatch))*$"
            }
          },
          {
            "name": "attachment_count",
            "in": "query",
            "description": "Filter on files. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_count[gte]",
            "in": "query",
            "description": "Only records whose attachment count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_count[lte]",
            "in": "query",
            "description": "Only records whose attachment count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_count[gt]",
            "in": "query",
            "description": "Only records whose attachment count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_count[lt]",
            "in": "query",
            "description": "Only records whose attachment count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "entity_id",
            "in": "query",
            "description": "Only records with these entity ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of received email.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InboundEmailList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/inbound_emails/{id}": {
      "get": {
        "operationId": "getInboundEmail",
        "tags": [
          "Received email"
        ],
        "summary": "Get a received email",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The received email.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InboundEmailResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/bid_packages": {
      "get": {
        "operationId": "listBidPackages",
        "tags": [
          "Bid packages"
        ],
        "summary": "List bid packages",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tender_status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: draft, issued, closed, awarded, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|issued|closed|awarded|cancelled)(,(draft|issued|closed|awarded|cancelled))*$"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter on package status. Comma-separated values (any of them matches). Values: open, closed, awarded.",
            "schema": {
              "type": "string",
              "pattern": "^(open|closed|awarded)(,(open|closed|awarded))*$"
            }
          },
          {
            "name": "due_date",
            "in": "query",
            "description": "Filter on due date. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gte]",
            "in": "query",
            "description": "Only records whose due date is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lte]",
            "in": "query",
            "description": "Only records whose due date is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[gt]",
            "in": "query",
            "description": "Only records whose due date is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_date[lt]",
            "in": "query",
            "description": "Only records whose due date is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "awarded_bid_id",
            "in": "query",
            "description": "Only records with these awarded bid ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of bid packages.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BidPackageList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/bid_packages/{id}": {
      "get": {
        "operationId": "getBidPackage",
        "tags": [
          "Bid packages"
        ],
        "summary": "Get a bid package",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The bid package.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BidPackageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/bids": {
      "get": {
        "operationId": "listBids",
        "tags": [
          "Bids"
        ],
        "summary": "List bids",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "updated_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: invited, received, declined, awarded.",
            "schema": {
              "type": "string",
              "pattern": "^(invited|received|declined|awarded)(,(invited|received|declined|awarded))*$"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "description": "Filter on subcontractor. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "intent",
            "in": "query",
            "description": "Filter on answer. Comma-separated values (any of them matches). Values: pending, accepted, declined.",
            "schema": {
              "type": "string",
              "pattern": "^(pending|accepted|declined)(,(pending|accepted|declined))*$"
            }
          },
          {
            "name": "returned_via",
            "in": "query",
            "description": "Filter on returned through. Comma-separated values (any of them matches); `null` for records without one. Values: portal, staff.",
            "schema": {
              "type": "string",
              "pattern": "^(portal|staff)(,(portal|staff))*$|^null$"
            }
          },
          {
            "name": "submission_count",
            "in": "query",
            "description": "Filter on returns sent. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "submission_count[gte]",
            "in": "query",
            "description": "Only records whose submission count is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "submission_count[lte]",
            "in": "query",
            "description": "Only records whose submission count is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "submission_count[gt]",
            "in": "query",
            "description": "Only records whose submission count is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "submission_count[lt]",
            "in": "query",
            "description": "Only records whose submission count is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bid_package_id",
            "in": "query",
            "description": "Only records with these bid package ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of bids.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BidList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/bids/{id}": {
      "get": {
        "operationId": "getBid",
        "tags": [
          "Bids"
        ],
        "summary": "Get a bid",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The bid.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BidResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/service_requests": {
      "get": {
        "operationId": "listServiceRequests",
        "tags": [
          "Service requests"
        ],
        "summary": "List service requests",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "reported_at",
                "reported_at.desc",
                "reported_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: new, triaged, assigned, scheduled, resolved, closed, rejected.",
            "schema": {
              "type": "string",
              "pattern": "^(new|triaged|assigned|scheduled|resolved|closed|rejected)(,(new|triaged|assigned|scheduled|resolved|closed|rejected))*$"
            }
          },
          {
            "name": "category",
            "in": "query",
            "description": "Filter on category. Comma-separated values (any of them matches). Values: plumbing, electrical, heating, ventilation, doors_windows, roof, finishes, appliances, drainage, structural, external, other.",
            "schema": {
              "type": "string",
              "pattern": "^(plumbing|electrical|heating|ventilation|doors_windows|roof|finishes|appliances|drainage|structural|external|other)(,(plumbing|electrical|heating|ventilation|doors_windows|roof|finishes|appliances|drainage|structural|external|other))*$"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "description": "Filter on priority. Comma-separated values (any of them matches). Values: emergency, urgent, routine, cosmetic.",
            "schema": {
              "type": "string",
              "pattern": "^(emergency|urgent|routine|cosmetic)(,(emergency|urgent|routine|cosmetic))*$"
            }
          },
          {
            "name": "source",
            "in": "query",
            "description": "Filter on source. Comma-separated values (any of them matches). Values: portal, qr, email, staff, api.",
            "schema": {
              "type": "string",
              "pattern": "^(portal|qr|email|staff|api)(,(portal|qr|email|staff|api))*$"
            }
          },
          {
            "name": "warranty_state",
            "in": "query",
            "description": "Filter on warranty. Comma-separated values (any of them matches). Values: within, expired, unknown.",
            "schema": {
              "type": "string",
              "pattern": "^(within|expired|unknown)(,(within|expired|unknown))*$"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assigned_contact_id",
            "in": "query",
            "description": "Only records with these assigned contact ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "punch_item_id",
            "in": "query",
            "description": "Only records with these punch item ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of service requests.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceRequestList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/service_requests/{id}": {
      "get": {
        "operationId": "getServiceRequest",
        "tags": [
          "Service requests"
        ],
        "summary": "Get a service request",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The service request.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceRequestResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/handover_packs": {
      "get": {
        "operationId": "listHandoverPacks",
        "tags": [
          "Handover packs"
        ],
        "summary": "List handover packs",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "version",
                "version.desc",
                "version.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: draft, issued, superseded.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|issued|superseded)(,(draft|issued|superseded))*$"
            }
          },
          {
            "name": "version",
            "in": "query",
            "description": "Filter on version. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version[gte]",
            "in": "query",
            "description": "Only records whose version is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version[lte]",
            "in": "query",
            "description": "Only records whose version is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version[gt]",
            "in": "query",
            "description": "Only records whose version is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "version[lt]",
            "in": "query",
            "description": "Only records whose version is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "frozen_package_id",
            "in": "query",
            "description": "Only records with these frozen package ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "transmittal_id",
            "in": "query",
            "description": "Only records with these transmittal ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of handover packs.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HandoverPackList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/handover_packs/{id}": {
      "get": {
        "operationId": "getHandoverPack",
        "tags": [
          "Handover packs"
        ],
        "summary": "Get a handover pack",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The handover pack.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HandoverPackResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/site_attendance": {
      "get": {
        "operationId": "listSiteAttendance",
        "tags": [
          "Site sign-ins"
        ],
        "summary": "List site sign-ins",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: on_site, signed_out, auto_signed_out.",
            "schema": {
              "type": "string",
              "pattern": "^(on_site|signed_out|auto_signed_out)(,(on_site|signed_out|auto_signed_out))*$"
            }
          },
          {
            "name": "method",
            "in": "query",
            "description": "Filter on signed in by. Comma-separated values (any of them matches). Values: kiosk, staff, app.",
            "schema": {
              "type": "string",
              "pattern": "^(kiosk|staff|app)(,(kiosk|staff|app))*$"
            }
          },
          {
            "name": "site_id",
            "in": "query",
            "description": "Only records with these site ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "description": "Only records with these contact ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "description": "Only records with these user ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of site sign-ins.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteAttendanceList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/site_attendance/{id}": {
      "get": {
        "operationId": "getSiteAttendance",
        "tags": [
          "Site sign-ins"
        ],
        "summary": "Get a site sign-in",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The site sign-in.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SiteAttendanceResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/work_calendars": {
      "get": {
        "operationId": "listWorkCalendars",
        "tags": [
          "Working calendars"
        ],
        "summary": "List working calendars",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours_per_day",
            "in": "query",
            "description": "Filter on hours per day. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours_per_day[gte]",
            "in": "query",
            "description": "Only records whose hours per day is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours_per_day[lte]",
            "in": "query",
            "description": "Only records whose hours per day is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours_per_day[gt]",
            "in": "query",
            "description": "Only records whose hours per day is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hours_per_day[lt]",
            "in": "query",
            "description": "Only records whose hours per day is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "region_preset",
            "in": "query",
            "description": "Filter on bank holidays. Comma-separated values (any of them matches); `null` for records without one. Values: england_wales, scotland, northern_ireland, us_federal.",
            "schema": {
              "type": "string",
              "pattern": "^(england_wales|scotland|northern_ireland|us_federal)(,(england_wales|scotland|northern_ireland|us_federal))*$|^null$"
            }
          },
          {
            "name": "applies_to_programme",
            "in": "query",
            "description": "Filter on programme uses it. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of working calendars.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkCalendarList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/work_calendars/{id}": {
      "get": {
        "operationId": "getWorkCalendar",
        "tags": [
          "Working calendars"
        ],
        "summary": "Get a working calendar",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The working calendar.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkCalendarResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_sections": {
      "get": {
        "operationId": "listEstimateSections",
        "tags": [
          "Estimate sections"
        ],
        "summary": "List estimate sections",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "estimate_id",
            "in": "query",
            "description": "Filter on estimate. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position",
            "in": "query",
            "description": "Filter on position. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[gte]",
            "in": "query",
            "description": "Only records whose position is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[lte]",
            "in": "query",
            "description": "Only records whose position is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[gt]",
            "in": "query",
            "description": "Only records whose position is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[lt]",
            "in": "query",
            "description": "Only records whose position is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parent_id",
            "in": "query",
            "description": "Only records with these parent ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of estimate sections.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateSectionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createEstimateSection",
        "tags": [
          "Estimate sections"
        ],
        "summary": "Create an estimate section",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_section.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateSectionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new estimate section.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateSectionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_sections/{id}": {
      "get": {
        "operationId": "getEstimateSection",
        "tags": [
          "Estimate sections"
        ],
        "summary": "Get an estimate section",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The estimate section.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateSectionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateEstimateSection",
        "tags": [
          "Estimate sections"
        ],
        "summary": "Update an estimate section",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_section.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateSectionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateSectionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "delete": {
        "operationId": "deleteEstimateSection",
        "tags": [
          "Estimate sections"
        ],
        "summary": "Delete an estimate section (permanent)",
        "description": "Needs the `records:delete` scope. Destructive: cannot be undone.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_section.delete",
        "x-konverge-tier": 3,
        "x-konverge-scope": "records:delete",
        "responses": {
          "200": {
            "description": "Deleted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_options": {
      "get": {
        "operationId": "listEstimateOptions",
        "tags": [
          "Estimate options"
        ],
        "summary": "List estimate options",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "updated_at",
                "updated_at.desc",
                "updated_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "estimate_id",
            "in": "query",
            "description": "Filter on estimate. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "Filter on kind. Comma-separated values (any of them matches). Values: option, alternate.",
            "schema": {
              "type": "string",
              "pattern": "^(option|alternate)(,(option|alternate))*$"
            }
          },
          {
            "name": "position",
            "in": "query",
            "description": "Filter on position. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[gte]",
            "in": "query",
            "description": "Only records whose position is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[lte]",
            "in": "query",
            "description": "Only records whose position is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[gt]",
            "in": "query",
            "description": "Only records whose position is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "position[lt]",
            "in": "query",
            "description": "Only records whose position is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_selected",
            "in": "query",
            "description": "Filter on selected. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of estimate options.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateOptionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "post": {
        "operationId": "createEstimateOption",
        "tags": [
          "Estimate options"
        ],
        "summary": "Create an estimate option",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_option.create",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateOptionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new estimate option.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateOptionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_options/{id}": {
      "get": {
        "operationId": "getEstimateOption",
        "tags": [
          "Estimate options"
        ],
        "summary": "Get an estimate option",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The estimate option.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateOptionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      },
      "patch": {
        "operationId": "updateEstimateOption",
        "tags": [
          "Estimate options"
        ],
        "summary": "Update an estimate option",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_option.update",
        "x-konverge-tier": 1,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateOptionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateOptionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_options/{id}/actions/select": {
      "post": {
        "operationId": "estimateOptionSelect",
        "tags": [
          "Estimate options"
        ],
        "summary": "Select or deselect the option (the estimate's totals change)",
        "description": "Needs the `records:write` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "x-konverge-kind": "estimate_option.select",
        "x-konverge-tier": 2,
        "x-konverge-scope": "records:write",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateOptionSelectParams"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done. The record as it is now.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateOptionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/takeoff_items": {
      "get": {
        "operationId": "listTakeoffItems",
        "tags": [
          "Takeoff items"
        ],
        "summary": "List takeoff items",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "estimate_id",
            "in": "query",
            "description": "Filter on estimate. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "measure",
            "in": "query",
            "description": "Filter on measure. Comma-separated values (any of them matches). Values: length, area, perimeter, count, wall_area, volume.",
            "schema": {
              "type": "string",
              "pattern": "^(length|area|perimeter|count|wall_area|volume)(,(length|area|perimeter|count|wall_area|volume))*$"
            }
          },
          {
            "name": "height_m",
            "in": "query",
            "description": "Filter on height (m). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "height_m[gte]",
            "in": "query",
            "description": "Only records whose height m is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "height_m[lte]",
            "in": "query",
            "description": "Only records whose height m is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "height_m[gt]",
            "in": "query",
            "description": "Only records whose height m is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "height_m[lt]",
            "in": "query",
            "description": "Only records whose height m is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth_m",
            "in": "query",
            "description": "Filter on depth (m). Comma-separated numbers (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth_m[gte]",
            "in": "query",
            "description": "Only records whose depth m is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth_m[lte]",
            "in": "query",
            "description": "Only records whose depth m is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth_m[gt]",
            "in": "query",
            "description": "Only records whose depth m is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "depth_m[lt]",
            "in": "query",
            "description": "Only records whose depth m is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "factor",
            "in": "query",
            "description": "Filter on multiplier. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "factor[gte]",
            "in": "query",
            "description": "Only records whose factor is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "factor[lte]",
            "in": "query",
            "description": "Only records whose factor is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "factor[gt]",
            "in": "query",
            "description": "Only records whose factor is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "factor[lt]",
            "in": "query",
            "description": "Only records whose factor is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deduct",
            "in": "query",
            "description": "Filter on deducted. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "unit",
            "in": "query",
            "description": "Filter on unit. Comma-separated values (any of them matches). Values: m, m2, m3, ea, ft, ft2, ft3, yd3.",
            "schema": {
              "type": "string",
              "pattern": "^(m|m2|m3|ea|ft|ft2|ft3|yd3)(,(m|m2|m3|ea|ft|ft2|ft3|yd3))*$"
            }
          },
          {
            "name": "quantity",
            "in": "query",
            "description": "Filter on quantity. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gte]",
            "in": "query",
            "description": "Only records whose quantity is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lte]",
            "in": "query",
            "description": "Only records whose quantity is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gt]",
            "in": "query",
            "description": "Only records whose quantity is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lt]",
            "in": "query",
            "description": "Only records whose quantity is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scale_source",
            "in": "query",
            "description": "Filter on scale. Comma-separated values (any of them matches). Values: region, sheet, none.",
            "schema": {
              "type": "string",
              "pattern": "^(region|sheet|none)(,(region|sheet|none))*$"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter on status. Comma-separated values (any of them matches). Values: current, stale, orphaned, no_scale.",
            "schema": {
              "type": "string",
              "pattern": "^(current|stale|orphaned|no_scale)(,(current|stale|orphaned|no_scale))*$"
            }
          },
          {
            "name": "estimate_item_id",
            "in": "query",
            "description": "Only records with these estimate item ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sheet_id",
            "in": "query",
            "description": "Only records with these sheet ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "markup_id",
            "in": "query",
            "description": "Only records with these markup ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "region_id",
            "in": "query",
            "description": "Only records with these region ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of takeoff items.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TakeoffItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/takeoff_items/{id}": {
      "get": {
        "operationId": "getTakeoffItem",
        "tags": [
          "Takeoff items"
        ],
        "summary": "Get a takeoff item",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The takeoff item.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TakeoffItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/proposal_templates": {
      "get": {
        "operationId": "listProposalTemplates",
        "tags": [
          "Proposal templates"
        ],
        "summary": "List proposal templates",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "name",
                "name.desc",
                "name.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "is_default",
            "in": "query",
            "description": "Filter on default. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "validity_days",
            "in": "query",
            "description": "Filter on valid for (days). Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "validity_days[gte]",
            "in": "query",
            "description": "Only records whose validity days is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "validity_days[lte]",
            "in": "query",
            "description": "Only records whose validity days is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "validity_days[gt]",
            "in": "query",
            "description": "Only records whose validity days is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "validity_days[lt]",
            "in": "query",
            "description": "Only records whose validity days is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "price_display",
            "in": "query",
            "description": "Filter on price display. Comma-separated values (any of them matches). Values: all, sections_only, total_only.",
            "schema": {
              "type": "string",
              "pattern": "^(all|sections_only|total_only)(,(all|sections_only|total_only))*$"
            }
          },
          {
            "name": "show_quantities",
            "in": "query",
            "description": "Filter on show quantities. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of proposal templates.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalTemplateList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/proposal_templates/{id}": {
      "get": {
        "operationId": "getProposalTemplate",
        "tags": [
          "Proposal templates"
        ],
        "summary": "Get a proposal template",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The proposal template.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProposalTemplateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_acceptances": {
      "get": {
        "operationId": "listEstimateAcceptances",
        "tags": [
          "Estimate acceptances"
        ],
        "summary": "List estimate acceptances",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "estimate_id",
            "in": "query",
            "description": "Filter on estimate. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number",
            "in": "query",
            "description": "Filter on revision. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[gte]",
            "in": "query",
            "description": "Only records whose revision number is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[lte]",
            "in": "query",
            "description": "Only records whose revision number is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[gt]",
            "in": "query",
            "description": "Only records whose revision number is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "revision_number[lt]",
            "in": "query",
            "description": "Only records whose revision number is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_via",
            "in": "query",
            "description": "Filter on accepted by. Comma-separated values (any of them matches). Values: portal, esign, staff.",
            "schema": {
              "type": "string",
              "pattern": "^(portal|esign|staff)(,(portal|esign|staff))*$"
            }
          },
          {
            "name": "accepted_subtotal",
            "in": "query",
            "description": "Filter on accepted subtotal. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_subtotal[gte]",
            "in": "query",
            "description": "Only records whose accepted subtotal is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_subtotal[lte]",
            "in": "query",
            "description": "Only records whose accepted subtotal is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_subtotal[gt]",
            "in": "query",
            "description": "Only records whose accepted subtotal is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_subtotal[lt]",
            "in": "query",
            "description": "Only records whose accepted subtotal is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_tax",
            "in": "query",
            "description": "Filter on accepted vat. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_tax[gte]",
            "in": "query",
            "description": "Only records whose accepted tax is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_tax[lte]",
            "in": "query",
            "description": "Only records whose accepted tax is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_tax[gt]",
            "in": "query",
            "description": "Only records whose accepted tax is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_tax[lt]",
            "in": "query",
            "description": "Only records whose accepted tax is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_total",
            "in": "query",
            "description": "Filter on accepted total. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_total[gte]",
            "in": "query",
            "description": "Only records whose accepted total is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_total[lte]",
            "in": "query",
            "description": "Only records whose accepted total is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_total[gt]",
            "in": "query",
            "description": "Only records whose accepted total is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_total[lt]",
            "in": "query",
            "description": "Only records whose accepted total is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "signature_request_id",
            "in": "query",
            "description": "Only records with these signature request ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of estimate acceptances.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateAcceptanceList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/estimate_acceptances/{id}": {
      "get": {
        "operationId": "getEstimateAcceptance",
        "tags": [
          "Estimate acceptances"
        ],
        "summary": "Get an estimate acceptance",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The estimate acceptance.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateAcceptanceResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/selection_items": {
      "get": {
        "operationId": "listSelectionItems",
        "tags": [
          "Selections"
        ],
        "summary": "List selections",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: draft, open, chosen, approved, ordered, installed, cancelled.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|open|chosen|approved|ordered|installed|cancelled)(,(draft|open|chosen|approved|ordered|installed|cancelled))*$"
            }
          },
          {
            "name": "quantity",
            "in": "query",
            "description": "Filter on quantity. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gte]",
            "in": "query",
            "description": "Only records whose quantity is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lte]",
            "in": "query",
            "description": "Only records whose quantity is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gt]",
            "in": "query",
            "description": "Only records whose quantity is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lt]",
            "in": "query",
            "description": "Only records whose quantity is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_on",
            "in": "query",
            "description": "Filter on due. Comma-separated dates (YYYY-MM-DD) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_on[gte]",
            "in": "query",
            "description": "Only records whose due on is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_on[lte]",
            "in": "query",
            "description": "Only records whose due on is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_on[gt]",
            "in": "query",
            "description": "Only records whose due on is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_on[lt]",
            "in": "query",
            "description": "Only records whose due on is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chosen_via",
            "in": "query",
            "description": "Filter on chosen in. Comma-separated values (any of them matches); `null` for records without one. Values: portal, staff.",
            "schema": {
              "type": "string",
              "pattern": "^(portal|staff)(,(portal|staff))*$|^null$"
            }
          },
          {
            "name": "allowance_id",
            "in": "query",
            "description": "Only records with these allowance ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "description": "Only records with these location ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "chosen_option_id",
            "in": "query",
            "description": "Only records with these chosen option ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "requires_signature",
            "in": "query",
            "description": "Filter on requires signature. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of selections.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelectionItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/selection_items/{id}": {
      "get": {
        "operationId": "getSelectionItem",
        "tags": [
          "Selections"
        ],
        "summary": "Get a selection",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The selection.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SelectionItemResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/takeoff_suggestions": {
      "get": {
        "operationId": "listTakeoffSuggestions",
        "tags": [
          "Takeoff suggestions"
        ],
        "summary": "List takeoff suggestions",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: open, accepted, dismissed, superseded.",
            "schema": {
              "type": "string",
              "pattern": "^(open|accepted|dismissed|superseded)(,(open|accepted|dismissed|superseded))*$"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "description": "Filter on kind. Comma-separated values (any of them matches). Values: room_area, schedule_count, symbol_count, length.",
            "schema": {
              "type": "string",
              "pattern": "^(room_area|schedule_count|symbol_count|length)(,(room_area|schedule_count|symbol_count|length))*$"
            }
          },
          {
            "name": "basis",
            "in": "query",
            "description": "Filter on read from. Comma-separated values (any of them matches). Values: printed, schedule, geometry.",
            "schema": {
              "type": "string",
              "pattern": "^(printed|schedule|geometry)(,(printed|schedule|geometry))*$"
            }
          },
          {
            "name": "quantity",
            "in": "query",
            "description": "Filter on quantity. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gte]",
            "in": "query",
            "description": "Only records whose quantity is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lte]",
            "in": "query",
            "description": "Only records whose quantity is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[gt]",
            "in": "query",
            "description": "Only records whose quantity is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "quantity[lt]",
            "in": "query",
            "description": "Only records whose quantity is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "unit",
            "in": "query",
            "description": "Filter on unit. Comma-separated values (any of them matches). Values: m, m2, ea, ft, ft2.",
            "schema": {
              "type": "string",
              "pattern": "^(m|m2|ea|ft|ft2)(,(m|m2|ea|ft|ft2))*$"
            }
          },
          {
            "name": "confidence",
            "in": "query",
            "description": "Filter on confidence. Comma-separated numbers (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confidence[gte]",
            "in": "query",
            "description": "Only records whose confidence is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confidence[lte]",
            "in": "query",
            "description": "Only records whose confidence is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confidence[gt]",
            "in": "query",
            "description": "Only records whose confidence is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "confidence[lt]",
            "in": "query",
            "description": "Only records whose confidence is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sheet_id",
            "in": "query",
            "description": "Only records with these sheet ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "region_id",
            "in": "query",
            "description": "Only records with these region ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "run_id",
            "in": "query",
            "description": "Only records with these run ids. Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_estimate_id",
            "in": "query",
            "description": "Only records with these accepted estimate ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "accepted_item_id",
            "in": "query",
            "description": "Only records with these accepted item ids. Comma-separated ids (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of takeoff suggestions.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TakeoffSuggestionList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/takeoff_suggestions/{id}": {
      "get": {
        "operationId": "getTakeoffSuggestion",
        "tags": [
          "Takeoff suggestions"
        ],
        "summary": "Get a takeoff suggestion",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The takeoff suggestion.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TakeoffSuggestionResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/client_updates": {
      "get": {
        "operationId": "listClientUpdates",
        "tags": [
          "Client updates"
        ],
        "summary": "List client updates",
        "description": "Newest first by default. Needs the `records:read` scope. Keys limited to some projects only see records on those projects.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "order",
            "in": "query",
            "description": "Sort column, newest / latest first; add `.asc` for oldest first.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "created_at.desc",
                "created_at.asc",
                "period_start",
                "period_start.desc",
                "period_start.asc"
              ],
              "default": "created_at"
            }
          },
          {
            "$ref": "#/components/parameters/CreatedSince"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "name": "project_id",
            "in": "query",
            "description": "Only records on these projects (project ids, comma-separated). Comma-separated ids (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only records with these values (comma-separated). Comma-separated values (any of them matches). Values: draft, published, discarded, expired.",
            "schema": {
              "type": "string",
              "pattern": "^(draft|published|discarded|expired)(,(draft|published|discarded|expired))*$"
            }
          },
          {
            "name": "period_start",
            "in": "query",
            "description": "Filter on from. Comma-separated dates (YYYY-MM-DD) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_start[gte]",
            "in": "query",
            "description": "Only records whose period start is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_start[lte]",
            "in": "query",
            "description": "Only records whose period start is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_start[gt]",
            "in": "query",
            "description": "Only records whose period start is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_start[lt]",
            "in": "query",
            "description": "Only records whose period start is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_end",
            "in": "query",
            "description": "Filter on to. Comma-separated dates (YYYY-MM-DD) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_end[gte]",
            "in": "query",
            "description": "Only records whose period end is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_end[lte]",
            "in": "query",
            "description": "Only records whose period end is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_end[gt]",
            "in": "query",
            "description": "Only records whose period end is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "period_end[lt]",
            "in": "query",
            "description": "Only records whose period end is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "drafted_by",
            "in": "query",
            "description": "Filter on drafted by. Comma-separated values (any of them matches). Values: ai, template, person.",
            "schema": {
              "type": "string",
              "pattern": "^(ai|template|person)(,(ai|template|person))*$"
            }
          },
          {
            "name": "names_removed",
            "in": "query",
            "description": "Filter on names removed. Comma-separated true or false (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "drafted_at",
            "in": "query",
            "description": "Filter on drafted. Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "drafted_at[gte]",
            "in": "query",
            "description": "Only records whose drafted at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "drafted_at[lte]",
            "in": "query",
            "description": "Only records whose drafted at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "drafted_at[gt]",
            "in": "query",
            "description": "Only records whose drafted at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "drafted_at[lt]",
            "in": "query",
            "description": "Only records whose drafted at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_at",
            "in": "query",
            "description": "Filter on expires. Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_at[gte]",
            "in": "query",
            "description": "Only records whose expires at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_at[lte]",
            "in": "query",
            "description": "Only records whose expires at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_at[gt]",
            "in": "query",
            "description": "Only records whose expires at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "expires_at[lt]",
            "in": "query",
            "description": "Only records whose expires at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "edited_at",
            "in": "query",
            "description": "Filter on edited. Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "edited_at[gte]",
            "in": "query",
            "description": "Only records whose edited at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "edited_at[lte]",
            "in": "query",
            "description": "Only records whose edited at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "edited_at[gt]",
            "in": "query",
            "description": "Only records whose edited at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "edited_at[lt]",
            "in": "query",
            "description": "Only records whose edited at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_at",
            "in": "query",
            "description": "Filter on published. Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_at[gte]",
            "in": "query",
            "description": "Only records whose published at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_at[lte]",
            "in": "query",
            "description": "Only records whose published at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_at[gt]",
            "in": "query",
            "description": "Only records whose published at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_at[lt]",
            "in": "query",
            "description": "Only records whose published at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discarded_at",
            "in": "query",
            "description": "Filter on discarded. Comma-separated timestamps (RFC 3339) (any of them matches); `null` for records without one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discarded_at[gte]",
            "in": "query",
            "description": "Only records whose discarded at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discarded_at[lte]",
            "in": "query",
            "description": "Only records whose discarded at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discarded_at[gt]",
            "in": "query",
            "description": "Only records whose discarded at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "discarded_at[lt]",
            "in": "query",
            "description": "Only records whose discarded at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "description": "When the record was created (use [gte] / [lte] for a range). Comma-separated timestamps (RFC 3339) (any of them matches).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "description": "Only records whose created at is on or after / at least this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "description": "Only records whose created at is on or before / at most this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[gt]",
            "in": "query",
            "description": "Only records whose created at is after / more than this value.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at[lt]",
            "in": "query",
            "description": "Only records whose created at is before / less than this value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "A page of client updates.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientUpdateList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/client_updates/{id}": {
      "get": {
        "operationId": "getClientUpdate",
        "tags": [
          "Client updates"
        ],
        "summary": "Get a client update",
        "description": "Needs the `records:read` scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Id"
          }
        ],
        "x-konverge-scope": "records:read",
        "responses": {
          "200": {
            "description": "The client update.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/X-RateLimit-Limit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/X-RateLimit-Remaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/X-RateLimit-Reset"
              },
              "Konverge-RateLimit-Scope": {
                "$ref": "#/components/headers/Konverge-RateLimit-Scope"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientUpdateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    }
  },
  "webhooks": {
    "event": {
      "post": {
        "operationId": "receiveWebhookEvent",
        "tags": [
          "Webhooks"
        ],
        "summary": "An event Konverge sends to your webhook address",
        "description": "Konverge POSTs one event per request, as JSON, within about a minute of the change, and waits 10 seconds for an answer. Redirects are not followed.\n\nCheck the signature before trusting the body: `Konverge-Signature: t=<unix seconds>,v1=<hex>` where `v1` = HMAC-SHA256(your secret, `<t>.<raw body>`). Compare in constant time and refuse a `t` more than 300 seconds from now. During a secret roll there are two `v1=` values; accept either.\n\nA failed delivery is retried 7 more times over about three days (5 minutes, 30 minutes, 2, 6, 12, 24 and 24 hours). Answer 410 Gone to unsubscribe a webhook made through the API.",
        "security": [],
        "parameters": [
          {
            "name": "Konverge-Signature",
            "in": "header",
            "required": true,
            "description": "`t=<unix seconds>,v1=<hex HMAC-SHA256>`.",
            "schema": {
              "type": "string"
            },
            "example": "t=1760000000,v1=5f2b…"
          },
          {
            "name": "Konverge-Event-Id",
            "in": "header",
            "required": true,
            "description": "The event's id (`evt_…`), the same on every retry: use it to ignore repeats.",
            "schema": {
              "type": "string"
            },
            "example": "evt_3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38"
          },
          {
            "name": "Konverge-Event-Type",
            "in": "header",
            "required": true,
            "description": "The event name, e.g. `task.created`.",
            "schema": {
              "type": "string"
            },
            "example": "task.created"
          },
          {
            "name": "Konverge-Delivery-Id",
            "in": "header",
            "required": true,
            "description": "This delivery attempt series.",
            "schema": {
              "type": "string"
            },
            "example": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received. Any 2xx answer counts; reply quickly and do the work afterwards."
          },
          "410": {
            "description": "Unsubscribe: a webhook made through the API is deleted and receives nothing more."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "kvg_live_… (production) or kvg_test_… (test) API key",
        "description": "An API key from Settings → Developers, sent as `Authorization: Bearer <key>`. Each key acts as its own account with the key's role, projects and scopes."
      }
    },
    "parameters": {
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "The record's id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Records per page, 1 to 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "`next_cursor` from the previous page (same list, same order). Opaque.",
        "schema": {
          "type": "string"
        }
      },
      "CreatedSince": {
        "name": "created_since",
        "in": "query",
        "description": "Only records created at or after this time (RFC 3339, or a date meaning midnight UTC).",
        "schema": {
          "type": "string"
        },
        "example": "2026-10-01T00:00:00Z"
      },
      "UpdatedSince": {
        "name": "updated_since",
        "in": "query",
        "description": "Only records changed at or after this time (RFC 3339, or a date meaning midnight UTC). Use it to sync changes.",
        "schema": {
          "type": "string"
        },
        "example": "2026-10-01T00:00:00Z"
      },
      "Search": {
        "name": "q",
        "in": "query",
        "description": "Case-insensitive text search across the resource's search fields (1 to 200 characters).",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Any unique string (1-255 visible ASCII characters; a UUID is ideal). Retrying with the same key and body within 24 hours returns the first result instead of acting twice.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "pattern": "^[\\x21-\\x7e]+$"
        }
      }
    },
    "headers": {
      "Request-Id": {
        "description": "This request's id (`req_…`). Quote it to support.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimit-Limit": {
        "description": "The key's bucket size for this kind of request (read or write).",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Remaining": {
        "description": "Requests left in the bucket right now.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Reset": {
        "description": "Seconds until the bucket is full again.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Limit": {
        "description": "The same as `RateLimit-Limit`, for clients that read the X- headers.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "The same as `RateLimit-Remaining`.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "The Unix time (seconds) at which the bucket is full again.",
        "schema": {
          "type": "integer"
        }
      },
      "Konverge-RateLimit-Scope": {
        "description": "Which bucket the rate headers describe: `key` (this key's own) or `plan` (the company's plan, shared by all its keys).",
        "schema": {
          "type": "string",
          "enum": [
            "key",
            "plan",
            "user"
          ]
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      },
      "Idempotent-Replayed": {
        "description": "`true` when this is the stored result of an earlier request with the same Idempotency-Key.",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      },
      "Location": {
        "description": "The new record's URL.",
        "schema": {
          "type": "string"
        }
      },
      "Allow": {
        "description": "The methods this path accepts.",
        "schema": {
          "type": "string"
        }
      },
      "WWW-Authenticate": {
        "description": "`Bearer realm=\"konverge-api\"`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "ErrorDetail": {
        "type": "object",
        "description": "One problem: with a field of the request, or with one record of a batch.",
        "required": [
          "message"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "The field or query parameter concerned."
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The record concerned (batches)."
          },
          "message": {
            "type": "string",
            "description": "What is wrong, in plain words."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "request_id"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "bad_request",
                  "unknown_filter",
                  "invalid_cursor",
                  "unauthenticated",
                  "insufficient_scope",
                  "forbidden",
                  "company_read_only",
                  "not_found",
                  "method_not_allowed",
                  "conflict",
                  "idempotency_key_reused",
                  "idempotency_in_progress",
                  "validation_failed",
                  "rate_limited",
                  "internal_error",
                  "api_not_configured",
                  "unavailable"
                ],
                "description": "Stable machine-readable code."
              },
              "message": {
                "type": "string",
                "description": "What happened and what to do, in plain words. Never database text."
              },
              "request_id": {
                "type": "string",
                "pattern": "^req_[0-9a-f]{24}$",
                "description": "Quote it to support. Same as the Request-Id header (on a replay: the original request's)."
              },
              "details": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ErrorDetail"
                }
              }
            }
          }
        }
      },
      "Deleted": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "id",
              "deleted"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "deleted": {
                "type": "boolean",
                "const": true
              }
            }
          }
        }
      },
      "RefResult": {
        "type": "object",
        "required": [
          "data"
        ],
        "description": "The id of the record the action created or changed (null when it has none).",
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              }
            }
          }
        }
      },
      "Me": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "key",
              "company",
              "rate_limits",
              "api_version"
            ],
            "properties": {
              "key": {
                "type": "object",
                "required": [
                  "id",
                  "name",
                  "display_key",
                  "environment",
                  "role",
                  "scopes",
                  "project_ids",
                  "expires_at"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "name": {
                    "type": "string"
                  },
                  "display_key": {
                    "type": "string",
                    "description": "The key's prefix and last 4 characters."
                  },
                  "environment": {
                    "type": "string",
                    "enum": [
                      "live",
                      "test"
                    ]
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "manager",
                      "member",
                      "viewer"
                    ]
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "records:read",
                        "records:write",
                        "records:delete",
                        "files:read",
                        "files:write",
                        "webhooks:manage"
                      ]
                    }
                  },
                  "project_ids": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "description": "The only projects this key sees and writes to; null = every project its role can see."
                  },
                  "expires_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  }
                }
              },
              "company": {
                "type": "object",
                "required": [
                  "id",
                  "name",
                  "currency_code"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "currency_code": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "ISO 4217; the currency of amounts that carry none."
                  }
                }
              },
              "rate_limits": {
                "type": "object",
                "required": [
                  "read_per_minute",
                  "write_per_minute"
                ],
                "properties": {
                  "read_per_minute": {
                    "type": "integer",
                    "description": "This key's own read allowance per minute."
                  },
                  "write_per_minute": {
                    "type": "integer",
                    "description": "This key's own write allowance per minute."
                  },
                  "plan": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "What the company's plan allows all its API keys together, per minute (null when it could not be read).",
                    "required": [
                      "band",
                      "read_per_minute",
                      "write_per_minute"
                    ],
                    "properties": {
                      "band": {
                        "type": "string",
                        "enum": [
                          "default",
                          "crew",
                          "company",
                          "enterprise"
                        ]
                      },
                      "read_per_minute": {
                        "type": "integer"
                      },
                      "write_per_minute": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "api_version": {
                "type": "string",
                "const": "v1"
              }
            }
          }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "title": "Webhook subscription",
        "description": "An https address Konverge sends events to, signed with the subscription's secret. It runs as the API key that made it: an event about a record that key cannot read is never sent.",
        "required": [
          "id",
          "target_url",
          "events",
          "description",
          "status",
          "disabled_reason",
          "display_secret",
          "last_delivery_at",
          "last_success_at",
          "last_failure_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "target_url": {
            "type": "string",
            "description": "Where Konverge POSTs each event (https, port 443, a public address)."
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^(\\*|[a-z_]+\\.(\\*|[a-z_]+))$"
            },
            "description": "Event names: `<object>.<verb>`, `<object>.*` or `*`. Objects: bid, bid_package, bill, change_order, client_payment, client_update, comment, compensation_event, contact, daily_log, delivery, early_warning, estimate, estimate_award, field_note, handover_pack, inbound_email, incident, inspection, instruction, location, material_request, meeting, milestone, ncr, payment_application, permit, po_receipt, project, project_allowance, project_contract, punch_item, purchase_order, rfi, schedule_baseline, selection_item, service_request, site_access_override, site_attendance, site_induction, subcontract, submittal, task, task_dependency, technical_query, transaction, workflow. Verbs: created, deleted, assigned, status_changed. An update that changes neither the status nor the assignee sends no event."
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ],
            "description": "A webhook is turned off when its API key is revoked or expires, or after 20 events in a row could not be delivered."
          },
          "disabled_reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "failing",
              "api_key_inactive",
              "disabled_by_user",
              null
            ]
          },
          "display_secret": {
            "type": [
              "string",
              "null"
            ],
            "description": "The signing secret's first characters and last 4, to tell secrets apart. Never the secret itself."
          },
          "last_delivery_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_success_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_failure_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "7d3c9f1a-2b4e-4c6d-8e5f-1a2b3c4d5e6f",
          "target_url": "https://hooks.example.com/konverge",
          "events": [
            "task.created",
            "task.status_changed"
          ],
          "description": "Tasks to the planning board",
          "status": "active",
          "disabled_reason": null,
          "display_secret": "whsec_…Xy9Q",
          "last_delivery_at": null,
          "last_success_at": null,
          "last_failure_at": null,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "WebhookSubscriptionCreate": {
        "type": "object",
        "title": "Subscribe an address to events",
        "additionalProperties": false,
        "required": [
          "target_url",
          "events"
        ],
        "properties": {
          "target_url": {
            "type": "string",
            "maxLength": 2048,
            "description": "Where to send events: https only, port 443, a public host (no private, loopback or cloud-metadata address, no user name or password in it)."
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": {
              "type": "string",
              "pattern": "^(\\*|[a-z_]+\\.(\\*|[a-z_]+))$"
            },
            "description": "What to send. Objects: bid, bid_package, bill, change_order, client_payment, client_update, comment, compensation_event, contact, daily_log, delivery, early_warning, estimate, estimate_award, field_note, handover_pack, inbound_email, incident, inspection, instruction, location, material_request, meeting, milestone, ncr, payment_application, permit, po_receipt, project, project_allowance, project_contract, punch_item, purchase_order, rfi, schedule_baseline, selection_item, service_request, site_access_override, site_attendance, site_induction, subcontract, submittal, task, task_dependency, technical_query, transaction, workflow. Verbs: created, deleted, assigned, status_changed. An update that changes neither the status nor the assignee sends no event."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200,
            "description": "A note to recognise the webhook by in Settings → Developers."
          }
        },
        "example": {
          "target_url": "https://hooks.example.com/konverge",
          "events": [
            "task.created",
            "task.status_changed"
          ],
          "description": "Tasks to the planning board"
        }
      },
      "WebhookSubscriptionCreated": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "id",
              "target_url",
              "events",
              "description",
              "status",
              "disabled_reason",
              "display_secret",
              "last_delivery_at",
              "last_success_at",
              "last_failure_at",
              "created_at",
              "updated_at",
              "secret"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "target_url": {
                "type": "string",
                "description": "Where Konverge POSTs each event (https, port 443, a public address)."
              },
              "events": {
                "type": "array",
                "items": {
                  "type": "string",
                  "pattern": "^(\\*|[a-z_]+\\.(\\*|[a-z_]+))$"
                },
                "description": "Event names: `<object>.<verb>`, `<object>.*` or `*`. Objects: bid, bid_package, bill, change_order, client_payment, client_update, comment, compensation_event, contact, daily_log, delivery, early_warning, estimate, estimate_award, field_note, handover_pack, inbound_email, incident, inspection, instruction, location, material_request, meeting, milestone, ncr, payment_application, permit, po_receipt, project, project_allowance, project_contract, punch_item, purchase_order, rfi, schedule_baseline, selection_item, service_request, site_access_override, site_attendance, site_induction, subcontract, submittal, task, task_dependency, technical_query, transaction, workflow. Verbs: created, deleted, assigned, status_changed. An update that changes neither the status nor the assignee sends no event."
              },
              "description": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": "string",
                "enum": [
                  "active",
                  "disabled"
                ],
                "description": "A webhook is turned off when its API key is revoked or expires, or after 20 events in a row could not be delivered."
              },
              "disabled_reason": {
                "type": [
                  "string",
                  "null"
                ],
                "enum": [
                  "failing",
                  "api_key_inactive",
                  "disabled_by_user",
                  null
                ]
              },
              "display_secret": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The signing secret's first characters and last 4, to tell secrets apart. Never the secret itself."
              },
              "last_delivery_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "last_success_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "last_failure_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              },
              "secret": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^whsec_[A-Za-z0-9_-]{43}$",
                "description": "The signing secret, shown this once (null on an Idempotency-Key replay). Verify every delivery's Konverge-Signature with it."
              }
            }
          }
        },
        "example": {
          "data": {
            "id": "7d3c9f1a-2b4e-4c6d-8e5f-1a2b3c4d5e6f",
            "target_url": "https://hooks.example.com/konverge",
            "events": [
              "task.created",
              "task.status_changed"
            ],
            "description": "Tasks to the planning board",
            "status": "active",
            "disabled_reason": null,
            "display_secret": "whsec_…Xy9Q",
            "last_delivery_at": null,
            "last_success_at": null,
            "last_failure_at": null,
            "created_at": "2026-10-04T09:30:00.000000+00:00",
            "updated_at": "2026-10-04T09:30:00.000000+00:00",
            "secret": "whsec_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
          }
        }
      },
      "WebhookSubscriptionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookSubscription"
          }
        }
      },
      "WebhookSubscriptionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookSubscription"
            }
          },
          "has_more": {
            "type": "boolean",
            "const": false,
            "description": "Always false: a company has at most 25 webhooks."
          },
          "next_cursor": {
            "type": "null"
          }
        }
      },
      "WebhookEvent": {
        "type": "object",
        "title": "Webhook event",
        "description": "What Konverge POSTs to a webhook's address. Deliveries are at least once: use `id` (also the Konverge-Event-Id header) to ignore repeats.",
        "required": [
          "id",
          "type",
          "api_version",
          "created_at",
          "company_id",
          "actor",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-9a-f-]{36}$"
          },
          "type": {
            "type": "string",
            "description": "`<object>.<verb>`, or `ping` for a test event."
          },
          "api_version": {
            "type": "string",
            "const": "v1"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "company_id": {
            "type": "string",
            "format": "uuid"
          },
          "actor": {
            "type": "object",
            "required": [
              "type",
              "id",
              "name"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "user",
                  "api_key",
                  "system"
                ]
              },
              "id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "data": {
            "type": "object",
            "required": [
              "object",
              "id",
              "project_id",
              "changes",
              "record"
            ],
            "properties": {
              "object": {
                "type": "string"
              },
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "project_id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "changes": {
                "type": "object",
                "description": "For status_changed: `{ \"status\": { \"from\", \"to\" } }`; for assigned: the assignee column's from / to."
              },
              "record": {
                "type": [
                  "object",
                  "null"
                ],
                "description": "The record as the API shows it, read when the event is sent, as the webhook's API key. Null after a delete."
              }
            }
          }
        },
        "example": {
          "id": "evt_3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "type": "task.status_changed",
          "api_version": "v1",
          "created_at": "2026-10-04T10:00:00Z",
          "company_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "actor": {
            "type": "user",
            "id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
            "name": "Sam Carter"
          },
          "data": {
            "object": "task",
            "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
            "changes": {
              "status": {
                "from": "open",
                "to": "done"
              }
            },
            "record": {
              "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
              "title": "Fix the fire door",
              "status": "done"
            }
          }
        }
      },
      "Task": {
        "type": "object",
        "title": "Task",
        "description": "A task on a project: what needs doing, its status and priority, who it is assigned to and when it is due.",
        "required": [
          "id",
          "title",
          "description",
          "status",
          "priority",
          "due_date",
          "assigned_to",
          "project_id",
          "created_at",
          "start_date",
          "progress",
          "parent_id",
          "wbs_code",
          "is_milestone",
          "location_id",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string",
            "description": "Title."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Status. Known values: pending, in_progress, completed, cancelled (more may be added)."
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "description": "Priority. Known values: low, medium, high, urgent (more may be added)."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          },
          "assigned_to": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Assigned to. Who the task is assigned to."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Start date. When the work starts (YYYY-MM-DD), or null. The due date is when it finishes."
          },
          "progress": {
            "type": [
              "number",
              "null"
            ],
            "description": "Progress. How far along the task is, 0 to 100 per cent."
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Under. The id of the summary task this one sits under in the programme's outline (WBS), or null for a top-level task. At most 6 levels."
          },
          "wbs_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "WBS. The task's outline number from its programme file, such as 1.2.3, or null."
          },
          "is_milestone": {
            "type": "boolean",
            "description": "Milestone. True for a zero-length key date on the programme."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The id of the project location (the `location` resource) the task is filed under, or null."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "title": "title",
          "description": "description",
          "status": "pending",
          "priority": "low",
          "due_date": "2026-10-05",
          "assigned_to": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "start_date": "2026-10-05",
          "progress": 1,
          "parent_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "wbs_code": "wbs code",
          "is_milestone": true,
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "TaskResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Task"
          }
        }
      },
      "TaskList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "TaskCreate": {
        "type": "object",
        "title": "New task",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_progress",
              "completed",
              "cancelled"
            ],
            "description": "Status.",
            "default": "pending"
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "urgent"
            ],
            "description": "Priority."
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "description": "Due date."
          },
          "assigned_to": {
            "type": "string",
            "format": "uuid",
            "description": "Assigned to. Who the task is assigned to. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "project_id",
          "title"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "title": "Example title"
        }
      },
      "TaskUpdate": {
        "type": "object",
        "title": "Changes to a task",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pending",
              "in_progress",
              "completed",
              "cancelled",
              null
            ],
            "description": "Status.",
            "default": "pending"
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              "urgent",
              null
            ],
            "description": "Priority."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          }
        },
        "minProperties": 1,
        "example": {
          "title": "Example title"
        }
      },
      "TaskSetStatusParams": {
        "type": "object",
        "title": "Change the task's status",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_progress",
              "completed",
              "cancelled"
            ],
            "description": "New status."
          }
        },
        "required": [
          "status"
        ],
        "example": {
          "status": "pending"
        }
      },
      "TaskAssignParams": {
        "type": "object",
        "title": "Assign the task to a team member",
        "additionalProperties": false,
        "properties": {
          "assigned_to": {
            "type": "string",
            "format": "uuid",
            "description": "Assign to. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "assigned_to"
        ],
        "example": {
          "assigned_to": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "TaskSetStatusBatchParams": {
        "type": "object",
        "title": "Change the task's status, for up to 20 at once",
        "additionalProperties": false,
        "properties": {
          "ids": {
            "type": "array",
            "description": "The ids of the records to act on (1 to 20, all visible to this key; if any is not, nothing is changed).",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_progress",
              "completed",
              "cancelled"
            ],
            "description": "New status."
          }
        },
        "required": [
          "ids",
          "status"
        ],
        "example": {
          "ids": [
            "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          ],
          "status": "pending"
        }
      },
      "TaskAssignBatchParams": {
        "type": "object",
        "title": "Assign the task to a team member, for up to 20 at once",
        "additionalProperties": false,
        "properties": {
          "ids": {
            "type": "array",
            "description": "The ids of the records to act on (1 to 20, all visible to this key; if any is not, nothing is changed).",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "assigned_to": {
            "type": "string",
            "format": "uuid",
            "description": "Assign to. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "ids",
          "assigned_to"
        ],
        "example": {
          "ids": [
            "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          ],
          "assigned_to": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "TaskRecords": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            }
          }
        }
      },
      "Project": {
        "type": "object",
        "title": "Project",
        "description": "A construction project. Its team is managed with the add_member, set_member_role and remove_member actions.",
        "required": [
          "id",
          "name",
          "description",
          "status",
          "address",
          "start_date",
          "end_date",
          "budget",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Status. Known values: planning, in_progress, on_hold, completed, cancelled (more may be added)."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Address."
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Start date."
          },
          "end_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "End date."
          },
          "budget": {
            "type": [
              "number",
              "null"
            ],
            "description": "Budget. An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "description": "description",
          "status": "planning",
          "address": "address",
          "start_date": "2026-10-05",
          "end_date": "2026-10-05",
          "budget": 1,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ProjectResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Project"
          }
        }
      },
      "ProjectList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ProjectCreate": {
        "type": "object",
        "title": "New project",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "address": {
            "type": "string",
            "maxLength": 10000,
            "description": "Address."
          },
          "status": {
            "type": "string",
            "enum": [
              "planning",
              "in_progress",
              "on_hold",
              "completed",
              "cancelled"
            ],
            "description": "Status."
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "Start date."
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "End date."
          },
          "budget": {
            "type": "number",
            "description": "Budget. An amount with at most 2 decimal places."
          }
        },
        "required": [
          "name"
        ],
        "example": {
          "name": "Example name"
        }
      },
      "ProjectUpdate": {
        "type": "object",
        "title": "Changes to a project",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Address."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "planning",
              "in_progress",
              "on_hold",
              "completed",
              "cancelled",
              null
            ],
            "description": "Status."
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Start date."
          },
          "end_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "End date."
          },
          "budget": {
            "type": [
              "number",
              "null"
            ],
            "description": "Budget. An amount with at most 2 decimal places."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "ProjectAddMemberParams": {
        "type": "object",
        "title": "Add a team member to the project",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          },
          "role": {
            "type": "string",
            "enum": [
              "manager",
              "supervisor",
              "member",
              "viewer"
            ],
            "description": "Project role.",
            "default": "member"
          }
        },
        "required": [
          "user_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "ProjectSetMemberRoleParams": {
        "type": "object",
        "title": "Change a member's role on the project",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          },
          "role": {
            "type": "string",
            "enum": [
              "manager",
              "supervisor",
              "member",
              "viewer"
            ],
            "description": "New role."
          }
        },
        "required": [
          "user_id",
          "role"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "role": "manager"
        }
      },
      "ProjectRemoveMemberParams": {
        "type": "object",
        "title": "Remove a member from the project",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "user_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "Milestone": {
        "type": "object",
        "title": "Milestone",
        "description": "A dated milestone on a project's programme.",
        "required": [
          "id",
          "name",
          "description",
          "status",
          "start_date",
          "due_date",
          "project_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "status": {
            "type": "string",
            "description": "Status. Known values: upcoming, in_progress, completed, missed (more may be added)."
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Start date."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "description": "description",
          "status": "upcoming",
          "start_date": "2026-10-05",
          "due_date": "2026-10-05",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "MilestoneResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Milestone"
          }
        }
      },
      "MilestoneList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Milestone"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "MilestoneCreate": {
        "type": "object",
        "title": "New milestone",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "status": {
            "type": "string",
            "enum": [
              "upcoming",
              "in_progress",
              "completed",
              "missed"
            ],
            "description": "Status."
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "Start date."
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "description": "Due date."
          }
        },
        "required": [
          "project_id",
          "name"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "Example name"
        }
      },
      "MilestoneUpdate": {
        "type": "object",
        "title": "Changes to a milestone",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "upcoming",
              "in_progress",
              "completed",
              "missed",
              null
            ],
            "description": "Status."
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Start date."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "ScheduleBaseline": {
        "type": "object",
        "title": "Schedule baseline",
        "description": "A captured copy of a project's programme: every task's start and finish at the moment it was captured, kept unchanged so the programme's slippage (variance) can be measured against it. Numbered per project; one baseline per project is the current one. Baselines are captured in the Konverge apps by owners, admins and managers and are never edited afterwards.",
        "required": [
          "id",
          "project_id",
          "number",
          "name",
          "note",
          "is_current",
          "task_count",
          "milestone_count",
          "start_date",
          "finish_date",
          "captured_by",
          "captured_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project whose programme was captured."
          },
          "number": {
            "type": "number",
            "description": "Number. The baseline's number on its project: 1, 2, 3 and so on."
          },
          "name": {
            "type": "string",
            "description": "Name. The baseline's name, such as Contract programme (1 to 80 characters)."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Note. Why it was captured, or null."
          },
          "is_current": {
            "type": "boolean",
            "description": "Current. True for the project's current baseline, the one variance is measured against by default."
          },
          "task_count": {
            "type": "number",
            "description": "Tasks. How many tasks (not cancelled) were captured."
          },
          "milestone_count": {
            "type": "number",
            "description": "Milestones. How many project milestones were captured."
          },
          "start_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Starts. The earliest start in the captured programme, or null."
          },
          "finish_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Finishes. The latest finish in the captured programme, or null."
          },
          "captured_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Captured by. The user id of the person who captured it."
          },
          "captured_at": {
            "type": "string",
            "format": "date-time",
            "description": "Captured. When it was captured."
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "number": 1,
          "name": "name",
          "note": "note",
          "is_current": true,
          "task_count": 1,
          "milestone_count": 1,
          "start_date": "2026-10-05",
          "finish_date": "2026-10-05",
          "captured_by": "captured by",
          "captured_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ScheduleBaselineResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ScheduleBaseline"
          }
        }
      },
      "ScheduleBaselineList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduleBaseline"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "TaskDependency": {
        "type": "object",
        "title": "Task link",
        "description": "A link between two tasks on the same project's programme: the successor waits for the predecessor. type is FS (finish-to-start: it starts when the other finishes), SS (start-to-start), FF (finish-to-finish) or SF (start-to-finish); lag_days (-365 to 365) adds days, or overlaps when negative. Links never form a loop. Links are made in the Konverge apps or by importing a programme.",
        "required": [
          "id",
          "project_id",
          "predecessor_id",
          "successor_id",
          "type",
          "lag_days",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project both tasks belong to."
          },
          "predecessor_id": {
            "type": "string",
            "format": "uuid",
            "description": "Waits for. The task the successor waits for (a task id)."
          },
          "successor_id": {
            "type": "string",
            "format": "uuid",
            "description": "Task. The task that waits (a task id)."
          },
          "type": {
            "type": "string",
            "description": "Type. FS finish-to-start, SS start-to-start, FF finish-to-finish or SF start-to-finish. Known values: FS, SS, FF, SF (more may be added)."
          },
          "lag_days": {
            "type": "number",
            "description": "Lag (days). Days added to the link, -365 to 365 (negative = overlap)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "predecessor_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "successor_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "type": "FS",
          "lag_days": 1,
          "created_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "TaskDependencyResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TaskDependency"
          }
        }
      },
      "TaskDependencyList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TaskDependency"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "Incident": {
        "type": "object",
        "title": "Incident",
        "description": "A safety or site incident report: an injury, near miss, damage, environmental or security event.",
        "required": [
          "id",
          "description",
          "incident_type",
          "incident_date",
          "location",
          "location_id",
          "status",
          "project_id",
          "created_at",
          "incident_time",
          "immediate_actions",
          "lost_time_incident",
          "days_lost",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "incident_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Type. Known values: injury, near_miss, property_damage, environmental, security, other (more may be added)."
          },
          "incident_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Date. The date the incident happened."
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Location."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Known values: open, investigating, resolved, closed (more may be added)."
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "incident_time": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?$",
            "description": "Time. Optional time, e.g. 14:30."
          },
          "immediate_actions": {
            "type": [
              "string",
              "null"
            ],
            "description": "Immediate actions."
          },
          "lost_time_incident": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Lost time."
          },
          "days_lost": {
            "type": [
              "number",
              "null"
            ],
            "description": "Days lost."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "description": "description",
          "incident_type": "injury",
          "incident_date": "2026-10-05",
          "location": "location",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "status": "open",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "incident_time": "14:30:00",
          "immediate_actions": "immediate actions",
          "lost_time_incident": true,
          "days_lost": 1,
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "IncidentResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Incident"
          }
        }
      },
      "IncidentList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Incident"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "IncidentCreate": {
        "type": "object",
        "title": "New incident",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "incident_type": {
            "type": "string",
            "enum": [
              "injury",
              "near_miss",
              "property_damage",
              "environmental",
              "security",
              "other"
            ],
            "description": "Type."
          },
          "incident_date": {
            "type": "string",
            "format": "date",
            "description": "Date. The date the incident happened."
          },
          "incident_time": {
            "type": "string",
            "maxLength": 10000,
            "description": "Time. Optional time, e.g. 14:30."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "location": {
            "type": "string",
            "maxLength": 10000,
            "description": "Location."
          },
          "immediate_actions": {
            "type": "string",
            "maxLength": 50000,
            "description": "Immediate actions."
          },
          "lost_time_incident": {
            "type": "boolean",
            "description": "Lost time."
          },
          "days_lost": {
            "type": "number",
            "description": "Days lost."
          }
        },
        "required": [
          "project_id",
          "incident_type",
          "incident_date",
          "description"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "incident_type": "injury",
          "incident_date": "2026-10-05",
          "description": "Example description"
        }
      },
      "IncidentSetStatusParams": {
        "type": "object",
        "title": "Change the incident's status",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "open",
              "investigating",
              "resolved",
              "closed"
            ],
            "description": "New status."
          }
        },
        "required": [
          "status"
        ],
        "example": {
          "status": "open"
        }
      },
      "Inspection": {
        "type": "object",
        "title": "Inspection",
        "description": "A site inspection run from one of the company's inspection templates (pass or fail checks). A new inspection starts from the template you name, or else the company's active template that matches its type.",
        "required": [
          "id",
          "inspection_number",
          "inspection_type",
          "status",
          "score_percentage",
          "pass_count",
          "fail_count",
          "location_id",
          "project_id",
          "created_at",
          "template_id",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "inspection_number": {
            "type": "string"
          },
          "inspection_type": {
            "type": "string",
            "description": "Type. e.g. safety walk, quality check, MEP rough-in."
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "score_percentage": {
            "type": [
              "number",
              "null"
            ]
          },
          "pass_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "fail_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Template. The id of the inspection template to run. Without it, the company's active template whose name or category matches the type is used."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "inspection_number": "inspection number",
          "inspection_type": "inspection type",
          "status": "status",
          "score_percentage": 1,
          "pass_count": 1,
          "fail_count": 1,
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "template_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "InspectionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Inspection"
          }
        }
      },
      "InspectionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Inspection"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "InspectionCreate": {
        "type": "object",
        "title": "New inspection",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "inspection_type": {
            "type": "string",
            "maxLength": 10000,
            "description": "Type. e.g. safety walk, quality check, MEP rough-in."
          },
          "template_id": {
            "type": "string",
            "maxLength": 10000,
            "description": "Template. The id of the inspection template to run. Without it, the company's active template whose name or category matches the type is used."
          }
        },
        "required": [
          "project_id"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "PunchList": {
        "type": "object",
        "title": "Punch list",
        "description": "A named list of snags (punch-list items) for an area or trade.",
        "required": [
          "id",
          "name",
          "punch_list_number",
          "description",
          "location",
          "status",
          "priority",
          "due_date",
          "total_items",
          "completed_items",
          "project_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "punch_list_number": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Location."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Status. Known values: open, in_progress, completed, verified (more may be added)."
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "description": "Priority. Known values: low, medium, high, critical (more may be added)."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          },
          "total_items": {
            "type": [
              "number",
              "null"
            ]
          },
          "completed_items": {
            "type": [
              "number",
              "null"
            ]
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "punch_list_number": "punch list number",
          "description": "description",
          "location": "location",
          "status": "open",
          "priority": "low",
          "due_date": "2026-10-05",
          "total_items": 1,
          "completed_items": 1,
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "PunchListResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PunchList"
          }
        }
      },
      "PunchListList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PunchList"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "PunchListCreate": {
        "type": "object",
        "title": "New punch list",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "location": {
            "type": "string",
            "maxLength": 10000,
            "description": "Location."
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ],
            "description": "Priority."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "in_progress",
              "completed",
              "verified"
            ],
            "description": "Status."
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "description": "Due date."
          }
        },
        "required": [
          "project_id",
          "name"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "Example name"
        }
      },
      "DailyLog": {
        "type": "object",
        "title": "Daily log",
        "description": "A daily site log: what was done on a project that day, the crew and the weather. One per project per day. A new log is a draft until it is submitted for approval; an approver then approves or rejects it.",
        "required": [
          "id",
          "work_summary",
          "log_date",
          "status",
          "crew_count",
          "weather_condition",
          "project_id",
          "created_at",
          "general_notes",
          "safety_notes",
          "delays",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "work_summary": {
            "type": [
              "string",
              "null"
            ],
            "description": "Work summary."
          },
          "log_date": {
            "type": "string",
            "format": "date",
            "description": "Date. The day the log covers (today in the company's time zone when left out). A project has one log per day."
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "crew_count": {
            "type": [
              "number",
              "null"
            ],
            "description": "Crew count. People on site; more than 0 when given."
          },
          "weather_condition": {
            "type": [
              "string",
              "null"
            ],
            "description": "Weather. Known values: sunny, cloudy, rainy, snowy, windy, mixed (more may be added)."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "general_notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes."
          },
          "safety_notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Safety notes."
          },
          "delays": {
            "type": [
              "string",
              "null"
            ],
            "description": "Delays."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "work_summary": "work summary",
          "log_date": "2026-10-05",
          "status": "status",
          "crew_count": 1,
          "weather_condition": "sunny",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "general_notes": "general notes",
          "safety_notes": "safety notes",
          "delays": "delays",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "DailyLogResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/DailyLog"
          }
        }
      },
      "DailyLogList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DailyLog"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "DailyLogCreate": {
        "type": "object",
        "title": "New daily log",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "log_date": {
            "type": "string",
            "format": "date",
            "description": "Date. The day the log covers (today in the company's time zone when left out). A project has one log per day."
          },
          "work_summary": {
            "type": "string",
            "maxLength": 50000,
            "description": "Work summary."
          },
          "crew_count": {
            "type": "number",
            "description": "Crew count. People on site; more than 0 when given."
          },
          "weather_condition": {
            "type": "string",
            "enum": [
              "sunny",
              "cloudy",
              "rainy",
              "snowy",
              "windy",
              "mixed"
            ],
            "description": "Weather."
          },
          "general_notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "required": [
          "project_id",
          "work_summary"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "work_summary": "Example work summary"
        }
      },
      "DailyLogUpdate": {
        "type": "object",
        "title": "Changes to a daily log",
        "additionalProperties": false,
        "properties": {
          "work_summary": {
            "type": "string",
            "maxLength": 50000,
            "description": "Work summary."
          },
          "crew_count": {
            "type": [
              "number",
              "null"
            ],
            "description": "Crew count. People on site; more than 0 when given."
          },
          "weather_condition": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "sunny",
              "cloudy",
              "rainy",
              "snowy",
              "windy",
              "mixed",
              null
            ],
            "description": "Weather."
          },
          "general_notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Notes."
          },
          "safety_notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Safety notes."
          },
          "delays": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Delays."
          }
        },
        "minProperties": 1,
        "example": {
          "work_summary": "Example work summary"
        }
      },
      "DailyLogSubmitParams": {
        "type": "object",
        "title": "Submit the daily log for approval",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "DailyLogApproveParams": {
        "type": "object",
        "title": "Approve the submitted daily log",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "DailyLogRejectParams": {
        "type": "object",
        "title": "Reject the submitted daily log",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 50000,
            "description": "Reason."
          }
        },
        "required": [
          "reason"
        ],
        "example": {
          "reason": "Example reason"
        }
      },
      "FieldNote": {
        "type": "object",
        "title": "Field note",
        "description": "A note from site: an observation, an issue, a question or something that needs action. It is acknowledged, then resolved, or turned into a follow-up task.",
        "required": [
          "id",
          "title",
          "content",
          "note_type",
          "status",
          "priority",
          "location_id",
          "project_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Title."
          },
          "content": {
            "type": "string",
            "description": "Note."
          },
          "note_type": {
            "type": "string",
            "description": "Type. Known values: observation, issue, question, action_required (more may be added)."
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "description": "Priority. Known values: low, medium, high (more may be added)."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "title": "title",
          "content": "content",
          "note_type": "observation",
          "status": "status",
          "priority": "low",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "FieldNoteResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/FieldNote"
          }
        }
      },
      "FieldNoteList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldNote"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "FieldNoteCreate": {
        "type": "object",
        "title": "New field note",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "note_type": {
            "type": "string",
            "enum": [
              "observation",
              "issue",
              "question",
              "action_required"
            ],
            "description": "Type.",
            "default": "observation"
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title."
          },
          "content": {
            "type": "string",
            "maxLength": 50000,
            "description": "Note."
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "description": "Priority."
          }
        },
        "required": [
          "project_id",
          "content"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "content": "Example note"
        }
      },
      "FieldNoteUpdate": {
        "type": "object",
        "title": "Changes to a field note",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Title."
          },
          "content": {
            "type": "string",
            "maxLength": 50000,
            "description": "Note."
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "medium",
              "high",
              null
            ],
            "description": "Priority."
          }
        },
        "minProperties": 1,
        "example": {
          "title": "Example title"
        }
      },
      "FieldNoteAcknowledgeParams": {
        "type": "object",
        "title": "Acknowledge the field note",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "FieldNoteResolveParams": {
        "type": "object",
        "title": "Resolve the field note",
        "additionalProperties": false,
        "properties": {
          "resolution_notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Resolution notes."
          }
        },
        "required": [
          "resolution_notes"
        ],
        "example": {
          "resolution_notes": "Example resolution notes"
        }
      },
      "FieldNoteToTaskParams": {
        "type": "object",
        "title": "Create a follow-up task from the field note",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "PunchItem": {
        "type": "object",
        "title": "Snag",
        "description": "A snag (punch-list item): a defect to put right, where it is and which trade owns it. A new snag goes on its project's punch list (one is started when the project has none). It is signed off as completed, rejected back to open, or turned into a follow-up task.",
        "required": [
          "id",
          "description",
          "location",
          "location_id",
          "trade",
          "status",
          "priority",
          "punch_list_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "description": {
            "type": "string",
            "description": "Description."
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Location."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "trade": {
            "type": [
              "string",
              "null"
            ],
            "description": "Trade."
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "description": "Priority. Known values: low, medium, high, critical (more may be added)."
          },
          "punch_list_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "description": "description",
          "location": "location",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "trade": "trade",
          "status": "status",
          "priority": "low",
          "punch_list_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "PunchItemResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PunchItem"
          }
        }
      },
      "PunchItemList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PunchItem"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "PunchItemCreate": {
        "type": "object",
        "title": "New snag",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project; the snag goes on its punch list. The id of a project in your company."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "location": {
            "type": "string",
            "maxLength": 10000,
            "description": "Location."
          },
          "trade": {
            "type": "string",
            "maxLength": 10000,
            "description": "Trade."
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ],
            "description": "Priority."
          }
        },
        "required": [
          "project_id",
          "description"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "description": "Example description"
        }
      },
      "PunchItemCompleteParams": {
        "type": "object",
        "title": "Mark the snag completed (sign-off)",
        "additionalProperties": false,
        "properties": {
          "resolution_notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Resolution notes."
          }
        },
        "example": {}
      },
      "PunchItemRejectParams": {
        "type": "object",
        "title": "Reject the completed snag back to open",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 50000,
            "description": "Reason."
          }
        },
        "required": [
          "reason"
        ],
        "example": {
          "reason": "Example reason"
        }
      },
      "PunchItemToTaskParams": {
        "type": "object",
        "title": "Create a follow-up task from the snag",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "PunchItemCompleteBatchParams": {
        "type": "object",
        "title": "Mark the snag completed (sign-off), for up to 20 at once",
        "additionalProperties": false,
        "properties": {
          "ids": {
            "type": "array",
            "description": "The ids of the records to act on (1 to 20, all visible to this key; if any is not, nothing is changed).",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "resolution_notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Resolution notes."
          }
        },
        "required": [
          "ids"
        ],
        "example": {
          "ids": [
            "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          ]
        }
      },
      "PunchItemRecords": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PunchItem"
            }
          }
        }
      },
      "Contact": {
        "type": "object",
        "title": "Contact",
        "description": "A party the company works with: a client, supplier, subcontractor or employee.",
        "required": [
          "id",
          "name",
          "contact_type",
          "phone",
          "email",
          "company_name",
          "city",
          "is_active",
          "current_balance",
          "created_at",
          "address",
          "opening_balance",
          "notes",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "contact_type": {
            "type": "string",
            "description": "Type. Known values: client, supplier, subcontractor, employee (more may be added)."
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Phone."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Email."
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company name."
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "description": "City."
          },
          "is_active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "current_balance": {
            "type": [
              "number",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "Address."
          },
          "opening_balance": {
            "type": [
              "number",
              "null"
            ],
            "description": "Opening balance. An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "contact_type": "client",
          "phone": "phone",
          "email": "email",
          "company_name": "company name",
          "city": "city",
          "is_active": true,
          "current_balance": 1,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "address": "address",
          "opening_balance": 1,
          "notes": "notes",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ContactResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Contact"
          }
        }
      },
      "ContactList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ContactCreate": {
        "type": "object",
        "title": "New contact",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "contact_type": {
            "type": "string",
            "enum": [
              "client",
              "supplier",
              "subcontractor",
              "employee"
            ],
            "description": "Type."
          },
          "phone": {
            "type": "string",
            "maxLength": 10000,
            "description": "Phone."
          },
          "email": {
            "type": "string",
            "maxLength": 10000,
            "description": "Email."
          },
          "address": {
            "type": "string",
            "maxLength": 10000,
            "description": "Address."
          },
          "city": {
            "type": "string",
            "maxLength": 10000,
            "description": "City."
          },
          "company_name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Company name."
          },
          "opening_balance": {
            "type": "number",
            "description": "Opening balance. An amount with at most 2 decimal places."
          },
          "notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "required": [
          "name",
          "contact_type"
        ],
        "example": {
          "name": "Example name",
          "contact_type": "client"
        }
      },
      "ContactUpdate": {
        "type": "object",
        "title": "Changes to a contact",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "contact_type": {
            "type": "string",
            "enum": [
              "client",
              "supplier",
              "subcontractor",
              "employee"
            ],
            "description": "Type."
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Phone."
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Email."
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Address."
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "City."
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Company name."
          },
          "opening_balance": {
            "type": [
              "number",
              "null"
            ],
            "description": "Opening balance. An amount with at most 2 decimal places."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "ContactToggleStatusParams": {
        "type": "object",
        "title": "Activate or deactivate the contact",
        "additionalProperties": false,
        "properties": {
          "is_active": {
            "type": "boolean",
            "description": "Active."
          }
        },
        "required": [
          "is_active"
        ],
        "example": {
          "is_active": true
        }
      },
      "Equipment": {
        "type": "object",
        "title": "Equipment",
        "description": "Plant, tools and vehicles, optionally assigned to a project.",
        "required": [
          "id",
          "name",
          "type",
          "model",
          "serial_number",
          "status",
          "project_id",
          "next_maintenance_date",
          "created_at",
          "purchase_date",
          "notes",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Type. Known values: plant, tool, vehicle, access, other (more may be added)."
          },
          "model": {
            "type": [
              "string",
              "null"
            ],
            "description": "Model."
          },
          "serial_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Serial number."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Status. Known values: available, in_use, maintenance, retired (more may be added)."
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project."
          },
          "next_maintenance_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Next maintenance."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "purchase_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Purchase date."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "type": "plant",
          "model": "model",
          "serial_number": "serial number",
          "status": "available",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "next_maintenance_date": "2026-10-05",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "purchase_date": "2026-10-05",
          "notes": "notes",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "EquipmentResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Equipment"
          }
        }
      },
      "EquipmentList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Equipment"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EquipmentCreate": {
        "type": "object",
        "title": "New equipment",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "type": {
            "type": "string",
            "enum": [
              "plant",
              "tool",
              "vehicle",
              "access",
              "other"
            ],
            "description": "Type."
          },
          "model": {
            "type": "string",
            "maxLength": 10000,
            "description": "Model."
          },
          "serial_number": {
            "type": "string",
            "maxLength": 10000,
            "description": "Serial number."
          },
          "status": {
            "type": "string",
            "enum": [
              "available",
              "in_use",
              "maintenance",
              "retired"
            ],
            "description": "Status."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "purchase_date": {
            "type": "string",
            "format": "date",
            "description": "Purchase date."
          },
          "next_maintenance_date": {
            "type": "string",
            "format": "date",
            "description": "Next maintenance."
          },
          "notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "required": [
          "name"
        ],
        "example": {
          "name": "Example name"
        }
      },
      "EquipmentUpdate": {
        "type": "object",
        "title": "Changes to equipment",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "plant",
              "tool",
              "vehicle",
              "access",
              "other",
              null
            ],
            "description": "Type."
          },
          "model": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Model."
          },
          "serial_number": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Serial number."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "available",
              "in_use",
              "maintenance",
              "retired",
              null
            ],
            "description": "Status."
          },
          "purchase_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Purchase date."
          },
          "next_maintenance_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Next maintenance."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "Transaction": {
        "type": "object",
        "title": "Transaction",
        "description": "A money record: an invoice, a payment in or out, an expense, a credit or debit note, or a material purchase, return or transfer. Every type can be created here.",
        "required": [
          "id",
          "transaction_number",
          "transaction_type",
          "amount",
          "currency",
          "status",
          "transaction_date",
          "due_date",
          "description",
          "from_party_id",
          "to_party_id",
          "project_id",
          "created_at",
          "payment_method",
          "notes",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "transaction_number": {
            "type": "string"
          },
          "transaction_type": {
            "type": "string",
            "description": "Type. Known values: payment_in, payment_out, expense, invoice, credit_note, debit_note, material_purchase, material_return, material_transfer, party_to_party (more may be added)."
          },
          "amount": {
            "type": "number",
            "description": "Amount. An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "transaction_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Date."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "from_party_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "From party. Who the money comes from (for payment_in: the payer)."
          },
          "to_party_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "To party. Who the money goes to (for payment_out/expense: the payee)."
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "payment_method": {
            "type": [
              "string",
              "null"
            ],
            "description": "Payment method. Known values: cash, cheque, bank_transfer, card, other (more may be added)."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "transaction_number": "transaction number",
          "transaction_type": "payment_in",
          "amount": 1,
          "currency": "currency",
          "status": "status",
          "transaction_date": "2026-10-05",
          "due_date": "2026-10-05",
          "description": "description",
          "from_party_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "to_party_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "payment_method": "cash",
          "notes": "notes",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "TransactionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Transaction"
          }
        }
      },
      "TransactionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "TransactionCreate": {
        "type": "object",
        "title": "New transaction",
        "additionalProperties": false,
        "properties": {
          "transaction_type": {
            "type": "string",
            "enum": [
              "payment_in",
              "payment_out",
              "expense",
              "invoice",
              "credit_note",
              "debit_note",
              "material_purchase",
              "material_return",
              "material_transfer",
              "party_to_party"
            ],
            "description": "Type."
          },
          "amount": {
            "type": "number",
            "description": "Amount. An amount with at most 2 decimal places."
          },
          "transaction_date": {
            "type": "string",
            "format": "date",
            "description": "Date."
          },
          "from_party_id": {
            "type": "string",
            "format": "uuid",
            "description": "From party. Who the money comes from (for payment_in: the payer). The id of a contact in your company."
          },
          "to_party_id": {
            "type": "string",
            "format": "uuid",
            "description": "To party. Who the money goes to (for payment_out/expense: the payee). The id of a contact in your company."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "cash",
              "cheque",
              "bank_transfer",
              "card",
              "other"
            ],
            "description": "Payment method."
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "description": "Due date."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "required": [
          "transaction_type",
          "amount",
          "transaction_date"
        ],
        "example": {
          "transaction_type": "payment_in",
          "amount": 1250.5,
          "transaction_date": "2026-10-05"
        }
      },
      "TransactionUpdate": {
        "type": "object",
        "title": "Changes to a transaction",
        "additionalProperties": false,
        "properties": {
          "transaction_type": {
            "type": "string",
            "enum": [
              "payment_in",
              "payment_out",
              "expense",
              "invoice",
              "credit_note",
              "debit_note",
              "material_purchase",
              "material_return",
              "material_transfer",
              "party_to_party"
            ],
            "description": "Type."
          },
          "amount": {
            "type": "number",
            "description": "Amount. An amount with at most 2 decimal places."
          },
          "transaction_date": {
            "type": "string",
            "format": "date",
            "description": "Date."
          },
          "payment_method": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "cash",
              "cheque",
              "bank_transfer",
              "card",
              "other",
              null
            ],
            "description": "Payment method."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "minProperties": 1,
        "example": {
          "transaction_type": "payment_in"
        }
      },
      "CostCode": {
        "type": "object",
        "title": "Cost code",
        "description": "A cost code for sorting spend (for example 03-300 Concrete).",
        "required": [
          "id",
          "code",
          "name",
          "category",
          "is_active",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "code": {
            "type": "string",
            "description": "Code."
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "description": "Category."
          },
          "is_active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "code": "code",
          "name": "name",
          "category": "category",
          "is_active": true,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "CostCodeResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CostCode"
          }
        }
      },
      "CostCodeList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CostCode"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "CostCodeCreate": {
        "type": "object",
        "title": "New cost code",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 10000,
            "description": "Code."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "category": {
            "type": "string",
            "maxLength": 10000,
            "description": "Category."
          }
        },
        "required": [
          "code",
          "name"
        ],
        "example": {
          "code": "Example code",
          "name": "Example name"
        }
      },
      "CostCodeUpdate": {
        "type": "object",
        "title": "Changes to a cost code",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 10000,
            "description": "Code."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Category."
          }
        },
        "minProperties": 1,
        "example": {
          "code": "Example code"
        }
      },
      "Estimate": {
        "type": "object",
        "title": "Estimate",
        "description": "A quotation or estimate for a client. Its lines are the estimate_items resource; the totals are worked out again whenever a line changes.",
        "required": [
          "id",
          "estimate_number",
          "party_id",
          "status",
          "subtotal",
          "tax_amount",
          "total_amount",
          "currency",
          "created_at",
          "project_id",
          "title",
          "revision_number",
          "notes",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_number": {
            "type": "string"
          },
          "party_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Client."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Known values: draft, sent, viewed, accepted, rejected, expired (more may be added)."
          },
          "subtotal": {
            "type": [
              "number",
              "null"
            ]
          },
          "tax_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "total_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project. The project the estimate is for, or null. Set when the estimate is awarded to a project."
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Title. The job name printed on the proposal (up to 200 characters), or null."
          },
          "revision_number": {
            "type": "number",
            "description": "Revision. 0 for the first issue; each revision adds one. A revision's estimate_number is the first issue's number followed by -R and this number (EST-2026-0012-R1), and the revision it replaced has status superseded."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "estimate_number": "estimate number",
          "party_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "status": "draft",
          "subtotal": 1,
          "tax_amount": 1,
          "total_amount": 1,
          "currency": "currency",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "title": "title",
          "revision_number": 1,
          "notes": "notes",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "EstimateResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Estimate"
          }
        }
      },
      "EstimateList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Estimate"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EstimateCreate": {
        "type": "object",
        "title": "New estimate",
        "additionalProperties": false,
        "properties": {
          "party_id": {
            "type": "string",
            "format": "uuid",
            "description": "Client. The id of a contact in your company."
          },
          "notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the estimate is for, or null. Set when the estimate is awarded to a project. The id of a project in your company."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title. The job name printed on the proposal (up to 200 characters), or null."
          },
          "revision_number": {
            "type": "number",
            "description": "Revision. 0 for the first issue; each revision adds one. A revision's estimate_number is the first issue's number followed by -R and this number (EST-2026-0012-R1), and the revision it replaced has status superseded."
          }
        },
        "required": [
          "party_id"
        ],
        "example": {
          "party_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "EstimateUpdate": {
        "type": "object",
        "title": "Changes to an estimate",
        "additionalProperties": false,
        "properties": {
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Notes."
          }
        },
        "minProperties": 1,
        "example": {
          "notes": "Example notes"
        }
      },
      "EstimateSetStatusParams": {
        "type": "object",
        "title": "Change the estimate's status (e.g. mark sent or accepted)",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "viewed",
              "accepted",
              "rejected",
              "expired"
            ],
            "description": "New status."
          }
        },
        "required": [
          "status"
        ],
        "example": {
          "status": "draft"
        }
      },
      "EstimateDuplicateParams": {
        "type": "object",
        "title": "Duplicate the estimate as a new draft",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "EstimateReviseParams": {
        "type": "object",
        "title": "Revise the estimate: a new draft revision (R1, R2, ...) replaces it, and this one becomes superseded",
        "additionalProperties": false,
        "properties": {
          "issue_date": {
            "type": "string",
            "format": "date",
            "description": "Issue date. The revision's issue date (YYYY-MM-DD); today when left out."
          }
        },
        "example": {}
      },
      "EstimateSaveAsTemplateParams": {
        "type": "object",
        "title": "Save a copy of the estimate as a reusable template",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Template name. The template's name (1-80 characters)."
          }
        },
        "required": [
          "name"
        ],
        "example": {
          "name": "Example template name"
        }
      },
      "EstimateFromTemplateParams": {
        "type": "object",
        "title": "Start a new draft estimate from one of the company's estimate templates",
        "additionalProperties": false,
        "properties": {
          "template": {
            "type": "string",
            "maxLength": 10000,
            "description": "Template. The estimate template to copy: its id, or its name (exact, capitals ignored)."
          },
          "party_id": {
            "type": "string",
            "format": "uuid",
            "description": "Client. The contact the new estimate is addressed to. The id of a contact in your company."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the estimate is for, or null. The id of a project in your company."
          },
          "issue_date": {
            "type": "string",
            "format": "date",
            "description": "Issue date. The new estimate's issue date (YYYY-MM-DD); today when left out."
          }
        },
        "required": [
          "template",
          "party_id"
        ],
        "example": {
          "template": "Example template",
          "party_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "EstimateItem": {
        "type": "object",
        "title": "Estimate line item",
        "description": "One line on an estimate. The estimate's totals are worked out again after every change.",
        "required": [
          "id",
          "estimate_id",
          "item_name",
          "description",
          "quantity",
          "unit",
          "rate",
          "amount",
          "created_at",
          "section_id",
          "option_id",
          "line_kind",
          "cost_code",
          "cost_item_id",
          "quantity_source",
          "tax_rate",
          "discount_percentage",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate."
          },
          "item_name": {
            "type": "string",
            "description": "Item."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "quantity": {
            "type": "number",
            "description": "Quantity."
          },
          "unit": {
            "type": [
              "string",
              "null"
            ],
            "description": "Unit."
          },
          "rate": {
            "type": "number",
            "description": "Rate. An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "amount": {
            "type": "number"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "section_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Section. The id of the estimate section (estimate_sections) the line is under, or null."
          },
          "option_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Option. The id of the option or alternate (estimate_options) the line belongs to, or null for the base offer. A line in an option counts towards the estimate's totals only while that option is selected."
          },
          "line_kind": {
            "type": "string",
            "description": "Kind. item, allowance (a provisional sum, adjusted to the actual selections), contingency (one per estimate, kept by Konverge from the estimate's contingency percentage) or note (words only: quantity, rate and amounts are always 0). Known values: item, allowance, contingency, note (more may be added)."
          },
          "cost_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cost code. The cost code the line is budgeted against (up to 40 characters), or null."
          },
          "cost_item_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Catalog item. The id of the cost catalog item the line was added from, or null."
          },
          "quantity_source": {
            "type": "string",
            "description": "Quantity from. Where the quantity comes from: manual (typed), takeoff (kept in step with measurements on a drawing while the estimate is a draft) or assembly (exploded from a catalog assembly). Known values: manual, takeoff, assembly (more may be added)."
          },
          "tax_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Tax %."
          },
          "discount_percentage": {
            "type": [
              "number",
              "null"
            ],
            "description": "Discount %."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "item_name": "item name",
          "description": "description",
          "quantity": 1,
          "unit": "unit",
          "rate": 1,
          "amount": 1,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "section_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "option_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "line_kind": "item",
          "cost_code": "cost code",
          "cost_item_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "quantity_source": "manual",
          "tax_rate": 1,
          "discount_percentage": 1,
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "EstimateItemResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/EstimateItem"
          }
        }
      },
      "EstimateItemList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EstimateItem"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EstimateItemCreate": {
        "type": "object",
        "title": "New estimate line item",
        "additionalProperties": false,
        "properties": {
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The id of an estimate in your company."
          },
          "item_name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Item."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          },
          "quantity": {
            "type": "number",
            "description": "Quantity."
          },
          "unit": {
            "type": "string",
            "maxLength": 10000,
            "description": "Unit."
          },
          "rate": {
            "type": "number",
            "description": "Rate. An amount with at most 2 decimal places."
          },
          "tax_rate": {
            "type": "number",
            "description": "Tax %."
          },
          "discount_percentage": {
            "type": "number",
            "description": "Discount %."
          }
        },
        "required": [
          "estimate_id",
          "item_name",
          "quantity",
          "rate"
        ],
        "example": {
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "item_name": "Example item",
          "quantity": 2,
          "rate": 1250.5
        }
      },
      "EstimateItemUpdate": {
        "type": "object",
        "title": "Changes to an estimate line item",
        "additionalProperties": false,
        "properties": {
          "item_name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Item."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          },
          "quantity": {
            "type": "number",
            "description": "Quantity."
          },
          "unit": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Unit."
          },
          "rate": {
            "type": "number",
            "description": "Rate. An amount with at most 2 decimal places."
          },
          "tax_rate": {
            "type": [
              "number",
              "null"
            ],
            "description": "Tax %."
          },
          "discount_percentage": {
            "type": [
              "number",
              "null"
            ],
            "description": "Discount %."
          }
        },
        "minProperties": 1,
        "example": {
          "item_name": "Example item"
        }
      },
      "Document": {
        "type": "object",
        "title": "Document",
        "description": "A project document (a specification, submittal, report and so on). Files are uploaded in the Konverge app; here you can rename documents, edit their description, delete them, send them for review, approve or reject them and comment on them.",
        "required": [
          "id",
          "name",
          "category",
          "discipline",
          "status",
          "drawing_number",
          "project_id",
          "folder_id",
          "created_at",
          "description",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "discipline": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "drawing_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Drawing number."
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "folder_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "category": "category",
          "discipline": "discipline",
          "status": "status",
          "drawing_number": "drawing number",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "folder_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "description": "description",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "DocumentResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Document"
          }
        }
      },
      "DocumentList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Document"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "DocumentUpdate": {
        "type": "object",
        "title": "Changes to a document",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          },
          "drawing_number": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Drawing number."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "DocumentSubmitReviewParams": {
        "type": "object",
        "title": "Submit the document for review",
        "additionalProperties": false,
        "properties": {
          "comment": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comment."
          }
        },
        "example": {}
      },
      "DocumentApproveParams": {
        "type": "object",
        "title": "Approve the document",
        "additionalProperties": false,
        "properties": {
          "comment": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comment."
          }
        },
        "example": {}
      },
      "DocumentRejectParams": {
        "type": "object",
        "title": "Reject the document",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 50000,
            "description": "Reason."
          }
        },
        "required": [
          "reason"
        ],
        "example": {
          "reason": "Example reason"
        }
      },
      "DocumentCommentParams": {
        "type": "object",
        "title": "Add a comment to the document",
        "additionalProperties": false,
        "properties": {
          "comment": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comment."
          }
        },
        "required": [
          "comment"
        ],
        "example": {
          "comment": "Example comment"
        }
      },
      "Folder": {
        "type": "object",
        "title": "Folder",
        "description": "A document folder within a project.",
        "required": [
          "id",
          "name",
          "description",
          "parent_folder_id",
          "project_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "parent_folder_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "description": "description",
          "parent_folder_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "FolderResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Folder"
          }
        }
      },
      "FolderList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Folder"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "FolderCreate": {
        "type": "object",
        "title": "New folder",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description."
          }
        },
        "required": [
          "project_id",
          "name"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "Example name"
        }
      },
      "FolderUpdate": {
        "type": "object",
        "title": "Changes to a folder",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "DrawingSheet": {
        "type": "object",
        "title": "Drawing sheet",
        "description": "A drawing sheet. New drawings and revisions are uploaded in the Konverge app; here you can read sheets, change a sheet's number or title, or delete one.",
        "required": [
          "id",
          "sheet_number",
          "sheet_name",
          "discipline",
          "revision",
          "is_current",
          "project_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sheet_number": {
            "type": "string",
            "description": "Sheet number."
          },
          "sheet_name": {
            "type": "string",
            "description": "Title."
          },
          "discipline": {
            "type": [
              "string",
              "null"
            ]
          },
          "revision": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_current": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "sheet_number": "sheet number",
          "sheet_name": "sheet name",
          "discipline": "discipline",
          "revision": "revision",
          "is_current": true,
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "DrawingSheetResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/DrawingSheet"
          }
        }
      },
      "DrawingSheetList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DrawingSheet"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "DrawingSheetUpdate": {
        "type": "object",
        "title": "Changes to a drawing sheet",
        "additionalProperties": false,
        "properties": {
          "sheet_name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Title."
          },
          "sheet_number": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Sheet number."
          }
        },
        "minProperties": 1,
        "example": {
          "sheet_name": "Example title"
        }
      },
      "Pin": {
        "type": "object",
        "title": "Drawing pin",
        "description": "An issue or note pinned to a spot on a drawing. Pins are placed on the drawing in the Konverge app; here you can change a pin's status, comment on it, turn it into a task or delete it.",
        "required": [
          "id",
          "pin_number",
          "title",
          "description",
          "status",
          "priority",
          "sheet_id",
          "project_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "pin_number": {
            "type": "number"
          },
          "title": {
            "type": "string",
            "description": "Title."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Known values: open, in_progress, completed, verified, rejected (more may be added)."
          },
          "priority": {
            "type": [
              "string",
              "null"
            ]
          },
          "sheet_id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "pin_number": 1,
          "title": "title",
          "description": "description",
          "status": "open",
          "priority": "priority",
          "sheet_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "PinResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Pin"
          }
        }
      },
      "PinList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Pin"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "PinSetStatusParams": {
        "type": "object",
        "title": "Change the pin's status",
        "additionalProperties": false,
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "open",
              "in_progress",
              "completed",
              "verified",
              "rejected"
            ],
            "description": "New status."
          }
        },
        "required": [
          "status"
        ],
        "example": {
          "status": "open"
        }
      },
      "PinCommentParams": {
        "type": "object",
        "title": "Add a comment to the pin",
        "additionalProperties": false,
        "properties": {
          "content": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comment."
          }
        },
        "required": [
          "content"
        ],
        "example": {
          "content": "Example comment"
        }
      },
      "PinToTaskParams": {
        "type": "object",
        "title": "Create a linked task from the pin",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "Workflow": {
        "type": "object",
        "title": "Approval workflow",
        "description": "A document review or approval workflow in progress. Workflows start in the Konverge app (each needs a template); here you can decide the current step, resubmit one that is on hold, or cancel it.",
        "required": [
          "id",
          "title",
          "status",
          "current_step",
          "project_id",
          "document_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "current_step": {
            "type": "number"
          },
          "project_id": {
            "type": "string",
            "format": "uuid"
          },
          "document_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "title": "title",
          "status": "status",
          "current_step": 1,
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "document_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "WorkflowResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Workflow"
          }
        }
      },
      "WorkflowList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Workflow"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "WorkflowTakeActionParams": {
        "type": "object",
        "title": "Approve / reject / request changes on the current step",
        "additionalProperties": false,
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "reject",
              "request_changes"
            ],
            "description": "Decision."
          },
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "required": [
          "action"
        ],
        "example": {
          "action": "approve"
        }
      },
      "WorkflowResubmitParams": {
        "type": "object",
        "title": "Resubmit an on-hold workflow",
        "additionalProperties": false,
        "properties": {
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "example": {}
      },
      "WorkflowCancelParams": {
        "type": "object",
        "title": "Cancel the workflow",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 50000,
            "description": "Reason."
          }
        },
        "example": {}
      },
      "WorkflowTakeActionBatchParams": {
        "type": "object",
        "title": "Approve / reject / request changes on the current step, for up to 20 at once",
        "additionalProperties": false,
        "properties": {
          "ids": {
            "type": "array",
            "description": "The ids of the records to act on (1 to 20, all visible to this key; if any is not, nothing is changed).",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "reject",
              "request_changes"
            ],
            "description": "Decision."
          },
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "required": [
          "ids",
          "action"
        ],
        "example": {
          "ids": [
            "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          ],
          "action": "approve"
        }
      },
      "WorkflowRecords": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Workflow"
            }
          }
        }
      },
      "Rfi": {
        "type": "object",
        "title": "RFI",
        "description": "A request for information: `title` is its subject, `description` the question and `workflow_number` its number. Here you can raise one (from a workflow template: template_id, or the company's only active RFI template), record the answer, comment, decide the current review step (one RFI, or up to 20 at once), resubmit or cancel.",
        "required": [
          "id",
          "workflow_number",
          "title",
          "status",
          "current_step",
          "ball_in_court",
          "due_date",
          "response_due_date",
          "spec_section",
          "cost_impact",
          "answer",
          "project_id",
          "document_id",
          "sheet_id",
          "created_at",
          "description",
          "template_id",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workflow_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Subject."
          },
          "status": {
            "type": "string"
          },
          "current_step": {
            "type": "number"
          },
          "ball_in_court": {
            "type": [
              "string",
              "null"
            ]
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "response_due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Response due."
          },
          "spec_section": {
            "type": [
              "string",
              "null"
            ],
            "description": "Spec section."
          },
          "cost_impact": {
            "type": [
              "string",
              "null"
            ]
          },
          "answer": {
            "type": [
              "string",
              "null"
            ]
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project."
          },
          "document_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "sheet_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Question."
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "description": "Workflow template. The id of the workflow template the RFI starts from. Optional when the company has exactly one active RFI template."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "workflow_number": "workflow number",
          "title": "title",
          "status": "status",
          "current_step": 1,
          "ball_in_court": "ball in court",
          "due_date": "2026-10-05",
          "response_due_date": "2026-10-04T09:30:00.000000+00:00",
          "spec_section": "spec section",
          "cost_impact": "cost impact",
          "answer": "answer",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "document_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "sheet_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "description": "description",
          "template_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "RfiResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Rfi"
          }
        }
      },
      "RfiList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rfi"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "RfiCreate": {
        "type": "object",
        "title": "New rfi",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The id of a project in your company."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Subject."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Question."
          },
          "spec_section": {
            "type": "string",
            "maxLength": 10000,
            "description": "Spec section."
          },
          "response_due_date": {
            "type": "string",
            "format": "date",
            "description": "Response due."
          },
          "template_id": {
            "type": "string",
            "maxLength": 10000,
            "description": "Workflow template. The id of the workflow template the RFI starts from. Optional when the company has exactly one active RFI template."
          }
        },
        "required": [
          "project_id"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "RfiAnswerParams": {
        "type": "object",
        "title": "Record the official answer/resolution for the RFI",
        "additionalProperties": false,
        "properties": {
          "answer": {
            "type": "string",
            "maxLength": 50000,
            "description": "Answer."
          }
        },
        "required": [
          "answer"
        ],
        "example": {
          "answer": "Example answer"
        }
      },
      "RfiCommentParams": {
        "type": "object",
        "title": "Add a comment to the RFI thread",
        "additionalProperties": false,
        "properties": {
          "content": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comment."
          }
        },
        "required": [
          "content"
        ],
        "example": {
          "content": "Example comment"
        }
      },
      "RfiTakeActionParams": {
        "type": "object",
        "title": "Approve / reject / request changes on the current review step",
        "additionalProperties": false,
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "reject",
              "request_changes"
            ],
            "description": "Decision."
          },
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "required": [
          "action"
        ],
        "example": {
          "action": "approve"
        }
      },
      "RfiResubmitParams": {
        "type": "object",
        "title": "Resubmit an on-hold RFI",
        "additionalProperties": false,
        "properties": {
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "example": {}
      },
      "RfiCancelParams": {
        "type": "object",
        "title": "Cancel the RFI",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 50000,
            "description": "Reason."
          }
        },
        "example": {}
      },
      "RfiTakeActionBatchParams": {
        "type": "object",
        "title": "Approve / reject / request changes on the current review step, for up to 20 at once",
        "additionalProperties": false,
        "properties": {
          "ids": {
            "type": "array",
            "description": "The ids of the records to act on (1 to 20, all visible to this key; if any is not, nothing is changed).",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "reject",
              "request_changes"
            ],
            "description": "Decision."
          },
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "required": [
          "ids",
          "action"
        ],
        "example": {
          "ids": [
            "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          ],
          "action": "approve"
        }
      },
      "RfiRecords": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rfi"
            }
          }
        }
      },
      "Conversation": {
        "type": "object",
        "title": "Conversation",
        "description": "A chat conversation: a direct chat or a named group. Post to it with the send action; add or remove people in a group with add_member and remove_member. Groups are started in the Konverge app.",
        "required": [
          "id",
          "name",
          "is_group",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Group name."
          },
          "is_group": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "is_group": true,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ConversationResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Conversation"
          }
        }
      },
      "ConversationList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Conversation"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ConversationSendParams": {
        "type": "object",
        "title": "Send a message to the conversation",
        "additionalProperties": false,
        "properties": {
          "content": {
            "type": "string",
            "maxLength": 50000,
            "description": "Message."
          }
        },
        "required": [
          "content"
        ],
        "example": {
          "content": "Example message"
        }
      },
      "ConversationAddMemberParams": {
        "type": "object",
        "title": "Add a member to the group",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "user_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "ConversationRemoveMemberParams": {
        "type": "object",
        "title": "Remove a member from the group",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "user_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "Invite": {
        "type": "object",
        "title": "Invite",
        "description": "An invite code a new person uses to join the company with the role it carries. The code, its expiry and how many times it can be used come back in the response.",
        "required": [
          "id",
          "role",
          "created_at",
          "code",
          "expires_at",
          "max_uses",
          "is_active",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "role": {
            "type": "string",
            "description": "Role. Known values: admin, manager, member, viewer, client (more may be added)."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "code": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "max_uses": {
            "type": [
              "number",
              "null"
            ]
          },
          "is_active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "role": "admin",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "code": "code",
          "expires_at": "2026-10-04T09:30:00.000000+00:00",
          "max_uses": 1,
          "is_active": true,
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "InviteResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Invite"
          }
        }
      },
      "InviteCreate": {
        "type": "object",
        "title": "New invite",
        "additionalProperties": false,
        "properties": {
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "manager",
              "member",
              "viewer",
              "client"
            ],
            "description": "Role.",
            "default": "member"
          },
          "expires_in_days": {
            "type": "number",
            "description": "Expires in (days).",
            "default": 7
          }
        },
        "example": {}
      },
      "CompanyMember": {
        "type": "object",
        "title": "Team member",
        "description": "A person's membership of the company and their role. Change someone's role, remove them from the company or change one of their permissions with the set_role, remove and set_permission actions, which take the person's user id.",
        "required": [
          "id",
          "user_id",
          "role",
          "is_active",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "role": {
            "type": "string"
          },
          "is_active": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "role": "role",
          "is_active": true,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "CompanyMemberResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CompanyMember"
          }
        }
      },
      "CompanyMemberSetRoleParams": {
        "type": "object",
        "title": "Change a team member's company role",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          },
          "role": {
            "type": "string",
            "enum": [
              "admin",
              "manager",
              "member",
              "viewer",
              "client"
            ],
            "description": "New role."
          }
        },
        "required": [
          "user_id",
          "role"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "role": "admin"
        }
      },
      "CompanyMemberRemoveParams": {
        "type": "object",
        "title": "Remove a member from the company",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          }
        },
        "required": [
          "user_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "CompanyMemberSetPermissionParams": {
        "type": "object",
        "title": "Toggle one permission for a team member",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          },
          "permission": {
            "type": "string",
            "enum": [
              "can_access_projects",
              "can_access_estimates",
              "can_access_documents",
              "can_access_contacts",
              "can_access_transactions",
              "can_access_field_ops",
              "can_access_reports",
              "can_access_settings",
              "can_access_team",
              "can_create",
              "can_edit",
              "can_delete"
            ],
            "description": "Permission."
          },
          "value": {
            "type": "boolean",
            "description": "Allowed."
          }
        },
        "required": [
          "user_id",
          "permission",
          "value"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "permission": "can_access_projects",
          "value": true
        }
      },
      "FolderAccess": {
        "type": "object",
        "title": "Folder access",
        "description": "Who may open a restricted document folder. Give one person access with grant and take it away with revoke.",
        "required": [
          "id",
          "member_id",
          "folder_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "member_id": {
            "type": "string",
            "format": "uuid"
          },
          "folder_id": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "member_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "folder_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "FolderAccessResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/FolderAccess"
          }
        }
      },
      "FolderAccessGrantParams": {
        "type": "object",
        "title": "Grant a member access to a folder",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          },
          "folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "Folder. The id of a folder in your company."
          }
        },
        "required": [
          "user_id",
          "folder_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "folder_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "FolderAccessRevokeParams": {
        "type": "object",
        "title": "Revoke a member's access to a folder",
        "additionalProperties": false,
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "description": "Member. The user id of an active team member (not an API key's account)."
          },
          "folder_id": {
            "type": "string",
            "format": "uuid",
            "description": "Folder. The id of a folder in your company."
          }
        },
        "required": [
          "user_id",
          "folder_id"
        ],
        "example": {
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "folder_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "Company": {
        "type": "object",
        "title": "Company",
        "description": "Your company's details: name, contact details, address and currency. update_details changes them.",
        "required": [
          "id",
          "name",
          "created_at",
          "email",
          "phone",
          "website",
          "address",
          "city",
          "currency_code",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "website": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "currency_code": {
            "type": "string"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "email": "email",
          "phone": "phone",
          "website": "website",
          "address": "address",
          "city": "city",
          "currency_code": "currency code",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "CompanyResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Company"
          }
        }
      },
      "CompanyUpdateDetailsParams": {
        "type": "object",
        "title": "Update the company's details",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name."
          },
          "email": {
            "type": "string",
            "maxLength": 10000,
            "description": "Email."
          },
          "phone": {
            "type": "string",
            "maxLength": 10000,
            "description": "Phone."
          },
          "website": {
            "type": "string",
            "maxLength": 10000,
            "description": "Website."
          },
          "address": {
            "type": "string",
            "maxLength": 10000,
            "description": "Address."
          },
          "city": {
            "type": "string",
            "maxLength": 10000,
            "description": "City."
          }
        },
        "example": {}
      },
      "Location": {
        "type": "object",
        "title": "Location",
        "description": "A place on a project: a site, building or block, level, zone, unit or plot, room or area, arranged as a tree (for example Block B > Level 3 > Flat 12). Snags, inspections, photos, field notes, incidents and tasks are filed under a location through their location_id. Each location's printed QR label opens https://getkonverge.com/l/{id}. Locations are set up in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "parent_id",
          "site_id",
          "kind",
          "name",
          "code",
          "full_name",
          "depth",
          "sort_order",
          "sheet_lineage_id",
          "sheet_region",
          "archived_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the location belongs to."
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Inside. The id of the location this one is inside, or null for a top-level location."
          },
          "site_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Site. The site (with its address, coordinates and geofence) the location's tree belongs to, when one is set."
          },
          "kind": {
            "type": "string",
            "description": "Kind. What sort of place it is: site, building, block, level, zone, unit, plot, room, area, external or other. Known values: site, building, block, level, zone, unit, plot, room, area, external, other (more may be added)."
          },
          "name": {
            "type": "string",
            "description": "Name. The location's own name, such as Level 3 or Flat 12 (1 to 80 characters)."
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Code. A short code, unique within the project (case-insensitive), such as B-L03-F12. Optional."
          },
          "full_name": {
            "type": "string",
            "description": "Full name. The names from the top of the tree down to this location, joined with \" › \" (Block B › Level 3 › Flat 12)."
          },
          "depth": {
            "type": "number",
            "description": "Depth. How deep the location sits: 0 for a top-level location, at most 7."
          },
          "sort_order": {
            "type": "number"
          },
          "sheet_lineage_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Floor plan. The drawing (by its lineage, so it follows new revisions) that shows this location, when one is linked."
          },
          "sheet_region": {},
          "archived_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Archived. When the location was archived (no longer offered for new records), or null while it is in use."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "parent_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "site_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "kind": "site",
          "name": "name",
          "code": "code",
          "full_name": "full name",
          "depth": 1,
          "sort_order": 1,
          "sheet_lineage_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "sheet_region": {},
          "archived_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "LocationResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Location"
          }
        }
      },
      "LocationList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Location"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "SiteInduction": {
        "type": "object",
        "title": "Site induction",
        "description": "A record that someone was inducted on a project: a team member (user_id), a contact such as a subcontractor's operative (contact_id), or a visitor (visitor_name); exactly one of the three is set. Inductions are made when the Site Induction form is signed in the Konverge apps (inspection_id is that form), or recorded by a manager. A person has at most one valid induction per project; it counts until expires_on (null = it does not expire) unless it is revoked. Read only.",
        "required": [
          "id",
          "project_id",
          "user_id",
          "contact_id",
          "visitor_name",
          "inducted_on",
          "expires_on",
          "inducted_by",
          "inspection_id",
          "status",
          "revoked_reason",
          "revoked_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the induction is for."
          },
          "user_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Team member. The team member who was inducted (a user id), or null for a contact or a visitor."
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Contact. The contact who was inducted, such as a subcontractor's operative, or null."
          },
          "visitor_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Visitor. The name of a visitor who was inducted without a Konverge account or contact record, or null."
          },
          "inducted_on": {
            "type": "string",
            "format": "date",
            "description": "Inducted on. The day the induction took place (YYYY-MM-DD)."
          },
          "expires_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Expires on. The last day the induction counts (YYYY-MM-DD), set from the project's site rules; null when it does not expire."
          },
          "inducted_by": {
            "type": "string",
            "description": "Inducted by. The user id of the person who carried out or recorded the induction."
          },
          "inspection_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Induction form. The signed Site Induction form (an inspection id) the induction came from, or null when recorded by hand."
          },
          "status": {
            "type": "string",
            "description": "Status. valid, or revoked (a manager withdrew it; revoked_reason says why). Known values: valid, revoked (more may be added)."
          },
          "revoked_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why revoked. Why the induction was revoked, or null while it is valid."
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "contact_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "visitor_name": "visitor name",
          "inducted_on": "2026-10-05",
          "expires_on": "2026-10-05",
          "inducted_by": "inducted by",
          "inspection_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "status": "valid",
          "revoked_reason": "revoked reason",
          "revoked_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "SiteInductionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SiteInduction"
          }
        }
      },
      "SiteInductionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SiteInduction"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "Permit": {
        "type": "object",
        "title": "Permit to work",
        "description": "A permit to work, numbered PTW-0001 per project: who may do which high-risk work (hot works, confined space, work at height, excavation, an electrical or mechanical isolation, a lifting operation, roof access, demolition or general), where, and between which times (at most 7 days). Its status moves draft → requested → issued, may be suspended and resumed, and ends handed back and closed, cancelled (before issue) or expired (when its time runs out). The API raises draft permits and sends them to be issued; a permit is issued, suspended, extended and closed with a signature in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "number",
          "permit_type",
          "type_label",
          "title",
          "description",
          "location_id",
          "location_text",
          "status",
          "valid_from",
          "valid_to",
          "requested_by",
          "issuer_id",
          "receiver_user_id",
          "receiver_contact_id",
          "receiver_name",
          "inspection_id",
          "fire_watch_until",
          "issued_at",
          "suspended_at",
          "suspended_reason",
          "handed_back_at",
          "handback_note",
          "closed_at",
          "closed_by",
          "cancelled_at",
          "cancelled_by",
          "cancel_reason",
          "created_by",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the permit is on."
          },
          "number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Number. The permit's number, PTW-0001 onwards within its project."
          },
          "permit_type": {
            "type": "string",
            "description": "Type. The kind of work: hot_works, confined_space, work_at_height, excavation, electrical_isolation, mechanical_isolation, lifting, roof_access, demolition, general or other. Known values: hot_works, confined_space, work_at_height, excavation, electrical_isolation, mechanical_isolation, lifting, roof_access, demolition, general, other (more may be added)."
          },
          "type_label": {
            "type": [
              "string",
              "null"
            ],
            "description": "Type (other). What kind of permit it is, in words, when permit_type is other; otherwise null."
          },
          "title": {
            "type": "string",
            "description": "Title. A short description of the work (1 to 160 characters)."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description. What the work is and how it will be done (up to 4,000 characters)."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The id of the project location (see location) where the work happens. Two live permits whose locations are the same or one inside the other are checked for clashing kinds of work before issue."
          },
          "location_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Location (text). Where the work happens, in words (the location's full name when one is chosen)."
          },
          "status": {
            "type": "string",
            "description": "Status. draft, requested, issued (work may go ahead within the window), suspended (work stopped), expired (its time ran out), closed (handed back and closed) or cancelled (before issue). Known values: draft, requested, issued, suspended, expired, closed, cancelled (more may be added)."
          },
          "valid_from": {
            "type": [
              "string",
              "null"
            ],
            "description": "Valid from. When the permit starts (RFC 3339). Proposed before issue, fixed at issue."
          },
          "valid_to": {
            "type": [
              "string",
              "null"
            ],
            "description": "Valid until. When the permit ends (RFC 3339); at most 7 days after valid_from. An extension moves it later."
          },
          "requested_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Requested by. The id of the person who sent the request to issue, or null."
          },
          "issuer_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Issued by. The id of the Authorised Person who issued and signed the permit, or null before issue."
          },
          "receiver_user_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Receiver. The id of the person in charge of the work who received the permit, when they are a member of the company."
          },
          "receiver_contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Receiver (contact). The id of the contact (for example a subcontractor's supervisor) who received the permit, when the receiver is a contact."
          },
          "receiver_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Receiver name. The receiver's name as printed on the permit."
          },
          "inspection_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Checklist. The id of the permit checklist: an inspection run of a Permit to Work form, completed before issue."
          },
          "fire_watch_until": {
            "type": [
              "string",
              "null"
            ],
            "description": "Fire watch until. Hot works only: when the fire watch after hand-back ends (RFC 3339). The permit closes after it."
          },
          "issued_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Issued. When the permit was issued (RFC 3339), or null."
          },
          "suspended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Suspended. When the work was stopped (RFC 3339) while the permit is suspended, or null."
          },
          "suspended_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why suspended. Why the work was stopped, while the permit is suspended."
          },
          "handed_back_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Handed back. When the receiver handed the permit back (work finished, area made safe), or null."
          },
          "handback_note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hand-back note. What the receiver wrote when handing the permit back."
          },
          "closed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Closed. When the permit was closed (RFC 3339), or null."
          },
          "closed_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Closed by. The id of the person who closed the permit, or null."
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Cancelled. When the permit was cancelled before issue (RFC 3339), or null."
          },
          "cancelled_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cancelled by. The id of the person who cancelled the permit, or null."
          },
          "cancel_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why cancelled. Why the permit was cancelled."
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Raised by. The id of the person who raised the permit."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "number": "number",
          "permit_type": "hot_works",
          "type_label": "type label",
          "title": "title",
          "description": "description",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "location_text": "location text",
          "status": "draft",
          "valid_from": "valid from",
          "valid_to": "valid to",
          "requested_by": "requested by",
          "issuer_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "receiver_user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "receiver_contact_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "receiver_name": "receiver name",
          "inspection_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "fire_watch_until": "fire watch until",
          "issued_at": "2026-10-04T09:30:00.000000+00:00",
          "suspended_at": "2026-10-04T09:30:00.000000+00:00",
          "suspended_reason": "suspended reason",
          "handed_back_at": "2026-10-04T09:30:00.000000+00:00",
          "handback_note": "handback note",
          "closed_at": "2026-10-04T09:30:00.000000+00:00",
          "closed_by": "closed by",
          "cancelled_at": "2026-10-04T09:30:00.000000+00:00",
          "cancelled_by": "cancelled by",
          "cancel_reason": "cancel reason",
          "created_by": "created by",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "PermitResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Permit"
          }
        }
      },
      "PermitList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permit"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "PermitCreate": {
        "type": "object",
        "title": "New permit to work",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the permit is on. The id of a project in your company."
          },
          "permit_type": {
            "type": "string",
            "enum": [
              "hot_works",
              "confined_space",
              "work_at_height",
              "excavation",
              "electrical_isolation",
              "mechanical_isolation",
              "lifting",
              "roof_access",
              "demolition",
              "general",
              "other"
            ],
            "description": "Type. The kind of work: hot_works, confined_space, work_at_height, excavation, electrical_isolation, mechanical_isolation, lifting, roof_access, demolition, general or other."
          },
          "type_label": {
            "type": "string",
            "maxLength": 10000,
            "description": "Type (other). What kind of permit it is, in words, when permit_type is other; otherwise null."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title. A short description of the work (1 to 160 characters)."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description. What the work is and how it will be done (up to 4,000 characters)."
          },
          "location_text": {
            "type": "string",
            "maxLength": 10000,
            "description": "Location (text). Where the work happens, in words (the location's full name when one is chosen)."
          },
          "valid_from": {
            "type": "string",
            "maxLength": 10000,
            "description": "Valid from. When the permit starts (RFC 3339). Proposed before issue, fixed at issue."
          },
          "valid_to": {
            "type": "string",
            "maxLength": 10000,
            "description": "Valid until. When the permit ends (RFC 3339); at most 7 days after valid_from. An extension moves it later."
          },
          "receiver_name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Receiver name. The receiver's name as printed on the permit."
          }
        },
        "required": [
          "project_id",
          "permit_type",
          "title"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "permit_type": "hot_works",
          "title": "Example title"
        }
      },
      "PermitRequestParams": {
        "type": "object",
        "title": "Send a draft permit to an Authorised Person to issue (a permit request)",
        "additionalProperties": false,
        "properties": {},
        "example": {}
      },
      "Delivery": {
        "type": "object",
        "title": "Delivery",
        "description": "A delivery to a project's site, numbered DEL-0001 per project: the supplier, the purchase order it is against, the booked day, time window, gate and location, the vehicle, and, once it arrives, when it was received, by whom, its condition and the outcome (received in full, part received or rejected). Receiving a delivery in the Konverge apps records the proof of delivery and posts the purchase order's receipts.",
        "required": [
          "id",
          "project_id",
          "number",
          "status",
          "supplier_contact_id",
          "supplier_name",
          "supplier_ref",
          "purchase_order_id",
          "expected_on",
          "window_start",
          "window_end",
          "gate",
          "location_id",
          "vehicle_reg",
          "driver_name",
          "carrier",
          "arrived_at",
          "received_at",
          "received_by",
          "condition",
          "notes",
          "cancelled_reason",
          "created_by",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the delivery is for."
          },
          "number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Number. The delivery's number within its project, such as DEL-0007. Set by Konverge when it is created."
          },
          "status": {
            "type": "string",
            "description": "Status. booked (expected), arrived (at the gate), received (all of it), part_received (some of it, or less than expected), rejected (refused at the gate) or cancelled. Known values: booked, arrived, received, part_received, rejected, cancelled (more may be added)."
          },
          "supplier_contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Supplier. The supplier's contact, when the delivery names one (from the purchase order when it has one)."
          },
          "supplier_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Supplier name. The supplier's name as typed, for a supplier who is not a contact (up to 120 characters)."
          },
          "supplier_ref": {
            "type": [
              "string",
              "null"
            ],
            "description": "Delivery note number. The number on the supplier's delivery note, when it was recorded (up to 100 characters)."
          },
          "purchase_order_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Purchase order. The id of the purchase order the delivery is against, on the same project, or null."
          },
          "expected_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Expected on. The day the delivery is booked for (YYYY-MM-DD), or null when it was not booked ahead."
          },
          "window_start": {
            "type": [
              "string",
              "null"
            ],
            "description": "Window from. The start of the booked time window (HH:MM:SS, site time), or null."
          },
          "window_end": {
            "type": [
              "string",
              "null"
            ],
            "description": "Window to. The end of the booked time window (HH:MM:SS, site time), or null."
          },
          "gate": {
            "type": [
              "string",
              "null"
            ],
            "description": "Gate. The gate or drop-off point the delivery is booked into (up to 80 characters)."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The project location the delivery is for, such as a block or a laydown area, or null."
          },
          "vehicle_reg": {
            "type": [
              "string",
              "null"
            ],
            "description": "Vehicle registration. The delivering vehicle's registration, in capitals (up to 16 characters)."
          },
          "driver_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Driver. The driver's name (up to 80 characters)."
          },
          "carrier": {
            "type": [
              "string",
              "null"
            ],
            "description": "Carrier. The haulier or carrier, when it is not the supplier (up to 80 characters)."
          },
          "arrived_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Arrived. When the delivery was marked as having arrived (RFC 3339), or null."
          },
          "received_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Received. When the delivery was received (RFC 3339), or null until it is."
          },
          "received_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Received by. The id of the person who received the delivery, or null until it is received."
          },
          "condition": {
            "type": [
              "string",
              "null"
            ],
            "description": "Condition. The condition it arrived in: good, damaged, short or mixed. Null until it is received. Known values: good, damaged, short, mixed (more may be added)."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes. Notes about the delivery: what was wrong with it, where it was put (up to 2,000 characters)."
          },
          "cancelled_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why cancelled. Why the delivery was cancelled, when a reason was given."
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "number": "number",
          "status": "booked",
          "supplier_contact_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "supplier_name": "supplier name",
          "supplier_ref": "supplier ref",
          "purchase_order_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "expected_on": "2026-10-05",
          "window_start": "window start",
          "window_end": "window end",
          "gate": "gate",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "vehicle_reg": "vehicle reg",
          "driver_name": "driver name",
          "carrier": "carrier",
          "arrived_at": "2026-10-04T09:30:00.000000+00:00",
          "received_at": "2026-10-04T09:30:00.000000+00:00",
          "received_by": "received by",
          "condition": "good",
          "notes": "notes",
          "cancelled_reason": "cancelled reason",
          "created_by": "created by",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "DeliveryResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Delivery"
          }
        }
      },
      "DeliveryList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Delivery"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "DeliveryCreate": {
        "type": "object",
        "title": "New delivery",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the delivery is for. The id of a project in your company."
          },
          "supplier_contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Supplier. The supplier's contact, when the delivery names one (from the purchase order when it has one). The id of a contact in your company."
          },
          "supplier_name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Supplier name. The supplier's name as typed, for a supplier who is not a contact (up to 120 characters)."
          },
          "supplier_ref": {
            "type": "string",
            "maxLength": 10000,
            "description": "Delivery note number. The number on the supplier's delivery note, when it was recorded (up to 100 characters)."
          },
          "purchase_order_id": {
            "type": "string",
            "maxLength": 10000,
            "description": "Purchase order. The id of the purchase order the delivery is against, on the same project, or null."
          },
          "expected_on": {
            "type": "string",
            "format": "date",
            "description": "Expected on. The day the delivery is booked for (YYYY-MM-DD), or null when it was not booked ahead."
          },
          "window_start": {
            "type": "string",
            "maxLength": 10000,
            "description": "Window from. The start of the booked time window (HH:MM:SS, site time), or null."
          },
          "window_end": {
            "type": "string",
            "maxLength": 10000,
            "description": "Window to. The end of the booked time window (HH:MM:SS, site time), or null."
          },
          "gate": {
            "type": "string",
            "maxLength": 10000,
            "description": "Gate. The gate or drop-off point the delivery is booked into (up to 80 characters)."
          },
          "vehicle_reg": {
            "type": "string",
            "maxLength": 10000,
            "description": "Vehicle registration. The delivering vehicle's registration, in capitals (up to 16 characters)."
          },
          "driver_name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Driver. The driver's name (up to 80 characters)."
          },
          "carrier": {
            "type": "string",
            "maxLength": 10000,
            "description": "Carrier. The haulier or carrier, when it is not the supplier (up to 80 characters)."
          },
          "notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes. Notes about the delivery: what was wrong with it, where it was put (up to 2,000 characters)."
          }
        },
        "required": [
          "project_id"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "MaterialRequest": {
        "type": "object",
        "title": "Material request",
        "description": "A request from site for materials, numbered MR-0001 per project: a title, the day it is needed by and its items. It is submitted for approval, approved or rejected (with a reason), and an approved request becomes a draft purchase order (purchase_order_id); it then follows that order's deliveries to delivered.",
        "required": [
          "id",
          "project_id",
          "number",
          "title",
          "status",
          "needed_by",
          "location_id",
          "requested_by",
          "submitted_at",
          "decided_by",
          "decided_at",
          "rejected_reason",
          "cancelled_reason",
          "purchase_order_id",
          "notes",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the materials are for."
          },
          "number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Number. The request's number within its project, such as MR-0003. Set by Konverge when it is created."
          },
          "title": {
            "type": "string",
            "description": "Title. A short title for what is needed (1 to 160 characters)."
          },
          "status": {
            "type": "string",
            "description": "Status. draft, submitted (waiting for approval), approved, rejected, ordered (a purchase order was made from it), part_delivered, delivered or cancelled. Known values: draft, submitted, approved, rejected, ordered, part_delivered, delivered, cancelled (more may be added)."
          },
          "needed_by": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Needed by. The day the materials are needed on site (YYYY-MM-DD), or null."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The project location the materials are for, or null."
          },
          "requested_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Requested by. The id of the person who raised the request."
          },
          "submitted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Submitted. When the request was last submitted for approval (RFC 3339), or null."
          },
          "decided_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Decided by. The id of the person who approved or rejected it, or null."
          },
          "decided_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Decided. When it was approved or rejected (RFC 3339), or null."
          },
          "rejected_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why rejected. Why the request was rejected, when it was."
          },
          "cancelled_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "purchase_order_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Purchase order. The id of the draft purchase order made from the request, once it is ordered."
          },
          "notes": {
            "type": [
              "string",
              "null"
            ],
            "description": "Notes. Notes for the buyer (up to 2,000 characters)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "number": "number",
          "title": "title",
          "status": "draft",
          "needed_by": "2026-10-05",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "requested_by": "requested by",
          "submitted_at": "2026-10-04T09:30:00.000000+00:00",
          "decided_by": "decided by",
          "decided_at": "2026-10-04T09:30:00.000000+00:00",
          "rejected_reason": "rejected reason",
          "cancelled_reason": "cancelled reason",
          "purchase_order_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "notes": "notes",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "MaterialRequestResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MaterialRequest"
          }
        }
      },
      "MaterialRequestList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MaterialRequest"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "MaterialRequestCreate": {
        "type": "object",
        "title": "New material request",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the materials are for. The id of a project in your company."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title. A short title for what is needed (1 to 160 characters)."
          },
          "needed_by": {
            "type": "string",
            "format": "date",
            "description": "Needed by. The day the materials are needed on site (YYYY-MM-DD), or null."
          },
          "notes": {
            "type": "string",
            "maxLength": 50000,
            "description": "Notes. Notes for the buyer (up to 2,000 characters)."
          }
        },
        "required": [
          "project_id",
          "title"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "title": "Example title"
        }
      },
      "MaterialRequestSubmitParams": {
        "type": "object",
        "title": "Send a material request for approval, adding its items first when they are given",
        "additionalProperties": false,
        "properties": {
          "items": {
            "type": "string",
            "maxLength": 50000,
            "description": "Items. Items to add to the request before it is submitted, one per line: the quantity first, then an optional unit, then what is needed (for example \"20 bags cement\"). Optional when the request already has items; a request with no items can't be submitted."
          }
        },
        "example": {}
      },
      "Meeting": {
        "type": "object",
        "title": "Meeting",
        "description": "A project meeting and its minutes: when (scheduled_start, scheduled_end) and where, who chairs it and who takes the minutes, and where it stands (status): scheduled, in progress, minutes written but not issued, minutes issued, or cancelled. Meetings in a series (series_id) are numbered from 1. Each time the minutes are issued, issued_version goes up by one and every open action owned by a team member becomes a task assigned to them. The API schedules meetings; they are minuted and issued in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "series_id",
          "number",
          "meeting_type",
          "title",
          "scheduled_start",
          "scheduled_end",
          "location_text",
          "location_id",
          "online_url",
          "status",
          "chair_id",
          "minute_taker_id",
          "summary",
          "issued_version",
          "issued_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the meeting is about."
          },
          "series_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Series. The id of the recurring meeting series (for example the weekly progress meeting), or null for a one-off meeting."
          },
          "number": {
            "type": [
              "number",
              "null"
            ],
            "description": "Number. The meeting's number within its series (1, 2, 3), or null for a one-off meeting."
          },
          "meeting_type": {
            "type": "string",
            "description": "Type. What sort of meeting it is: progress, site, design, pre_start, safety, client, subcontractor or other. Known values: progress, site, design, pre_start, safety, client, subcontractor, other (more may be added)."
          },
          "title": {
            "type": "string",
            "description": "Title. The meeting's title (1 to 160 characters)."
          },
          "scheduled_start": {
            "type": "string",
            "description": "Starts. When the meeting starts (RFC 3339, UTC)."
          },
          "scheduled_end": {
            "type": [
              "string",
              "null"
            ],
            "description": "Ends. When the meeting ends (RFC 3339, UTC), or null when no end time was set."
          },
          "location_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where. Where the meeting is held, in words (for example Site cabin), or null."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The project location the meeting is held at, when one is chosen (see the locations resource)."
          },
          "online_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Online link. The https link to join the meeting online, or null."
          },
          "status": {
            "type": "string",
            "description": "Status. Where the meeting stands: scheduled; in_progress; minutes written but not issued yet; issued (the minutes were sent and are read-only); or cancelled. The exact values are listed in the schema. Known values: scheduled, in_progress, draft_minutes, issued, cancelled (more may be added)."
          },
          "chair_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Chair. The user id of the person chairing the meeting, or null."
          },
          "minute_taker_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Minute taker. The user id of the person taking the minutes, or null."
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "description": "Summary. A short summary of the meeting written with the minutes (up to 20,000 characters), or null."
          },
          "issued_version": {
            "type": "number",
            "description": "Issued version. How many times the minutes have been issued: 0 until they are first issued, then 1, 2 and so on."
          },
          "issued_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Issued. When the minutes were last issued (RFC 3339, UTC), or null if they never were."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "series_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "number": 1,
          "meeting_type": "progress",
          "title": "title",
          "scheduled_start": "scheduled start",
          "scheduled_end": "scheduled end",
          "location_text": "location text",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "online_url": "online url",
          "status": "scheduled",
          "chair_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "minute_taker_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "summary": "summary",
          "issued_version": 1,
          "issued_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "MeetingResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Meeting"
          }
        }
      },
      "MeetingList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Meeting"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "MeetingCreate": {
        "type": "object",
        "title": "New meeting",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the meeting is about. The id of a project in your company."
          },
          "meeting_type": {
            "type": "string",
            "enum": [
              "progress",
              "site",
              "design",
              "pre_start",
              "safety",
              "client",
              "subcontractor",
              "other"
            ],
            "description": "Type. What sort of meeting it is: progress, site, design, pre_start, safety, client, subcontractor or other."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title. The meeting's title (1 to 160 characters)."
          },
          "scheduled_start": {
            "type": "string",
            "maxLength": 10000,
            "description": "Starts. When the meeting starts (RFC 3339, UTC)."
          },
          "scheduled_end": {
            "type": "string",
            "maxLength": 10000,
            "description": "Ends. When the meeting ends (RFC 3339, UTC), or null when no end time was set."
          },
          "location_text": {
            "type": "string",
            "maxLength": 10000,
            "description": "Where. Where the meeting is held, in words (for example Site cabin), or null."
          },
          "online_url": {
            "type": "string",
            "maxLength": 10000,
            "description": "Online link. The https link to join the meeting online, or null."
          }
        },
        "required": [
          "project_id",
          "title",
          "scheduled_start"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "title": "Example title",
          "scheduled_start": "Example starts"
        }
      },
      "Submittal": {
        "type": "object",
        "title": "Submittal",
        "description": "A submittal under review: `title` says what is submitted, `workflow_number` is its number, `status` where it stands (active, on_hold when changes were asked for, completed, cancelled) and `outcome` how it ended (approved, approved_with_comments, rejected, for_information, cancelled). `ball_in_court` is the person it is waiting on; a parallel review (engine_version 2) has several places, listed as workflow_step records. Here you can start one (from a workflow template: template_id, or the company's only active submittal template), decide the review (one submittal, or up to 20 at once), resubmit or cancel.",
        "required": [
          "id",
          "project_id",
          "workflow_number",
          "workflow_type",
          "title",
          "status",
          "outcome",
          "priority",
          "ball_in_court",
          "current_step",
          "round",
          "engine_version",
          "due_date",
          "response_due_date",
          "spec_section",
          "review_outcome_code",
          "initiated_by",
          "initiated_at",
          "completed_at",
          "document_id",
          "created_at",
          "updated_at",
          "description",
          "template_id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the submittal is on."
          },
          "workflow_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "workflow_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Title. What is being submitted."
          },
          "status": {
            "type": "string"
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ]
          },
          "ball_in_court": {
            "type": [
              "string",
              "null"
            ]
          },
          "current_step": {
            "type": "number"
          },
          "round": {
            "type": "number"
          },
          "engine_version": {
            "type": "number"
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due. When the review is due (a date)."
          },
          "response_due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "spec_section": {
            "type": [
              "string",
              "null"
            ],
            "description": "Spec section. The specification section it answers."
          },
          "review_outcome_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "initiated_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "initiated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "document_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description. More about the submittal."
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "description": "Workflow template. The id of the workflow template the submittal starts from. Optional when the company has exactly one active submittal template."
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "workflow_number": "workflow number",
          "workflow_type": "workflow type",
          "title": "title",
          "status": "status",
          "outcome": "outcome",
          "priority": "priority",
          "ball_in_court": "ball in court",
          "current_step": 1,
          "round": 1,
          "engine_version": 1,
          "due_date": "2026-10-05",
          "response_due_date": "2026-10-04T09:30:00.000000+00:00",
          "spec_section": "spec section",
          "review_outcome_code": "review outcome code",
          "initiated_by": "initiated by",
          "initiated_at": "2026-10-04T09:30:00.000000+00:00",
          "completed_at": "2026-10-04T09:30:00.000000+00:00",
          "document_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00",
          "description": "description",
          "template_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "SubmittalResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Submittal"
          }
        }
      },
      "SubmittalList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Submittal"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "SubmittalCreate": {
        "type": "object",
        "title": "New submittal",
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the submittal is on. The id of a project in your company."
          },
          "title": {
            "type": "string",
            "maxLength": 10000,
            "description": "Title. What is being submitted."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description. More about the submittal."
          },
          "spec_section": {
            "type": "string",
            "maxLength": 10000,
            "description": "Spec section. The specification section it answers."
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "description": "Due. When the review is due (a date)."
          },
          "template_id": {
            "type": "string",
            "maxLength": 10000,
            "description": "Workflow template. The id of the workflow template the submittal starts from. Optional when the company has exactly one active submittal template."
          }
        },
        "required": [
          "project_id"
        ],
        "example": {
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
        }
      },
      "SubmittalTakeActionParams": {
        "type": "object",
        "title": "Approve / reject / request changes on the current review step",
        "additionalProperties": false,
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "reject",
              "request_changes"
            ],
            "description": "Decision."
          },
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "required": [
          "action"
        ],
        "example": {
          "action": "approve"
        }
      },
      "SubmittalResubmitParams": {
        "type": "object",
        "title": "Resubmit a submittal sent back for changes",
        "additionalProperties": false,
        "properties": {
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "example": {}
      },
      "SubmittalCancelParams": {
        "type": "object",
        "title": "Cancel the submittal",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 50000,
            "description": "Reason."
          }
        },
        "example": {}
      },
      "SubmittalTakeActionBatchParams": {
        "type": "object",
        "title": "Approve / reject / request changes on the current review step, for up to 20 at once",
        "additionalProperties": false,
        "properties": {
          "ids": {
            "type": "array",
            "description": "The ids of the records to act on (1 to 20, all visible to this key; if any is not, nothing is changed).",
            "minItems": 1,
            "maxItems": 20,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "action": {
            "type": "string",
            "enum": [
              "approve",
              "reject",
              "request_changes"
            ],
            "description": "Decision."
          },
          "comments": {
            "type": "string",
            "maxLength": 50000,
            "description": "Comments."
          }
        },
        "required": [
          "ids",
          "action"
        ],
        "example": {
          "ids": [
            "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
            "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54"
          ],
          "action": "approve"
        }
      },
      "SubmittalRecords": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Submittal"
            }
          }
        }
      },
      "WorkflowStep": {
        "type": "object",
        "title": "Workflow place",
        "description": "One place on a parallel workflow review (engine 2): `instance_id` is the workflow (an rfi, submittal or workflow record), `step_number` and `group_no` the step and the group of steps that open together, `round` goes up each time the workflow is resubmitted or routed back. `state` is waiting, open, decided, skipped, superseded (the group finished without it) or cancelled. The holder is `holder_user_id`, or anyone with `holder_role` or in the project organisation `holder_organisation_id`. Read only.",
        "required": [
          "id",
          "instance_id",
          "project_id",
          "round",
          "step_number",
          "group_no",
          "seat",
          "name",
          "step_type",
          "holder_user_id",
          "holder_role",
          "holder_organisation_id",
          "state",
          "decision",
          "outcome_code",
          "outcome_meaning",
          "decided_by",
          "decided_at",
          "decided_on_behalf_of",
          "opened_at",
          "due_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "instance_id": {
            "type": "string",
            "format": "uuid",
            "description": "Workflow. The id of the workflow this place belongs to."
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the workflow is on."
          },
          "round": {
            "type": "number"
          },
          "step_number": {
            "type": "number"
          },
          "group_no": {
            "type": "number"
          },
          "seat": {
            "type": "number"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "step_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "holder_user_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "holder_role": {
            "type": [
              "string",
              "null"
            ]
          },
          "holder_organisation_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "state": {
            "type": "string"
          },
          "decision": {
            "type": [
              "string",
              "null"
            ]
          },
          "outcome_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "outcome_meaning": {
            "type": [
              "string",
              "null"
            ]
          },
          "decided_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "decided_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "decided_on_behalf_of": {
            "type": [
              "string",
              "null"
            ]
          },
          "opened_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "instance_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "round": 1,
          "step_number": 1,
          "group_no": 1,
          "seat": 1,
          "name": "name",
          "step_type": "step type",
          "holder_user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "holder_role": "holder role",
          "holder_organisation_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "state": "state",
          "decision": "decision",
          "outcome_code": "outcome code",
          "outcome_meaning": "outcome meaning",
          "decided_by": "decided by",
          "decided_at": "2026-10-04T09:30:00.000000+00:00",
          "decided_on_behalf_of": "decided on behalf of",
          "opened_at": "2026-10-04T09:30:00.000000+00:00",
          "due_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "WorkflowStepResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WorkflowStep"
          }
        }
      },
      "WorkflowStepList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowStep"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ProjectContract": {
        "type": "object",
        "title": "Contract",
        "description": "A contract on a project: its form (NEC4 ECC, ECS or PSC; JCT Design and Build, Standard, Intermediate or Minor Works; AIA A201; or other), which side your company is on, the organisation notices go to, the starting and completion dates, and the contract data the notice clocks read (the period for reply, the notification period, the reply and quotation periods and deemed acceptance). Konverge tracks the periods in the contract data; it is not legal advice.",
        "required": [
          "id",
          "project_id",
          "title",
          "reference",
          "form",
          "main_option",
          "our_role",
          "counterparty_organisation_id",
          "is_primary",
          "starting_date",
          "completion_date",
          "period_for_reply_days",
          "notification_bar_weeks",
          "reply_to_notification_days",
          "quotation_days",
          "reply_to_quotation_days",
          "deemed_acceptance",
          "deemed_acceptance_notice_days",
          "clocks_on",
          "currency",
          "created_by",
          "created_at",
          "updated_at",
          "archived_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the contract is on."
          },
          "title": {
            "type": "string",
            "description": "Title. The contract's name (1 to 120 characters)."
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reference. The contract's own number or reference, when one was entered."
          },
          "form": {
            "type": "string",
            "description": "Form. The form of contract: nec4_ecc, nec4_ecs, nec4_psc, jct_db, jct_sbc, jct_ic, jct_mw, aia_a201 or other. Known values: nec4_ecc, nec4_ecs, nec4_psc, jct_db, jct_sbc, jct_ic, jct_mw, aia_a201, other (more may be added)."
          },
          "main_option": {
            "type": [
              "string",
              "null"
            ],
            "description": "Main option. The NEC main option letter (A to G), or null for any other form."
          },
          "our_role": {
            "type": "string",
            "description": "Our side. Which side of the contract your company is on: contractor, employer, subcontractor or consultant. Known values: contractor, employer, subcontractor, consultant (more may be added)."
          },
          "counterparty_organisation_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Counterparty. The id of the project organisation the notices go to (the Project Manager, Architect or Owner side), or null."
          },
          "is_primary": {
            "type": "boolean",
            "description": "Primary. True for the project's main contract (new notices use it unless told otherwise)."
          },
          "starting_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Starting date. The contract's starting date (YYYY-MM-DD), if entered."
          },
          "completion_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Completion date. The contract's completion date (YYYY-MM-DD), if entered."
          },
          "period_for_reply_days": {
            "type": [
              "number",
              "null"
            ],
            "description": "Period for reply (days). Contract data: the days a party has to reply to a communication (NEC4 13.3)."
          },
          "notification_bar_weeks": {
            "type": [
              "number",
              "null"
            ],
            "description": "Notification period (weeks). Contract data: the weeks within which a compensation event must be notified after becoming aware (NEC4 61.3); null = none."
          },
          "reply_to_notification_days": {
            "type": [
              "number",
              "null"
            ],
            "description": "Reply to a notification (days). Contract data: the days to reply to a notified compensation event (NEC4 61.4)."
          },
          "quotation_days": {
            "type": [
              "number",
              "null"
            ],
            "description": "Quotation (days). Contract data: the days to submit a quotation once instructed (NEC4 62.3)."
          },
          "reply_to_quotation_days": {
            "type": [
              "number",
              "null"
            ],
            "description": "Reply to a quotation (days). Contract data: the days to reply to a quotation (NEC4 62.3)."
          },
          "deemed_acceptance": {
            "type": "boolean",
            "description": "Deemed acceptance. Contract data: whether a failure to reply, once notified, is treated as acceptance after a further period (NEC4 61.4, 62.6)."
          },
          "deemed_acceptance_notice_days": {
            "type": [
              "number",
              "null"
            ],
            "description": "Deemed acceptance (days). Contract data: the days after a failure notice before deemed acceptance."
          },
          "clocks_on": {
            "type": "boolean",
            "description": "Clocks on. False when the notice clocks are switched off for this contract."
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "Currency. The contract's currency as a three-letter code (GBP, USD …)."
          },
          "created_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Created by. The id of the person who set the contract up."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Created. When the contract was set up."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Updated. When the contract was last changed."
          },
          "archived_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Archived. When the contract was archived, or null while it is live."
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "title": "title",
          "reference": "reference",
          "form": "nec4_ecc",
          "main_option": "main option",
          "our_role": "contractor",
          "counterparty_organisation_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "is_primary": true,
          "starting_date": "2026-10-05",
          "completion_date": "2026-10-05",
          "period_for_reply_days": 1,
          "notification_bar_weeks": 1,
          "reply_to_notification_days": 1,
          "quotation_days": 1,
          "reply_to_quotation_days": 1,
          "deemed_acceptance": true,
          "deemed_acceptance_notice_days": 1,
          "clocks_on": true,
          "currency": "currency",
          "created_by": "created by",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00",
          "archived_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ProjectContractResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ProjectContract"
          }
        }
      },
      "ProjectContractList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProjectContract"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ContractEvent": {
        "type": "object",
        "title": "Contract notice",
        "description": "A contract notice on a project, run as a workflow: a technical query, an early warning, a compensation event, an instruction or a non-conformance report (filter by workflow_type). It carries the contract data and the clocks Konverge computes from the contract (the notification period, the reply and quotation periods and deemed acceptance, with the clause number) and the clock state. Amounts are never included. Konverge tracks the periods in the contract data; it is not legal advice.",
        "required": [
          "id",
          "project_id",
          "workflow_number",
          "workflow_type",
          "title",
          "status",
          "outcome",
          "priority",
          "ball_in_court",
          "current_step",
          "round",
          "initiated_by",
          "initiated_at",
          "completed_at",
          "updated_at",
          "contract_id",
          "clause",
          "raised_by_party",
          "aware_on",
          "event_date",
          "notified_on",
          "replied_on",
          "reply_due_on",
          "quotation_due_on",
          "assessment_due_on",
          "deemed_accepted_on",
          "time_bar_on",
          "next_due_on",
          "clock_state",
          "ew_status",
          "ew_likelihood",
          "ew_impacts",
          "instruction_kind",
          "ncr_severity",
          "ncr_disposition",
          "location_id",
          "closed_on"
        ],
        "properties": {
          "id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project. The project the notice is on."
          },
          "workflow_number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Number. The notice's number within its project: TQ-001, EW-001, CE-001, NCR-001, PMI-001 and so on."
          },
          "workflow_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Register. Which register it is in: technical_query, early_warning, compensation_event, instruction or ncr. Known values: technical_query, early_warning, compensation_event, instruction, ncr (more may be added)."
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Title. A short description of the notice."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Status. The workflow's status: active, on_hold, completed or cancelled."
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ],
            "description": "Outcome. How it ended (approved, approved_with_comments, rejected, for_information, cancelled), or null while open."
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "description": "Priority. low, normal, high or urgent."
          },
          "ball_in_court": {
            "type": [
              "string",
              "null"
            ],
            "description": "With. The id of the person it is waiting on, or null."
          },
          "current_step": {
            "type": [
              "number",
              "null"
            ],
            "description": "Current step. The step number it is at."
          },
          "round": {
            "type": [
              "number",
              "null"
            ],
            "description": "Round. How many times it has gone round (a revised quotation starts a new round)."
          },
          "initiated_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Raised by. The id of the person who raised it."
          },
          "initiated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Raised. When it was raised."
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Completed. When its workflow ended, or null."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Updated. When it last changed."
          },
          "contract_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Contract. The id of the contract (project_contract) whose data drives its clocks, or null."
          },
          "clause": {
            "type": [
              "string",
              "null"
            ],
            "description": "Clause. The clause it relies on, as a short reference (for example 60.1(12)); no clause text."
          },
          "raised_by_party": {
            "type": [
              "string",
              "null"
            ],
            "description": "Raised by (party). Which side raised it: contractor, pm, employer, architect, supervisor, client or other."
          },
          "aware_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Aware on. The day the party became aware of the event (starts the notification period)."
          },
          "event_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Event date. The day the event happened, if known."
          },
          "notified_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Notified on. The day it was notified or raised."
          },
          "replied_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Replied on. The day the other side replied (to a compensation event's notification or a technical query)."
          },
          "reply_due_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Reply due. The day the reply is due (the reply to a notification, or the period for reply)."
          },
          "quotation_due_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Quotation due. A compensation event's quotation due day."
          },
          "assessment_due_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Reply to quotation due. The day the reply to a compensation event's quotation is due."
          },
          "deemed_accepted_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Deemed accepted on. The day it is treated as accepted after a notified failure to reply (never applied by itself)."
          },
          "time_bar_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Notify by. The last day to notify a compensation event under the contract's notification period."
          },
          "next_due_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Next due. The earliest due day of a clock still running."
          },
          "clock_state": {
            "type": [
              "string",
              "null"
            ],
            "description": "Clock state. The most urgent clock: none, running, warning (due within 7 days), overdue, deemed_accepted, time_barred or closed. Known values: none, running, warning, overdue, deemed_accepted, time_barred, closed (more may be added)."
          },
          "ew_status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Early warning status. An early warning's status: open, mitigated, closed or became_ce; null for other registers."
          },
          "ew_likelihood": {
            "type": [
              "string",
              "null"
            ],
            "description": "Likelihood. An early warning's likelihood: low, medium or high."
          },
          "ew_impacts": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            },
            "description": "Impacts. An early warning's impacts: any of cost, time, quality, safety and performance."
          },
          "instruction_kind": {
            "type": [
              "string",
              "null"
            ],
            "description": "Instruction kind. An instruction's kind: pmi, ai, si, ei, asi, ccd or other."
          },
          "ncr_severity": {
            "type": [
              "string",
              "null"
            ],
            "description": "Severity. An NCR's severity: minor, major or critical."
          },
          "ncr_disposition": {
            "type": [
              "string",
              "null"
            ],
            "description": "Disposition. An NCR's disposition: rework, repair, use_as_is, reject or concession."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The id of the project location it concerns, or null."
          },
          "closed_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Closed on. The day an NCR was closed out or an early warning closed."
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "workflow_number": "workflow number",
          "workflow_type": "technical_query",
          "title": "title",
          "status": "status",
          "outcome": "outcome",
          "priority": "priority",
          "ball_in_court": "ball in court",
          "current_step": 1,
          "round": 1,
          "initiated_by": "initiated by",
          "initiated_at": "2026-10-04T09:30:00.000000+00:00",
          "completed_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00",
          "contract_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "clause": "clause",
          "raised_by_party": "raised by party",
          "aware_on": "2026-10-05",
          "event_date": "2026-10-05",
          "notified_on": "2026-10-05",
          "replied_on": "2026-10-05",
          "reply_due_on": "2026-10-05",
          "quotation_due_on": "2026-10-05",
          "assessment_due_on": "2026-10-05",
          "deemed_accepted_on": "2026-10-05",
          "time_bar_on": "2026-10-05",
          "next_due_on": "2026-10-05",
          "clock_state": "none",
          "ew_status": "ew status",
          "ew_likelihood": "ew likelihood",
          "ew_impacts": [],
          "instruction_kind": "instruction kind",
          "ncr_severity": "ncr severity",
          "ncr_disposition": "ncr disposition",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "closed_on": "2026-10-05"
        }
      },
      "ContractEventResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ContractEvent"
          }
        }
      },
      "ContractEventList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ContractEvent"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "InboundEmail": {
        "type": "object",
        "title": "Received email",
        "description": "An email that arrived for a project: a reply by email to an RFI, submittal, approval or meeting action (route reply, added to that item as a comment) or a message sent to the project's own inbox address (route project). Lists who sent it, when, its subject, how many files came with it and where it was filed; the message text is not included. Mail from an unknown or unverified sender is held for a person to check and is visible only to owners, admins and managers. Received email is managed in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "route",
          "status",
          "sender_status",
          "from_email",
          "from_name",
          "subject",
          "received_at",
          "attachment_count",
          "entity_type",
          "entity_id",
          "filed_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project. The project the email arrived for, or null for a reply to an item that is not on a project."
          },
          "route": {
            "type": "string",
            "description": "Arrived as. How it arrived: reply (a reply to an item email), project (sent to the project's inbox address) or unknown. Known values: reply, project, unknown (more may be added)."
          },
          "status": {
            "type": "string",
            "description": "Status. Where it stands: received (in the project inbox), filed (added to an item or filed into folders), held (waiting for a person to check the sender), refused (over a limit), dropped (an automatic reply or a loop) or released (a held email a person accepted). Known values: received, filed, held, refused, dropped, released (more may be added)."
          },
          "sender_status": {
            "type": "string",
            "description": "Sender. Who the sender is to the project: token_match (the person the item email went to), member (someone on the team), contact (a contact on the project), org_domain (an address at a project firm's domain), unknown, or mismatch (someone other than the person the item email went to). Known values: token_match, member, contact, org_domain, unknown, mismatch (more may be added)."
          },
          "from_email": {
            "type": [
              "string",
              "null"
            ],
            "description": "From. The sender's email address (lower case)."
          },
          "from_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "From (name). The sender's display name, or null."
          },
          "subject": {
            "type": [
              "string",
              "null"
            ],
            "description": "Subject. The subject line (up to 300 characters), or null."
          },
          "received_at": {
            "type": "string",
            "format": "date-time",
            "description": "Received. When it arrived (RFC 3339, UTC)."
          },
          "attachment_count": {
            "type": "number",
            "description": "Files. How many files came with it, including any that were not kept (programs, archives and similar are refused)."
          },
          "entity_type": {
            "type": [
              "string",
              "null"
            ],
            "description": "Filed as. The kind of record it was added to or filed as: workflow (an RFI, submittal or approval), meeting_item or service_request; null when not filed that way."
          },
          "entity_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Filed on. The id of the record it was added to or filed as, or null."
          },
          "filed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Filed. When it was filed (RFC 3339, UTC), or null."
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "route": "reply",
          "status": "received",
          "sender_status": "token_match",
          "from_email": "from email",
          "from_name": "from name",
          "subject": "subject",
          "received_at": "2026-10-04T09:30:00.000000+00:00",
          "attachment_count": 1,
          "entity_type": "entity type",
          "entity_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "filed_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "InboundEmailResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/InboundEmail"
          }
        }
      },
      "InboundEmailList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InboundEmail"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "BidPackage": {
        "type": "object",
        "title": "Bid package",
        "description": "A package of work put out to subcontractors for prices. `status` is the package's own state (open, closed, awarded); `tender_status` is its tender's: draft until issued to the bidders through private links, then issued, closed at the return deadline (late returns are refused), awarded, or withdrawn. Prices are not included. Tenders are issued and awarded in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "name",
          "status",
          "tender_status",
          "due_date",
          "returns_due_at",
          "accept_by",
          "issued_at",
          "awarded_bid_id",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project. The project the package is for, or null for a package tendered before a project exists."
          },
          "name": {
            "type": "string",
            "description": "Name. The package's name, such as \"Groundworks and drainage\"."
          },
          "status": {
            "type": "string",
            "description": "Package status. open (taking bids), closed (no more bids), or awarded (a bid won). Known values: open, closed, awarded (more may be added)."
          },
          "tender_status": {
            "type": "string",
            "description": "Tender status. draft (not issued), issued (bidders have their links), closed (the deadline passed or it was closed early), awarded, or cancelled (withdrawn: every bidder's link was revoked). Known values: draft, issued, closed, awarded, cancelled (more may be added)."
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due date. The day returns are due (YYYY-MM-DD), the return deadline's date in the project's time zone."
          },
          "returns_due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Return deadline. The exact return deadline (ISO 8601 timestamp). A bidder's return at or after it is refused; there is no override."
          },
          "accept_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "Reply by. When bidders were asked to say whether they will price it (ISO 8601 timestamp), or null."
          },
          "issued_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Issued at. When the tender was issued to the bidders (ISO 8601 timestamp), or null while it is a draft."
          },
          "awarded_bid_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Winning bid. The id of the bid that won, once the package is awarded."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "name",
          "status": "open",
          "tender_status": "draft",
          "due_date": "2026-10-05",
          "returns_due_at": "2026-10-04T09:30:00.000000+00:00",
          "accept_by": "accept by",
          "issued_at": "2026-10-04T09:30:00.000000+00:00",
          "awarded_bid_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "BidPackageResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/BidPackage"
          }
        }
      },
      "BidPackageList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BidPackage"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "Bid": {
        "type": "object",
        "title": "Bid",
        "description": "One subcontractor invited to price a bid package: their answer to the invitation (`intent`), the bid's status (invited, received, declined, awarded), when the price came in, whether through their tender link or recorded by your team, and how many times they sent it. Prices are not included.",
        "required": [
          "id",
          "bid_package_id",
          "contact_id",
          "status",
          "intent",
          "received_at",
          "returned_via",
          "submission_count",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "bid_package_id": {
            "type": "string",
            "format": "uuid",
            "description": "Bid package. The id of the bid package this bid is for."
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Subcontractor. The subcontractor's contact."
          },
          "status": {
            "type": "string",
            "description": "Status. invited, received (a price is in), declined (not bidding) or awarded (this bid won). Known values: invited, received, declined, awarded (more may be added)."
          },
          "intent": {
            "type": "string",
            "description": "Answer. The subcontractor's own answer to the invitation through their tender link: pending (no answer yet), accepted (will price it) or declined. Known values: pending, accepted, declined (more may be added)."
          },
          "received_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Received at. When the first price came in (ISO 8601 timestamp), or null."
          },
          "returned_via": {
            "type": [
              "string",
              "null"
            ],
            "description": "Returned through. portal (the subcontractor sent it through their tender link) or staff (your team recorded it), or null. Known values: portal, staff (more may be added)."
          },
          "submission_count": {
            "type": "number",
            "description": "Returns sent. How many times the subcontractor sent a price through their link (each one replaces the last)."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "bid_package_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "contact_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "status": "invited",
          "intent": "pending",
          "received_at": "2026-10-04T09:30:00.000000+00:00",
          "returned_via": "portal",
          "submission_count": 1,
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "BidResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Bid"
          }
        }
      },
      "BidList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Bid"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ServiceRequest": {
        "type": "object",
        "title": "Service request",
        "description": "A defect reported after handover (aftercare): where it is (location_id or unit_text), what kind of problem it is (category), how urgent (priority) and when it is due under the company's service levels (due_at). warranty_state says whether it was reported within the defects period. status moves from new through triaged, assigned and scheduled to resolved and closed, or rejected when it isn't covered. When it is assigned, one warranty snag is created for the contractor (punch_item_id). The reporter's contact details and photos are never included. Requests are reported, triaged and assigned in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "number",
          "location_id",
          "unit_text",
          "category",
          "title",
          "priority",
          "status",
          "source",
          "warranty_state",
          "due_at",
          "assigned_contact_id",
          "punch_item_id",
          "scheduled_for",
          "reported_at",
          "resolved_at",
          "closed_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the defect was reported on."
          },
          "number": {
            "type": [
              "string",
              "null"
            ],
            "description": "Number. The request's reference, SR- followed by a number counted per project (for example SR-0042)."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Location. The project location (unit, plot or room) the defect is in, when one was chosen (see the locations resource)."
          },
          "unit_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "Unit. Where the defect is, in words, when no location was chosen (up to 120 characters), or null."
          },
          "category": {
            "type": "string",
            "description": "Category. What kind of problem it is, such as plumbing, electrical, heating, doors_windows or finishes. The exact values are listed in the schema. Known values: plumbing, electrical, heating, ventilation, doors_windows, roof, finishes, appliances, drainage, structural, external, other (more may be added)."
          },
          "title": {
            "type": "string",
            "description": "Title. What is wrong, in a few words (1 to 160 characters)."
          },
          "priority": {
            "type": "string",
            "description": "Priority. How urgent it is: emergency, urgent, routine or cosmetic. Each has a service level (by default 24 hours, 72 hours and 28 days; cosmetic defects are batched to the end of the defects period). Known values: emergency, urgent, routine, cosmetic (more may be added)."
          },
          "status": {
            "type": "string",
            "description": "Status. Where the request stands: new; triaged (reviewed and prioritised); assigned (a contractor has the repair); scheduled (a date is booked); resolved (the repair is done); closed; or rejected (not covered). Known values: new, triaged, assigned, scheduled, resolved, closed, rejected (more may be added)."
          },
          "source": {
            "type": "string",
            "description": "Source. How it was reported: portal (the client portal), qr (a unit's Report a defect QR code), email, staff (by the team) or api. Known values: portal, qr, email, staff, api (more may be added)."
          },
          "warranty_state": {
            "type": "string",
            "description": "Warranty. Whether it was reported within the project's defects period: within, expired, or unknown when the project has no completion dates yet. Known values: within, expired, unknown (more may be added)."
          },
          "due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Due. When the repair is due under the company's service levels (RFC 3339, UTC), or null when none applies yet."
          },
          "assigned_contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Contractor. The contact id of the contractor given the repair, or null before it is assigned."
          },
          "punch_item_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Warranty snag. The id of the warranty snag created for the repair (see the punch items resource), or null before it is assigned."
          },
          "scheduled_for": {
            "type": [
              "string",
              "null"
            ],
            "description": "Booked for. When the repair visit is booked (RFC 3339, UTC), or null."
          },
          "reported_at": {
            "type": "string",
            "format": "date-time",
            "description": "Reported. When the defect was reported (RFC 3339, UTC). The service level and warranty are judged from this time."
          },
          "resolved_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Resolved. When the repair was marked done (RFC 3339, UTC), or null."
          },
          "closed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Closed. When the request was closed (RFC 3339, UTC), or null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "number": "number",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "unit_text": "unit text",
          "category": "plumbing",
          "title": "title",
          "priority": "emergency",
          "status": "new",
          "source": "portal",
          "warranty_state": "within",
          "due_at": "2026-10-04T09:30:00.000000+00:00",
          "assigned_contact_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "punch_item_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "scheduled_for": "scheduled for",
          "reported_at": "2026-10-04T09:30:00.000000+00:00",
          "resolved_at": "2026-10-04T09:30:00.000000+00:00",
          "closed_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ServiceRequestResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ServiceRequest"
          }
        }
      },
      "ServiceRequestList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceRequest"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "HandoverPack": {
        "type": "object",
        "title": "Handover pack",
        "description": "One issue of a project's handover pack: the certificates, manuals and drawings a client receives at handover, in sections by system or trade, with an index first. version counts the issues on the project (1, 2 …). status is draft while it is being put together, issued once sent, and superseded when a newer version is issued. An issued pack is a locked, frozen document package (frozen_package_id) sent with a transmittal (transmittal_id). Packs are built and issued in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "title",
          "version",
          "status",
          "frozen_package_id",
          "transmittal_id",
          "issued_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the handover pack is for."
          },
          "title": {
            "type": "string",
            "description": "Title. The pack's title (1 to 160 characters)."
          },
          "version": {
            "type": "number",
            "description": "Version. The issue number of the pack on its project: 1 for the first, then 2, 3 and so on."
          },
          "status": {
            "type": "string",
            "description": "Status. draft while it is being put together, issued once sent, superseded when a newer version is issued. Known values: draft, issued, superseded (more may be added)."
          },
          "frozen_package_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Issued package. The id of the frozen, locked document package issued as this pack, or null for a draft."
          },
          "transmittal_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Transmittal. The id of the transmittal the pack was sent with, or null for a draft."
          },
          "issued_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Issued. When the pack was issued (RFC 3339, UTC), or null for a draft."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "title": "title",
          "version": 1,
          "status": "draft",
          "frozen_package_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "transmittal_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "issued_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "HandoverPackResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/HandoverPack"
          }
        }
      },
      "HandoverPackList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HandoverPack"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "SiteAttendance": {
        "type": "object",
        "title": "Site sign-in",
        "description": "One visit in a project's site sign-in book: who signed in (a contact, or a team member; a visitor has neither, and their name and details are never part of the API), on which site, when they signed in and out, how (at the kiosk, by staff or in the app) and their trade. Status on_site, signed_out or auto_signed_out (signed out by Konverge at the site's end-of-day time). Fire roll calls read the same book in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "site_id",
          "contact_id",
          "user_id",
          "status",
          "method",
          "signed_in_at",
          "signed_out_at",
          "trade",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project whose sign-in book the visit is in."
          },
          "site_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Site. The id of the project's site (gate) the person signed in at, or null."
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Contact. The id of the contact who signed in (for example a subcontractor's operative), or null."
          },
          "user_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Team member. The id of the team member who signed in, or null. Team members who clock in count as on site without a sign-in."
          },
          "status": {
            "type": "string",
            "description": "Status. on_site (still there), signed_out, or auto_signed_out (still signed in at the site's end-of-day time, so Konverge signed them out). Known values: on_site, signed_out, auto_signed_out (more may be added)."
          },
          "method": {
            "type": "string",
            "description": "Signed in by. How they signed in: kiosk (the site's sign-in tablet), staff (a team member signed them in) or app. Known values: kiosk, staff, app (more may be added)."
          },
          "signed_in_at": {
            "type": "string",
            "format": "date-time",
            "description": "Signed in. When they signed in (RFC 3339). A sign-in made with no signal keeps the time it was made."
          },
          "signed_out_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Signed out. When they signed out (RFC 3339), or null while they are on site."
          },
          "trade": {
            "type": [
              "string",
              "null"
            ],
            "description": "Trade. The trade they worked in on this visit (for example Groundworks), or null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "site_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "contact_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "user_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "status": "on_site",
          "method": "kiosk",
          "signed_in_at": "2026-10-04T09:30:00.000000+00:00",
          "signed_out_at": "2026-10-04T09:30:00.000000+00:00",
          "trade": "trade",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "SiteAttendanceResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SiteAttendance"
          }
        }
      },
      "SiteAttendanceList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SiteAttendance"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "WorkCalendar": {
        "type": "object",
        "title": "Working calendar",
        "description": "A working calendar: the company's default (project_id null) or one project's own, which replaces the default for that project. It says which days of the week are worked (ISO weekday numbers, 1 = Monday), the hours in a working day, the bank-holiday list it was filled from (England and Wales, Scotland, Northern Ireland or US federal) and whether the project programme counts durations and lags in working days on it.",
        "required": [
          "id",
          "project_id",
          "name",
          "working_weekdays",
          "hours_per_day",
          "region_preset",
          "applies_to_programme",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project. The project this calendar belongs to, or null for the company's default calendar."
          },
          "name": {
            "type": "string",
            "description": "Name. The calendar's name (1 to 80 characters), for example Monday to Friday."
          },
          "working_weekdays": {
            "type": "array",
            "items": {
              "type": "number"
            }
          },
          "hours_per_day": {
            "type": "number",
            "description": "Hours per day. The hours in a working day on this calendar (more than 0, at most 24)."
          },
          "region_preset": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bank holidays. The bank-holiday list the calendar was filled from: england_wales, scotland, northern_ireland or us_federal, or null. Known values: england_wales, scotland, northern_ireland, us_federal (more may be added)."
          },
          "applies_to_programme": {
            "type": "boolean",
            "description": "Programme uses it. True when the project programme counts task durations and link lags in working days on this calendar (tasks start on the next working day); false when it counts calendar days."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "name",
          "working_weekdays": [],
          "hours_per_day": 1,
          "region_preset": "england_wales",
          "applies_to_programme": true,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "WorkCalendarResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WorkCalendar"
          }
        }
      },
      "WorkCalendarList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkCalendar"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EstimateSection": {
        "type": "object",
        "title": "Estimate section",
        "description": "A section of an estimate, such as Groundworks or Kitchen. Sections go two levels deep: a section with a parent_id sits under a top-level section. Estimate lines point at their section through section_id. cost_code is the default cost code for new lines in the section. Created, renamed and deleted by people with edit rights on the estimate (deleting a section keeps its lines, with no section).",
        "required": [
          "id",
          "estimate_id",
          "parent_id",
          "name",
          "description",
          "cost_code",
          "position",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The estimate the section belongs to."
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Parent section. The id of the top-level section this one sits under, or null for a top-level section. Set when the section is created; it can't be moved under another section afterwards."
          },
          "name": {
            "type": "string",
            "description": "Name. The section's name (1-120 characters)."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description. What the section covers (up to 4,000 characters), or null."
          },
          "cost_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cost code. The default cost code for lines added to the section (up to 40 characters), or null."
          },
          "position": {
            "type": "number",
            "description": "Position. The section's place among its siblings; lower comes first."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "parent_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "name",
          "description": "description",
          "cost_code": "cost code",
          "position": 1,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "EstimateSectionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/EstimateSection"
          }
        }
      },
      "EstimateSectionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EstimateSection"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EstimateSectionCreate": {
        "type": "object",
        "title": "New estimate section",
        "additionalProperties": false,
        "properties": {
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The estimate the section belongs to. The id of an estimate in your company."
          },
          "parent_id": {
            "type": "string",
            "maxLength": 10000,
            "description": "Parent section. The id of the top-level section this one sits under, or null for a top-level section. Set when the section is created; it can't be moved under another section afterwards."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name. The section's name (1-120 characters)."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description. What the section covers (up to 4,000 characters), or null."
          },
          "cost_code": {
            "type": "string",
            "maxLength": 10000,
            "description": "Cost code. The default cost code for lines added to the section (up to 40 characters), or null."
          },
          "position": {
            "type": "number",
            "description": "Position. The section's place among its siblings; lower comes first."
          }
        },
        "required": [
          "estimate_id",
          "name"
        ],
        "example": {
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "name": "Example name"
        }
      },
      "EstimateSectionUpdate": {
        "type": "object",
        "title": "Changes to an estimate section",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name. The section's name (1-120 characters)."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description. What the section covers (up to 4,000 characters), or null."
          },
          "cost_code": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10000,
            "description": "Cost code. The default cost code for lines added to the section (up to 40 characters), or null."
          },
          "position": {
            "type": [
              "number",
              "null"
            ],
            "description": "Position. The section's place among its siblings; lower comes first."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "EstimateOption": {
        "type": "object",
        "title": "Estimate option",
        "description": "An option or an alternate on an estimate. An option (kind option) is an add-on the client may take; alternates (kind alternate) share a group_key and are offered instead of each other, so at most one per group is selected. is_selected is the offer's default and, once the estimate is accepted, the client's choice. Lines in an option count towards the estimate's totals only while it is selected. Created and renamed by people with edit rights on the estimate; `select` (de)selects one and the totals are worked out again.",
        "required": [
          "id",
          "estimate_id",
          "kind",
          "group_key",
          "name",
          "description",
          "position",
          "is_selected",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The estimate the option belongs to."
          },
          "kind": {
            "type": "string",
            "description": "Kind. option (an add-on) or alternate (one of a group, instead of the others). Known values: option, alternate (more may be added)."
          },
          "group_key": {
            "type": [
              "string",
              "null"
            ],
            "description": "Group. For an alternate, the group it belongs to (1-40 characters); null for an option. Set when it is created."
          },
          "name": {
            "type": "string",
            "description": "Name. The option's name (1-120 characters)."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Description. What the option includes (up to 4,000 characters), or null."
          },
          "position": {
            "type": "number",
            "description": "Position. The option's place in the list; lower comes first."
          },
          "is_selected": {
            "type": "boolean",
            "description": "Selected. Whether the option is in the estimate's totals: the offer's default before acceptance, the client's choice after it. Changed by the select action."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "kind": "option",
          "group_key": "group key",
          "name": "name",
          "description": "description",
          "position": 1,
          "is_selected": true,
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "EstimateOptionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/EstimateOption"
          }
        }
      },
      "EstimateOptionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EstimateOption"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EstimateOptionCreate": {
        "type": "object",
        "title": "New estimate option",
        "additionalProperties": false,
        "properties": {
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The estimate the option belongs to. The id of an estimate in your company."
          },
          "kind": {
            "type": "string",
            "enum": [
              "option",
              "alternate"
            ],
            "description": "Kind. option (an add-on) or alternate (one of a group, instead of the others)."
          },
          "group_key": {
            "type": "string",
            "maxLength": 10000,
            "description": "Group. For an alternate, the group it belongs to (1-40 characters); null for an option. Set when it is created."
          },
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name. The option's name (1-120 characters)."
          },
          "description": {
            "type": "string",
            "maxLength": 50000,
            "description": "Description. What the option includes (up to 4,000 characters), or null."
          },
          "position": {
            "type": "number",
            "description": "Position. The option's place in the list; lower comes first."
          }
        },
        "required": [
          "estimate_id",
          "kind",
          "name"
        ],
        "example": {
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "kind": "option",
          "name": "Example name"
        }
      },
      "EstimateOptionUpdate": {
        "type": "object",
        "title": "Changes to an estimate option",
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 10000,
            "description": "Name. The option's name (1-120 characters)."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50000,
            "description": "Description. What the option includes (up to 4,000 characters), or null."
          },
          "position": {
            "type": [
              "number",
              "null"
            ],
            "description": "Position. The option's place in the list; lower comes first."
          }
        },
        "minProperties": 1,
        "example": {
          "name": "Example name"
        }
      },
      "EstimateOptionSelectParams": {
        "type": "object",
        "title": "Select or deselect the option (the estimate's totals change)",
        "additionalProperties": false,
        "properties": {
          "selected": {
            "type": "boolean",
            "description": "Selected. true to include the option in the estimate's totals, false to leave it out. Selecting an alternate deselects the other alternates of its group.",
            "default": true
          }
        },
        "example": {
          "selected": true
        }
      },
      "TakeoffItem": {
        "type": "object",
        "title": "Takeoff item",
        "description": "A quantity measured on a drawing for an estimate: a length, area, perimeter, wall area, volume or count taken off a markup, in metric or imperial units. Konverge works the quantity out from the markup and the drawing's scale (or the confirmed scale of the view the markup sits in). While the estimate is a draft, the line it feeds is kept equal to its measured quantities; once the estimate is sent, a drawing change marks the item stale instead. Takeoff items are made by people in the Konverge apps and through the assistant, never by an API key.",
        "required": [
          "id",
          "estimate_id",
          "estimate_item_id",
          "sheet_id",
          "markup_id",
          "region_id",
          "measure",
          "height_m",
          "depth_m",
          "factor",
          "deduct",
          "unit",
          "quantity",
          "scale_source",
          "sheet_revision",
          "status",
          "label",
          "computed_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The estimate the quantity was measured for."
          },
          "estimate_item_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Line. The estimate line the quantity feeds, or null when it is measured but not yet on a line."
          },
          "sheet_id": {
            "type": "string",
            "format": "uuid",
            "description": "Drawing. The drawing sheet it was measured on. It stays on that revision of the drawing."
          },
          "markup_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Markup. The measured markup on the drawing, or null once the markup was deleted (status orphaned)."
          },
          "region_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "View. The drawing view whose confirmed scale was used, when the markup sits in one; otherwise null."
          },
          "measure": {
            "type": "string",
            "description": "Measure. What was taken off: length, area, perimeter, count, wall_area (length or perimeter times a height) or volume (area times a depth). Known values: length, area, perimeter, count, wall_area, volume (more may be added)."
          },
          "height_m": {
            "type": [
              "number",
              "null"
            ],
            "description": "Height (m). For a wall area: the wall height in metres. Null otherwise."
          },
          "depth_m": {
            "type": [
              "number",
              "null"
            ],
            "description": "Depth (m). For a volume: the depth in metres. Null otherwise."
          },
          "factor": {
            "type": "number",
            "description": "Multiplier. What the quantity is multiplied by on the line, for example 2 for two coats or an assembly's quantity per unit. 1 for none."
          },
          "deduct": {
            "type": "boolean",
            "description": "Deducted. True when the quantity is subtracted from the line, as for a door or window opening."
          },
          "unit": {
            "type": "string",
            "description": "Unit. The unit of the quantity: m, m2, m3, ea (a count), ft, ft2, ft3 or yd3. Known values: m, m2, m3, ea, ft, ft2, ft3, yd3 (more may be added)."
          },
          "quantity": {
            "type": "number",
            "description": "Quantity. The measured quantity in the unit, to three decimal places, as Konverge worked it out. 0 when the drawing has no scale."
          },
          "scale_source": {
            "type": "string",
            "description": "Scale. Where the scale came from: region (the confirmed scale of a view on the drawing), sheet (the drawing's calibration) or none. Known values: region, sheet, none (more may be added)."
          },
          "sheet_revision": {
            "type": [
              "string",
              "null"
            ],
            "description": "Drawing revision. The revision of the drawing it was measured on."
          },
          "status": {
            "type": "string",
            "description": "Status. current; stale (the drawing changed after the estimate was sent, so the line keeps the sent quantity); orphaned (the markup was deleted); no_scale (the drawing has no scale). Known values: current, stale, orphaned, no_scale (more may be added)."
          },
          "label": {
            "type": [
              "string",
              "null"
            ],
            "description": "Note. A short note shown with the quantity, for example North wall (up to 120 characters). Optional."
          },
          "computed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Measured at. When Konverge last worked the quantity out."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "estimate_item_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "sheet_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "markup_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "region_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "measure": "length",
          "height_m": 1,
          "depth_m": 1,
          "factor": 1,
          "deduct": true,
          "unit": "m",
          "quantity": 1,
          "scale_source": "region",
          "sheet_revision": "sheet revision",
          "status": "current",
          "label": "label",
          "computed_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "TakeoffItemResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TakeoffItem"
          }
        }
      },
      "TakeoffItemList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TakeoffItem"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ProposalTemplate": {
        "type": "object",
        "title": "Proposal template",
        "description": "A company's proposal wording, used to start each estimate's proposal: cover letter, scope introduction, inclusions and exclusions, terms, payment schedule, validity and price display. Text is plain text with merge fields in double braces ({{client_name}}, {{company_name}}, {{project_name}}, {{estimate_number}}, {{estimate_title}}, {{valid_until}}, {{total}}), filled in when the proposal is printed or shown. One template can be the company default. Templates are written in the Konverge apps.",
        "required": [
          "id",
          "name",
          "is_default",
          "cover_letter",
          "scope_intro",
          "inclusions",
          "exclusions",
          "terms",
          "payment_schedule",
          "validity_days",
          "price_display",
          "show_quantities",
          "archived_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name. The template's name (1 to 80 characters)."
          },
          "is_default": {
            "type": "boolean",
            "description": "Default. True for the company's default template (at most one), used when an estimate's proposal is started without choosing one."
          },
          "cover_letter": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cover letter. The cover letter, plain text with merge fields (up to 8,000 characters), or null."
          },
          "scope_intro": {
            "type": [
              "string",
              "null"
            ],
            "description": "Scope introduction. Text printed above the scope of work, plain text with merge fields (up to 8,000 characters), or null."
          },
          "inclusions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Included. What the price includes: a list of up to 100 lines of up to 300 characters each."
          },
          "exclusions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Not included. What the price does not include: a list of up to 100 lines of up to 300 characters each."
          },
          "terms": {
            "type": [
              "string",
              "null"
            ],
            "description": "Terms. The terms and conditions, plain text (up to 20,000 characters), or null."
          },
          "payment_schedule": {
            "description": "Payment schedule. The payment stages, up to 20, each {label, percent or amount, due, days}: due is on_acceptance, on_start, milestone, on_completion or days_after_acceptance (with days, 1 to 3,650). A schedule made only of percentages adds up to 100. Amounts are worked out from the estimate's total when the proposal is printed."
          },
          "validity_days": {
            "type": "number",
            "description": "Valid for (days). How many days a price stays valid (1 to 365); starting a proposal sets the estimate's valid-until date from it when it has none."
          },
          "price_display": {
            "type": "string",
            "description": "Price display. How prices show on the proposal: all (every line priced), sections_only (a subtotal per section) or total_only (the total alone). Known values: all, sections_only, total_only (more may be added)."
          },
          "show_quantities": {
            "type": "boolean",
            "description": "Show quantities. Whether the proposal prints quantities and units beside each line."
          },
          "archived_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Archived. When the template was archived (RFC 3339, UTC), or null while it can be used."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "name": "name",
          "is_default": true,
          "cover_letter": "cover letter",
          "scope_intro": "scope intro",
          "inclusions": [],
          "exclusions": [],
          "terms": "terms",
          "payment_schedule": {},
          "validity_days": 1,
          "price_display": "all",
          "show_quantities": true,
          "archived_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ProposalTemplateResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ProposalTemplate"
          }
        }
      },
      "ProposalTemplateList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProposalTemplate"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "EstimateAcceptance": {
        "type": "object",
        "title": "Estimate acceptance",
        "description": "The record of an estimate's acceptance, written once and never changed. accepted_via says how: portal (the client accepted in the client portal), esign (by electronic signature) or staff (recorded by the team on the client's behalf, with a note saying how). chosen_option_ids are the options and alternates the client chose; accepted_subtotal, accepted_tax and accepted_total are the totals for that choice. offer_hash is the sha256 of the whole offer (every line, option and section) when it was accepted. Estimates are accepted in the Konverge apps, the client portal or by e-signature, never through the API.",
        "required": [
          "id",
          "estimate_id",
          "revision_number",
          "accepted_via",
          "accepted_by_user",
          "signer_name",
          "signature_request_id",
          "chosen_option_ids",
          "accepted_subtotal",
          "accepted_tax",
          "accepted_total",
          "currency",
          "offer_hash",
          "note",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid",
            "description": "Estimate. The estimate that was accepted (see the estimates resource)."
          },
          "revision_number": {
            "type": "number",
            "description": "Revision. The revision of the estimate that was accepted: 0 for the first issue, then 1, 2 and so on."
          },
          "accepted_via": {
            "type": "string",
            "description": "Accepted by. How it was accepted: portal (the client, in the client portal), esign (by electronic signature) or staff (recorded on the client's behalf). Known values: portal, esign, staff (more may be added)."
          },
          "accepted_by_user": {
            "type": [
              "string",
              "null"
            ],
            "description": "Accepted by (person). The user id of the person who accepted in the portal or recorded it, or null for an electronic signature."
          },
          "signer_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Signer. The name the client signed or accepted with, or null when the team recorded it."
          },
          "signature_request_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Signature request. The signature request it was signed through, or null when it was not accepted by electronic signature."
          },
          "chosen_option_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Options chosen. The ids of the options and alternates the client chose (one alternate of each group), possibly empty."
          },
          "accepted_subtotal": {
            "type": "number",
            "description": "Accepted subtotal. The accepted total before VAT (or sales tax), after any discounts, in the currency. An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "accepted_tax": {
            "type": "number",
            "description": "Accepted VAT. The VAT (or sales tax) of the accepted total. An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "accepted_total": {
            "type": "number",
            "description": "Accepted total. The accepted total including VAT (or sales tax). An amount with at most 2 decimal places, in the record's currency (or the company's)."
          },
          "currency": {
            "type": "string",
            "description": "Currency. The ISO 4217 currency code of the totals, such as GBP or USD."
          },
          "offer_hash": {
            "type": "string",
            "description": "Offer fingerprint. The sha256 (64 hex characters) of the whole offer when it was accepted: every line, option and section."
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Note. The note left with the acceptance (up to 2,000 characters), or null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "revision_number": 1,
          "accepted_via": "portal",
          "accepted_by_user": "accepted by user",
          "signer_name": "signer name",
          "signature_request_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "chosen_option_ids": [],
          "accepted_subtotal": 1,
          "accepted_tax": 1,
          "accepted_total": 1,
          "currency": "currency",
          "offer_hash": "offer hash",
          "note": "note",
          "created_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "EstimateAcceptanceResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/EstimateAcceptance"
          }
        }
      },
      "EstimateAcceptanceList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EstimateAcceptance"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "SelectionItem": {
        "type": "object",
        "title": "Selection",
        "description": "Something the client chooses on a project, such as a kitchen worktop or a front door. allowance_id is the allowance it is measured against, chosen_option_id the option chosen (by the client in the portal, or by the builder on the client's behalf: chosen_via). Status: draft (not shown to the client yet), open (waiting for the client), chosen, approved (confirmed by the builder), ordered, installed or cancelled. Prices live on the options. Read only.",
        "required": [
          "id",
          "project_id",
          "allowance_id",
          "location_id",
          "category",
          "name",
          "quantity",
          "unit",
          "due_on",
          "requires_signature",
          "status",
          "chosen_option_id",
          "chosen_at",
          "chosen_via",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the selection is on."
          },
          "allowance_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Allowance. The allowance (project_allowance) this choice is measured against; null when it isn't on one."
          },
          "location_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "description": "Category. A grouping such as Kitchen or Bathroom (free text)."
          },
          "name": {
            "type": "string",
            "description": "Name. What is being chosen, for example Kitchen worktop."
          },
          "quantity": {
            "type": "number",
            "description": "Quantity. How many, in unit; an option priced per unit costs its price times this."
          },
          "unit": {
            "type": "string"
          },
          "due_on": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Due. The date the client should choose by (YYYY-MM-DD)."
          },
          "requires_signature": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "description": "Status. draft (not shown to the client), open (waiting for the client's choice), chosen, approved (confirmed by the builder), ordered, installed or cancelled. Known values: draft, open, chosen, approved, ordered, installed, cancelled (more may be added)."
          },
          "chosen_option_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Chosen option. The selection_option chosen, once there is one."
          },
          "chosen_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "chosen_via": {
            "type": [
              "string",
              "null"
            ],
            "description": "Chosen in. portal (the client chose it in the client portal) or staff (the builder chose it on the client's behalf). Known values: portal, staff (more may be added)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "allowance_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "location_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "category": "category",
          "name": "name",
          "quantity": 1,
          "unit": "unit",
          "due_on": "2026-10-05",
          "requires_signature": true,
          "status": "draft",
          "chosen_option_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "chosen_at": "2026-10-04T09:30:00.000000+00:00",
          "chosen_via": "portal",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "SelectionItemResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SelectionItem"
          }
        }
      },
      "SelectionItemList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SelectionItem"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "TakeoffSuggestion": {
        "type": "object",
        "title": "Takeoff suggestion",
        "description": "A quantity Konverge's drawing intelligence read off a drawing sheet for an estimate: a room area exactly as it is printed on a plan, or the number of doors or windows of one type in a schedule. It is a suggestion for a person to check: someone with edit rights accepts it onto a draft estimate (the line's rate always comes from the company's own catalog, never from the suggestion) or dismisses it. A newer reading of the same drawing replaces the suggestions still open. Suggestions carry quantities and labels only, never a rate, a cost or a price. They are made, accepted and dismissed by people in the Konverge apps, never by an API key.",
        "required": [
          "id",
          "project_id",
          "sheet_id",
          "region_id",
          "run_id",
          "kind",
          "basis",
          "label",
          "quantity",
          "unit",
          "printed_text",
          "confidence",
          "status",
          "sheet_revision",
          "model",
          "prompt_version",
          "decided_at",
          "accepted_estimate_id",
          "accepted_item_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Project. The project of the drawing."
          },
          "sheet_id": {
            "type": "string",
            "format": "uuid",
            "description": "Drawing. The drawing sheet the quantity was read from (that revision of it)."
          },
          "region_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "View. The view on the drawing it was read from (a plan or a schedule), or null."
          },
          "run_id": {
            "type": "string",
            "format": "uuid",
            "description": "Reading. The reading of the drawing that produced it; every suggestion of one reading shares it."
          },
          "kind": {
            "type": "string",
            "description": "Kind. room_area (a room's floor area), schedule_count (how many of one door, window or other type a schedule lists), symbol_count (symbols counted on a plan) or length. Known values: room_area, schedule_count, symbol_count, length (more may be added)."
          },
          "basis": {
            "type": "string",
            "description": "Read from. printed (a value printed on the drawing), schedule (a schedule table) or geometry (a shape on the drawing that Konverge measures when the suggestion is accepted). Known values: printed, schedule, geometry (more may be added)."
          },
          "label": {
            "type": "string",
            "description": "Label. What it is, as printed: a room name such as Kitchen, or a type such as Door type FD30 (up to 160 characters)."
          },
          "quantity": {
            "type": "number",
            "description": "Quantity. The quantity in the unit, to three decimal places, exactly as printed or counted."
          },
          "unit": {
            "type": "string",
            "description": "Unit. The unit: m2 or ft2 for an area, ea for a count, m or ft for a length. Known values: m, m2, ea, ft, ft2 (more may be added)."
          },
          "printed_text": {
            "type": [
              "string",
              "null"
            ],
            "description": "As printed. The text on the drawing it was read from, for example 12.5 m² or D1 × 14, or null."
          },
          "confidence": {
            "type": "number",
            "description": "Confidence. How sure the reading is, from 0 to 1."
          },
          "status": {
            "type": "string",
            "description": "Status. open (waiting for a person), accepted (put on an estimate), dismissed, or superseded (a newer reading of the drawing replaced it). Known values: open, accepted, dismissed, superseded (more may be added)."
          },
          "sheet_revision": {
            "type": [
              "string",
              "null"
            ],
            "description": "Drawing revision. The revision of the drawing it was read from."
          },
          "model": {
            "type": "string",
            "description": "Model. The AI model that read the drawing."
          },
          "prompt_version": {
            "type": "string",
            "description": "Reader version. The version of Konverge's drawing reader that produced it."
          },
          "decided_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Decided. When it was accepted or dismissed (RFC 3339, UTC), or null while open."
          },
          "accepted_estimate_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Estimate. The estimate it was accepted onto, or null."
          },
          "accepted_item_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Line. The estimate line it was accepted onto, or null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "sheet_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "region_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "run_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "kind": "room_area",
          "basis": "printed",
          "label": "label",
          "quantity": 1,
          "unit": "m",
          "printed_text": "printed text",
          "confidence": 1,
          "status": "open",
          "sheet_revision": "sheet revision",
          "model": "model",
          "prompt_version": "prompt version",
          "decided_at": "2026-10-04T09:30:00.000000+00:00",
          "accepted_estimate_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "accepted_item_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "created_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "TakeoffSuggestionResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TakeoffSuggestion"
          }
        }
      },
      "TakeoffSuggestionList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TakeoffSuggestion"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      },
      "ClientUpdate": {
        "type": "object",
        "title": "Client update",
        "description": "A weekly update for a project's client. Konverge drafts it from the period's approved site records (with AI, or as a plain list of facts), a project manager checks and edits it, and only then is it published to the client's portal and emailed (status published). A draft nobody publishes within 7 days expires and is never sent. What a draft was built from, the settings and who received it are not included. Updates are approved and published in the Konverge apps.",
        "required": [
          "id",
          "project_id",
          "period_start",
          "period_end",
          "status",
          "title",
          "body_md",
          "photo_ids",
          "drafted_by",
          "names_removed",
          "drafted_at",
          "expires_at",
          "edited_at",
          "published_at",
          "discarded_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "project_id": {
            "type": "string",
            "format": "uuid",
            "description": "Project. The project the update is about."
          },
          "period_start": {
            "type": "string",
            "format": "date",
            "description": "From. The first day of the period the update covers (one or two weeks)."
          },
          "period_end": {
            "type": "string",
            "format": "date",
            "description": "To. The last day of the period the update covers."
          },
          "status": {
            "type": "string",
            "description": "Status. draft (waiting for the project manager), published (sent to the client), discarded (not sent), or expired (not published within 7 days, never sent). Known values: draft, published, discarded, expired (more may be added)."
          },
          "title": {
            "type": "string",
            "description": "Title. The update's title (1 to 160 characters)."
          },
          "body_md": {
            "type": "string",
            "description": "Text. The update's text in simple Markdown: headings, paragraphs, lists and bold only (up to 20,000 characters)."
          },
          "photo_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Photos. Up to 12 ids of the project's site photos shown with the update (see the photos resource)."
          },
          "drafted_by": {
            "type": "string",
            "description": "Drafted by. How the draft was written: ai, template (a plain list of facts, no AI) or person. Known values: ai, template, person (more may be added)."
          },
          "names_removed": {
            "type": "boolean",
            "description": "Names removed. True when people's names were taken out of the draft before anyone saw it."
          },
          "drafted_at": {
            "type": "string",
            "format": "date-time",
            "description": "Drafted. When the draft was written (ISO 8601)."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Expires. When an unpublished draft expires: 7 days after it was drafted (ISO 8601)."
          },
          "edited_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Edited. When a person last edited the draft, or null."
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Published. When it was published to the client, or null."
          },
          "discarded_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Discarded. When a draft was discarded, or null."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "example": {
          "id": "3f6c2a9e-8b1d-4c7e-9a52-6d0e4b1f7a38",
          "project_id": "b1e0d7c4-5a3f-4e2b-8c19-0f6a7d2e9b54",
          "period_start": "2026-10-05",
          "period_end": "2026-10-05",
          "status": "draft",
          "title": "title",
          "body_md": "body md",
          "photo_ids": [],
          "drafted_by": "ai",
          "names_removed": true,
          "drafted_at": "2026-10-04T09:30:00.000000+00:00",
          "expires_at": "2026-10-04T09:30:00.000000+00:00",
          "edited_at": "2026-10-04T09:30:00.000000+00:00",
          "published_at": "2026-10-04T09:30:00.000000+00:00",
          "discarded_at": "2026-10-04T09:30:00.000000+00:00",
          "created_at": "2026-10-04T09:30:00.000000+00:00",
          "updated_at": "2026-10-04T09:30:00.000000+00:00"
        }
      },
      "ClientUpdateResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ClientUpdate"
          }
        }
      },
      "ClientUpdateList": {
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ClientUpdate"
            }
          },
          "has_more": {
            "type": "boolean",
            "description": "True when there is another page."
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to get the next page; null on the last page."
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request is malformed: a query parameter, the cursor, the JSON body or the Idempotency-Key. Codes: `bad_request`, `unknown_filter`, `invalid_cursor`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "bad_request",
                "message": "Some query parameters are not valid. See details.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0",
                "details": [
                  {
                    "field": "limit",
                    "message": "Use a whole number from 1 to 100."
                  }
                ]
              }
            }
          }
        }
      },
      "Unauthenticated": {
        "description": "No valid API key: missing, mistyped, revoked or expired (one answer for all). Codes: `unauthenticated`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WWW-Authenticate"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "unauthenticated",
                "message": "Send a valid Konverge API key as \"Authorization: Bearer <key>\". This key is missing, mistyped, revoked or expired.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key may not do this: a missing scope, its role or permissions, or a read-only (unpaid) company. Codes: `insufficient_scope`, `forbidden`, `company_read_only`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "insufficient_scope",
                "message": "This API key cannot do that. It needs the \"records:write\" scope: create a key with it in Settings → Developers.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "No such record in your company, or this key cannot see it (another company's records answer the same). Codes: `not_found`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "not_found",
                "message": "No record with that id exists in your company, or this API key cannot see it.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "This resource does not support that method or action. Codes: `method_not_allowed`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          },
          "Allow": {
            "$ref": "#/components/headers/Allow"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "method_not_allowed",
                "message": "/v1/rfis accepts GET.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "The record's state does not allow this, or the Idempotency-Key was reused or is still running. Codes: `conflict`, `idempotency_key_reused`, `idempotency_in_progress`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "conflict",
                "message": "The record isn't in a state that allows this yet. Refresh and try again.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "A field is missing, has the wrong type, or names a record this key cannot see. `details` lists each problem. Codes: `validation_failed`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "validation_failed",
                "message": "Some fields are not valid. See details.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0",
                "details": [
                  {
                    "field": "title",
                    "message": "Required."
                  }
                ]
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "This key's token bucket, or the bucket its company's plan shares between all its keys, is empty. Retry after `Retry-After` seconds; `Konverge-RateLimit-Scope` says which (`key` or `plan`). Codes: `rate_limited`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "rate_limited",
                "message": "Too many requests with this API key. Wait for the number of seconds in Retry-After, then try again.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Something went wrong on our side. A write may or may not have been made (a server error is not kept for Idempotency-Key replay): check before retrying. Codes: `internal_error`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "internal_error",
                "message": "Something went wrong on our side. If you were changing something, check whether the change was made before you try again. Contact support with the request id if it keeps happening.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The API or the database is not available right now. Retry later. Codes: `api_not_configured`, `unavailable`.",
        "headers": {
          "Request-Id": {
            "$ref": "#/components/headers/Request-Id"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          },
          "Konverge-RateLimit-Scope": {
            "$ref": "#/components/headers/Konverge-RateLimit-Scope"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "api_not_configured",
                "message": "The Konverge API is not switched on here yet. Try again later or contact Konverge support.",
                "request_id": "req_4c1f9b2d7e6a8035c2d1e9f0"
              }
            }
          }
        }
      }
    }
  },
  "x-konverge-catalog": {
    "entities": {
      "task": {
        "resource": "/v1/tasks",
        "table": "tasks",
        "queryable": true
      },
      "project": {
        "resource": "/v1/projects",
        "table": "projects",
        "queryable": true
      },
      "milestone": {
        "resource": "/v1/milestones",
        "table": "milestones",
        "queryable": true
      },
      "timesheet": {
        "resource": null,
        "table": "timesheets",
        "reason": "Nothing on this entity is offered over the REST API (see unexposed kinds)."
      },
      "schedule_baseline": {
        "resource": "/v1/schedule_baselines",
        "table": "schedule_baselines",
        "queryable": true
      },
      "task_dependency": {
        "resource": "/v1/task_dependencies",
        "table": "task_dependencies",
        "queryable": true
      },
      "incident": {
        "resource": "/v1/incidents",
        "table": "incidents",
        "queryable": true
      },
      "inspection": {
        "resource": "/v1/inspections",
        "table": "inspections",
        "queryable": true
      },
      "punch_list": {
        "resource": "/v1/punch_lists",
        "table": "punch_lists",
        "queryable": true
      },
      "daily_log": {
        "resource": "/v1/daily_logs",
        "table": "daily_logs",
        "queryable": true
      },
      "field_note": {
        "resource": "/v1/field_notes",
        "table": "field_notes",
        "queryable": true
      },
      "punch_item": {
        "resource": "/v1/punch_items",
        "table": "punch_list_items",
        "queryable": true
      },
      "contact": {
        "resource": "/v1/contacts",
        "table": "contacts",
        "queryable": true
      },
      "equipment": {
        "resource": "/v1/equipment",
        "table": "equipment",
        "queryable": true
      },
      "transaction": {
        "resource": "/v1/transactions",
        "table": "transactions",
        "queryable": true
      },
      "cost_code": {
        "resource": "/v1/cost_codes",
        "table": "cost_codes",
        "queryable": true
      },
      "estimate": {
        "resource": "/v1/estimates",
        "table": "estimates",
        "queryable": true
      },
      "estimate_item": {
        "resource": "/v1/estimate_items",
        "table": "estimate_items",
        "queryable": true
      },
      "document": {
        "resource": "/v1/documents",
        "table": "documents",
        "queryable": true
      },
      "folder": {
        "resource": "/v1/folders",
        "table": "document_folders",
        "queryable": true
      },
      "drawing_sheet": {
        "resource": "/v1/drawing_sheets",
        "table": "drawing_sheets",
        "queryable": true
      },
      "pin": {
        "resource": "/v1/pins",
        "table": "drawing_pins",
        "queryable": true
      },
      "workflow": {
        "resource": "/v1/workflows",
        "table": "document_workflow_instances",
        "queryable": true
      },
      "rfi": {
        "resource": "/v1/rfis",
        "table": "document_workflow_instances",
        "queryable": true
      },
      "conversation": {
        "resource": "/v1/conversations",
        "table": "conversations",
        "queryable": true
      },
      "invite": {
        "resource": "/v1/invites",
        "table": "company_invites",
        "queryable": false
      },
      "company_member": {
        "resource": "/v1/company_members",
        "table": "company_members",
        "queryable": false
      },
      "folder_access": {
        "resource": "/v1/folder_access",
        "table": "folder_access",
        "queryable": false
      },
      "company": {
        "resource": "/v1/company",
        "table": "companies",
        "queryable": false
      },
      "profile": {
        "resource": null,
        "table": "users",
        "reason": "Nothing on this entity is offered over the REST API (see unexposed kinds)."
      },
      "notification_prefs": {
        "resource": null,
        "table": "notification_preferences",
        "reason": "Nothing on this entity is offered over the REST API (see unexposed kinds)."
      },
      "location": {
        "resource": "/v1/locations",
        "table": "project_locations",
        "queryable": true
      },
      "site_induction": {
        "resource": "/v1/site_inductions",
        "table": "site_inductions",
        "queryable": true
      },
      "permit": {
        "resource": "/v1/permits",
        "table": "permits",
        "queryable": true
      },
      "delivery": {
        "resource": "/v1/deliveries",
        "table": "deliveries",
        "queryable": true
      },
      "material_request": {
        "resource": "/v1/material_requests",
        "table": "material_requests",
        "queryable": true
      },
      "meeting": {
        "resource": "/v1/meetings",
        "table": "meetings",
        "queryable": true
      },
      "submittal": {
        "resource": "/v1/submittals",
        "table": "document_workflow_instances",
        "queryable": true
      },
      "workflow_step": {
        "resource": "/v1/workflow_steps",
        "table": "workflow_instance_steps",
        "queryable": true
      },
      "project_contract": {
        "resource": "/v1/project_contracts",
        "table": "project_contracts",
        "queryable": true
      },
      "contract_event": {
        "resource": "/v1/contract_events",
        "table": "catalog_contract_events",
        "queryable": true
      },
      "inbound_email": {
        "resource": "/v1/inbound_emails",
        "table": "inbound_emails",
        "queryable": true
      },
      "bid_package": {
        "resource": "/v1/bid_packages",
        "table": "bid_packages",
        "queryable": true
      },
      "bid": {
        "resource": "/v1/bids",
        "table": "bids",
        "queryable": true
      },
      "service_request": {
        "resource": "/v1/service_requests",
        "table": "service_requests",
        "queryable": true
      },
      "handover_pack": {
        "resource": "/v1/handover_packs",
        "table": "handover_packs",
        "queryable": true
      },
      "site_attendance": {
        "resource": "/v1/site_attendance",
        "table": "site_attendance",
        "queryable": true
      },
      "work_calendar": {
        "resource": "/v1/work_calendars",
        "table": "work_calendars",
        "queryable": true
      },
      "estimate_section": {
        "resource": "/v1/estimate_sections",
        "table": "estimate_sections",
        "queryable": true
      },
      "estimate_option": {
        "resource": "/v1/estimate_options",
        "table": "estimate_options",
        "queryable": true
      },
      "takeoff_item": {
        "resource": "/v1/takeoff_items",
        "table": "takeoff_items",
        "queryable": true
      },
      "proposal_template": {
        "resource": "/v1/proposal_templates",
        "table": "proposal_templates",
        "queryable": true
      },
      "estimate_acceptance": {
        "resource": "/v1/estimate_acceptances",
        "table": "estimate_acceptances",
        "queryable": true
      },
      "selection_item": {
        "resource": "/v1/selection_items",
        "table": "selection_items",
        "queryable": true
      },
      "takeoff_suggestion": {
        "resource": "/v1/takeoff_suggestions",
        "table": "takeoff_suggestions",
        "queryable": true
      },
      "client_update": {
        "resource": "/v1/client_updates",
        "table": "client_updates",
        "queryable": true
      }
    },
    "kinds": {
      "company.update_details": {
        "operation": "POST /v1/company/actions/update_details"
      },
      "company_member.remove": {
        "operation": "POST /v1/company_members/actions/remove"
      },
      "company_member.set_permission": {
        "operation": "POST /v1/company_members/actions/set_permission"
      },
      "company_member.set_role": {
        "operation": "POST /v1/company_members/actions/set_role"
      },
      "contact.create": {
        "operation": "POST /v1/contacts"
      },
      "contact.delete": {
        "operation": "DELETE /v1/contacts/{id}"
      },
      "contact.toggle_status": {
        "operation": "POST /v1/contacts/{id}/actions/toggle_status"
      },
      "contact.update": {
        "operation": "PATCH /v1/contacts/{id}"
      },
      "conversation.add_member": {
        "operation": "POST /v1/conversations/{id}/actions/add_member"
      },
      "conversation.create": {
        "unexposed": "Only in the Konverge app: Pick the participants in the group screen."
      },
      "conversation.remove_member": {
        "operation": "POST /v1/conversations/{id}/actions/remove_member"
      },
      "conversation.send": {
        "operation": "POST /v1/conversations/{id}/actions/send"
      },
      "cost_code.create": {
        "operation": "POST /v1/cost_codes"
      },
      "cost_code.delete": {
        "operation": "DELETE /v1/cost_codes/{id}"
      },
      "cost_code.update": {
        "operation": "PATCH /v1/cost_codes/{id}"
      },
      "daily_log": {
        "operation": "POST /v1/daily_logs"
      },
      "daily_log.approve": {
        "operation": "POST /v1/daily_logs/{id}/actions/approve"
      },
      "daily_log.reject": {
        "operation": "POST /v1/daily_logs/{id}/actions/reject"
      },
      "daily_log.submit": {
        "operation": "POST /v1/daily_logs/{id}/actions/submit"
      },
      "daily_log.update": {
        "operation": "PATCH /v1/daily_logs/{id}"
      },
      "delivery.create": {
        "operation": "POST /v1/deliveries"
      },
      "document.approve": {
        "operation": "POST /v1/documents/{id}/actions/approve"
      },
      "document.comment": {
        "operation": "POST /v1/documents/{id}/actions/comment"
      },
      "document.delete": {
        "operation": "DELETE /v1/documents/{id}"
      },
      "document.reject": {
        "operation": "POST /v1/documents/{id}/actions/reject"
      },
      "document.submit_review": {
        "operation": "POST /v1/documents/{id}/actions/submit_review"
      },
      "document.update": {
        "operation": "PATCH /v1/documents/{id}"
      },
      "drawing_sheet.delete": {
        "operation": "DELETE /v1/drawing_sheets/{id}"
      },
      "drawing_sheet.update": {
        "operation": "PATCH /v1/drawing_sheets/{id}"
      },
      "equipment.create": {
        "operation": "POST /v1/equipment"
      },
      "equipment.delete": {
        "operation": "DELETE /v1/equipment/{id}"
      },
      "equipment.update": {
        "operation": "PATCH /v1/equipment/{id}"
      },
      "estimate.accept_for_client": {
        "unexposed": "Recording a client's acceptance is a person's decision (tier 3, typed confirmation); an API key never accepts an estimate. A client accepts in the portal or by e-signature."
      },
      "estimate.create": {
        "operation": "POST /v1/estimates"
      },
      "estimate.delete": {
        "operation": "DELETE /v1/estimates/{id}"
      },
      "estimate.duplicate": {
        "operation": "POST /v1/estimates/{id}/actions/duplicate"
      },
      "estimate.from_template": {
        "operation": "POST /v1/estimates/actions/from_template"
      },
      "estimate.revise": {
        "operation": "POST /v1/estimates/{id}/actions/revise"
      },
      "estimate.save_as_template": {
        "operation": "POST /v1/estimates/{id}/actions/save_as_template"
      },
      "estimate.set_status": {
        "operation": "POST /v1/estimates/{id}/actions/set_status"
      },
      "estimate.update": {
        "operation": "PATCH /v1/estimates/{id}"
      },
      "estimate_item.create": {
        "operation": "POST /v1/estimate_items"
      },
      "estimate_item.delete": {
        "operation": "DELETE /v1/estimate_items/{id}"
      },
      "estimate_item.update": {
        "operation": "PATCH /v1/estimate_items/{id}"
      },
      "estimate_option.create": {
        "operation": "POST /v1/estimate_options"
      },
      "estimate_option.select": {
        "operation": "POST /v1/estimate_options/{id}/actions/select"
      },
      "estimate_option.update": {
        "operation": "PATCH /v1/estimate_options/{id}"
      },
      "estimate_section.create": {
        "operation": "POST /v1/estimate_sections"
      },
      "estimate_section.delete": {
        "operation": "DELETE /v1/estimate_sections/{id}"
      },
      "estimate_section.update": {
        "operation": "PATCH /v1/estimate_sections/{id}"
      },
      "field_note": {
        "operation": "POST /v1/field_notes"
      },
      "field_note.acknowledge": {
        "operation": "POST /v1/field_notes/{id}/actions/acknowledge"
      },
      "field_note.resolve": {
        "operation": "POST /v1/field_notes/{id}/actions/resolve"
      },
      "field_note.to_task": {
        "operation": "POST /v1/field_notes/{id}/actions/to_task"
      },
      "field_note.update": {
        "operation": "PATCH /v1/field_notes/{id}"
      },
      "folder.create": {
        "operation": "POST /v1/folders"
      },
      "folder.delete": {
        "operation": "DELETE /v1/folders/{id}"
      },
      "folder.update": {
        "operation": "PATCH /v1/folders/{id}"
      },
      "folder_access.grant": {
        "operation": "POST /v1/folder_access/actions/grant"
      },
      "folder_access.revoke": {
        "operation": "POST /v1/folder_access/actions/revoke"
      },
      "incident.create": {
        "operation": "POST /v1/incidents"
      },
      "incident.set_status": {
        "operation": "POST /v1/incidents/{id}/actions/set_status"
      },
      "inspection.create": {
        "operation": "POST /v1/inspections"
      },
      "invite.create": {
        "operation": "POST /v1/invites"
      },
      "material_request.create": {
        "operation": "POST /v1/material_requests"
      },
      "material_request.submit": {
        "operation": "POST /v1/material_requests/{id}/actions/submit"
      },
      "meeting.create": {
        "operation": "POST /v1/meetings"
      },
      "milestone.create": {
        "operation": "POST /v1/milestones"
      },
      "milestone.delete": {
        "operation": "DELETE /v1/milestones/{id}"
      },
      "milestone.update": {
        "operation": "PATCH /v1/milestones/{id}"
      },
      "notification_prefs.update": {
        "unexposed": "An API key's account never receives notifications, so it has no preferences to set."
      },
      "permit.create": {
        "operation": "POST /v1/permits"
      },
      "permit.request": {
        "operation": "POST /v1/permits/{id}/actions/request"
      },
      "pin.comment": {
        "operation": "POST /v1/pins/{id}/actions/comment"
      },
      "pin.delete": {
        "operation": "DELETE /v1/pins/{id}"
      },
      "pin.set_status": {
        "operation": "POST /v1/pins/{id}/actions/set_status"
      },
      "pin.to_task": {
        "operation": "POST /v1/pins/{id}/actions/to_task"
      },
      "profile.update": {
        "unexposed": "An API key's account has no profile to edit: its name comes from the key, and a key renaming itself would pass its writes off as a person's. Rename or replace the key in Settings → Developers."
      },
      "project.add_member": {
        "operation": "POST /v1/projects/{id}/actions/add_member"
      },
      "project.create": {
        "operation": "POST /v1/projects"
      },
      "project.delete": {
        "operation": "DELETE /v1/projects/{id}"
      },
      "project.remove_member": {
        "operation": "POST /v1/projects/{id}/actions/remove_member"
      },
      "project.set_member_role": {
        "operation": "POST /v1/projects/{id}/actions/set_member_role"
      },
      "project.update": {
        "operation": "PATCH /v1/projects/{id}"
      },
      "punch_item": {
        "operation": "POST /v1/punch_items"
      },
      "punch_item.batch_complete": {
        "operation": "POST /v1/punch_items/actions/complete"
      },
      "punch_item.complete": {
        "operation": "POST /v1/punch_items/{id}/actions/complete"
      },
      "punch_item.reject": {
        "operation": "POST /v1/punch_items/{id}/actions/reject"
      },
      "punch_item.to_task": {
        "operation": "POST /v1/punch_items/{id}/actions/to_task"
      },
      "punch_list.create": {
        "operation": "POST /v1/punch_lists"
      },
      "rfi.answer": {
        "operation": "POST /v1/rfis/{id}/actions/answer"
      },
      "rfi.batch_take_action": {
        "operation": "POST /v1/rfis/actions/take_action"
      },
      "rfi.cancel": {
        "operation": "POST /v1/rfis/{id}/actions/cancel"
      },
      "rfi.comment": {
        "operation": "POST /v1/rfis/{id}/actions/comment"
      },
      "rfi.create": {
        "operation": "POST /v1/rfis"
      },
      "rfi.resubmit": {
        "operation": "POST /v1/rfis/{id}/actions/resubmit"
      },
      "rfi.take_action": {
        "operation": "POST /v1/rfis/{id}/actions/take_action"
      },
      "submittal.batch_take_action": {
        "operation": "POST /v1/submittals/actions/take_action"
      },
      "submittal.cancel": {
        "operation": "POST /v1/submittals/{id}/actions/cancel"
      },
      "submittal.create": {
        "operation": "POST /v1/submittals"
      },
      "submittal.resubmit": {
        "operation": "POST /v1/submittals/{id}/actions/resubmit"
      },
      "submittal.take_action": {
        "operation": "POST /v1/submittals/{id}/actions/take_action"
      },
      "takeoff_item.link": {
        "unexposed": "Takeoff quantities are measured by people on drawings; an API key's account is refused by the takeoff guard. Read takeoff items, or use the Konverge apps."
      },
      "takeoff_item.unlink": {
        "unexposed": "Takeoff quantities are changed by people on drawings; an API key's account is refused by the takeoff guard. Read takeoff items, or use the Konverge apps."
      },
      "task.assign": {
        "operation": "POST /v1/tasks/{id}/actions/assign"
      },
      "task.batch_assign": {
        "operation": "POST /v1/tasks/actions/assign"
      },
      "task.batch_set_status": {
        "operation": "POST /v1/tasks/actions/set_status"
      },
      "task.create": {
        "operation": "POST /v1/tasks"
      },
      "task.delete": {
        "operation": "DELETE /v1/tasks/{id}"
      },
      "task.set_status": {
        "operation": "POST /v1/tasks/{id}/actions/set_status"
      },
      "task.update": {
        "operation": "PATCH /v1/tasks/{id}"
      },
      "timesheet.clock_in": {
        "unexposed": "Clocking in records the caller's own attendance; an API key's account is not a person on site."
      },
      "timesheet.clock_out": {
        "unexposed": "Clocking out records the caller's own attendance; an API key's account is not a person on site."
      },
      "transaction.create": {
        "operation": "POST /v1/transactions"
      },
      "transaction.delete": {
        "operation": "DELETE /v1/transactions/{id}"
      },
      "transaction.update": {
        "operation": "PATCH /v1/transactions/{id}"
      },
      "workflow.batch_take_action": {
        "operation": "POST /v1/workflows/actions/take_action"
      },
      "workflow.cancel": {
        "operation": "POST /v1/workflows/{id}/actions/cancel"
      },
      "workflow.resubmit": {
        "operation": "POST /v1/workflows/{id}/actions/resubmit"
      },
      "workflow.take_action": {
        "operation": "POST /v1/workflows/{id}/actions/take_action"
      }
    }
  }
}
