{
 "openapi": "3.1.0",
 "info": {
  "title": "Scale Up Timesheets API",
  "version": "1.0.0",
  "description": "External REST API for Scale Up Timesheets. Send an organisation-scoped API key in the X-Api-Key header. Make and revoke keys in Timesheets under Settings > API keys. A key has admin rights for the organisation. List endpoints take limit (1 to 200) and offset."
 },
 "servers": [
  {
   "url": "https://time.scaleupsolutions.asia/api/v1/external"
  }
 ],
 "security": [
  {
   "ApiKeyAuth": []
  }
 ],
 "paths": {
  "/people": {
   "get": {
    "tags": [
     "people"
    ],
    "summary": "List people",
    "operationId": "list_people_api_v1_external_people_get",
    "parameters": [
     {
      "name": "active",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "boolean"
        },
        {
         "type": "null"
        }
       ],
       "title": "Active"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 200,
       "minimum": 1,
       "description": "Page size (1 to 200).",
       "default": 50,
       "title": "Limit"
      },
      "description": "Page size (1 to 200)."
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "description": "Number of items to skip.",
       "default": 0,
       "title": "Offset"
      },
      "description": "Number of items to skip."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Page_PersonOut_"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/customers": {
   "get": {
    "tags": [
     "customers"
    ],
    "summary": "List customers",
    "operationId": "list_customers_api_v1_external_customers_get",
    "parameters": [
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 200,
       "minimum": 1,
       "description": "Page size (1 to 200).",
       "default": 50,
       "title": "Limit"
      },
      "description": "Page size (1 to 200)."
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "description": "Number of items to skip.",
       "default": 0,
       "title": "Offset"
      },
      "description": "Number of items to skip."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Page_CustomerOut_"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/projects": {
   "get": {
    "tags": [
     "projects"
    ],
    "summary": "List projects",
    "operationId": "list_projects__api_v1_external_projects_get",
    "parameters": [
     {
      "name": "customer_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "uuid"
        },
        {
         "type": "null"
        }
       ],
       "title": "Customer Id"
      }
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "title": "Status"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 200,
       "minimum": 1,
       "description": "Page size (1 to 200).",
       "default": 50,
       "title": "Limit"
      },
      "description": "Page size (1 to 200)."
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "description": "Number of items to skip.",
       "default": 0,
       "title": "Offset"
      },
      "description": "Number of items to skip."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Page_ProjectOut_"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "projects"
    ],
    "summary": "Create a project",
    "operationId": "create_project__api_v1_external_projects_post",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ProjectIn"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ProjectOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/projects/{project_id}": {
   "get": {
    "tags": [
     "projects"
    ],
    "summary": "Get one project with its usage",
    "operationId": "get_project_api_v1_external_projects__project_id__get",
    "parameters": [
     {
      "name": "project_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Project Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ProjectDetail"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/projects/{project_id}/tasks": {
   "get": {
    "tags": [
     "projects"
    ],
    "summary": "List a project's tasks",
    "operationId": "get_tasks_api_v1_external_projects__project_id__tasks_get",
    "parameters": [
     {
      "name": "project_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Project Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/TaskOut"
         },
         "title": "Response Get Tasks Api V1 External Projects  Project Id  Tasks Get"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "projects"
    ],
    "summary": "Add a task to a project",
    "operationId": "add_task_api_v1_external_projects__project_id__tasks_post",
    "parameters": [
     {
      "name": "project_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Project Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TaskIn"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TaskOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/projects/{project_id}/assignments": {
   "get": {
    "tags": [
     "projects"
    ],
    "summary": "List who is assigned to a project",
    "operationId": "get_assignments_api_v1_external_projects__project_id__assignments_get",
    "parameters": [
     {
      "name": "project_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Project Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "type": "array",
         "items": {
          "$ref": "#/components/schemas/AssignmentOut"
         },
         "title": "Response Get Assignments Api V1 External Projects  Project Id  Assignments Get"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "projects"
    ],
    "summary": "Assign a person to a project",
    "operationId": "add_assignment_api_v1_external_projects__project_id__assignments_post",
    "parameters": [
     {
      "name": "project_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Project Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/AssignmentIn"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/AssignmentOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/time-entries": {
   "get": {
    "tags": [
     "time entries"
    ],
    "summary": "List time entries",
    "operationId": "list_time_entries_api_v1_external_time_entries_get",
    "parameters": [
     {
      "name": "person_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "uuid"
        },
        {
         "type": "null"
        }
       ],
       "title": "Person Id"
      }
     },
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "uuid"
        },
        {
         "type": "null"
        }
       ],
       "title": "Project Id"
      }
     },
     {
      "name": "start",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "date"
        },
        {
         "type": "null"
        }
       ],
       "description": "First date to include.",
       "title": "Start"
      },
      "description": "First date to include."
     },
     {
      "name": "end",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "date"
        },
        {
         "type": "null"
        }
       ],
       "description": "Last date to include.",
       "title": "End"
      },
      "description": "Last date to include."
     },
     {
      "name": "status",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "null"
        }
       ],
       "description": "draft, submitted, approved, invoiced or written_off",
       "title": "Status"
      },
      "description": "draft, submitted, approved, invoiced or written_off"
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "maximum": 200,
       "minimum": 1,
       "description": "Page size (1 to 200).",
       "default": 50,
       "title": "Limit"
      },
      "description": "Page size (1 to 200)."
     },
     {
      "name": "offset",
      "in": "query",
      "required": false,
      "schema": {
       "type": "integer",
       "minimum": 0,
       "description": "Number of items to skip.",
       "default": 0,
       "title": "Offset"
      },
      "description": "Number of items to skip."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Page_TimeEntryOut_"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "post": {
    "tags": [
     "time entries"
    ],
    "summary": "Log time for a person",
    "operationId": "create_entry_api_v1_external_time_entries_post",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TimeEntryIn"
       }
      }
     }
    },
    "responses": {
     "201": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TimeEntryCreated"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/time-entries/{entry_id}": {
   "get": {
    "tags": [
     "time entries"
    ],
    "summary": "Get one time entry",
    "operationId": "get_entry_api_v1_external_time_entries__entry_id__get",
    "parameters": [
     {
      "name": "entry_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Entry Id"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TimeEntryOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "patch": {
    "tags": [
     "time entries"
    ],
    "summary": "Edit a draft time entry",
    "operationId": "patch_entry_api_v1_external_time_entries__entry_id__patch",
    "parameters": [
     {
      "name": "entry_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Entry Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/TimeEntryPatch"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/TimeEntryOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   },
   "delete": {
    "tags": [
     "time entries"
    ],
    "summary": "Delete a draft time entry",
    "operationId": "delete_entry_api_v1_external_time_entries__entry_id__delete",
    "parameters": [
     {
      "name": "entry_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Entry Id"
      }
     }
    ],
    "responses": {
     "204": {
      "description": "Successful Response"
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/time-entries/submit": {
   "post": {
    "tags": [
     "time entries"
    ],
    "summary": "Submit draft entries for approval",
    "operationId": "submit_api_v1_external_time_entries_submit_post",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/SubmitIn"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CountOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/time-entries/approve": {
   "post": {
    "tags": [
     "time entries"
    ],
    "summary": "Approve submitted entries",
    "operationId": "approve_api_v1_external_time_entries_approve_post",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/EntryIds"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CountOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/time-entries/reject": {
   "post": {
    "tags": [
     "time entries"
    ],
    "summary": "Send submitted entries back to draft",
    "operationId": "reject_api_v1_external_time_entries_reject_post",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/RejectIn"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CountOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/time-entries/write-off": {
   "post": {
    "tags": [
     "time entries"
    ],
    "summary": "Write off entries so they are never billed",
    "operationId": "write_off_api_v1_external_time_entries_write_off_post",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/WriteOffIn"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CountOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/projects/{project_id}/invoice": {
   "post": {
    "tags": [
     "invoicing"
    ],
    "summary": "Raise an invoice in Books for approved hours",
    "description": "Needs the org's Books connection and default income account (Settings).\nOnly approved, billable, not-yet-invoiced entries in the date range are billed.",
    "operationId": "invoice_project_api_v1_external_projects__project_id__invoice_post",
    "parameters": [
     {
      "name": "project_id",
      "in": "path",
      "required": true,
      "schema": {
       "type": "string",
       "format": "uuid",
       "title": "Project Id"
      }
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/InvoiceIn"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/InvoiceOut"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  },
  "/reports/hours": {
   "get": {
    "tags": [
     "reports"
    ],
    "summary": "Hours report",
    "operationId": "hours_report_api_v1_external_reports_hours_get",
    "parameters": [
     {
      "name": "start",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "format": "date",
       "title": "Start"
      }
     },
     {
      "name": "end",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "format": "date",
       "title": "End"
      }
     },
     {
      "name": "person_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "uuid"
        },
        {
         "type": "null"
        }
       ],
       "title": "Person Id"
      }
     },
     {
      "name": "project_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "uuid"
        },
        {
         "type": "null"
        }
       ],
       "title": "Project Id"
      }
     },
     {
      "name": "customer_id",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "string",
         "format": "uuid"
        },
        {
         "type": "null"
        }
       ],
       "title": "Customer Id"
      }
     },
     {
      "name": "chargeable",
      "in": "query",
      "required": false,
      "schema": {
       "anyOf": [
        {
         "type": "boolean"
        },
        {
         "type": "null"
        }
       ],
       "description": "true: chargeable only. false: non-chargeable only. Omit for both.",
       "title": "Chargeable"
      },
      "description": "true: chargeable only. false: non-chargeable only. Omit for both."
     }
    ],
    "responses": {
     "200": {
      "description": "Successful Response",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HoursReport"
        }
       }
      }
     },
     "422": {
      "description": "Validation Error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/HTTPValidationError"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "AssignmentIn": {
    "properties": {
     "person_id": {
      "type": "string",
      "format": "uuid",
      "title": "Person Id"
     },
     "hourly_rate": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       }
      ],
      "title": "Hourly Rate"
     },
     "max_hours": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Hours"
     }
    },
    "type": "object",
    "required": [
     "person_id",
     "hourly_rate"
    ],
    "title": "AssignmentIn"
   },
   "AssignmentOut": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "project_id": {
      "type": "string",
      "format": "uuid",
      "title": "Project Id"
     },
     "person_id": {
      "type": "string",
      "format": "uuid",
      "title": "Person Id"
     },
     "hourly_rate": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Hourly Rate"
     },
     "max_hours": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Hours"
     }
    },
    "type": "object",
    "required": [
     "id",
     "project_id",
     "person_id",
     "hourly_rate"
    ],
    "title": "AssignmentOut"
   },
   "CountOut": {
    "properties": {
     "count": {
      "type": "integer",
      "title": "Count"
     }
    },
    "type": "object",
    "required": [
     "count"
    ],
    "title": "CountOut"
   },
   "CustomerOut": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "ledger_contact_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ledger Contact Id"
     },
     "is_vat_registered": {
      "type": "boolean",
      "title": "Is Vat Registered"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "is_vat_registered"
    ],
    "title": "CustomerOut"
   },
   "EntryIds": {
    "properties": {
     "entry_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "minItems": 1,
      "title": "Entry Ids"
     }
    },
    "type": "object",
    "required": [
     "entry_ids"
    ],
    "title": "EntryIds"
   },
   "HTTPValidationError": {
    "properties": {
     "detail": {
      "items": {
       "$ref": "#/components/schemas/ValidationError"
      },
      "type": "array",
      "title": "Detail"
     }
    },
    "type": "object",
    "title": "HTTPValidationError"
   },
   "HoursReport": {
    "properties": {
     "start": {
      "type": "string",
      "format": "date",
      "title": "Start"
     },
     "end": {
      "type": "string",
      "format": "date",
      "title": "End"
     },
     "total_hours": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Total Hours"
     },
     "chargeable_hours": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Chargeable Hours"
     },
     "rows": {
      "items": {
       "$ref": "#/components/schemas/HoursReportRow"
      },
      "type": "array",
      "title": "Rows"
     }
    },
    "type": "object",
    "required": [
     "start",
     "end",
     "total_hours",
     "chargeable_hours",
     "rows"
    ],
    "title": "HoursReport"
   },
   "HoursReportRow": {
    "properties": {
     "date": {
      "type": "string",
      "format": "date",
      "title": "Date"
     },
     "person_id": {
      "type": "string",
      "format": "uuid",
      "title": "Person Id"
     },
     "person_name": {
      "type": "string",
      "title": "Person Name"
     },
     "project_id": {
      "type": "string",
      "format": "uuid",
      "title": "Project Id"
     },
     "project_name": {
      "type": "string",
      "title": "Project Name"
     },
     "customer_name": {
      "type": "string",
      "title": "Customer Name"
     },
     "task_name": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Name"
     },
     "hours": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Hours"
     },
     "billable": {
      "type": "boolean",
      "title": "Billable"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     }
    },
    "type": "object",
    "required": [
     "date",
     "person_id",
     "person_name",
     "project_id",
     "project_name",
     "customer_name",
     "hours",
     "billable",
     "status"
    ],
    "title": "HoursReportRow"
   },
   "InvoiceIn": {
    "properties": {
     "start": {
      "type": "string",
      "format": "date",
      "title": "Start"
     },
     "end": {
      "type": "string",
      "format": "date",
      "title": "End"
     },
     "amount_override": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Amount Override",
      "description": "Bill this amount instead of hours times rate."
     },
     "stream_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Stream Id",
      "description": "Books document stream. Default: chosen from the customer's VAT status."
     }
    },
    "type": "object",
    "required": [
     "start",
     "end"
    ],
    "title": "InvoiceIn"
   },
   "InvoiceOut": {
    "properties": {
     "invoice_id": {
      "type": "string",
      "format": "uuid",
      "title": "Invoice Id"
     },
     "invoice_no": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Invoice No"
     },
     "total": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Total"
     },
     "entry_count": {
      "type": "integer",
      "title": "Entry Count"
     }
    },
    "type": "object",
    "required": [
     "invoice_id",
     "total",
     "entry_count"
    ],
    "title": "InvoiceOut"
   },
   "Page_CustomerOut_": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/CustomerOut"
      },
      "type": "array",
      "title": "Items"
     },
     "total": {
      "type": "integer",
      "title": "Total",
      "description": "Number of items that match, before paging."
     },
     "limit": {
      "type": "integer",
      "title": "Limit"
     },
     "offset": {
      "type": "integer",
      "title": "Offset"
     }
    },
    "type": "object",
    "required": [
     "items",
     "total",
     "limit",
     "offset"
    ],
    "title": "Page[CustomerOut]"
   },
   "Page_PersonOut_": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/PersonOut"
      },
      "type": "array",
      "title": "Items"
     },
     "total": {
      "type": "integer",
      "title": "Total",
      "description": "Number of items that match, before paging."
     },
     "limit": {
      "type": "integer",
      "title": "Limit"
     },
     "offset": {
      "type": "integer",
      "title": "Offset"
     }
    },
    "type": "object",
    "required": [
     "items",
     "total",
     "limit",
     "offset"
    ],
    "title": "Page[PersonOut]"
   },
   "Page_ProjectOut_": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/ProjectOut"
      },
      "type": "array",
      "title": "Items"
     },
     "total": {
      "type": "integer",
      "title": "Total",
      "description": "Number of items that match, before paging."
     },
     "limit": {
      "type": "integer",
      "title": "Limit"
     },
     "offset": {
      "type": "integer",
      "title": "Offset"
     }
    },
    "type": "object",
    "required": [
     "items",
     "total",
     "limit",
     "offset"
    ],
    "title": "Page[ProjectOut]"
   },
   "Page_TimeEntryOut_": {
    "properties": {
     "items": {
      "items": {
       "$ref": "#/components/schemas/TimeEntryOut"
      },
      "type": "array",
      "title": "Items"
     },
     "total": {
      "type": "integer",
      "title": "Total",
      "description": "Number of items that match, before paging."
     },
     "limit": {
      "type": "integer",
      "title": "Limit"
     },
     "offset": {
      "type": "integer",
      "title": "Offset"
     }
    },
    "type": "object",
    "required": [
     "items",
     "total",
     "limit",
     "offset"
    ],
    "title": "Page[TimeEntryOut]"
   },
   "PersonOut": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "email": {
      "type": "string",
      "title": "Email"
     },
     "kind": {
      "type": "string",
      "title": "Kind",
      "description": "employee or contractor"
     },
     "standard_hourly_rate": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Standard Hourly Rate"
     },
     "is_admin": {
      "type": "boolean",
      "title": "Is Admin"
     },
     "active": {
      "type": "boolean",
      "title": "Active"
     }
    },
    "type": "object",
    "required": [
     "id",
     "name",
     "email",
     "kind",
     "is_admin",
     "active"
    ],
    "title": "PersonOut"
   },
   "ProjectDetail": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "customer_id": {
      "type": "string",
      "format": "uuid",
      "title": "Customer Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "is_internal": {
      "type": "boolean",
      "title": "Is Internal"
     },
     "max_total_hours": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Total Hours"
     },
     "max_hourly_rate": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Hourly Rate"
     },
     "total_project_value": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Total Project Value"
     },
     "approver_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approver Id"
     },
     "ledger_contact_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ledger Contact Id"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     },
     "hours_used": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Hours Used"
     },
     "value_used": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Value Used"
     }
    },
    "type": "object",
    "required": [
     "id",
     "customer_id",
     "name",
     "status",
     "is_internal",
     "created_at",
     "hours_used",
     "value_used"
    ],
    "title": "ProjectDetail"
   },
   "ProjectIn": {
    "properties": {
     "customer_id": {
      "type": "string",
      "format": "uuid",
      "title": "Customer Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "max_total_hours": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Total Hours"
     },
     "max_hourly_rate": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Hourly Rate"
     },
     "total_project_value": {
      "anyOf": [
       {
        "type": "number"
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Total Project Value",
      "description": "Contract value."
     }
    },
    "type": "object",
    "required": [
     "customer_id",
     "name"
    ],
    "title": "ProjectIn"
   },
   "ProjectOut": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "customer_id": {
      "type": "string",
      "format": "uuid",
      "title": "Customer Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "status": {
      "type": "string",
      "title": "Status"
     },
     "is_internal": {
      "type": "boolean",
      "title": "Is Internal"
     },
     "max_total_hours": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Total Hours"
     },
     "max_hourly_rate": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Max Hourly Rate"
     },
     "total_project_value": {
      "anyOf": [
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Total Project Value"
     },
     "approver_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Approver Id"
     },
     "ledger_contact_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ledger Contact Id"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "customer_id",
     "name",
     "status",
     "is_internal",
     "created_at"
    ],
    "title": "ProjectOut"
   },
   "RejectIn": {
    "properties": {
     "entry_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "minItems": 1,
      "title": "Entry Ids"
     },
     "note": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Note"
     }
    },
    "type": "object",
    "required": [
     "entry_ids"
    ],
    "title": "RejectIn"
   },
   "SubmitIn": {
    "properties": {
     "entry_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "minItems": 1,
      "title": "Entry Ids"
     },
     "person_id": {
      "type": "string",
      "format": "uuid",
      "title": "Person Id",
      "description": "The person who owns the entries."
     }
    },
    "type": "object",
    "required": [
     "entry_ids",
     "person_id"
    ],
    "title": "SubmitIn"
   },
   "TaskIn": {
    "properties": {
     "name": {
      "type": "string",
      "title": "Name"
     }
    },
    "type": "object",
    "required": [
     "name"
    ],
    "title": "TaskIn"
   },
   "TaskOut": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "project_id": {
      "type": "string",
      "format": "uuid",
      "title": "Project Id"
     },
     "name": {
      "type": "string",
      "title": "Name"
     },
     "active": {
      "type": "boolean",
      "title": "Active"
     }
    },
    "type": "object",
    "required": [
     "id",
     "project_id",
     "name",
     "active"
    ],
    "title": "TaskOut"
   },
   "TimeEntryCreated": {
    "properties": {
     "entry": {
      "$ref": "#/components/schemas/TimeEntryOut"
     },
     "warning": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Warning",
      "description": "A cap warning. The entry is saved anyway."
     }
    },
    "type": "object",
    "required": [
     "entry"
    ],
    "title": "TimeEntryCreated"
   },
   "TimeEntryIn": {
    "properties": {
     "project_id": {
      "type": "string",
      "format": "uuid",
      "title": "Project Id"
     },
     "person_id": {
      "type": "string",
      "format": "uuid",
      "title": "Person Id"
     },
     "date": {
      "type": "string",
      "format": "date",
      "title": "Date"
     },
     "hours": {
      "anyOf": [
       {
        "type": "number",
        "maximum": 24.0,
        "exclusiveMinimum": 0.0
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       }
      ],
      "title": "Hours"
     },
     "task_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Id"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "billable": {
      "type": "boolean",
      "title": "Billable",
      "default": true
     }
    },
    "type": "object",
    "required": [
     "project_id",
     "person_id",
     "date",
     "hours"
    ],
    "title": "TimeEntryIn"
   },
   "TimeEntryOut": {
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "title": "Id"
     },
     "project_id": {
      "type": "string",
      "format": "uuid",
      "title": "Project Id"
     },
     "person_id": {
      "type": "string",
      "format": "uuid",
      "title": "Person Id"
     },
     "task_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Id"
     },
     "date": {
      "type": "string",
      "format": "date",
      "title": "Date"
     },
     "hours": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Hours"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "rate_at_entry": {
      "type": "string",
      "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
      "title": "Rate At Entry"
     },
     "billable": {
      "type": "boolean",
      "title": "Billable"
     },
     "status": {
      "type": "string",
      "title": "Status",
      "description": "draft, submitted, approved, invoiced or written_off"
     },
     "rejection_note": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Rejection Note"
     },
     "ledger_invoice_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Ledger Invoice Id"
     },
     "created_at": {
      "type": "string",
      "format": "date-time",
      "title": "Created At"
     }
    },
    "type": "object",
    "required": [
     "id",
     "project_id",
     "person_id",
     "date",
     "hours",
     "rate_at_entry",
     "billable",
     "status",
     "created_at"
    ],
    "title": "TimeEntryOut"
   },
   "TimeEntryPatch": {
    "properties": {
     "date": {
      "anyOf": [
       {
        "type": "string",
        "format": "date"
       },
       {
        "type": "null"
       }
      ],
      "title": "Date"
     },
     "hours": {
      "anyOf": [
       {
        "type": "number",
        "maximum": 24.0,
        "exclusiveMinimum": 0.0
       },
       {
        "type": "string",
        "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"
       },
       {
        "type": "null"
       }
      ],
      "title": "Hours"
     },
     "task_id": {
      "anyOf": [
       {
        "type": "string",
        "format": "uuid"
       },
       {
        "type": "null"
       }
      ],
      "title": "Task Id"
     },
     "description": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Description"
     },
     "billable": {
      "anyOf": [
       {
        "type": "boolean"
       },
       {
        "type": "null"
       }
      ],
      "title": "Billable"
     }
    },
    "type": "object",
    "title": "TimeEntryPatch"
   },
   "ValidationError": {
    "properties": {
     "loc": {
      "items": {
       "anyOf": [
        {
         "type": "string"
        },
        {
         "type": "integer"
        }
       ]
      },
      "type": "array",
      "title": "Location"
     },
     "msg": {
      "type": "string",
      "title": "Message"
     },
     "type": {
      "type": "string",
      "title": "Error Type"
     },
     "input": {
      "title": "Input"
     },
     "ctx": {
      "type": "object",
      "title": "Context"
     }
    },
    "type": "object",
    "required": [
     "loc",
     "msg",
     "type"
    ],
    "title": "ValidationError"
   },
   "WriteOffIn": {
    "properties": {
     "entry_ids": {
      "items": {
       "type": "string",
       "format": "uuid"
      },
      "type": "array",
      "minItems": 1,
      "title": "Entry Ids"
     },
     "reason": {
      "anyOf": [
       {
        "type": "string"
       },
       {
        "type": "null"
       }
      ],
      "title": "Reason"
     }
    },
    "type": "object",
    "required": [
     "entry_ids"
    ],
    "title": "WriteOffIn"
   }
  },
  "securitySchemes": {
   "ApiKeyAuth": {
    "type": "apiKey",
    "in": "header",
    "name": "X-Api-Key"
   }
  }
 }
}