{
  "openapi": "3.1.0",
  "info": {
    "title": "Galaxy Unit API",
    "version": "1.0.0",
    "description": "REST for AI agents and scripts. A key acts as the member who made it (never above admin) under row-level security. Money is a decimal string. Dates are YYYY-MM-DD in the business time zone (see /me). Errors carry code, field and a hint the agent can act on. Read /for-agents first: https://galaxyunit.app/for-agents",
    "contact": {
      "url": "https://galaxyunit.app/contact"
    },
    "termsOfService": "https://galaxyunit.app/terms"
  },
  "servers": [
    {
      "url": "https://app.galaxyunit.app"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer gu_live_… — issued in Settings → Integrations by an owner or admin."
      }
    }
  },
  "paths": {
    "/api/v1/me": {
      "get": {
        "operationId": "me",
        "summary": "Who am I: key, member role, business, today in the business time zone. Call this first.",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/business/summary": {
      "get": {
        "operationId": "businessSummary",
        "summary": "What needs attention: setup gaps, today's jobs, unpaid invoices. No parameters.",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/business/money": {
      "get": {
        "operationId": "businessMoney",
        "summary": "Unpaid invoices, spend by category and revenue for a period (analytics.read).",
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "month",
                "quarter",
                "year"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/events": {
      "get": {
        "operationId": "events",
        "summary": "Activity log, newest first. Poll with since=<ISO>. Agent writes carry actor_kind=agent.",
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/estimate": {
      "post": {
        "operationId": "estimate",
        "summary": "Price services from the business price list (per-unit, hourly, flat, tax). Never send a price.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "services"
                ],
                "properties": {
                  "services": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "name"
                      ],
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "qty": {
                          "type": "number"
                        },
                        "hours": {
                          "type": "number"
                        }
                      }
                    }
                  },
                  "size": {
                    "type": "number"
                  },
                  "client": {
                    "type": "string"
                  },
                  "contact_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Priced estimate"
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts": {
      "get": {
        "operationId": "contactsList",
        "summary": "List contacts (newest updated first, cursor pages).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "ILIKE on name, company_name, email, boat_name, marina",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {},
                          "name": {},
                          "company_name": {},
                          "is_company": {},
                          "phone": {},
                          "email": {},
                          "marina": {},
                          "boat_name": {},
                          "boat_length_ft": {},
                          "boat_model": {},
                          "boat_year": {},
                          "dock_slip": {},
                          "billing_address": {},
                          "billing_city": {},
                          "billing_province": {},
                          "billing_postal": {},
                          "billing_email": {},
                          "client_hst_number": {},
                          "status": {},
                          "lead_source": {},
                          "tags": {},
                          "notes": {},
                          "version": {},
                          "created_at": {},
                          "updated_at": {}
                        }
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "contactsCreate",
        "summary": "Create a contact (write scope). Idempotency-Key required; ?dry_run=1 previews without writing.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "company_name": {
                    "type": "string"
                  },
                  "marina": {
                    "type": "string",
                    "description": "Location (marina / site / address — whatever this industry uses)"
                  },
                  "boat_name": {
                    "type": "string",
                    "description": "Object reference (boat / vehicle / property name)"
                  },
                  "boat_length_ft": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 9999,
                    "description": "Object size (boat length ft, area sqft, …) — drives size-based pricing. Must be > 0 and <= 9999; omit it rather than guessing"
                  },
                  "notes": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false,
                "description": "Add a client/contact. Use for \"add a client\", \"new customer\"."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "name": {},
                        "company_name": {},
                        "is_company": {},
                        "phone": {},
                        "email": {},
                        "marina": {},
                        "boat_name": {},
                        "boat_length_ft": {},
                        "boat_model": {},
                        "boat_year": {},
                        "dock_slip": {},
                        "billing_address": {},
                        "billing_city": {},
                        "billing_province": {},
                        "billing_postal": {},
                        "billing_email": {},
                        "client_hst_number": {},
                        "status": {},
                        "lead_source": {},
                        "tags": {},
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Named client/job not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contacts/{id}": {
      "patch": {
        "operationId": "contactsUpdate",
        "summary": "Update a contact (write scope). Send If-Match: <version> from GET; a stale version answers 412 with the current row.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "data.version from the last GET"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact": {
                    "type": "string",
                    "description": "Which client — the name (or boat / company) however the user referred to them"
                  },
                  "name": {
                    "type": "string",
                    "description": "New name — only when the user is renaming the client"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  },
                  "company_name": {
                    "type": "string"
                  },
                  "marina": {
                    "type": "string",
                    "description": "Location (marina / site / address — whatever this industry uses)"
                  },
                  "boat_name": {
                    "type": "string",
                    "description": "Object reference (boat / vehicle / property name)"
                  },
                  "boat_length_ft": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "maximum": 9999,
                    "description": "Object size (boat length ft, area sqft, …) — must be > 0 and <= 9999"
                  },
                  "boat_model": {
                    "type": "string"
                  },
                  "boat_year": {
                    "type": "integer",
                    "minimum": -9007199254740991,
                    "maximum": 9007199254740991,
                    "description": "4-digit year"
                  },
                  "dock_slip": {
                    "type": "string",
                    "description": "Slip / unit / bay number"
                  },
                  "notes": {
                    "type": "string",
                    "description": "REPLACES the notes field"
                  },
                  "billing_address": {
                    "type": "string"
                  },
                  "billing_city": {
                    "type": "string"
                  },
                  "billing_province": {
                    "type": "string"
                  },
                  "billing_postal": {
                    "type": "string"
                  },
                  "billing_email": {
                    "type": "string"
                  },
                  "client_hst_number": {
                    "type": "string",
                    "description": "Client tax number as printed on their documents"
                  }
                },
                "required": [
                  "contact"
                ],
                "additionalProperties": false,
                "description": "Change an EXISTING client/contact: phone, email, location (marina), object (boat) name / size / model / year, slip, notes, billing address, company or name. Use for \"поменяй телефон Janet\", \"Sarah moved to Bluffers Park\", \"update Mike's boat length to 40\". Only pass the fields being changed — everything omitted is left exactly as it is. NEVER create a second contact to \"fix\" one; to add a NEW client use create_contact. For jobs use update_job. Only the fields being changed; the id comes from the path."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "name": {},
                        "company_name": {},
                        "is_company": {},
                        "phone": {},
                        "email": {},
                        "marina": {},
                        "boat_name": {},
                        "boat_length_ft": {},
                        "boat_model": {},
                        "boat_year": {},
                        "dock_slip": {},
                        "billing_address": {},
                        "billing_city": {},
                        "billing_province": {},
                        "billing_postal": {},
                        "billing_email": {},
                        "client_hst_number": {},
                        "status": {},
                        "lead_source": {},
                        "tags": {},
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "412": {
            "description": "Version conflict: body.current holds the row as it is now"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "428": {
            "description": "If-Match missing"
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "contactsGet",
        "summary": "One contact by id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "name": {},
                        "company_name": {},
                        "is_company": {},
                        "phone": {},
                        "email": {},
                        "marina": {},
                        "boat_name": {},
                        "boat_length_ft": {},
                        "boat_model": {},
                        "boat_year": {},
                        "dock_slip": {},
                        "billing_address": {},
                        "billing_city": {},
                        "billing_province": {},
                        "billing_postal": {},
                        "billing_email": {},
                        "client_hst_number": {},
                        "status": {},
                        "lead_source": {},
                        "tags": {},
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs": {
      "get": {
        "operationId": "jobsList",
        "summary": "List jobs (newest updated first, cursor pages).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "ILIKE on title, marina, job_type",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {},
                          "contact_id": {},
                          "title": {},
                          "description": {},
                          "stage": {},
                          "start_date": {},
                          "end_date": {},
                          "start_time": {},
                          "end_time": {},
                          "marina": {},
                          "job_type": {},
                          "total_price": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "deposit_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "services": {},
                          "workers": {},
                          "work_hours": {},
                          "expenses_total": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "payroll_total": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "profit": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "notes": {},
                          "version": {},
                          "created_at": {},
                          "updated_at": {}
                        }
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "jobsCreate",
        "summary": "Create a job (write scope). Idempotency-Key required; ?dry_run=1 previews without writing.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string",
                    "description": "Existing client name (match from data)"
                  },
                  "title": {
                    "type": "string"
                  },
                  "start_date": {
                    "type": "string",
                    "description": "YYYY-MM-DD"
                  },
                  "end_date": {
                    "type": "string",
                    "description": "YYYY-MM-DD; default same as start"
                  },
                  "marina": {
                    "type": "string",
                    "description": "Location (marina / site / address)"
                  },
                  "description": {
                    "type": "string"
                  },
                  "job_type": {
                    "type": "string"
                  },
                  "total_price": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Total job price in CAD (if not itemized by services)"
                  },
                  "deposit_amount": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Deposit in CAD"
                  },
                  "services": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "price": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Unit price CAD — only if the owner said it; omit to take the price-list price"
                        },
                        "qty": {
                          "type": "number",
                          "description": "default 1"
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Line-item services; price optional (price list fills it)"
                  },
                  "workers": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "hours": {
                          "type": "number",
                          "minimum": 0
                        },
                        "rate": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Hourly rate CAD"
                        }
                      },
                      "required": [
                        "name",
                        "hours"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Assigned workers with hours and hourly rate"
                  }
                },
                "required": [
                  "client_name",
                  "title",
                  "start_date"
                ],
                "additionalProperties": false,
                "description": "Create a job/booking for a client. Can set price, deposit, services and assigned workers with hours. Use for \"book a job\", \"schedule…\", \"create a job for X at $Y with worker Z for N hours\". BOOK FIRST: a job needs only a client, a title and a date — do NOT ask for size, price or deposit before creating it, and do not withhold the booking because pricing is unknown. Always pass the requested service as a services line; give a price ONLY when the owner said one — otherwise OMIT price and the server takes it from the price list (per-foot services are multiplied by the client's boat length on the server). Never invent a price. REST callers may pass contact_id (uuid) instead of client_name."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "title": {},
                        "description": {},
                        "stage": {},
                        "start_date": {},
                        "end_date": {},
                        "start_time": {},
                        "end_time": {},
                        "marina": {},
                        "job_type": {},
                        "total_price": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "services": {},
                        "workers": {},
                        "work_hours": {},
                        "expenses_total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "payroll_total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "profit": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Named client/job not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}": {
      "patch": {
        "operationId": "jobsUpdate",
        "summary": "Update a job (write scope). Send If-Match: <version> from GET; a stale version answers 412 with the current row.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "data.version from the last GET"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "job": {
                    "type": "string",
                    "description": "Which job — the client name or the job title, however the user referred to it"
                  },
                  "stage": {
                    "type": "string",
                    "enum": [
                      "lead",
                      "quoted",
                      "scheduled",
                      "in_progress",
                      "completed",
                      "cancelled",
                      "weather_hold",
                      "lost"
                    ],
                    "description": "The new stage. These are the ONLY valid values — never invent one"
                  },
                  "title": {
                    "type": "string"
                  },
                  "start_date": {
                    "type": "string",
                    "description": "YYYY-MM-DD"
                  },
                  "end_date": {
                    "type": "string",
                    "description": "YYYY-MM-DD"
                  },
                  "start_time": {
                    "type": "string",
                    "description": "HH:MM 24h"
                  },
                  "end_time": {
                    "type": "string",
                    "description": "HH:MM 24h"
                  },
                  "marina": {
                    "type": "string",
                    "description": "Location (marina / site / address)"
                  },
                  "deposit_amount": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Deposit in CAD"
                  },
                  "notes": {
                    "type": "string"
                  },
                  "total_price": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 10000000,
                    "description": "Whole-job price in CAD — ONLY for a job that has no service lines (\"поставь цену 1200\"). If the job is itemized, change a line instead (set_service_price / add_services); the server refuses a bare total on an itemized job."
                  },
                  "add_services": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Service name as the user said it"
                        },
                        "unit_price": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 10000000,
                          "description": "Unit price in CAD — only if the user said a price; omit to take it from the price list"
                        },
                        "qty": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "description": "default 1"
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Lines to ADD to the job"
                  },
                  "set_service_price": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Existing line on the job"
                        },
                        "unit_price": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 10000000,
                          "description": "New unit price in CAD"
                        }
                      },
                      "required": [
                        "name",
                        "unit_price"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Change the price of existing lines"
                  },
                  "remove_services": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Names of lines to REMOVE from the job"
                  }
                },
                "required": [
                  "job"
                ],
                "additionalProperties": false,
                "description": "Change an EXISTING job: its stage, dates, title, location, price, deposit or notes, or its service lines (add / reprice / remove a line; the total is recomputed on the server). Use for \"move X to scheduled\", \"перенеси на пятницу\", \"поменяй этап\", \"raise the price on Y\". Only pass the fields being changed — everything omitted is left exactly as it is. To create a NEW job use create_job; for worker hours use log_job_hours. Only the fields being changed; the id comes from the path."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "title": {},
                        "description": {},
                        "stage": {},
                        "start_date": {},
                        "end_date": {},
                        "start_time": {},
                        "end_time": {},
                        "marina": {},
                        "job_type": {},
                        "total_price": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "services": {},
                        "workers": {},
                        "work_hours": {},
                        "expenses_total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "payroll_total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "profit": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "412": {
            "description": "Version conflict: body.current holds the row as it is now"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "428": {
            "description": "If-Match missing"
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "jobsGet",
        "summary": "One job by id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "title": {},
                        "description": {},
                        "stage": {},
                        "start_date": {},
                        "end_date": {},
                        "start_time": {},
                        "end_time": {},
                        "marina": {},
                        "job_type": {},
                        "total_price": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "services": {},
                        "workers": {},
                        "work_hours": {},
                        "expenses_total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "payroll_total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "profit": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes": {
      "get": {
        "operationId": "quotesList",
        "summary": "List quotes (newest updated first, cursor pages).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "ILIKE on number",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {},
                          "contact_id": {},
                          "job_id": {},
                          "number": {},
                          "status": {},
                          "issue_date": {},
                          "valid_until": {},
                          "subtotal": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "tax_rate": {},
                          "tax_label": {},
                          "tax_enabled": {},
                          "tax_inclusive": {},
                          "tax_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "discount_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "total": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "deposit_pct": {},
                          "deposit_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "notes": {},
                          "sent_at": {},
                          "approved_at": {},
                          "converted_to_invoice_id": {},
                          "version": {},
                          "created_at": {},
                          "updated_at": {}
                        }
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "quotesCreate",
        "summary": "Create a quote (write scope). Idempotency-Key required; ?dry_run=1 previews without writing.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string",
                    "description": "Client name (match from data). Required unless job is given"
                  },
                  "job": {
                    "type": "string",
                    "description": "An existing job to quote — its title or its client name; the job's service lines are copied"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "description": {
                          "type": "string"
                        },
                        "qty": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "description": "default 1; for per-foot / per-sq-ft lines the size"
                        },
                        "unit": {
                          "type": "string",
                          "description": "ft, sq ft, hr, visit… or empty"
                        },
                        "unit_price": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Price per unit in the business currency"
                        }
                      },
                      "required": [
                        "description",
                        "unit_price"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Line items when not copied from a job"
                  },
                  "valid_days": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991,
                    "description": "How many days the quote is valid; omit = no expiry"
                  },
                  "deposit_pct": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100,
                    "description": "Deposit required, percent"
                  },
                  "notes": {
                    "type": "string",
                    "description": "Note visible to the client"
                  }
                },
                "additionalProperties": false,
                "description": "Create a QUOTE (estimate) for a client as a draft document. Use for \"send a quote\", \"quote Kai for…\", \"сделай квоту / смету\". Either name the JOB to quote (its service lines are copied) or give the client and the line items with prices. Never invent a price: take it from what the user said or from get_price_list, otherwise ask. Tax comes from the business settings; the card shows lines and total before anything is created. REST callers may pass contact_id (uuid) instead of client_name."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "job_id": {},
                        "number": {},
                        "status": {},
                        "issue_date": {},
                        "valid_until": {},
                        "subtotal": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "tax_rate": {},
                        "tax_label": {},
                        "tax_enabled": {},
                        "tax_inclusive": {},
                        "tax_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "discount_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_pct": {},
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "sent_at": {},
                        "approved_at": {},
                        "converted_to_invoice_id": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Named client/job not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/quotes/{id}": {
      "get": {
        "operationId": "quotesGet",
        "summary": "One quote by id, with line items.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "job_id": {},
                        "number": {},
                        "status": {},
                        "issue_date": {},
                        "valid_until": {},
                        "subtotal": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "tax_rate": {},
                        "tax_label": {},
                        "tax_enabled": {},
                        "tax_inclusive": {},
                        "tax_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "discount_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_pct": {},
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "sent_at": {},
                        "approved_at": {},
                        "converted_to_invoice_id": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/invoices": {
      "get": {
        "operationId": "invoicesList",
        "summary": "List invoices (newest updated first, cursor pages).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "ILIKE on number",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {},
                          "contact_id": {},
                          "job_id": {},
                          "quote_id": {},
                          "number": {},
                          "status": {},
                          "issue_date": {},
                          "due_date": {},
                          "subtotal": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "tax_rate": {},
                          "tax_label": {},
                          "tax_enabled": {},
                          "tax_inclusive": {},
                          "tax_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "discount_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "total": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "amount_paid": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "deposit_pct": {},
                          "deposit_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "notes": {},
                          "sent_at": {},
                          "paid_at": {},
                          "version": {},
                          "created_at": {},
                          "updated_at": {}
                        }
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "invoicesCreate",
        "summary": "Create a invoice (write scope). Idempotency-Key required; ?dry_run=1 previews without writing.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string",
                    "description": "Client name (match from data). Required unless job is given"
                  },
                  "job": {
                    "type": "string",
                    "description": "An existing job to invoice — its title or its client name; the job's service lines are copied"
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "description": {
                          "type": "string"
                        },
                        "qty": {
                          "type": "number",
                          "exclusiveMinimum": 0,
                          "description": "default 1; for per-foot / per-sq-ft lines the size"
                        },
                        "unit": {
                          "type": "string",
                          "description": "ft, sq ft, hr, visit… or empty"
                        },
                        "unit_price": {
                          "type": "number",
                          "minimum": 0,
                          "description": "Price per unit in the business currency"
                        }
                      },
                      "required": [
                        "description",
                        "unit_price"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Line items when not copied from a job"
                  },
                  "due_days": {
                    "type": "integer",
                    "exclusiveMinimum": 0,
                    "maximum": 9007199254740991,
                    "description": "Days until due; omit = business payment terms"
                  },
                  "notes": {
                    "type": "string",
                    "description": "Note visible to the client"
                  }
                },
                "additionalProperties": false,
                "description": "Create an INVOICE as a draft document. Use for \"invoice X\", \"bill Nuno for yesterday's job\", \"выставь счёт\". Either name the JOB (its service lines are copied) or give the client and the line items with prices. Never invent a price — ask. Tax comes from the business settings and the due date from its payment terms; the card shows lines, tax and total before anything is created. To record money already received use add_payment, not this. REST callers may pass contact_id (uuid) instead of client_name."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "job_id": {},
                        "quote_id": {},
                        "number": {},
                        "status": {},
                        "issue_date": {},
                        "due_date": {},
                        "subtotal": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "tax_rate": {},
                        "tax_label": {},
                        "tax_enabled": {},
                        "tax_inclusive": {},
                        "tax_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "discount_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "amount_paid": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_pct": {},
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "sent_at": {},
                        "paid_at": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Named client/job not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/invoices/{id}": {
      "get": {
        "operationId": "invoicesGet",
        "summary": "One invoice by id, with line items.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "contact_id": {},
                        "job_id": {},
                        "quote_id": {},
                        "number": {},
                        "status": {},
                        "issue_date": {},
                        "due_date": {},
                        "subtotal": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "tax_rate": {},
                        "tax_label": {},
                        "tax_enabled": {},
                        "tax_inclusive": {},
                        "tax_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "discount_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "total": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "amount_paid": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "deposit_pct": {},
                        "deposit_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "notes": {},
                        "sent_at": {},
                        "paid_at": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/expenses": {
      "get": {
        "operationId": "expensesList",
        "summary": "List expenses (newest updated first, cursor pages).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "description": "ILIKE on description, vendor, category",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor from the previous page",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {},
                          "job_id": {},
                          "description": {},
                          "amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "category": {},
                          "date": {},
                          "vendor": {},
                          "tax_amount": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Decimal string, e.g. \"1234.56\""
                          },
                          "currency": {},
                          "receipt_number": {},
                          "kind": {},
                          "notes": {},
                          "version": {},
                          "created_at": {},
                          "updated_at": {}
                        }
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "expensesCreate",
        "summary": "Create a expense (write scope). Idempotency-Key required; ?dry_run=1 previews without writing.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 128
            }
          },
          {
            "name": "dry_run",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "number",
                    "exclusiveMinimum": 0,
                    "description": "Total amount in CAD — must be greater than 0"
                  },
                  "category": {
                    "type": "string",
                    "description": "Category KEY copied EXACTLY from the \"Expense category keys\" list in the INDUSTRY line of the system prompt — never invent a key; unknown keys fall back to other"
                  },
                  "description": {
                    "type": "string"
                  },
                  "vendor": {
                    "type": "string"
                  },
                  "date": {
                    "type": "string",
                    "description": "YYYY-MM-DD; default today"
                  }
                },
                "required": [
                  "amount"
                ],
                "additionalProperties": false,
                "description": "Record a business expense. Use for \"log/record an expense\", \"I spent X on Y\"."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "job_id": {},
                        "description": {},
                        "amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "category": {},
                        "date": {},
                        "vendor": {},
                        "tax_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "currency": {},
                        "receipt_number": {},
                        "kind": {},
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Named client/job not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/expenses/{id}": {
      "get": {
        "operationId": "expensesGet",
        "summary": "One expense by id.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {},
                        "job_id": {},
                        "description": {},
                        "amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "category": {},
                        "date": {},
                        "vendor": {},
                        "tax_amount": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Decimal string, e.g. \"1234.56\""
                        },
                        "currency": {},
                        "receipt_number": {},
                        "kind": {},
                        "notes": {},
                        "version": {},
                        "created_at": {},
                        "updated_at": {}
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Plan required",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Answered with HTTP 402 when a plan is required. Relay message_for_owner and approve_url to the human, then retry the same call.",
                  "properties": {
                    "code": {
                      "const": "PLAN_REQUIRED"
                    },
                    "needed": {
                      "type": "string"
                    },
                    "for": {
                      "type": "string"
                    },
                    "what_you_get": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "price": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "approve_url": {
                      "type": "string"
                    },
                    "trial_url": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "message_for_owner": {
                      "type": "string"
                    },
                    "retryable": {
                      "const": true
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Key lacks scope or member lacks role",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found in this business"
          },
          "422": {
            "description": "Validation error (see field, hint)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (Retry-After)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        },
                        "field": {
                          "type": "string"
                        },
                        "hint": {
                          "type": "string"
                        },
                        "retryable": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "code",
                        "message",
                        "retryable"
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
