{
  "openapi": "3.1.0",
  "info": {
    "title": "HailMate",
    "version": "2.1.0",
    "description": "Read and update a HailMate workspace: jobs, contacts, tasks and appointments, notes, estimates, invoices, payments, door knocks and hail history. Nothing here texts or emails a homeowner."
  },
  "servers": [
    {
      "url": "https://app.hailmate.ai/api/v1"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "paths": {
    "/jobs": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "listJobs",
        "summary": "List jobs",
        "description": "Newest first. Archived jobs are left out unless you ask for them.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          },
          {
            "name": "stage",
            "in": "query",
            "description": "A stage `key` from `/stages`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pipeline_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "job_type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "insurance",
                "retail"
              ]
            }
          },
          {
            "name": "assigned_to",
            "in": "query",
            "description": "A user id. Matches the primary assignee OR any co-assignee.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "description": "Jobs where this contact is the homeowner, the adjuster, or a secondary contact.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "archived",
            "in": "query",
            "description": "Omitted, only live jobs. `true` returns archived jobs, `any` returns both.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "any"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of jobs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Jobs"
        ],
        "operationId": "createJob",
        "summary": "Create a job",
        "description": "Only `name` and `address` are required. With no `stage` the job lands on the first column of your default pipeline. `stage` may be a stage **key** or its **label** as your board shows it (\"Claim Approved\"). `notes`, when sent, becomes the first note on the job's timeline.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/jobs/search": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "searchJobs",
        "summary": "Find jobs",
        "description": "`address` and `name` match part of the value (\"1804 Cedar\" finds \"1804 Cedar Ridge Dr\"); `job_number` and `claim_number` must match whole (case-insensitive). With no criteria the result is EMPTY — never \"the newest jobs\", which is how a blank search step writes to the wrong job.",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "job_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "claim_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching jobs, newest first. Not paged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/jobs/{id}": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "getJob",
        "summary": "Get a job",
        "responses": {
          "200": {
            "description": "The job.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Jobs"
        ],
        "operationId": "updateJob",
        "summary": "Update a job",
        "description": "Send only the fields to change. A field sent as `null` (or `\"\"`) is cleared; a field left out is untouched. `name` and `address` cannot be cleared. **Moving a job** is `{\"stage\": \"Claim Approved\"}` — a key or a label.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JobUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The job, as it is now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/jobs/{id}/notes": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "listJobNotes",
        "summary": "List a job's notes",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of notes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NoteList"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/jobs/{id}/messages": {
      "get": {
        "tags": [
          "Messages"
        ],
        "operationId": "listJobMessages",
        "summary": "Read a job's texts, emails and calls",
        "description": "The job's conversation, newest first — the same history the job's page shows: its own messages and the threads they started. Use it to answer \"what did the homeowner say?\" before writing back.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/MessageChannel"
          },
          {
            "$ref": "#/components/parameters/MessageDirection"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of messages.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageList"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/jobs/{id}/photos": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "listJobPhotos",
        "summary": "List a job's photos",
        "description": "`/jobs/{id}/files?category=photo`, as its own path.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of photos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/contacts": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "operationId": "createContact",
        "summary": "Create a contact",
        "description": "At least one of a name, `email`, `phone` or `company` is required — a contact with none of them is refused rather than filling your CRM with blank rows. Send `name` alone and it is split into first and last. US phone numbers are stored as `(615) 555-0148`, the way your team types them.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          }
        }
      }
    },
    "/contacts/search": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "searchContacts",
        "summary": "Find contacts",
        "description": "Tries `email` first, then `phone`, then `name`, and returns the first that matches. A phone number matches however it was typed into HailMate — `+16155550148`, `615-555-0148` and `(615) 555-0148` are the same number. `name` matches a first name, last name, \"first last\" or a company.",
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching contacts. Not paged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/contacts/{id}": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "getContact",
        "summary": "Get a contact",
        "responses": {
          "200": {
            "description": "The contact.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Contacts"
        ],
        "operationId": "updateContact",
        "summary": "Update a contact",
        "description": "Send only the fields to change; `null` clears a field.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The contact, as it is now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/contacts/{id}/jobs": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "listContactJobs",
        "summary": "List a contact's jobs",
        "description": "Every job this person is on — as homeowner, adjuster or secondary contact — archived included.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of jobs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/texts": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "sendText",
        "summary": "Send a text message",
        "description": "Texts a contact (their main number) or a number, FOR REAL, from the sending rep's own HailMate number, into their inbox thread. Refused if the number replied STOP. Confirm the wording and recipient with the person before sending. At most 20 sends a minute per key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TextSend"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        }
      }
    },
    "/emails": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "sendEmail",
        "summary": "Send an email",
        "description": "Emails a contact (their address) or named addresses, FOR REAL, from the sending rep's connected mailbox when they have one, else the company address. The body is Markdown. Attach a job's files by file_id. Confirm the wording and recipient with the person before sending.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailSend"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          }
        }
      }
    },
    "/tasks": {
      "get": {
        "tags": [
          "Tasks"
        ],
        "operationId": "listTasks",
        "summary": "List tasks and appointments",
        "description": "`/appointments` is the same list narrowed to appointments.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          },
          {
            "name": "completed",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "appointments",
            "in": "query",
            "description": "`true` returns appointments only.",
            "schema": {
              "type": "string",
              "enum": [
                "true"
              ]
            }
          },
          {
            "name": "job_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "assigned_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "due_after",
            "in": "query",
            "description": "Wall-clock, e.g. `2026-10-01` or `2026-10-01T08:00:00`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "due_before",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of tasks.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Tasks"
        ],
        "operationId": "createTask",
        "summary": "Create a task or an appointment",
        "description": "Set `appointment_type` (`inspection`, `adjuster_meeting`, `build_day`) to make it an appointment; `POST /appointments` requires one. **Times are wall-clock.** `due_date` is the local time your crew will read.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          }
        }
      }
    },
    "/tasks/{id}": {
      "patch": {
        "tags": [
          "Tasks"
        ],
        "operationId": "updateTask",
        "summary": "Update a task",
        "description": "Reschedule it, reassign it, or finish it with `{\"completed\": true}` (fires `task.completed`). `null` clears a field.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The task, as it is now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/estimates": {
      "get": {
        "tags": [
          "Estimates"
        ],
        "operationId": "listEstimates",
        "summary": "List estimates",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "sent",
                "viewed",
                "signed",
                "expired",
                "declined"
              ]
            }
          },
          {
            "name": "job_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "estimate_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of estimates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Estimates"
        ],
        "operationId": "createEstimate",
        "summary": "Create an estimate",
        "description": "Makes a **draft** estimate on a job, one of two ways — the same two the app offers: - **From one of your templates** (`template_id`, from `GET /estimate_templates`): an exact copy, with its smart fields (`{{customer_name}}`, `{{property_address}}`…) filled in from the job.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EstimateCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created, as a draft.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/estimates/{id}": {
      "get": {
        "tags": [
          "Estimates"
        ],
        "operationId": "getEstimate",
        "summary": "Get an estimate",
        "responses": {
          "200": {
            "description": "The estimate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/estimate_templates": {
      "get": {
        "tags": [
          "Estimates"
        ],
        "operationId": "listEstimateTemplates",
        "summary": "List estimate templates",
        "description": "The workspace's own templates, most recently changed first — what a \"which template?\" dropdown lists.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "The templates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateTemplateList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/invoices": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "operationId": "listInvoices",
        "summary": "List invoices",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "$ref": "#/components/parameters/UpdatedSince"
          },
          {
            "$ref": "#/components/parameters/CreatedAfter"
          },
          {
            "$ref": "#/components/parameters/CreatedBefore"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "sent",
                "viewed",
                "partially_paid",
                "paid",
                "overdue",
                "void",
                "bad_debt"
              ]
            }
          },
          {
            "name": "job_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "invoice_number",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Invoices"
        ],
        "operationId": "createInvoice",
        "summary": "Create an invoice",
        "description": "Makes a **draft** invoice for a job (`job_id`) or a contact (`contact_id`), with at least one line. HailMate numbers it (`INV-0312`) and totals it with the same calculator the app uses: lines, minus any discount, plus tax on the taxable lines. A negative price is a credit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created, as a draft.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/invoices/{id}": {
      "get": {
        "tags": [
          "Invoices"
        ],
        "operationId": "getInvoice",
        "summary": "Get an invoice",
        "responses": {
          "200": {
            "description": "The invoice.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "parameters": [
        {
          "$ref": "#/components/parameters/Id"
        }
      ]
    },
    "/payments": {
      "post": {
        "tags": [
          "Payments"
        ],
        "operationId": "createPayment",
        "summary": "Record a payment",
        "description": "Records money that arrived — a cheque logged in your accounting app, a deposit from a bank feed. The job's money and, when you name one, the invoice's balance and status update exactly as they do for a payment logged in HailMate.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaymentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          }
        }
      }
    },
    "/notes": {
      "post": {
        "tags": [
          "Notes"
        ],
        "operationId": "createNote",
        "summary": "Add a note to a job",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoteCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          }
        }
      }
    },
    "/hail_history": {
      "get": {
        "tags": [
          "Hail"
        ],
        "operationId": "getHailHistory",
        "summary": "Hail and wind history at an address",
        "description": "Every hail day and damaging-wind day at an address (or a latitude and longitude) since `since` — the same Evidence Grade™ ruling HailMate shows on its maps and storm reports, combining radar-estimated hail size, severe-hail probability and verified ground reports.",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "description": "A US street address. Or send `latitude` and `longitude`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "latitude",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "longitude",
            "in": "query",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "`YYYY-MM-DD`. Defaults to five years ago.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HailReport"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/stages": {
      "get": {
        "tags": [
          "Lookups"
        ],
        "operationId": "listStages",
        "summary": "List pipeline stages",
        "description": "Every stage on every board. `key` is what you send and filter on; `label` is what to show a person. `/pipeline_stages` is the same list.",
        "responses": {
          "200": {
            "description": "The stages, default pipeline first, in board order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PipelineStage"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/users": {
      "get": {
        "tags": [
          "Lookups"
        ],
        "operationId": "listUsers",
        "summary": "List your team",
        "responses": {
          "200": {
            "description": "The workspace's people.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "parameters": {
      "CreatedAfter": {
        "name": "created_after",
        "in": "query",
        "description": "Only records created at or after this ISO date or date-time.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "CreatedBefore": {
        "name": "created_before",
        "in": "query",
        "description": "Only records created before this ISO date or date-time.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "The `next_cursor` from the previous page, exactly as received. A cursor we did not issue is a 400.",
        "schema": {
          "type": "string"
        }
      },
      "Id": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Page size. Out-of-range values fall back to the default.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "MessageChannel": {
        "name": "channel",
        "in": "query",
        "description": "Only this kind of message.",
        "schema": {
          "type": "string",
          "enum": [
            "text",
            "email",
            "call",
            "voicemail"
          ]
        }
      },
      "MessageDirection": {
        "name": "direction",
        "in": "query",
        "description": "inbound (they wrote or called us) or outbound (we did).",
        "schema": {
          "type": "string",
          "enum": [
            "inbound",
            "outbound"
          ]
        }
      },
      "UpdatedSince": {
        "name": "updated_since",
        "in": "query",
        "description": "Only records changed at or after this ISO date or date-time. The way to sync only what moved.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "responses": {
      "Conflict": {
        "description": "A conflict: an Idempotency-Key clash, a record in a state that refuses the change, or a send refused (the number replied STOP, or the rep has no texting number).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "A read-only key tried to change something.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InvalidRequest": {
        "description": "Something in the request was wrong; `field` names what.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such record in this workspace.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Over 120 requests a minute (or 20 hail lookups a minute). Wait `Retry-After` seconds.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The key is missing, wrong or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "contact"
          },
          "first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "full_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone_label": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "mobile",
              "office",
              "home",
              "work",
              "fax",
              "other",
              null
            ]
          },
          "additional_phones": {
            "type": "array",
            "description": "Up to five more numbers, each belonging to this contact only.",
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string"
                },
                "label": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "$ref": "#/components/schemas/ContactType"
          },
          "trades": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "For a subcontractor — gutters, siding…"
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "claim_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "adjuster_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "adjuster_extension": {
            "type": [
              "string",
              "null"
            ]
          },
          "assigned_to_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "assigned_to_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "ContactCreate": {
        "type": "object",
        "description": "At least one of a name, email, phone or company.",
        "properties": {
          "name": {
            "type": "string",
            "description": "A full name, split into first and last when those are not sent."
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phone": {
            "type": "string",
            "description": "Any format."
          },
          "phone_label": {
            "type": "string",
            "enum": [
              "mobile",
              "office",
              "home",
              "work",
              "fax",
              "other"
            ]
          },
          "additional_phones": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            },
            "description": "Up to five more numbers: [{phone, label}]."
          },
          "company": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/ContactType"
          },
          "trades": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "address": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "postal_code": {
            "type": "string"
          },
          "notes": {
            "type": "string"
          },
          "claim_number": {
            "type": "string"
          },
          "adjuster_type": {
            "type": "string"
          },
          "adjuster_extension": {
            "type": "string"
          },
          "assigned_to": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "ContactList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          }
        ]
      },
      "ContactType": {
        "type": "string",
        "enum": [
          "homeowner",
          "commercial",
          "adjuster",
          "contractor",
          "subcontractor",
          "install_crew",
          "inspector",
          "mortgage_company",
          "other"
        ]
      },
      "ContactUpdate": {
        "type": "object",
        "description": "Any subset of ContactCreate's fields (except `name`). `null` clears.",
        "properties": {
          "first_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone_label": {
            "type": [
              "string",
              "null"
            ]
          },
          "additional_phones": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "phone": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            },
            "description": "Replaces the list."
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "$ref": "#/components/schemas/ContactType"
          },
          "trades": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "claim_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "adjuster_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "adjuster_extension": {
            "type": [
              "string",
              "null"
            ]
          },
          "assigned_to": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "EmailSend": {
        "type": "object",
        "required": [
          "subject",
          "body"
        ],
        "description": "Name the recipient — a contact_id or addresses in `to`.",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Emails the contact's address."
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "subject": {
            "type": "string",
            "maxLength": 300
          },
          "body": {
            "type": "string",
            "description": "Markdown."
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "invoice_id": {
            "type": "string",
            "format": "uuid"
          },
          "from_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "The teammate it is sent as. Default: whoever made the key or connected the app."
          },
          "send_as": {
            "type": "string",
            "enum": [
              "mailbox",
              "workspace"
            ],
            "description": "mailbox (default when connected) sends from the rep's own email; workspace from the company address."
          },
          "attachments": {
            "type": "array",
            "description": "At most 5. A file on the job by file_id, or a public https link elsewhere.",
            "items": {
              "type": "object",
              "properties": {
                "file_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "filename": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message",
              "doc_url"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "unauthorized",
                  "forbidden",
                  "not_found",
                  "invalid_request",
                  "conflict",
                  "payload_too_large",
                  "rate_limited",
                  "plan_required",
                  "method_not_allowed",
                  "server_error"
                ],
                "description": "Machine-readable. Branch on this."
              },
              "message": {
                "type": "string",
                "description": "For a person. May be reworded."
              },
              "field": {
                "type": "string",
                "description": "The request field that was wrong, when there was one."
              },
              "request_id": {
                "type": "string"
              },
              "doc_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "Estimate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "estimate"
          },
          "estimate_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "document_type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "proposal",
              "estimate",
              null
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "draft",
              "sent",
              "viewed",
              "signed",
              "expired",
              "declined",
              null
            ]
          },
          "signature_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "total": {
            "type": [
              "number",
              "null"
            ],
            "description": "The selected package's price, else the base package. Null — never 0 — when it could not be computed."
          },
          "package_totals": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {
              "type": "number"
            },
            "description": "Every package's price, keyed by package."
          },
          "upgrades_total": {
            "type": [
              "number",
              "null"
            ],
            "description": "Optional upgrades, quoted outside the package price."
          },
          "selected_tier": {
            "type": [
              "string",
              "null"
            ],
            "description": "The package the homeowner chose."
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "valid_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "first_viewed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_viewed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "view_count": {
            "type": "integer"
          },
          "signed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "signer_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "pdf_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "signed_pdf_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "view_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The homeowner's view of the estimate."
          },
          "line_items": {
            "type": "array",
            "description": "What is on the estimate. Only on `GET /estimates/{id}`; lists and webhooks leave it out.",
            "items": {
              "$ref": "#/components/schemas/EstimateLine"
            }
          }
        }
      },
      "EstimateCreate": {
        "type": "object",
        "required": [
          "job_id"
        ],
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "description": "One of your templates. Leave out for your standard proposal."
          },
          "title": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "One price for the whole job."
          },
          "valid_until": {
            "type": "string",
            "format": "date",
            "description": "Defaults to your workspace's setting."
          },
          "line_items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/LineItemInput"
            },
            "description": "The Scope of Work, without a template. Leave out for the standard checklist."
          }
        }
      },
      "EstimateLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "estimate_line"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "quantity": {
            "type": [
              "number",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ],
            "description": "sq, lf, ea…"
          },
          "unit_price": {
            "type": [
              "number",
              "null"
            ]
          },
          "line_total": {
            "type": [
              "number",
              "null"
            ]
          },
          "option": {
            "type": [
              "string",
              "null"
            ],
            "description": "The package the line belongs to (good, better, best). Null = every package."
          },
          "optional": {
            "type": "boolean",
            "description": "An optional upgrade the homeowner can add."
          }
        }
      },
      "EstimateList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Estimate"
                }
              }
            }
          }
        ]
      },
      "EstimateTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "estimate_template"
          },
          "name": {
            "type": "string"
          },
          "template_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EstimateTemplateList": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EstimateTemplate"
            }
          },
          "has_more": {
            "type": "boolean",
            "const": false
          },
          "next_cursor": {
            "type": "null"
          }
        }
      },
      "File": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "file"
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "enum": [
              "photo",
              "document",
              "scope",
              "estimate",
              "contract",
              "other"
            ]
          },
          "mime_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_photo": {
            "type": "boolean"
          },
          "is_video": {
            "type": "boolean"
          },
          "size_bytes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "The caption."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "description": "Where a photo was taken."
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "taken_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "uploaded_by_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "uploaded_by_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "download_url": {
            "type": "string",
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        }
      },
      "FileList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/File"
                }
              }
            }
          }
        ]
      },
      "HailEvent": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "size_in": {
            "type": [
              "number",
              "null"
            ],
            "description": "The size HailMate stands behind for this day at this address."
          },
          "confidence": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "confirmed",
              "likely",
              "radar",
              null
            ]
          },
          "confirmed_by_ground_report": {
            "type": "boolean"
          },
          "radar_estimated_size_in": {
            "type": [
              "number",
              "null"
            ]
          },
          "severe_hail_probability": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Percent."
          },
          "ground_report_size_in": {
            "type": [
              "number",
              "null"
            ]
          },
          "ground_report_distance_mi": {
            "type": [
              "number",
              "null"
            ]
          },
          "ground_report_count": {
            "type": "integer"
          }
        }
      },
      "HailReport": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "hail_report"
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "description": "The address as it was found."
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "since": {
            "type": "string",
            "format": "date"
          },
          "hail_day_count": {
            "type": "integer"
          },
          "largest_hail_in": {
            "type": [
              "number",
              "null"
            ]
          },
          "last_hail_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "hail_events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HailEvent"
            }
          },
          "wind_events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "max_gust_mph": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Null when the report was damage with no measured gust."
                }
              }
            }
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "invoice"
          },
          "invoice_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "sent",
              "viewed",
              "partially_paid",
              "paid",
              "overdue",
              "void",
              "bad_debt"
            ]
          },
          "purpose": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "claim_scope",
              "deductible",
              "supplement",
              "depreciation",
              "contract",
              "other",
              null
            ]
          },
          "subtotal": {
            "type": [
              "number",
              "null"
            ]
          },
          "discount_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "tax_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "late_fee_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "total_amount": {
            "type": "number"
          },
          "amount_paid": {
            "type": "number"
          },
          "balance_due": {
            "type": "number",
            "description": "`total_amount - amount_paid`, never below zero."
          },
          "part_number": {
            "type": [
              "integer",
              "null"
            ],
            "description": "When billed in parts, which part this is."
          },
          "part_count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "issue_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "first_viewed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "paid_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "estimate_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pdf_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "payment_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The homeowner's pay page — the same link \"Copy Pay Link\" gives."
          },
          "line_items": {
            "type": "array",
            "description": "What is billed. Only on `GET /invoices/{id}`; lists and webhooks leave it out.",
            "items": {
              "$ref": "#/components/schemas/InvoiceLine"
            }
          }
        }
      },
      "InvoiceCreate": {
        "type": "object",
        "required": [
          "line_items"
        ],
        "description": "Needs a `job_id` or a `contact_id`.",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Who it bills."
          },
          "estimate_id": {
            "type": "string",
            "format": "uuid"
          },
          "title": {
            "type": "string"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "claim_scope",
              "deductible",
              "supplement",
              "depreciation",
              "contract",
              "other"
            ]
          },
          "issue_date": {
            "type": "string",
            "format": "date",
            "description": "Defaults to today."
          },
          "due_date": {
            "type": "string",
            "format": "date"
          },
          "line_items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/LineItemInput"
            }
          },
          "tax_rate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "description": "A percent",
            "on the taxable lines.": null
          },
          "discount_type": {
            "type": "string",
            "enum": [
              "amount",
              "percent"
            ]
          },
          "discount_value": {
            "type": "number",
            "minimum": 0
          },
          "notes": {
            "type": "string"
          },
          "terms": {
            "type": "string"
          },
          "allow_partial_payments": {
            "type": "boolean"
          }
        }
      },
      "InvoiceLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "invoice_line"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "quantity": {
            "type": [
              "number",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "unit_price": {
            "type": [
              "number",
              "null"
            ]
          },
          "line_total": {
            "type": [
              "number",
              "null"
            ]
          },
          "taxable": {
            "type": "boolean"
          },
          "late_fee": {
            "type": "boolean",
            "description": "A late fee HailMate added."
          }
        }
      },
      "InvoiceList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Invoice"
                }
              }
            }
          }
        ]
      },
      "Job": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "job"
          },
          "job_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "job_type": {
            "type": "string",
            "enum": [
              "insurance",
              "retail"
            ]
          },
          "stage": {
            "type": [
              "string",
              "null"
            ],
            "description": "The stage key. Filter on this."
          },
          "stage_label": {
            "type": [
              "string",
              "null"
            ],
            "description": "The stage as your board names it."
          },
          "stage_is_completed": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "The stage is a won / completed column."
          },
          "stage_is_lost": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "The stage is a lost column."
          },
          "stage_entered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "pipeline_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "pipeline_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": [
              "string",
              "null"
            ],
            "description": "Two-letter code."
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "county": {
            "type": [
              "string",
              "null"
            ]
          },
          "homeowner_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "homeowner": {
            "$ref": "#/components/schemas/PersonRef"
          },
          "adjuster_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "adjuster": {
            "$ref": "#/components/schemas/PersonRef"
          },
          "secondary_contact_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "secondary_adjuster_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "assigned_to_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The primary assignee."
          },
          "assigned_to_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "assignee_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Everyone on the job, primary included."
          },
          "assignee_names": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "insurance_company": {
            "type": [
              "string",
              "null"
            ]
          },
          "claim_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "policy_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "date_of_loss": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "damage_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "cover_photo_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The photo shown as the job's cover."
          },
          "lead_source": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "normal",
              "high",
              "urgent",
              null
            ]
          },
          "mortgage_company": {
            "type": [
              "string",
              "null"
            ]
          },
          "financing_method": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "cash",
              "check",
              "credit_card",
              "financing",
              "other",
              null
            ]
          },
          "rcv_amount": {
            "type": [
              "number",
              "null"
            ],
            "description": "Replacement cost value on the claim."
          },
          "acv_amount": {
            "type": [
              "number",
              "null"
            ],
            "description": "Actual cash value."
          },
          "deductible": {
            "type": [
              "number",
              "null"
            ]
          },
          "supplements_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "estimated_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "final_amount": {
            "type": [
              "number",
              "null"
            ],
            "description": "Contract value on a retail job."
          },
          "total_job_value": {
            "type": [
              "number",
              "null"
            ],
            "description": "What the job is worth — the same figure the Money tab shows."
          },
          "amount_received": {
            "type": [
              "number",
              "null"
            ],
            "description": "Money received on the job so far."
          },
          "balance_due": {
            "type": [
              "number",
              "null"
            ]
          },
          "contract_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "installation_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "archived": {
            "type": "boolean"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lost_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lost_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Opens the job in HailMate."
          },
          "portal_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The homeowner's job page — the same link \"Copy Homeowner Link\" gives."
          }
        }
      },
      "JobCreate": {
        "type": "object",
        "required": [
          "name",
          "address"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200,
            "description": "`job_name` works too."
          },
          "address": {
            "type": "string",
            "maxLength": 300,
            "description": "`property_address` works too."
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "description": "A code or a name — \"TX\" or \"Texas\"."
          },
          "postal_code": {
            "type": "string",
            "description": "`zip` works too."
          },
          "county": {
            "type": "string"
          },
          "job_type": {
            "type": "string",
            "enum": [
              "insurance",
              "retail"
            ],
            "default": "insurance"
          },
          "stage": {
            "type": "string",
            "description": "A stage key or label. Defaults to the first stage of the default pipeline."
          },
          "pipeline_id": {
            "type": "string",
            "format": "uuid"
          },
          "homeowner_id": {
            "type": "string",
            "format": "uuid"
          },
          "adjuster_id": {
            "type": "string",
            "format": "uuid"
          },
          "assigned_to": {
            "type": "string",
            "format": "uuid",
            "description": "A teammate's user id from `/users`."
          },
          "lead_source": {
            "type": "string"
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "normal",
              "high",
              "urgent"
            ]
          },
          "insurance_company": {
            "type": "string"
          },
          "claim_number": {
            "type": "string"
          },
          "policy_number": {
            "type": "string"
          },
          "date_of_loss": {
            "type": "string",
            "format": "date"
          },
          "mortgage_company": {
            "type": "string"
          },
          "financing_method": {
            "type": "string",
            "enum": [
              "cash",
              "check",
              "credit_card",
              "financing",
              "other"
            ]
          },
          "rcv_amount": {
            "type": "number"
          },
          "acv_amount": {
            "type": "number"
          },
          "deductible": {
            "type": "number"
          },
          "supplements_amount": {
            "type": "number"
          },
          "estimated_amount": {
            "type": "number"
          },
          "final_amount": {
            "type": "number"
          },
          "contract_date": {
            "type": "string",
            "format": "date"
          },
          "installation_date": {
            "type": "string",
            "format": "date"
          },
          "damage_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Or a comma-separated string."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Or a comma-separated string."
          },
          "assignee_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Every rep on the job (user ids). assigned_to, if sent, is the primary."
          },
          "secondary_contact_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Other contacts on the job."
          },
          "secondary_adjuster_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "More adjusters (insurance jobs)."
          },
          "notes": {
            "type": "string",
            "description": "Becomes the first note on the job."
          }
        }
      },
      "JobList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          }
        ]
      },
      "JobUpdate": {
        "type": "object",
        "description": "Any subset of JobCreate's fields (except `notes`), plus `archived` and `lost_reason`. `null` clears.",
        "properties": {
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": [
              "string",
              "null"
            ]
          },
          "postal_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "county": {
            "type": [
              "string",
              "null"
            ]
          },
          "job_type": {
            "type": "string",
            "enum": [
              "insurance",
              "retail"
            ]
          },
          "stage": {
            "type": "string"
          },
          "pipeline_id": {
            "type": "string",
            "format": "uuid"
          },
          "homeowner_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "adjuster_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "assigned_to": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "lead_source": {
            "type": [
              "string",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "normal",
              "high",
              "urgent",
              null
            ]
          },
          "insurance_company": {
            "type": [
              "string",
              "null"
            ]
          },
          "claim_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "policy_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "date_of_loss": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "mortgage_company": {
            "type": [
              "string",
              "null"
            ]
          },
          "financing_method": {
            "type": [
              "string",
              "null"
            ]
          },
          "rcv_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "acv_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "deductible": {
            "type": [
              "number",
              "null"
            ]
          },
          "supplements_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "estimated_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "final_amount": {
            "type": [
              "number",
              "null"
            ]
          },
          "contract_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "installation_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "damage_types": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "archived": {
            "type": "boolean"
          },
          "lost_reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "assignee_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Every rep on the job, replacing the list. The primary (assigned_to) stays on it."
          },
          "secondary_contact_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "secondary_adjuster_ids": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "cover_photo_file_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "One of this job's photos (from list_job_photos) to show as its cover; null removes it."
          }
        }
      },
      "LineItemInput": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "quantity": {
            "type": "number",
            "minimum": 0,
            "default": 1
          },
          "unit": {
            "type": "string",
            "description": "sq, lf, ea…"
          },
          "unit_price": {
            "type": "number",
            "description": "Required on an invoice line. Negative on an invoice is a credit."
          },
          "taxable": {
            "type": "boolean",
            "default": true,
            "description": "Invoices only."
          }
        }
      },
      "ListMeta": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass back as `?cursor=`. `null` means that was the last page."
          }
        }
      },
      "Message": {
        "type": "object",
        "description": "One text, email, call or voicemail.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "message"
          },
          "channel": {
            "type": "string",
            "enum": [
              "text",
              "email",
              "call",
              "voicemail"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "estimate_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "invoice_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "rep_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The teammate it was sent by or to."
          },
          "rep_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "to": {
            "description": "Outbound text: the number. Email: the addresses. Inbound text: null."
          },
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "Email only: the sender's address."
          },
          "subject": {
            "type": [
              "string",
              "null"
            ]
          },
          "body": {
            "type": [
              "string",
              "null"
            ],
            "description": "The text, the email's plain body, or a voicemail transcript."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "sent, delivered, failed, received, opened…"
          },
          "delivery_error": {
            "type": [
              "string",
              "null"
            ]
          },
          "call_status": {
            "type": [
              "string",
              "null"
            ]
          },
          "call_duration_seconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "description": "A call's written summary."
          },
          "recording_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "thread_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "ai_drafted": {
            "type": "boolean"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "opened_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "read_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        }
      },
      "MessageList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Message"
                }
              }
            }
          }
        ]
      },
      "Note": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "note"
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "content": {
            "type": "string"
          },
          "author_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Null for a note written through the API."
          },
          "author_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "NoteCreate": {
        "type": "object",
        "required": [
          "job_id",
          "content"
        ],
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "content": {
            "type": "string",
            "maxLength": 10000
          }
        }
      },
      "NoteList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          }
        ]
      },
      "Payment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "payment"
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "invoice_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "amount": {
            "type": "number",
            "description": "Negative for a refund."
          },
          "payment_type": {
            "$ref": "#/components/schemas/PaymentType"
          },
          "payer_type": {
            "type": "string",
            "enum": [
              "insurance",
              "homeowner",
              "mortgage_company",
              "other"
            ]
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "check",
              "cash",
              "card",
              "ach",
              "financing",
              "other"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "expected",
              "received",
              "sent_to_mortgage",
              "endorsed",
              "deposited"
            ]
          },
          "check_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "date_received": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "date_deposited": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_refund": {
            "type": "boolean"
          },
          "refund_of_payment_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "online": {
            "type": "boolean",
            "description": "Paid through HailMate's online payment page."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          }
        }
      },
      "PaymentCreate": {
        "type": "object",
        "required": [
          "job_id",
          "amount"
        ],
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "invoice_id": {
            "type": "string",
            "format": "uuid",
            "description": "An invoice ON THIS JOB to apply it to. Never guessed."
          },
          "payment_type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentType"
              }
            ],
            "default": "other"
          },
          "payer_type": {
            "type": "string",
            "enum": [
              "insurance",
              "homeowner",
              "mortgage_company",
              "other"
            ],
            "default": "homeowner"
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "check",
              "cash",
              "card",
              "ach",
              "financing",
              "other"
            ],
            "default": "check"
          },
          "status": {
            "type": "string",
            "enum": [
              "expected",
              "received",
              "sent_to_mortgage",
              "endorsed",
              "deposited"
            ],
            "default": "received"
          },
          "check_number": {
            "type": "string"
          },
          "date_received": {
            "type": "string",
            "format": "date",
            "description": "Defaults to today (US Central)."
          },
          "date_deposited": {
            "type": "string",
            "format": "date"
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "PaymentType": {
        "type": "string",
        "enum": [
          "acv",
          "deductible",
          "supplement",
          "depreciation",
          "retail",
          "other"
        ]
      },
      "PersonRef": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "PipelineStage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "pipeline_stage"
          },
          "pipeline_id": {
            "type": "string",
            "format": "uuid"
          },
          "key": {
            "type": "string",
            "description": "What you send and filter on."
          },
          "label": {
            "type": "string",
            "description": "What to show a person."
          },
          "color": {
            "type": [
              "string",
              "null"
            ]
          },
          "order": {
            "type": "integer"
          },
          "is_completed": {
            "type": "boolean"
          },
          "is_lost": {
            "type": "boolean"
          }
        }
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "task"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "description": "Wall-clock — the local time the crew reads. No offset."
          },
          "end_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "The last day of a task that blocks off several days."
          },
          "duration_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "low",
              "normal",
              "high",
              null
            ]
          },
          "completed": {
            "type": "boolean"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "is_appointment": {
            "type": "boolean"
          },
          "appointment_type": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "inspection",
              "adjuster_meeting",
              "build_day",
              null
            ]
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "completed",
              "no_show",
              "rescheduled",
              "canceled",
              null
            ]
          },
          "customer_reminder": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "none",
              "sms",
              "email",
              "both",
              null
            ],
            "description": "Whether HailMate reminds the homeowner the day before."
          },
          "reminder_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "assigned_to_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "assigned_to_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "TaskCreate": {
        "type": "object",
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "description": {
            "type": "string"
          },
          "due_date": {
            "type": "string",
            "description": "A date or date-time. Any offset is dropped; the digits are kept."
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "duration_minutes": {
            "type": "integer",
            "minimum": 15,
            "maximum": 480
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "normal",
              "high"
            ]
          },
          "appointment_type": {
            "type": "string",
            "enum": [
              "inspection",
              "adjuster_meeting",
              "build_day"
            ]
          },
          "customer_reminder": {
            "type": "string",
            "enum": [
              "none",
              "sms",
              "email",
              "both"
            ],
            "description": "Remind the homeowner the day before."
          },
          "reminder_minutes": {
            "type": "integer",
            "enum": [
              -1,
              0,
              5,
              10,
              15,
              30,
              60,
              120,
              1440
            ]
          },
          "job_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "assigned_to": {
            "type": "string",
            "format": "uuid"
          },
          "completed": {
            "type": "boolean"
          }
        }
      },
      "TaskList": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            }
          }
        ]
      },
      "TaskUpdate": {
        "type": "object",
        "description": "Any subset of TaskCreate's fields, plus `outcome`. `null` clears.",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ]
          },
          "end_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "duration_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "priority": {
            "type": [
              "string",
              "null"
            ]
          },
          "appointment_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "completed",
              "no_show",
              "rescheduled",
              "canceled",
              null
            ]
          },
          "customer_reminder": {
            "type": "string"
          },
          "reminder_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "job_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "contact_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "assigned_to": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "completed": {
            "type": "boolean"
          }
        }
      },
      "TextSend": {
        "type": "object",
        "required": [
          "body"
        ],
        "description": "Name the recipient — a contact_id or a number in `to`.",
        "properties": {
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "description": "Texts the contact's main number."
          },
          "to": {
            "type": "string",
            "description": "A phone number, e.g. (972) 555-0148 or +19725550148."
          },
          "body": {
            "type": "string",
            "maxLength": 1600
          },
          "job_id": {
            "type": "string",
            "format": "uuid",
            "description": "Files the text on this job too."
          },
          "from_user_id": {
            "type": "string",
            "format": "uuid",
            "description": "The teammate it is sent as (must have a HailMate number). Default: whoever made the key or connected the app."
          },
          "media_urls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Public https images",
            "at most 10.": null
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "object": {
            "type": "string",
            "const": "user"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "admin",
              "member"
            ]
          }
        }
      }
    }
  }
}
