Repository: google/turbinia (language: python)

Issue:
[Bug]: Error in turbinia-client result task 
### What steps will reproduce the bug?

* Install from HEAD
* `$ turbinia-client result task <TaskID>`

### What is the expected behavior?

Get results/output from task

### What do you see instead?

```
$ turbinia-client result task 2a6eda8baeb74a5787e7fc58f244a934
2023-10-04 15:25:15,766 INFO turbinia - Using configuration instance name -> default with host http://localhost:8000
Traceback (most recent call last):
  File "/home/aaronpeterson/src/turbinia/turbinia/api/cli/turbinia_client/core/commands.py", line 88, in get_task_result
    api_response = api_instance.get_task_output(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "pydantic/decorator.py", line 40, in pydantic.decorator.validate_arguments.validate.wrapper_function
  File "pydantic/decorator.py", line 134, in pydantic.decorator.ValidatedFunction.call
  File "pydantic/decorator.py", line 206, in pydantic.decorator.ValidatedFunction.execute
  File "/home/aaronpeterson/src/turbinia/turbinia/api/client/turbinia_api_lib/api/turbinia_request_results_api.py", line 211, in get_task_output
    raise ValueError("Error! Please call the get_task_output_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
ValueError: Error! Please call the get_task_output_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/bin/turbinia-client", line 33, in <module>
    sys.exit(load_entry_point('turbinia-client', 'console_scripts', 'turbinia-client')())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/bin/turbinia-client", line 25, in importlib_load_entry_point
    return next(matches).load()
           ^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/importlib/metadata/__init__.py", line 202, in load
    module = import_module(match.group('module'))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 940, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/aaronpeterson/src/turbinia/turbinia/api/cli/turbinia_client/turbiniacli_tool.py", line 109, in <module>
    main()
  File "/home/aaronpeterson/src/turbinia/turbinia/api/cli/turbinia_client/turbiniacli_tool.py", line 102, in main
    cli.main()
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia-talks/env/turbinia-client/lib/python3.11/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/aaronpeterson/src/turbinia/turbinia/api/cli/turbinia_client/core/commands.py", line 104, in get_task_result
    log.error(f'Error reading saved results file {filename}: {exception}')
                                                  ^^^^^^^^
UnboundLocalError: cannot access local variable 'filename' where it is not associated with a value
```

### Additional information

_No response_


Discussion / hints:

Fix patch:
diff --git a/requirements.txt b/requirements.txt
index cdea30ef5..102d59a9e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@ celery>=5.2.2
 cryptography>=2.0.2,>3.8
 docker
 fakeredis>=1.8.1
-fastapi>=0.75.0
+fastapi>=0.75.0, <0.99.0
 filelock
 google-api-core<2.0.0dev
 google-api-python-client
@@ -21,13 +21,14 @@ pandas
 protobuf>=3.19.0,<4.0.0dev
 proto-plus<2.0.0dev,>=1.22.0
 psq
+pydantic >= 1.10.5, < 2
 pyparsing<3
 pyyaml>=5.4.1
-pyOpenSSL
+pyOpenSSL>=23.2.0
 python-multipart
 redis<4.2
 six>=1.15.0
-urllib3[secure]
+urllib3 >= 1.25.3, < 2
 uvicorn>=0.17.6
 vine>=5.0.0
 PyJWT[crypto]<2
diff --git a/turbinia/api/api_server.py b/turbinia/api/api_server.py
index 55b98f1b9..cdd0970df 100644
--- a/turbinia/api/api_server.py
+++ b/turbinia/api/api_server.py
@@ -18,7 +18,6 @@
 import logging
 import yaml
 import uvicorn
-import pathlib
 
 from fastapi import FastAPI
 from fastapi.responses import Response
@@ -37,7 +36,9 @@
 
 def get_application() -> FastAPI:
   """Returns a FastAPI application object."""
-  description: str = 'Turbinia API server'
+  description: str = (
+      'Turbinia is an open-source framework for deploying,'
+      ' managing, and running distributed forensic workloads')
   fastapi_app = FastAPI(
       title='Turbinia API Server', description=description, version='1.0.0',
       license_info={
diff --git a/turbinia/api/cli/turbinia_client/core/commands.py b/turbinia/api/cli/turbinia_client/core/commands.py
index 35350ecc4..d25e22e45 100644
--- a/turbinia/api/cli/turbinia_client/core/commands.py
+++ b/turbinia/api/cli/turbinia_client/core/commands.py
@@ -58,15 +58,14 @@ def get_request_result(ctx: click.Context, request_id: str) -> None:
   """Gets Turbinia request results / output files."""
   client: api_client.ApiClient = ctx.obj.api_client
   api_instance = turbinia_request_results_api.TurbiniaRequestResultsApi(client)
+  filename = f'{request_id}.tgz'
   try:
-    api_response = api_instance.get_request_output(
-        request_id, _preload_content=False, _request_timeout=(30, 30))
-    filename = f'{request_id}.tgz'
+    api_response = api_instance.get_request_output_with_http_info(
+        request_id, _preload_content=False, _request_timeout=(30, 300))
     click.echo(f'Saving output for request {request_id} to: {filename}')
     # Read the response and save into a local file.
     with open(filename, 'wb') as file:
-      for chunk in api_response.read_chunked():
-        file.write(chunk)
+      file.write(api_response.raw_data)
   except exceptions.ApiException as exception:
     log.error(
         f'Received status code {exception.status} '
@@ -84,16 +83,14 @@ def get_task_result(ctx: click.Context, task_id: str) -> None:
   """Gets Turbinia task results / output files."""
   client: api_client.ApiClient = ctx.obj.api_client
   api_instance = turbinia_request_results_api.TurbiniaRequestResultsApi(client)
+  filename = f'{task_id}.tgz'
   try:
-    api_response = api_instance.get_task_output(
-        task_id, _preload_content=False, _request_timeout=(30, 30))
-    filename = f'{task_id}.tgz'
+    api_response = api_instance.get_task_output_with_http_info(
+        task_id, _preload_content=False, request_timeout=(30, 300))
     click.echo(f'Saving output for task {task_id} to: {filename}')
-
     # Read the response and save into a local file.
     with open(filename, 'wb') as file:
-      for chunk in api_response.read_chunked():
-        file.write(chunk)
+      file.write(api_response.raw_data)
   except exceptions.ApiException as exception:
     log.error(
         f'Received status code {exception.status} '
@@ -497,18 +494,12 @@ def upload_evidence(
         log.error(error_message)
         continue
       abs_path = os.path.abspath(file_path)
-      with open(file_path, 'rb') as f:
-        filename = os.path.basename(f.name)
-        filedata = f.read()
-        mimetype = (
-            mimetypes.guess_type(filename)[0] or 'application/octet-stream')
-        upload_file = tuple([filename, filedata, mimetype])
     except OSError:
       log.error(f'Unable to read file in {file_path}')
       continue
     try:
-      api_response = api_instance.upload_evidence(
-          upload_file, ticket_id, calculate_hash)
+      api_response = api_instance.upload_evidence([file_path], ticket_id,
+                                                  calculate_hash)
       report[abs_path] = api_response
     except exceptions.ApiException as exception:
       error_message = (
diff --git a/turbinia/api/client/.github/workflows/python.yml b/turbinia/api/client/.github/workflows/python.yml
index ea3bc01df..6a92fa126 100644
--- a/turbinia/api/client/.github/workflows/python.yml
+++ b/turbinia/api/client/.github/workflows/python.yml
@@ -26,6 +26,7 @@ jobs:
           python -m pip install --upgrade pip
           pip install flake8 pytest
           if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+          if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi
       - name: Lint with flake8
         run: |
           # stop the build if there are Python syntax errors or undefined names
diff --git a/turbinia/api/client/.gitlab-ci.yml b/turbinia/api/client/.gitlab-ci.yml
index 905ffa102..c84371da0 100644
--- a/turbinia/api/client/.gitlab-ci.yml
+++ b/turbinia/api/client/.gitlab-ci.yml
@@ -22,4 +22,10 @@ pytest-3.8:
   image: python:3.8-alpine
 pytest-3.9:
   extends: .pytest
-  image: python:3.9-alpine
\ No newline at end of file
+  image: python:3.9-alpine
+pytest-3.10:
+  extends: .pytest
+  image: python:3.10-alpine
+pytest-3.11:
+  extends: .pytest
+  image: python:3.11-alpine
diff --git a/turbinia/api/client/README.md b/turbinia/api/client/README.md
index b70a1e2f9..8271227c7 100644
--- a/turbinia/api/client/README.md
+++ b/turbinia/api/client/README.md
@@ -1,5 +1,5 @@
 # turbinia-api-lib
-Turbinia API server
+Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
 This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
 
@@ -115,6 +115,7 @@ Class | Method | HTTP request | Description
  - [BaseRequestOptions](docs/BaseRequestOptions.md)
  - [CompleteTurbiniaStats](docs/CompleteTurbiniaStats.md)
  - [HTTPValidationError](docs/HTTPValidationError.md)
+ - [LocationInner](docs/LocationInner.md)
  - [Request](docs/Request.md)
  - [ValidationError](docs/ValidationError.md)
 
diff --git a/turbinia/api/client/docs/BaseRequestOptions.md b/turbinia/api/client/docs/BaseRequestOptions.md
index 6e599266a..3b9d63f9c 100644
--- a/turbinia/api/client/docs/BaseRequestOptions.md
+++ b/turbinia/api/client/docs/BaseRequestOptions.md
@@ -5,17 +5,17 @@ Base Request Options class to be extended by other option types.
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**filter_patterns** | **object** |  | [optional] 
-**group_id** | **object** |  | [optional] 
-**jobs_allowlist** | **object** |  | [optional] 
-**jobs_denylist** | **object** |  | [optional] 
-**reason** | **object** |  | [optional] 
-**recipe_data** | **object** |  | [optional] 
-**recipe_name** | **object** |  | [optional] 
-**request_id** | **object** |  | [optional] 
-**requester** | **object** |  | [optional] 
-**sketch_id** | **object** |  | [optional] 
-**yara_rules** | **object** |  | [optional] 
+**filter_patterns** | **List[str]** |  | [optional] 
+**group_id** | **str** |  | [optional] 
+**jobs_allowlist** | **List[str]** |  | [optional] 
+**jobs_denylist** | **List[str]** |  | [optional] 
+**reason** | **str** |  | [optional] 
+**recipe_data** | **str** |  | [optional] 
+**recipe_name** | **str** |  | [optional] 
+**request_id** | **str** |  | [optional] 
+**requester** | **str** |  | [optional] 
+**sketch_id** | **int** |  | [optional] 
+**yara_rules** | **str** |  | [optional] 
 
 ## Example
 
diff --git a/turbinia/api/client/docs/BodyUploadEvidenceApiEvidenceUploadPost.md b/turbinia/api/client/docs/BodyUploadEvidenceApiEvidenceUploadPost.md
new file mode 100644
index 000000000..831ca3d15
--- /dev/null
+++ b/turbinia/api/client/docs/BodyUploadEvidenceApiEvidenceUploadPost.md
@@ -0,0 +1,30 @@
+# BodyUploadEvidenceApiEvidenceUploadPost
+
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**calculate_hash** | **object** |  | [optional] 
+**files** | **object** |  | 
+**ticket_id** | **object** |  | 
+
+## Example
+
+```python
+from turbinia_api_lib.models.body_upload_evidence_api_evidence_upload_post import BodyUploadEvidenceApiEvidenceUploadPost
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of BodyUploadEvidenceApiEvidenceUploadPost from a JSON string
+body_upload_evidence_api_evidence_upload_post_instance = BodyUploadEvidenceApiEvidenceUploadPost.from_json(json)
+# print the JSON string representation of the object
+print BodyUploadEvidenceApiEvidenceUploadPost.to_json()
+
+# convert the object into a dict
+body_upload_evidence_api_evidence_upload_post_dict = body_upload_evidence_api_evidence_upload_post_instance.to_dict()
+# create an instance of BodyUploadEvidenceApiEvidenceUploadPost from a dict
+body_upload_evidence_api_evidence_upload_post_form_dict = body_upload_evidence_api_evidence_upload_post.from_dict(body_upload_evidence_api_evidence_upload_post_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/turbinia/api/client/docs/CompleteTurbiniaStats.md b/turbinia/api/client/docs/CompleteTurbiniaStats.md
index d4ddb2425..dcf5a37fd 100644
--- a/turbinia/api/client/docs/CompleteTurbiniaStats.md
+++ b/turbinia/api/client/docs/CompleteTurbiniaStats.md
@@ -5,13 +5,13 @@ Statistics for different groups of tasks.
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**all_tasks** | **object** |  | 
-**failed_tasks** | **object** |  | 
-**requests** | **object** |  | 
-**successful_tasks** | **object** |  | 
-**tasks_per_type** | **object** |  | 
-**tasks_per_user** | **object** |  | 
-**tasks_per_worker** | **object** |  | 
+**all_tasks** | **object** |  | [optional] 
+**failed_tasks** | **object** |  | [optional] 
+**requests** | **object** |  | [optional] 
+**successful_tasks** | **object** |  | [optional] 
+**tasks_per_type** | **object** |  | [optional] 
+**tasks_per_user** | **object** |  | [optional] 
+**tasks_per_worker** | **object** |  | [optional] 
 
 ## Example
 
diff --git a/turbinia/api/client/docs/HTTPValidationError.md b/turbinia/api/client/docs/HTTPValidationError.md
index 9786c60e1..2ada76450 100644
--- a/turbinia/api/client/docs/HTTPValidationError.md
+++ b/turbinia/api/client/docs/HTTPValidationError.md
@@ -4,7 +4,7 @@
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**detail** | **object** |  | [optional] 
+**detail** | [**List[ValidationError]**](ValidationError.md) |  | [optional] 
 
 ## Example
 
diff --git a/turbinia/api/client/docs/LocationInner.md b/turbinia/api/client/docs/LocationInner.md
new file mode 100644
index 000000000..6fa987f6e
--- /dev/null
+++ b/turbinia/api/client/docs/LocationInner.md
@@ -0,0 +1,27 @@
+# LocationInner
+
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+
+## Example
+
+```python
+from turbinia_api_lib.models.location_inner import LocationInner
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of LocationInner from a JSON string
+location_inner_instance = LocationInner.from_json(json)
+# print the JSON string representation of the object
+print LocationInner.to_json()
+
+# convert the object into a dict
+location_inner_dict = location_inner_instance.to_dict()
+# create an instance of LocationInner from a dict
+location_inner_form_dict = location_inner.from_dict(location_inner_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/turbinia/api/client/docs/Request.md b/turbinia/api/client/docs/Request.md
index 4aebd6f73..5f1cd59a9 100644
--- a/turbinia/api/client/docs/Request.md
+++ b/turbinia/api/client/docs/Request.md
@@ -5,7 +5,7 @@ Base request object.
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**description** | **object** |  | [optional] 
+**description** | **str** |  | [optional] [default to 'Turbinia request object']
 **evidence** | **object** |  | 
 **request_options** | [**BaseRequestOptions**](BaseRequestOptions.md) |  | 
 
diff --git a/turbinia/api/client/docs/TurbiniaConfigurationApi.md b/turbinia/api/client/docs/TurbiniaConfigurationApi.md
index de3d652aa..5134c045d 100644
--- a/turbinia/api/client/docs/TurbiniaConfigurationApi.md
+++ b/turbinia/api/client/docs/TurbiniaConfigurationApi.md
@@ -53,6 +53,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 This endpoint does not need any parameter.
 
@@ -121,6 +122,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 This endpoint does not need any parameter.
 
diff --git a/turbinia/api/client/docs/TurbiniaEvidenceApi.md b/turbinia/api/client/docs/TurbiniaEvidenceApi.md
index 67c7603b2..3a5847263 100644
--- a/turbinia/api/client/docs/TurbiniaEvidenceApi.md
+++ b/turbinia/api/client/docs/TurbiniaEvidenceApi.md
@@ -58,6 +58,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
@@ -131,6 +132,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
@@ -192,8 +194,8 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaEvidenceApi(api_client)
-    group = None # object |  (optional)
-    output = None # object |  (optional)
+    group = 'group_example' # str |  (optional)
+    output = 'keys' # str |  (optional) (default to 'keys')
 
     try:
         # Get Evidence Summary
@@ -205,12 +207,13 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **group** | [**object**](.md)|  | [optional] 
- **output** | [**object**](.md)|  | [optional] 
+ **group** | **str**|  | [optional] 
+ **output** | **str**|  | [optional] [default to &#39;keys&#39;]
 
 ### Return type
 
@@ -278,6 +281,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 This endpoint does not need any parameter.
 
@@ -335,9 +339,9 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaEvidenceApi(api_client)
-    attribute_value = None # object | 
-    attribute_name = None # object |  (optional)
-    output = None # object |  (optional)
+    attribute_value = 'attribute_value_example' # str | 
+    attribute_name = 'request_id' # str |  (optional) (default to 'request_id')
+    output = 'keys' # str |  (optional) (default to 'keys')
 
     try:
         # Query Evidence
@@ -349,13 +353,14 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **attribute_value** | [**object**](.md)|  | 
- **attribute_name** | [**object**](.md)|  | [optional] 
- **output** | [**object**](.md)|  | [optional] 
+ **attribute_value** | **str**|  | 
+ **attribute_name** | **str**|  | [optional] [default to &#39;request_id&#39;]
+ **output** | **str**|  | [optional] [default to &#39;keys&#39;]
 
 ### Return type
 
@@ -412,9 +417,9 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaEvidenceApi(api_client)
-    files = None # object | 
-    ticket_id = None # object | 
-    calculate_hash = None # object |  (optional)
+    files = None # List[bytearray] | 
+    ticket_id = 'ticket_id_example' # str | 
+    calculate_hash = False # bool |  (optional) (default to False)
 
     try:
         # Upload Evidence
@@ -426,13 +431,14 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **files** | [**object**](object.md)|  | 
- **ticket_id** | [**object**](object.md)|  | 
- **calculate_hash** | [**object**](object.md)|  | [optional] 
+ **files** | **List[bytearray]**|  | 
+ **ticket_id** | **str**|  | 
+ **calculate_hash** | **bool**|  | [optional] [default to False]
 
 ### Return type
 
diff --git a/turbinia/api/client/docs/TurbiniaJobsApi.md b/turbinia/api/client/docs/TurbiniaJobsApi.md
index d65bd0e80..18e12d77c 100644
--- a/turbinia/api/client/docs/TurbiniaJobsApi.md
+++ b/turbinia/api/client/docs/TurbiniaJobsApi.md
@@ -52,6 +52,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 This endpoint does not need any parameter.
 
diff --git a/turbinia/api/client/docs/TurbiniaLogsApi.md b/turbinia/api/client/docs/TurbiniaLogsApi.md
index 6b3201e2e..2e30228cd 100644
--- a/turbinia/api/client/docs/TurbiniaLogsApi.md
+++ b/turbinia/api/client/docs/TurbiniaLogsApi.md
@@ -41,7 +41,7 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaLogsApi(api_client)
-    query = None # object | 
+    query = 'query_example' # str | 
 
     try:
         # Get Logs
@@ -53,11 +53,12 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **query** | [**object**](.md)|  | 
+ **query** | **str**|  | 
 
 ### Return type
 
diff --git a/turbinia/api/client/docs/TurbiniaRequestResultsApi.md b/turbinia/api/client/docs/TurbiniaRequestResultsApi.md
index fa849b9ab..5010b2c5a 100644
--- a/turbinia/api/client/docs/TurbiniaRequestResultsApi.md
+++ b/turbinia/api/client/docs/TurbiniaRequestResultsApi.md
@@ -9,7 +9,7 @@ Method | HTTP request | Description
 
 
 # **get_request_output**
-> object get_request_output(request_id)
+> bytearray get_request_output(request_id)
 
 Get Request Output
 
@@ -42,7 +42,7 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaRequestResultsApi(api_client)
-    request_id = None # object | 
+    request_id = 'request_id_example' # str | 
 
     try:
         # Get Request Output
@@ -54,15 +54,16 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **request_id** | [**object**](.md)|  | 
+ **request_id** | **str**|  | 
 
 ### Return type
 
-**object**
+**bytearray**
 
 ### Authorization
 
@@ -82,7 +83,7 @@ Name | Type | Description  | Notes
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
 # **get_task_output**
-> object get_task_output(task_id)
+> bytearray get_task_output(task_id)
 
 Get Task Output
 
@@ -115,7 +116,7 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaRequestResultsApi(api_client)
-    task_id = None # object | 
+    task_id = 'task_id_example' # str | 
 
     try:
         # Get Task Output
@@ -127,15 +128,16 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **task_id** | [**object**](.md)|  | 
+ **task_id** | **str**|  | 
 
 ### Return type
 
-**object**
+**bytearray**
 
 ### Authorization
 
diff --git a/turbinia/api/client/docs/TurbiniaRequestsApi.md b/turbinia/api/client/docs/TurbiniaRequestsApi.md
index c7e0de7e0..d51cc1555 100644
--- a/turbinia/api/client/docs/TurbiniaRequestsApi.md
+++ b/turbinia/api/client/docs/TurbiniaRequestsApi.md
@@ -56,6 +56,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
@@ -117,7 +118,7 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaRequestsApi(api_client)
-    request_id = None # object | 
+    request_id = 'request_id_example' # str | 
 
     try:
         # Get Request Status
@@ -129,11 +130,12 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **request_id** | [**object**](.md)|  | 
+ **request_id** | **str**|  | 
 
 ### Return type
 
@@ -201,6 +203,7 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 This endpoint does not need any parameter.
 
diff --git a/turbinia/api/client/docs/TurbiniaTasksApi.md b/turbinia/api/client/docs/TurbiniaTasksApi.md
index 02bb91262..e687d6b92 100644
--- a/turbinia/api/client/docs/TurbiniaTasksApi.md
+++ b/turbinia/api/client/docs/TurbiniaTasksApi.md
@@ -44,10 +44,10 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaTasksApi(api_client)
-    days = None # object |  (optional)
-    task_id = None # object |  (optional)
-    request_id = None # object |  (optional)
-    user = None # object |  (optional)
+    days = 56 # int |  (optional)
+    task_id = 'task_id_example' # str |  (optional)
+    request_id = 'request_id_example' # str |  (optional)
+    user = 'user_example' # str |  (optional)
 
     try:
         # Get Task Statistics
@@ -59,14 +59,15 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **days** | [**object**](.md)|  | [optional] 
- **task_id** | [**object**](.md)|  | [optional] 
- **request_id** | [**object**](.md)|  | [optional] 
- **user** | [**object**](.md)|  | [optional] 
+ **days** | **int**|  | [optional] 
+ **task_id** | **str**|  | [optional] 
+ **request_id** | **str**|  | [optional] 
+ **user** | **str**|  | [optional] 
 
 ### Return type
 
@@ -123,7 +124,7 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaTasksApi(api_client)
-    task_id = None # object | 
+    task_id = 'task_id_example' # str | 
 
     try:
         # Get Task Status
@@ -135,11 +136,12 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **task_id** | [**object**](.md)|  | 
+ **task_id** | **str**|  | 
 
 ### Return type
 
@@ -196,8 +198,8 @@ configuration.access_token = os.environ["ACCESS_TOKEN"]
 with turbinia_api_lib.ApiClient(configuration) as api_client:
     # Create an instance of the API class
     api_instance = turbinia_api_lib.TurbiniaTasksApi(api_client)
-    days = None # object |  (optional)
-    all_fields = None # object |  (optional)
+    days = 7 # int |  (optional) (default to 7)
+    all_fields = False # bool |  (optional) (default to False)
 
     try:
         # Get Workers Status
@@ -209,12 +211,13 @@ with turbinia_api_lib.ApiClient(configuration) as api_client:
 ```
 
 
+
 ### Parameters
 
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
- **days** | [**object**](.md)|  | [optional] 
- **all_fields** | [**object**](.md)|  | [optional] 
+ **days** | **int**|  | [optional] [default to 7]
+ **all_fields** | **bool**|  | [optional] [default to False]
 
 ### Return type
 
diff --git a/turbinia/api/client/docs/ValidationError.md b/turbinia/api/client/docs/ValidationError.md
index b93c074d5..f5748dac9 100644
--- a/turbinia/api/client/docs/ValidationError.md
+++ b/turbinia/api/client/docs/ValidationError.md
@@ -4,9 +4,9 @@
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**loc** | **object** |  | 
-**msg** | **object** |  | 
-**type** | **object** |  | 
+**loc** | [**List[LocationInner]**](LocationInner.md) |  | 
+**msg** | **str** |  | 
+**type** | **str** |  | 
 
 ## Example
 
diff --git a/turbinia/api/client/docs/ValidationErrorLocInner.md b/turbinia/api/client/docs/ValidationErrorLocInner.md
index 607989b43..6c14c4e56 100644
--- a/turbinia/api/client/docs/ValidationErrorLocInner.md
+++ b/turbinia/api/client/docs/ValidationErrorLocInner.md
@@ -4,8 +4,24 @@
 ## Properties
 Name | Type | Description | Notes
 ------------ | ------------- | ------------- | -------------
-**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]
 
+## Example
+
+```python
+from turbinia_api_lib.models.validation_error_loc_inner import ValidationErrorLocInner
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of ValidationErrorLocInner from a JSON string
+validation_error_loc_inner_instance = ValidationErrorLocInner.from_json(json)
+# print the JSON string representation of the object
+print ValidationErrorLocInner.to_json()
+
+# convert the object into a dict
+validation_error_loc_inner_dict = validation_error_loc_inner_instance.to_dict()
+# create an instance of ValidationErrorLocInner from a dict
+validation_error_loc_inner_form_dict = validation_error_loc_inner.from_dict(validation_error_loc_inner_dict)
+```
 [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 
 
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaConfigurationApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaConfigurationApi.md
new file mode 100644
index 000000000..48fe0afbf
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaConfigurationApi.md
@@ -0,0 +1,158 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_configuration_api.TurbiniaConfigurationApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**get_request_options**](#get_request_options) | **get** /api/config/request_options | Get Request Options
+[**read_config**](#read_config) | **get** /api/config/ | Read Config
+
+# **get_request_options**
+<a name="get_request_options"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_request_options()
+
+Get Request Options
+
+Returns a list BaseRequestOptions attributes.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_configuration_api
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_configuration_api.TurbiniaConfigurationApi(api_client)
+
+    # example, this endpoint has no required or optional parameters
+    try:
+        # Get Request Options
+        api_response = api_instance.get_request_options()
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaConfigurationApi->get_request_options: %s\n" % e)
+```
+### Parameters
+This endpoint does not need any parameter.
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_request_options.ApiResponseFor200) | Successful Response
+
+#### get_request_options.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **read_config**
+<a name="read_config"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type read_config()
+
+Read Config
+
+Retrieve turbinia config.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_configuration_api
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_configuration_api.TurbiniaConfigurationApi(api_client)
+
+    # example, this endpoint has no required or optional parameters
+    try:
+        # Read Config
+        api_response = api_instance.read_config()
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaConfigurationApi->read_config: %s\n" % e)
+```
+### Parameters
+This endpoint does not need any parameter.
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#read_config.ApiResponseFor200) | Successful Response
+
+#### read_config.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaEvidenceApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaEvidenceApi.md
new file mode 100644
index 000000000..fa3ca0545
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaEvidenceApi.md
@@ -0,0 +1,705 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_evidence_api.TurbiniaEvidenceApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**get_evidence_attributes**](#get_evidence_attributes) | **get** /api/evidence/types/{evidence_type} | Get Evidence Attributes
+[**get_evidence_by_id**](#get_evidence_by_id) | **get** /api/evidence/{evidence_id} | Get Evidence By Id
+[**get_evidence_summary**](#get_evidence_summary) | **get** /api/evidence/summary | Get Evidence Summary
+[**get_evidence_types**](#get_evidence_types) | **get** /api/evidence/types | Get Evidence Types
+[**query_evidence**](#query_evidence) | **get** /api/evidence/query | Query Evidence
+[**upload_evidence**](#upload_evidence) | **post** /api/evidence/upload | Upload Evidence
+
+# **get_evidence_attributes**
+<a name="get_evidence_attributes"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_evidence_attributes(evidence_type)
+
+Get Evidence Attributes
+
+Returns supported required parameters for evidence type.  Args:   evidence_type (str): Name of evidence type.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_evidence_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_evidence_api.TurbiniaEvidenceApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'evidence_type': None,
+    }
+    try:
+        # Get Evidence Attributes
+        api_response = api_instance.get_evidence_attributes(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->get_evidence_attributes: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+evidence_type | EvidenceTypeSchema | | 
+
+# EvidenceTypeSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_evidence_attributes.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_evidence_attributes.ApiResponseFor422) | Validation Error
+
+#### get_evidence_attributes.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_evidence_attributes.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_evidence_by_id**
+<a name="get_evidence_by_id"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_evidence_by_id(evidence_id)
+
+Get Evidence By Id
+
+Retrieves an evidence in Redis by using its UUID.  Args:   evidence_id (str): The UUID of the evidence.  Raises:   HTTPException: if the evidence is not found.  Returns:   Dictionary of the stored evidence
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_evidence_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_evidence_api.TurbiniaEvidenceApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'evidence_id': None,
+    }
+    try:
+        # Get Evidence By Id
+        api_response = api_instance.get_evidence_by_id(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->get_evidence_by_id: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+evidence_id | EvidenceIdSchema | | 
+
+# EvidenceIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_evidence_by_id.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_evidence_by_id.ApiResponseFor422) | Validation Error
+
+#### get_evidence_by_id.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_evidence_by_id.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_evidence_summary**
+<a name="get_evidence_summary"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_evidence_summary()
+
+Get Evidence Summary
+
+Retrieves a summary of all evidences in Redis.  Args:   group Optional(str): Attribute used to group summary.   output Optional(str): Sets how the evidence found will be output.   Returns:   summary (dict): Summary of all evidences and their content.  Raises:   HTTPException: if there are no evidences.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_evidence_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_evidence_api.TurbiniaEvidenceApi(api_client)
+
+    # example passing only optional values
+    query_params = {
+        'group': "_name",
+        'output': "keys",
+    }
+    try:
+        # Get Evidence Summary
+        api_response = api_instance.get_evidence_summary(
+            query_params=query_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->get_evidence_summary: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+query_params | RequestQueryParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### query_params
+#### RequestQueryParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+group | GroupSchema | | optional
+output | OutputSchema | | optional
+
+
+# GroupSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | must be one of ["_name", "cloud_only", "context_dependent", "copyable", "creation_time", "description", "has_child_evidence", "last_update", "local_path", "mount_path", "parent_evidence", "request_id", "resource_id", "resource_tracked", "save_metadata", "saved_path", "saved_path_type", "size", "source", "source_path", "type", ] 
+
+# OutputSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | must be one of ["keys", "content", "count", ] if omitted the server will use the default value of "keys"
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_evidence_summary.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_evidence_summary.ApiResponseFor422) | Validation Error
+
+#### get_evidence_summary.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_evidence_summary.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_evidence_types**
+<a name="get_evidence_types"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_evidence_types()
+
+Get Evidence Types
+
+Returns supported Evidence object types and required parameters.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_evidence_api
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_evidence_api.TurbiniaEvidenceApi(api_client)
+
+    # example, this endpoint has no required or optional parameters
+    try:
+        # Get Evidence Types
+        api_response = api_instance.get_evidence_types()
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->get_evidence_types: %s\n" % e)
+```
+### Parameters
+This endpoint does not need any parameter.
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_evidence_types.ApiResponseFor200) | Successful Response
+
+#### get_evidence_types.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **query_evidence**
+<a name="query_evidence"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type query_evidence(attribute_value)
+
+Query Evidence
+
+Queries evidence in Redis that have the specified attribute value.  Args:   attribute_name (str): Name of attribute to be queried.   attribute_value (str): Value the attribute must have.   output Optional(str): Sets how the evidence found will be output.  Returns:   summary (dict): Summary of all evidences and their content.  Raises:   HTTPException: If no matching evidence is found.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_evidence_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_evidence_api.TurbiniaEvidenceApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    query_params = {
+        'attribute_value': "attribute_value_example",
+    }
+    try:
+        # Query Evidence
+        api_response = api_instance.query_evidence(
+            query_params=query_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->query_evidence: %s\n" % e)
+
+    # example passing only optional values
+    query_params = {
+        'attribute_name': "request_id",
+        'attribute_value': "attribute_value_example",
+        'output': "keys",
+    }
+    try:
+        # Query Evidence
+        api_response = api_instance.query_evidence(
+            query_params=query_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->query_evidence: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+query_params | RequestQueryParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### query_params
+#### RequestQueryParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+attribute_name | AttributeNameSchema | | optional
+attribute_value | AttributeValueSchema | | 
+output | OutputSchema | | optional
+
+
+# AttributeNameSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | must be one of ["_name", "cloud_only", "context_dependent", "copyable", "creation_time", "description", "has_child_evidence", "last_update", "local_path", "mount_path", "parent_evidence", "request_id", "resource_id", "resource_tracked", "save_metadata", "saved_path", "saved_path_type", "size", "source", "source_path", "type", "tasks", ] if omitted the server will use the default value of "request_id"
+
+# AttributeValueSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+# OutputSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | must be one of ["keys", "content", "count", ] if omitted the server will use the default value of "keys"
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#query_evidence.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#query_evidence.ApiResponseFor422) | Validation Error
+
+#### query_evidence.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### query_evidence.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **upload_evidence**
+<a name="upload_evidence"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type upload_evidence()
+
+Upload Evidence
+
+Upload evidence file to server for processing.  Args:   ticket_id (str): ID of the ticket, which will be the name of the folder      where the evidence will be saved.   calculate_hash (bool): Boolean defining if the hash of the evidence should     be calculated.   file (List[UploadFile]): Evidence files to be uploaded to folder for later       processing. The maximum size of the file is 10 GB.   Returns:   List of uploaded evidences or warning messages if any.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_evidence_api
+from turbinia_api_lib.model.body_upload_evidence_api_evidence_upload_post import BodyUploadEvidenceApiEvidenceUploadPost
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_evidence_api.TurbiniaEvidenceApi(api_client)
+
+    # example passing only optional values
+    body = dict(
+        calculate_hash=False,
+        files=[
+            open('/path/to/file', 'rb')
+        ],
+        ticket_id="ticket_id_example",
+    )
+    try:
+        # Upload Evidence
+        api_response = api_instance.upload_evidence(
+            body=body,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaEvidenceApi->upload_evidence: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+body | typing.Union[SchemaForRequestBodyMultipartFormData, Unset] | optional, default is unset |
+content_type | str | optional, default is 'multipart/form-data' | Selects the schema and serialization of the request body
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### body
+
+# SchemaForRequestBodyMultipartFormData
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**BodyUploadEvidenceApiEvidenceUploadPost**](../../models/BodyUploadEvidenceApiEvidenceUploadPost.md) |  | 
+
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#upload_evidence.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#upload_evidence.ApiResponseFor422) | Validation Error
+
+#### upload_evidence.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### upload_evidence.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaJobsApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaJobsApi.md
new file mode 100644
index 000000000..87f924721
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaJobsApi.md
@@ -0,0 +1,83 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_jobs_api.TurbiniaJobsApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**read_jobs**](#read_jobs) | **get** /api/jobs/ | Read Jobs
+
+# **read_jobs**
+<a name="read_jobs"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type read_jobs()
+
+Read Jobs
+
+Return enabled jobs from the current Turbinia config.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_jobs_api
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_jobs_api.TurbiniaJobsApi(api_client)
+
+    # example, this endpoint has no required or optional parameters
+    try:
+        # Read Jobs
+        api_response = api_instance.read_jobs()
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaJobsApi->read_jobs: %s\n" % e)
+```
+### Parameters
+This endpoint does not need any parameter.
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#read_jobs.ApiResponseFor200) | Successful Response
+
+#### read_jobs.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaLogsApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaLogsApi.md
new file mode 100644
index 000000000..0065c7124
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaLogsApi.md
@@ -0,0 +1,124 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_logs_api.TurbiniaLogsApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**get_logs**](#get_logs) | **get** /api/logs/{query} | Get Logs
+
+# **get_logs**
+<a name="get_logs"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_logs(query)
+
+Get Logs
+
+Retrieve log data.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_logs_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_logs_api.TurbiniaLogsApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'query': "query_example",
+    }
+    try:
+        # Get Logs
+        api_response = api_instance.get_logs(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaLogsApi->get_logs: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+query | QuerySchema | | 
+
+# QuerySchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_logs.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_logs.ApiResponseFor422) | Validation Error
+
+#### get_logs.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_logs.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaRequestResultsApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaRequestResultsApi.md
new file mode 100644
index 000000000..a0920842b
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaRequestResultsApi.md
@@ -0,0 +1,240 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_request_results_api.TurbiniaRequestResultsApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**get_request_output**](#get_request_output) | **get** /api/result/request/{request_id} | Get Request Output
+[**get_task_output**](#get_task_output) | **get** /api/result/task/{task_id} | Get Task Output
+
+# **get_request_output**
+<a name="get_request_output"></a>
+> file_type get_request_output(request_id)
+
+Get Request Output
+
+Retrieve request output.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_request_results_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_request_results_api.TurbiniaRequestResultsApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'request_id': "request_id_example",
+    }
+    try:
+        # Get Request Output
+        api_response = api_instance.get_request_output(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaRequestResultsApi->get_request_output: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/octet-stream', 'application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+request_id | RequestIdSchema | | 
+
+# RequestIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_request_output.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_request_output.ApiResponseFor422) | Validation Error
+
+#### get_request_output.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationOctetStream, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationOctetStream
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+bytes, io.FileIO, io.BufferedReader,  | bytes, FileIO,  |  | 
+
+#### get_request_output.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_task_output**
+<a name="get_task_output"></a>
+> file_type get_task_output(task_id)
+
+Get Task Output
+
+Retrieves a task's output files.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_request_results_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_request_results_api.TurbiniaRequestResultsApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'task_id': "task_id_example",
+    }
+    try:
+        # Get Task Output
+        api_response = api_instance.get_task_output(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaRequestResultsApi->get_task_output: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/octet-stream', 'application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+task_id | TaskIdSchema | | 
+
+# TaskIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_task_output.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_task_output.ApiResponseFor422) | Validation Error
+
+#### get_task_output.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationOctetStream, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationOctetStream
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+bytes, io.FileIO, io.BufferedReader,  | bytes, FileIO,  |  | 
+
+#### get_task_output.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaRequestsApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaRequestsApi.md
new file mode 100644
index 000000000..9e92ab063
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaRequestsApi.md
@@ -0,0 +1,331 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_requests_api.TurbiniaRequestsApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**create_request**](#create_request) | **post** /api/request/ | Create Request
+[**get_request_status**](#get_request_status) | **get** /api/request/{request_id} | Get Request Status
+[**get_requests_summary**](#get_requests_summary) | **get** /api/request/summary | Get Requests Summary
+
+# **create_request**
+<a name="create_request"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type create_request(request)
+
+Create Request
+
+Create a new Turbinia request.  Args:   request (Request): FastAPI request object.   req (turbinia.api.schema.request): JSON object from the HTTP POST data       matching the schema defined for a Turbinia Request. The schema is used       by pydantic for field validation.  Raises:   ValidationError: if the Request object contains invalid data.   HTTPException: If pre-conditions are not met.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_requests_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from turbinia_api_lib.model.request import Request
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_requests_api.TurbiniaRequestsApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    body = Request(
+        description="Turbinia request object",
+        evidence=dict(),
+        request_options=BaseRequestOptions(
+            filter_patterns=[
+                "filter_patterns_example"
+            ],
+            group_id="group_id_example",
+            jobs_allowlist=[
+                "jobs_allowlist_example"
+            ],
+            jobs_denylist=[
+                "jobs_denylist_example"
+            ],
+            reason="reason_example",
+            recipe_data="recipe_data_example",
+            recipe_name="recipe_name_example",
+            request_id="request_id_example",
+            requester="requester_example",
+            sketch_id=1,
+            yara_rules="yara_rules_example",
+        ),
+    )
+    try:
+        # Create Request
+        api_response = api_instance.create_request(
+            body=body,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaRequestsApi->create_request: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+body | typing.Union[SchemaForRequestBodyApplicationJson] | required |
+content_type | str | optional, default is 'application/json' | Selects the schema and serialization of the request body
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### body
+
+# SchemaForRequestBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**Request**](../../models/Request.md) |  | 
+
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#create_request.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#create_request.ApiResponseFor422) | Validation Error
+
+#### create_request.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### create_request.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_request_status**
+<a name="get_request_status"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_request_status(request_id)
+
+Get Request Status
+
+Retrieves status for a Turbinia Request.  Args:   request (Request): FastAPI request object.   request_id (str): A Turbinia request identifier.  Raises:   HTTPException: if another exception is caught.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_requests_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_requests_api.TurbiniaRequestsApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'request_id': "request_id_example",
+    }
+    try:
+        # Get Request Status
+        api_response = api_instance.get_request_status(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaRequestsApi->get_request_status: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+request_id | RequestIdSchema | | 
+
+# RequestIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_request_status.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_request_status.ApiResponseFor422) | Validation Error
+
+#### get_request_status.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_request_status.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_requests_summary**
+<a name="get_requests_summary"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_requests_summary()
+
+Get Requests Summary
+
+Retrieves a summary of all Turbinia requests.  The response is validated against the RequestSummary model.  Raises:   HTTPException: if another exception is caught.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_requests_api
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_requests_api.TurbiniaRequestsApi(api_client)
+
+    # example, this endpoint has no required or optional parameters
+    try:
+        # Get Requests Summary
+        api_response = api_instance.get_requests_summary()
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaRequestsApi->get_requests_summary: %s\n" % e)
+```
+### Parameters
+This endpoint does not need any parameter.
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_requests_summary.ApiResponseFor200) | Successful Response
+
+#### get_requests_summary.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/apis/tags/TurbiniaTasksApi.md b/turbinia/api/client/docs/apis/tags/TurbiniaTasksApi.md
new file mode 100644
index 000000000..3c8f33b07
--- /dev/null
+++ b/turbinia/api/client/docs/apis/tags/TurbiniaTasksApi.md
@@ -0,0 +1,394 @@
+<a name="__pageTop"></a>
+# turbinia_api_lib.apis.tags.turbinia_tasks_api.TurbiniaTasksApi
+
+All URIs are relative to *http://localhost*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**get_task_statistics**](#get_task_statistics) | **get** /api/task/statistics | Get Task Statistics
+[**get_task_status**](#get_task_status) | **get** /api/task/{task_id} | Get Task Status
+[**get_workers_status**](#get_workers_status) | **get** /api/task/workers | Get Workers Status
+
+# **get_task_statistics**
+<a name="get_task_statistics"></a>
+> CompleteTurbiniaStats get_task_statistics()
+
+Get Task Statistics
+
+Retrieves  statistics for Turbinia execution.  Args:   days (int): The number of days we want history for.   task_id (string): The Id of the task.   request_id (string): The Id of the request we want tasks for.   user (string): The user of the request we want tasks for.  Returns:   statistics (str): JSON-formatted task statistics report.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_tasks_api
+from turbinia_api_lib.model.complete_turbinia_stats import CompleteTurbiniaStats
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_tasks_api.TurbiniaTasksApi(api_client)
+
+    # example passing only optional values
+    query_params = {
+        'days': 1,
+        'task_id': "task_id_example",
+        'request_id': "request_id_example",
+        'user': "user_example",
+    }
+    try:
+        # Get Task Statistics
+        api_response = api_instance.get_task_statistics(
+            query_params=query_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaTasksApi->get_task_statistics: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+query_params | RequestQueryParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### query_params
+#### RequestQueryParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+days | DaysSchema | | optional
+task_id | TaskIdSchema | | optional
+request_id | RequestIdSchema | | optional
+user | UserSchema | | optional
+
+
+# DaysSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+decimal.Decimal, int,  | decimal.Decimal,  |  | 
+
+# TaskIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+# RequestIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+# UserSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_task_statistics.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_task_statistics.ApiResponseFor422) | Validation Error
+
+#### get_task_statistics.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**CompleteTurbiniaStats**](../../models/CompleteTurbiniaStats.md) |  | 
+
+
+#### get_task_statistics.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_task_status**
+<a name="get_task_status"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_task_status(task_id)
+
+Get Task Status
+
+Retrieve task information.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_tasks_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_tasks_api.TurbiniaTasksApi(api_client)
+
+    # example passing only required values which don't have defaults set
+    path_params = {
+        'task_id': "task_id_example",
+    }
+    try:
+        # Get Task Status
+        api_response = api_instance.get_task_status(
+            path_params=path_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaTasksApi->get_task_status: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+path_params | RequestPathParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### path_params
+#### RequestPathParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+task_id | TaskIdSchema | | 
+
+# TaskIdSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_task_status.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_task_status.ApiResponseFor422) | Validation Error
+
+#### get_task_status.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_task_status.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
+# **get_workers_status**
+<a name="get_workers_status"></a>
+> bool, date, datetime, dict, float, int, list, str, none_type get_workers_status()
+
+Get Workers Status
+
+Retrieves the workers status.  Args:   days (int): The UUID of the evidence.   all_fields (bool): Returns all status fields if set to true.  Returns:   workers_status (str): JSON-formatted workers status.  Raises:   HTTPException: if no worker is found.
+
+### Example
+
+* OAuth Authentication (oAuth2):
+```python
+import turbinia_api_lib
+from turbinia_api_lib.apis.tags import turbinia_tasks_api
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from pprint import pprint
+# Defining the host is optional and defaults to http://localhost
+# See configuration.py for a list of all supported configuration parameters.
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure OAuth2 access token for authorization: oAuth2
+configuration = turbinia_api_lib.Configuration(
+    host = "http://localhost",
+    access_token = 'YOUR_ACCESS_TOKEN'
+)
+# Enter a context with an instance of the API client
+with turbinia_api_lib.ApiClient(configuration) as api_client:
+    # Create an instance of the API class
+    api_instance = turbinia_tasks_api.TurbiniaTasksApi(api_client)
+
+    # example passing only optional values
+    query_params = {
+        'days': 7,
+        'all_fields': False,
+    }
+    try:
+        # Get Workers Status
+        api_response = api_instance.get_workers_status(
+            query_params=query_params,
+        )
+        pprint(api_response)
+    except turbinia_api_lib.ApiException as e:
+        print("Exception when calling TurbiniaTasksApi->get_workers_status: %s\n" % e)
+```
+### Parameters
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+query_params | RequestQueryParams | |
+accept_content_types | typing.Tuple[str] | default is ('application/json', ) | Tells the server the content type(s) that are accepted by the client
+stream | bool | default is False | if True then the response.content will be streamed and loaded from a file like object. When downloading a file, set this to True to force the code to deserialize the content to a FileSchema file
+timeout | typing.Optional[typing.Union[int, typing.Tuple]] | default is None | the timeout used by the rest client
+skip_deserialization | bool | default is False | when True, headers and body will be unset and an instance of api_client.ApiResponseWithoutDeserialization will be returned
+
+### query_params
+#### RequestQueryParams
+
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+days | DaysSchema | | optional
+all_fields | AllFieldsSchema | | optional
+
+
+# DaysSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+decimal.Decimal, int,  | decimal.Decimal,  |  | if omitted the server will use the default value of 7
+
+# AllFieldsSchema
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+bool,  | BoolClass,  |  | if omitted the server will use the default value of False
+
+### Return Types, Responses
+
+Code | Class | Description
+------------- | ------------- | -------------
+n/a | api_client.ApiResponseWithoutDeserialization | When skip_deserialization is True this response is returned
+200 | [ApiResponseFor200](#get_workers_status.ApiResponseFor200) | Successful Response
+422 | [ApiResponseFor422](#get_workers_status.ApiResponseFor422) | Validation Error
+
+#### get_workers_status.ApiResponseFor200
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor200ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor200ResponseBodyApplicationJson
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+#### get_workers_status.ApiResponseFor422
+Name | Type | Description  | Notes
+------------- | ------------- | ------------- | -------------
+response | urllib3.HTTPResponse | Raw response |
+body | typing.Union[SchemaFor422ResponseBodyApplicationJson, ] |  |
+headers | Unset | headers were not defined |
+
+# SchemaFor422ResponseBodyApplicationJson
+Type | Description  | Notes
+------------- | ------------- | -------------
+[**HTTPValidationError**](../../models/HTTPValidationError.md) |  | 
+
+
+### Authorization
+
+[oAuth2](../../../README.md#oAuth2)
+
+[[Back to top]](#__pageTop) [[Back to API list]](../../../README.md#documentation-for-api-endpoints) [[Back to Model list]](../../../README.md#documentation-for-models) [[Back to README]](../../../README.md)
+
diff --git a/turbinia/api/client/docs/models/BaseRequestOptions.md b/turbinia/api/client/docs/models/BaseRequestOptions.md
new file mode 100644
index 000000000..553276fe9
--- /dev/null
+++ b/turbinia/api/client/docs/models/BaseRequestOptions.md
@@ -0,0 +1,63 @@
+# turbinia_api_lib.model.base_request_options.BaseRequestOptions
+
+Base Request Options class to be extended by other option types. 
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  | Base Request Options class to be extended by other option types.  | 
+
+### Dictionary Keys
+Key | Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | ------------- | -------------
+**[filter_patterns](#filter_patterns)** | list, tuple,  | tuple,  |  | [optional] 
+**group_id** | str,  | str,  |  | [optional] 
+**[jobs_allowlist](#jobs_allowlist)** | list, tuple,  | tuple,  |  | [optional] 
+**[jobs_denylist](#jobs_denylist)** | list, tuple,  | tuple,  |  | [optional] 
+**reason** | str,  | str,  |  | [optional] 
+**recipe_data** | str,  | str,  |  | [optional] 
+**recipe_name** | str,  | str,  |  | [optional] 
+**request_id** | str,  | str,  |  | [optional] 
+**requester** | str,  | str,  |  | [optional] 
+**sketch_id** | decimal.Decimal, int,  | decimal.Decimal,  |  | [optional] 
+**yara_rules** | str,  | str,  |  | [optional] 
+**any_string_name** | dict, frozendict.frozendict, str, date, datetime, int, float, bool, decimal.Decimal, None, list, tuple, bytes, io.FileIO, io.BufferedReader | frozendict.frozendict, str, BoolClass, decimal.Decimal, NoneClass, tuple, bytes, FileIO | any string name can be used but the value must be the correct type | [optional]
+
+# filter_patterns
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+list, tuple,  | tuple,  |  | 
+
+### Tuple Items
+Class Name | Input Type | Accessed Type | Description | Notes
+------------- | ------------- | ------------- | ------------- | -------------
+items | str,  | str,  |  | 
+
+# jobs_allowlist
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+list, tuple,  | tuple,  |  | 
+
+### Tuple Items
+Class Name | Input Type | Accessed Type | Description | Notes
+------------- | ------------- | ------------- | ------------- | -------------
+items | str,  | str,  |  | 
+
+# jobs_denylist
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+list, tuple,  | tuple,  |  | 
+
+### Tuple Items
+Class Name | Input Type | Accessed Type | Description | Notes
+------------- | ------------- | ------------- | ------------- | -------------
+items | str,  | str,  |  | 
+
+[[Back to Model list]](../../README.md#documentation-for-models) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to README]](../../README.md)
+
diff --git a/turbinia/api/client/docs/models/CompleteTurbiniaStats.md b/turbinia/api/client/docs/models/CompleteTurbiniaStats.md
new file mode 100644
index 000000000..7475352a1
--- /dev/null
+++ b/turbinia/api/client/docs/models/CompleteTurbiniaStats.md
@@ -0,0 +1,72 @@
+# turbinia_api_lib.model.complete_turbinia_stats.CompleteTurbiniaStats
+
+Statistics for different groups of tasks.
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  | Statistics for different groups of tasks. | 
+
+### Dictionary Keys
+Key | Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | ------------- | -------------
+**[all_tasks](#all_tasks)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**[failed_tasks](#failed_tasks)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**[requests](#requests)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**[successful_tasks](#successful_tasks)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**[tasks_per_type](#tasks_per_type)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**[tasks_per_user](#tasks_per_user)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**[tasks_per_worker](#tasks_per_worker)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | [optional] if omitted the server will use the default value of {}
+**any_string_name** | dict, frozendict.frozendict, str, date, datetime, int, float, bool, decimal.Decimal, None, list, tuple, bytes, io.FileIO, io.BufferedReader | frozendict.frozendict, str, BoolClass, decimal.Decimal, NoneClass, tuple, bytes, FileIO | any string name can be used but the value must be the correct type | [optional]
+
+# all_tasks
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+# failed_tasks
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+# requests
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+# successful_tasks
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+# tasks_per_type
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+# tasks_per_user
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+# tasks_per_worker
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | if omitted the server will use the default value of {}
+
+[[Back to Model list]](../../README.md#documentation-for-models) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to README]](../../README.md)
+
diff --git a/turbinia/api/client/docs/models/HTTPValidationError.md b/turbinia/api/client/docs/models/HTTPValidationError.md
new file mode 100644
index 000000000..0c393bd19
--- /dev/null
+++ b/turbinia/api/client/docs/models/HTTPValidationError.md
@@ -0,0 +1,27 @@
+# turbinia_api_lib.model.http_validation_error.HTTPValidationError
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | 
+
+### Dictionary Keys
+Key | Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | ------------- | -------------
+**[detail](#detail)** | list, tuple,  | tuple,  |  | [optional] 
+**any_string_name** | dict, frozendict.frozendict, str, date, datetime, int, float, bool, decimal.Decimal, None, list, tuple, bytes, io.FileIO, io.BufferedReader | frozendict.frozendict, str, BoolClass, decimal.Decimal, NoneClass, tuple, bytes, FileIO | any string name can be used but the value must be the correct type | [optional]
+
+# detail
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+list, tuple,  | tuple,  |  | 
+
+### Tuple Items
+Class Name | Input Type | Accessed Type | Description | Notes
+------------- | ------------- | ------------- | ------------- | -------------
+[**ValidationError**](ValidationError.md) | [**ValidationError**](ValidationError.md) | [**ValidationError**](ValidationError.md) |  | 
+
+[[Back to Model list]](../../README.md#documentation-for-models) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to README]](../../README.md)
+
diff --git a/turbinia/api/client/docs/models/Request.md b/turbinia/api/client/docs/models/Request.md
new file mode 100644
index 000000000..81791485d
--- /dev/null
+++ b/turbinia/api/client/docs/models/Request.md
@@ -0,0 +1,26 @@
+# turbinia_api_lib.model.request.Request
+
+Base request object. 
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  | Base request object.  | 
+
+### Dictionary Keys
+Key | Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | ------------- | -------------
+**request_options** | [**BaseRequestOptions**](BaseRequestOptions.md) | [**BaseRequestOptions**](BaseRequestOptions.md) |  | 
+**[evidence](#evidence)** | dict, frozendict.frozendict,  | frozendict.frozendict,  |  | 
+**description** | str,  | str,  |  | [optional] if omitted the server will use the default value of "Turbinia request object"
+**any_string_name** | dict, frozendict.frozendict, str, date, datetime, int, float, bool, decimal.Decimal, None, list, tuple, bytes, io.FileIO, io.BufferedReader | frozendict.frozendict, str, BoolClass, decimal.Decimal, NoneClass, tuple, bytes, FileIO | any string name can be used but the value must be the correct type | [optional]
+
+# evidence
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | 
+
+[[Back to Model list]](../../README.md#documentation-for-models) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to README]](../../README.md)
+
diff --git a/turbinia/api/client/docs/models/ValidationError.md b/turbinia/api/client/docs/models/ValidationError.md
new file mode 100644
index 000000000..ded6ac748
--- /dev/null
+++ b/turbinia/api/client/docs/models/ValidationError.md
@@ -0,0 +1,57 @@
+# turbinia_api_lib.model.validation_error.ValidationError
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict,  | frozendict.frozendict,  |  | 
+
+### Dictionary Keys
+Key | Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | ------------- | -------------
+**msg** | str,  | str,  |  | 
+**[loc](#loc)** | list, tuple,  | tuple,  |  | 
+**type** | str,  | str,  |  | 
+**any_string_name** | dict, frozendict.frozendict, str, date, datetime, int, float, bool, decimal.Decimal, None, list, tuple, bytes, io.FileIO, io.BufferedReader | frozendict.frozendict, str, BoolClass, decimal.Decimal, NoneClass, tuple, bytes, FileIO | any string name can be used but the value must be the correct type | [optional]
+
+# loc
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+list, tuple,  | tuple,  |  | 
+
+### Tuple Items
+Class Name | Input Type | Accessed Type | Description | Notes
+------------- | ------------- | ------------- | ------------- | -------------
+[items](#items) | dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+# items
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader,  | frozendict.frozendict, str, decimal.Decimal, BoolClass, NoneClass, tuple, bytes, FileIO |  | 
+
+### Composed Schemas (allOf/anyOf/oneOf/not)
+#### anyOf
+Class Name | Input Type | Accessed Type | Description | Notes
+------------- | ------------- | ------------- | ------------- | -------------
+[any_of_0](#any_of_0) | str,  | str,  |  | 
+[any_of_1](#any_of_1) | decimal.Decimal, int,  | decimal.Decimal,  |  | 
+
+# any_of_0
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+str,  | str,  |  | 
+
+# any_of_1
+
+## Model Type Info
+Input Type | Accessed Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+decimal.Decimal, int,  | decimal.Decimal,  |  | 
+
+[[Back to Model list]](../../README.md#documentation-for-models) [[Back to API list]](../../README.md#documentation-for-api-endpoints) [[Back to README]](../../README.md)
+
diff --git a/turbinia/api/client/setup.py b/turbinia/api/client/setup.py
index c7b418f84..42a5c148d 100644
--- a/turbinia/api/client/setup.py
+++ b/turbinia/api/client/setup.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 from setuptools import setup, find_packages  # noqa: H301
@@ -44,7 +44,7 @@
     license="Apache License 2.0",
     long_description_content_type='text/markdown',
     long_description="""\
-    Turbinia API server  # noqa: E501
-    """,
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
+    """,  # noqa: E501
     package_data={"turbinia_api_lib": ["py.typed"]},
 )
diff --git a/turbinia/api/client/turbinia_api_lib/__init__.py b/turbinia/api/client/turbinia_api_lib/__init__.py
index 95755aa31..eb4c22b35 100644
--- a/turbinia/api/client/turbinia_api_lib/__init__.py
+++ b/turbinia/api/client/turbinia_api_lib/__init__.py
@@ -5,13 +5,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 __version__ = "1.0.0"
@@ -40,5 +40,6 @@
 from turbinia_api_lib.models.base_request_options import BaseRequestOptions
 from turbinia_api_lib.models.complete_turbinia_stats import CompleteTurbiniaStats
 from turbinia_api_lib.models.http_validation_error import HTTPValidationError
+from turbinia_api_lib.models.location_inner import LocationInner
 from turbinia_api_lib.models.request import Request
 from turbinia_api_lib.models.validation_error import ValidationError
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_configuration_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_configuration_api.py
index 905de3b03..562d039ae 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_configuration_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_configuration_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,7 +17,6 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
 
 from typing import Any
 
@@ -30,14 +29,14 @@
 )
 
 
-class TurbiniaConfigurationApi(object):
+class TurbiniaConfigurationApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
@@ -55,10 +54,10 @@ def get_request_options(self, **kwargs) -> object:  # noqa: E501
 
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -66,7 +65,8 @@ def get_request_options(self, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_request_options_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_request_options_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_request_options_with_http_info(**kwargs)  # noqa: E501
 
     @validate_arguments
@@ -83,7 +83,7 @@ def get_request_options_with_http_info(self, **kwargs) -> ApiResponse:  # noqa:
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -186,10 +186,10 @@ def read_config(self, **kwargs) -> object:  # noqa: E501
 
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -197,7 +197,8 @@ def read_config(self, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the read_config_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the read_config_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.read_config_with_http_info(**kwargs)  # noqa: E501
 
     @validate_arguments
@@ -214,7 +215,7 @@ def read_config_with_http_info(self, **kwargs) -> ApiResponse:  # noqa: E501
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_evidence_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_evidence_api.py
index 6d981e7b2..d866978c5 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_evidence_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_evidence_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,9 +17,10 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
 
-from typing import Any, Optional
+from pydantic import StrictBool, StrictBytes, StrictStr, conlist
+
+from typing import Any, Optional, Union
 
 
 from turbinia_api_lib.api_client import ApiClient
@@ -30,14 +31,14 @@
 )
 
 
-class TurbiniaEvidenceApi(object):
+class TurbiniaEvidenceApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
@@ -57,10 +58,10 @@ def get_evidence_attributes(self, evidence_type : Any, **kwargs) -> object:  # n
         :type evidence_type: object
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -68,7 +69,8 @@ def get_evidence_attributes(self, evidence_type : Any, **kwargs) -> object:  # n
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_evidence_attributes_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_evidence_attributes_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_evidence_attributes_with_http_info(evidence_type, **kwargs)  # noqa: E501
 
     @validate_arguments
@@ -87,7 +89,7 @@ def get_evidence_attributes_with_http_info(self, evidence_type : Any, **kwargs)
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -197,10 +199,10 @@ def get_evidence_by_id(self, evidence_id : Any, **kwargs) -> object:  # noqa: E5
         :type evidence_id: object
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -208,7 +210,8 @@ def get_evidence_by_id(self, evidence_id : Any, **kwargs) -> object:  # noqa: E5
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_evidence_by_id_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_evidence_by_id_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_evidence_by_id_with_http_info(evidence_id, **kwargs)  # noqa: E501
 
     @validate_arguments
@@ -227,7 +230,7 @@ def get_evidence_by_id_with_http_info(self, evidence_id : Any, **kwargs) -> ApiR
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -323,7 +326,7 @@ def get_evidence_by_id_with_http_info(self, evidence_id : Any, **kwargs) -> ApiR
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def get_evidence_summary(self, group : Optional[Any] = None, output : Optional[Any] = None, **kwargs) -> object:  # noqa: E501
+    def get_evidence_summary(self, group : Optional[StrictStr] = None, output : Optional[StrictStr] = None, **kwargs) -> object:  # noqa: E501
         """Get Evidence Summary  # noqa: E501
 
         Retrieves a summary of all evidences in Redis.  Args:   group Optional(str): Attribute used to group summary.   output Optional(str): Sets how the evidence found will be output.   Returns:   summary (dict): Summary of all evidences and their content.  Raises:   HTTPException: if there are no evidences.  # noqa: E501
@@ -334,15 +337,15 @@ def get_evidence_summary(self, group : Optional[Any] = None, output : Optional[A
         >>> result = thread.get()
 
         :param group:
-        :type group: object
+        :type group: str
         :param output:
-        :type output: object
+        :type output: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -350,11 +353,12 @@ def get_evidence_summary(self, group : Optional[Any] = None, output : Optional[A
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_evidence_summary_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_evidence_summary_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_evidence_summary_with_http_info(group, output, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_evidence_summary_with_http_info(self, group : Optional[Any] = None, output : Optional[Any] = None, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_evidence_summary_with_http_info(self, group : Optional[StrictStr] = None, output : Optional[StrictStr] = None, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Evidence Summary  # noqa: E501
 
         Retrieves a summary of all evidences in Redis.  Args:   group Optional(str): Attribute used to group summary.   output Optional(str): Sets how the evidence found will be output.   Returns:   summary (dict): Summary of all evidences and their content.  Raises:   HTTPException: if there are no evidences.  # noqa: E501
@@ -365,13 +369,13 @@ def get_evidence_summary_with_http_info(self, group : Optional[Any] = None, outp
         >>> result = thread.get()
 
         :param group:
-        :type group: object
+        :type group: str
         :param output:
-        :type output: object
+        :type output: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -483,10 +487,10 @@ def get_evidence_types(self, **kwargs) -> object:  # noqa: E501
 
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -494,7 +498,8 @@ def get_evidence_types(self, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_evidence_types_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_evidence_types_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_evidence_types_with_http_info(**kwargs)  # noqa: E501
 
     @validate_arguments
@@ -511,7 +516,7 @@ def get_evidence_types_with_http_info(self, **kwargs) -> ApiResponse:  # noqa: E
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -602,7 +607,7 @@ def get_evidence_types_with_http_info(self, **kwargs) -> ApiResponse:  # noqa: E
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def query_evidence(self, attribute_value : Any, attribute_name : Optional[Any] = None, output : Optional[Any] = None, **kwargs) -> object:  # noqa: E501
+    def query_evidence(self, attribute_value : StrictStr, attribute_name : Optional[StrictStr] = None, output : Optional[StrictStr] = None, **kwargs) -> object:  # noqa: E501
         """Query Evidence  # noqa: E501
 
         Queries evidence in Redis that have the specified attribute value.  Args:   attribute_name (str): Name of attribute to be queried.   attribute_value (str): Value the attribute must have.   output Optional(str): Sets how the evidence found will be output.  Returns:   summary (dict): Summary of all evidences and their content.  Raises:   HTTPException: If no matching evidence is found.  # noqa: E501
@@ -613,17 +618,17 @@ def query_evidence(self, attribute_value : Any, attribute_name : Optional[Any] =
         >>> result = thread.get()
 
         :param attribute_value: (required)
-        :type attribute_value: object
+        :type attribute_value: str
         :param attribute_name:
-        :type attribute_name: object
+        :type attribute_name: str
         :param output:
-        :type output: object
+        :type output: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -631,11 +636,12 @@ def query_evidence(self, attribute_value : Any, attribute_name : Optional[Any] =
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the query_evidence_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the query_evidence_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.query_evidence_with_http_info(attribute_value, attribute_name, output, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def query_evidence_with_http_info(self, attribute_value : Any, attribute_name : Optional[Any] = None, output : Optional[Any] = None, **kwargs) -> ApiResponse:  # noqa: E501
+    def query_evidence_with_http_info(self, attribute_value : StrictStr, attribute_name : Optional[StrictStr] = None, output : Optional[StrictStr] = None, **kwargs) -> ApiResponse:  # noqa: E501
         """Query Evidence  # noqa: E501
 
         Queries evidence in Redis that have the specified attribute value.  Args:   attribute_name (str): Name of attribute to be queried.   attribute_value (str): Value the attribute must have.   output Optional(str): Sets how the evidence found will be output.  Returns:   summary (dict): Summary of all evidences and their content.  Raises:   HTTPException: If no matching evidence is found.  # noqa: E501
@@ -646,15 +652,15 @@ def query_evidence_with_http_info(self, attribute_value : Any, attribute_name :
         >>> result = thread.get()
 
         :param attribute_value: (required)
-        :type attribute_value: object
+        :type attribute_value: str
         :param attribute_name:
-        :type attribute_name: object
+        :type attribute_name: str
         :param output:
-        :type output: object
+        :type output: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -758,7 +764,7 @@ def query_evidence_with_http_info(self, attribute_value : Any, attribute_name :
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def upload_evidence(self, files : Optional[Any], ticket_id : Optional[Any], calculate_hash : Optional[Any] = None, **kwargs) -> object:  # noqa: E501
+    def upload_evidence(self, files : conlist(Union[StrictBytes, StrictStr]), ticket_id : StrictStr, calculate_hash : Optional[StrictBool] = None, **kwargs) -> object:  # noqa: E501
         """Upload Evidence  # noqa: E501
 
         Upload evidence file to server for processing.  Args:   ticket_id (str): ID of the ticket, which will be the name of the folder      where the evidence will be saved.   calculate_hash (bool): Boolean defining if the hash of the evidence should     be calculated.   file (List[UploadFile]): Evidence files to be uploaded to folder for later       processing. The maximum size of the file is 10 GB.   Returns:   List of uploaded evidences or warning messages if any.  # noqa: E501
@@ -769,17 +775,17 @@ def upload_evidence(self, files : Optional[Any], ticket_id : Optional[Any], calc
         >>> result = thread.get()
 
         :param files: (required)
-        :type files: object
+        :type files: List[bytearray]
         :param ticket_id: (required)
-        :type ticket_id: object
+        :type ticket_id: str
         :param calculate_hash:
-        :type calculate_hash: object
+        :type calculate_hash: bool
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -787,11 +793,12 @@ def upload_evidence(self, files : Optional[Any], ticket_id : Optional[Any], calc
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the upload_evidence_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the upload_evidence_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.upload_evidence_with_http_info(files, ticket_id, calculate_hash, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def upload_evidence_with_http_info(self, files : Optional[Any], ticket_id : Optional[Any], calculate_hash : Optional[Any] = None, **kwargs) -> ApiResponse:  # noqa: E501
+    def upload_evidence_with_http_info(self, files : conlist(Union[StrictBytes, StrictStr]), ticket_id : StrictStr, calculate_hash : Optional[StrictBool] = None, **kwargs) -> ApiResponse:  # noqa: E501
         """Upload Evidence  # noqa: E501
 
         Upload evidence file to server for processing.  Args:   ticket_id (str): ID of the ticket, which will be the name of the folder      where the evidence will be saved.   calculate_hash (bool): Boolean defining if the hash of the evidence should     be calculated.   file (List[UploadFile]): Evidence files to be uploaded to folder for later       processing. The maximum size of the file is 10 GB.   Returns:   List of uploaded evidences or warning messages if any.  # noqa: E501
@@ -802,15 +809,15 @@ def upload_evidence_with_http_info(self, files : Optional[Any], ticket_id : Opti
         >>> result = thread.get()
 
         :param files: (required)
-        :type files: object
+        :type files: List[bytearray]
         :param ticket_id: (required)
-        :type ticket_id: object
+        :type ticket_id: str
         :param calculate_hash:
-        :type calculate_hash: object
+        :type calculate_hash: bool
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -877,7 +884,8 @@ def upload_evidence_with_http_info(self, files : Optional[Any], ticket_id : Opti
             _form_params.append(('calculate_hash', _params['calculate_hash']))
 
         if _params['files']:
-            _form_params.append(('files', _params['files']))
+            _files['files'] = _params['files']
+            _collection_formats['files'] = 'csv'
 
         if _params['ticket_id']:
             _form_params.append(('ticket_id', _params['ticket_id']))
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_jobs_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_jobs_api.py
index d31d9834b..0d205f640 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_jobs_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_jobs_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,7 +17,6 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
 
 from typing import Any
 
@@ -30,14 +29,14 @@
 )
 
 
-class TurbiniaJobsApi(object):
+class TurbiniaJobsApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
@@ -55,10 +54,10 @@ def read_jobs(self, **kwargs) -> object:  # noqa: E501
 
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -66,7 +65,8 @@ def read_jobs(self, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the read_jobs_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the read_jobs_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.read_jobs_with_http_info(**kwargs)  # noqa: E501
 
     @validate_arguments
@@ -83,7 +83,7 @@ def read_jobs_with_http_info(self, **kwargs) -> ApiResponse:  # noqa: E501
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_logs_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_logs_api.py
index f53b5362b..2cf868132 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_logs_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_logs_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,7 +17,8 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
+
+from pydantic import StrictStr
 
 from typing import Any
 
@@ -30,20 +31,20 @@
 )
 
 
-class TurbiniaLogsApi(object):
+class TurbiniaLogsApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
 
     @validate_arguments
-    def get_logs(self, query : Any, **kwargs) -> object:  # noqa: E501
+    def get_logs(self, query : StrictStr, **kwargs) -> object:  # noqa: E501
         """Get Logs  # noqa: E501
 
         Retrieve log data.  # noqa: E501
@@ -54,13 +55,13 @@ def get_logs(self, query : Any, **kwargs) -> object:  # noqa: E501
         >>> result = thread.get()
 
         :param query: (required)
-        :type query: object
+        :type query: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -68,11 +69,12 @@ def get_logs(self, query : Any, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_logs_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_logs_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_logs_with_http_info(query, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_logs_with_http_info(self, query : Any, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_logs_with_http_info(self, query : StrictStr, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Logs  # noqa: E501
 
         Retrieve log data.  # noqa: E501
@@ -83,11 +85,11 @@ def get_logs_with_http_info(self, query : Any, **kwargs) -> ApiResponse:  # noqa
         >>> result = thread.get()
 
         :param query: (required)
-        :type query: object
+        :type query: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_request_results_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_request_results_api.py
index 5f05fb8da..a3a05678d 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_request_results_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_request_results_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,9 +17,10 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
 
-from typing import Any
+from pydantic import StrictStr
+
+from typing import Union
 
 
 from turbinia_api_lib.api_client import ApiClient
@@ -30,20 +31,20 @@
 )
 
 
-class TurbiniaRequestResultsApi(object):
+class TurbiniaRequestResultsApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
 
     @validate_arguments
-    def get_request_output(self, request_id : Any, **kwargs) -> object:  # noqa: E501
+    def get_request_output(self, request_id : StrictStr, **kwargs) -> bytearray:  # noqa: E501
         """Get Request Output  # noqa: E501
 
         Retrieve request output.  # noqa: E501
@@ -54,25 +55,26 @@ def get_request_output(self, request_id : Any, **kwargs) -> object:  # noqa: E50
         >>> result = thread.get()
 
         :param request_id: (required)
-        :type request_id: object
+        :type request_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
-        :rtype: object
+        :rtype: bytearray
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_request_output_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_request_output_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_request_output_with_http_info(request_id, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_request_output_with_http_info(self, request_id : Any, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_request_output_with_http_info(self, request_id : StrictStr, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Request Output  # noqa: E501
 
         Retrieve request output.  # noqa: E501
@@ -83,11 +85,11 @@ def get_request_output_with_http_info(self, request_id : Any, **kwargs) -> ApiRe
         >>> result = thread.get()
 
         :param request_id: (required)
-        :type request_id: object
+        :type request_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -106,7 +108,7 @@ def get_request_output_with_http_info(self, request_id : Any, **kwargs) -> ApiRe
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
-        :rtype: tuple(object, status_code(int), headers(HTTPHeaderDict))
+        :rtype: tuple(bytearray, status_code(int), headers(HTTPHeaderDict))
         """
 
         _params = locals()
@@ -161,7 +163,7 @@ def get_request_output_with_http_info(self, request_id : Any, **kwargs) -> ApiRe
         _auth_settings = ['oAuth2']  # noqa: E501
 
         _response_types_map = {
-            '200': "object",
+            '200': "bytearray",
             '422': "HTTPValidationError",
         }
 
@@ -183,7 +185,7 @@ def get_request_output_with_http_info(self, request_id : Any, **kwargs) -> ApiRe
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def get_task_output(self, task_id : Any, **kwargs) -> object:  # noqa: E501
+    def get_task_output(self, task_id : StrictStr, **kwargs) -> bytearray:  # noqa: E501
         """Get Task Output  # noqa: E501
 
         Retrieves a task's output files.  # noqa: E501
@@ -194,25 +196,26 @@ def get_task_output(self, task_id : Any, **kwargs) -> object:  # noqa: E501
         >>> result = thread.get()
 
         :param task_id: (required)
-        :type task_id: object
+        :type task_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
-        :rtype: object
+        :rtype: bytearray
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_task_output_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_task_output_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_task_output_with_http_info(task_id, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_task_output_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_task_output_with_http_info(self, task_id : StrictStr, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Task Output  # noqa: E501
 
         Retrieves a task's output files.  # noqa: E501
@@ -223,11 +226,11 @@ def get_task_output_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse
         >>> result = thread.get()
 
         :param task_id: (required)
-        :type task_id: object
+        :type task_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -246,7 +249,7 @@ def get_task_output_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
-        :rtype: tuple(object, status_code(int), headers(HTTPHeaderDict))
+        :rtype: tuple(bytearray, status_code(int), headers(HTTPHeaderDict))
         """
 
         _params = locals()
@@ -301,7 +304,7 @@ def get_task_output_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse
         _auth_settings = ['oAuth2']  # noqa: E501
 
         _response_types_map = {
-            '200': "object",
+            '200': "bytearray",
             '422': "HTTPValidationError",
         }
 
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_requests_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_requests_api.py
index 21d65f887..a5c77bda3 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_requests_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_requests_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,7 +17,8 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
+
+from pydantic import StrictStr
 
 from typing import Any
 
@@ -31,14 +32,14 @@
 )
 
 
-class TurbiniaRequestsApi(object):
+class TurbiniaRequestsApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
@@ -58,10 +59,10 @@ def create_request(self, request : Request, **kwargs) -> object:  # noqa: E501
         :type request: Request
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -69,7 +70,8 @@ def create_request(self, request : Request, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the create_request_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the create_request_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.create_request_with_http_info(request, **kwargs)  # noqa: E501
 
     @validate_arguments
@@ -88,7 +90,7 @@ def create_request_with_http_info(self, request : Request, **kwargs) -> ApiRespo
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -191,7 +193,7 @@ def create_request_with_http_info(self, request : Request, **kwargs) -> ApiRespo
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def get_request_status(self, request_id : Any, **kwargs) -> object:  # noqa: E501
+    def get_request_status(self, request_id : StrictStr, **kwargs) -> object:  # noqa: E501
         """Get Request Status  # noqa: E501
 
         Retrieves status for a Turbinia Request.  Args:   request (Request): FastAPI request object.   request_id (str): A Turbinia request identifier.  Raises:   HTTPException: if another exception is caught.  # noqa: E501
@@ -202,13 +204,13 @@ def get_request_status(self, request_id : Any, **kwargs) -> object:  # noqa: E50
         >>> result = thread.get()
 
         :param request_id: (required)
-        :type request_id: object
+        :type request_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -216,11 +218,12 @@ def get_request_status(self, request_id : Any, **kwargs) -> object:  # noqa: E50
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_request_status_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_request_status_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_request_status_with_http_info(request_id, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_request_status_with_http_info(self, request_id : Any, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_request_status_with_http_info(self, request_id : StrictStr, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Request Status  # noqa: E501
 
         Retrieves status for a Turbinia Request.  Args:   request (Request): FastAPI request object.   request_id (str): A Turbinia request identifier.  Raises:   HTTPException: if another exception is caught.  # noqa: E501
@@ -231,11 +234,11 @@ def get_request_status_with_http_info(self, request_id : Any, **kwargs) -> ApiRe
         >>> result = thread.get()
 
         :param request_id: (required)
-        :type request_id: object
+        :type request_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -343,10 +346,10 @@ def get_requests_summary(self, **kwargs) -> object:  # noqa: E501
 
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -354,7 +357,8 @@ def get_requests_summary(self, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_requests_summary_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_requests_summary_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_requests_summary_with_http_info(**kwargs)  # noqa: E501
 
     @validate_arguments
@@ -371,7 +375,7 @@ def get_requests_summary_with_http_info(self, **kwargs) -> ApiResponse:  # noqa:
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
diff --git a/turbinia/api/client/turbinia_api_lib/api/turbinia_tasks_api.py b/turbinia/api/client/turbinia_api_lib/api/turbinia_tasks_api.py
index b0e38fe81..6deff2671 100644
--- a/turbinia/api/client/turbinia_api_lib/api/turbinia_tasks_api.py
+++ b/turbinia/api/client/turbinia_api_lib/api/turbinia_tasks_api.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import re  # noqa: F401
@@ -17,7 +17,8 @@
 import warnings
 
 from pydantic import validate_arguments, ValidationError
-from typing_extensions import Annotated
+
+from pydantic import StrictBool, StrictInt, StrictStr
 
 from typing import Any, Optional
 
@@ -31,20 +32,20 @@
 )
 
 
-class TurbiniaTasksApi(object):
+class TurbiniaTasksApi:
     """NOTE: This class is auto generated by OpenAPI Generator
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
     """
 
-    def __init__(self, api_client=None):
+    def __init__(self, api_client=None) -> None:
         if api_client is None:
             api_client = ApiClient.get_default()
         self.api_client = api_client
 
     @validate_arguments
-    def get_task_statistics(self, days : Optional[Any] = None, task_id : Optional[Any] = None, request_id : Optional[Any] = None, user : Optional[Any] = None, **kwargs) -> CompleteTurbiniaStats:  # noqa: E501
+    def get_task_statistics(self, days : Optional[StrictInt] = None, task_id : Optional[StrictStr] = None, request_id : Optional[StrictStr] = None, user : Optional[StrictStr] = None, **kwargs) -> CompleteTurbiniaStats:  # noqa: E501
         """Get Task Statistics  # noqa: E501
 
         Retrieves  statistics for Turbinia execution.  Args:   days (int): The number of days we want history for.   task_id (string): The Id of the task.   request_id (string): The Id of the request we want tasks for.   user (string): The user of the request we want tasks for.  Returns:   statistics (str): JSON-formatted task statistics report.  # noqa: E501
@@ -55,19 +56,19 @@ def get_task_statistics(self, days : Optional[Any] = None, task_id : Optional[An
         >>> result = thread.get()
 
         :param days:
-        :type days: object
+        :type days: int
         :param task_id:
-        :type task_id: object
+        :type task_id: str
         :param request_id:
-        :type request_id: object
+        :type request_id: str
         :param user:
-        :type user: object
+        :type user: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -75,11 +76,12 @@ def get_task_statistics(self, days : Optional[Any] = None, task_id : Optional[An
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_task_statistics_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_task_statistics_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_task_statistics_with_http_info(days, task_id, request_id, user, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_task_statistics_with_http_info(self, days : Optional[Any] = None, task_id : Optional[Any] = None, request_id : Optional[Any] = None, user : Optional[Any] = None, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_task_statistics_with_http_info(self, days : Optional[StrictInt] = None, task_id : Optional[StrictStr] = None, request_id : Optional[StrictStr] = None, user : Optional[StrictStr] = None, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Task Statistics  # noqa: E501
 
         Retrieves  statistics for Turbinia execution.  Args:   days (int): The number of days we want history for.   task_id (string): The Id of the task.   request_id (string): The Id of the request we want tasks for.   user (string): The user of the request we want tasks for.  Returns:   statistics (str): JSON-formatted task statistics report.  # noqa: E501
@@ -90,17 +92,17 @@ def get_task_statistics_with_http_info(self, days : Optional[Any] = None, task_i
         >>> result = thread.get()
 
         :param days:
-        :type days: object
+        :type days: int
         :param task_id:
-        :type task_id: object
+        :type task_id: str
         :param request_id:
-        :type request_id: object
+        :type request_id: str
         :param user:
-        :type user: object
+        :type user: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -208,7 +210,7 @@ def get_task_statistics_with_http_info(self, days : Optional[Any] = None, task_i
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def get_task_status(self, task_id : Any, **kwargs) -> object:  # noqa: E501
+    def get_task_status(self, task_id : StrictStr, **kwargs) -> object:  # noqa: E501
         """Get Task Status  # noqa: E501
 
         Retrieve task information.  # noqa: E501
@@ -219,13 +221,13 @@ def get_task_status(self, task_id : Any, **kwargs) -> object:  # noqa: E501
         >>> result = thread.get()
 
         :param task_id: (required)
-        :type task_id: object
+        :type task_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -233,11 +235,12 @@ def get_task_status(self, task_id : Any, **kwargs) -> object:  # noqa: E501
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_task_status_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_task_status_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_task_status_with_http_info(task_id, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_task_status_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_task_status_with_http_info(self, task_id : StrictStr, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Task Status  # noqa: E501
 
         Retrieve task information.  # noqa: E501
@@ -248,11 +251,11 @@ def get_task_status_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse
         >>> result = thread.get()
 
         :param task_id: (required)
-        :type task_id: object
+        :type task_id: str
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
@@ -348,7 +351,7 @@ def get_task_status_with_http_info(self, task_id : Any, **kwargs) -> ApiResponse
             _request_auth=_params.get('_request_auth'))
 
     @validate_arguments
-    def get_workers_status(self, days : Optional[Any] = None, all_fields : Optional[Any] = None, **kwargs) -> object:  # noqa: E501
+    def get_workers_status(self, days : Optional[StrictInt] = None, all_fields : Optional[StrictBool] = None, **kwargs) -> object:  # noqa: E501
         """Get Workers Status  # noqa: E501
 
         Retrieves the workers status.  Args:   days (int): The UUID of the evidence.   all_fields (bool): Returns all status fields if set to true.  Returns:   workers_status (str): JSON-formatted workers status.  Raises:   HTTPException: if no worker is found.  # noqa: E501
@@ -359,15 +362,15 @@ def get_workers_status(self, days : Optional[Any] = None, all_fields : Optional[
         >>> result = thread.get()
 
         :param days:
-        :type days: object
+        :type days: int
         :param all_fields:
-        :type all_fields: object
+        :type all_fields: bool
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
-        :param _request_timeout: timeout setting for this request. If one
-                                 number provided, it will be total request
-                                 timeout. It can also be a pair (tuple) of
-                                 (connection, read) timeouts.
+        :param _request_timeout: timeout setting for this request.
+               If one number provided, it will be total request
+               timeout. It can also be a pair (tuple) of
+               (connection, read) timeouts.
         :return: Returns the result object.
                  If the method is called asynchronously,
                  returns the request thread.
@@ -375,11 +378,12 @@ def get_workers_status(self, days : Optional[Any] = None, all_fields : Optional[
         """
         kwargs['_return_http_data_only'] = True
         if '_preload_content' in kwargs:
-            raise ValueError("Error! Please call the get_workers_status_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data")
+            message = "Error! Please call the get_workers_status_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data"  # noqa: E501
+            raise ValueError(message)
         return self.get_workers_status_with_http_info(days, all_fields, **kwargs)  # noqa: E501
 
     @validate_arguments
-    def get_workers_status_with_http_info(self, days : Optional[Any] = None, all_fields : Optional[Any] = None, **kwargs) -> ApiResponse:  # noqa: E501
+    def get_workers_status_with_http_info(self, days : Optional[StrictInt] = None, all_fields : Optional[StrictBool] = None, **kwargs) -> ApiResponse:  # noqa: E501
         """Get Workers Status  # noqa: E501
 
         Retrieves the workers status.  Args:   days (int): The UUID of the evidence.   all_fields (bool): Returns all status fields if set to true.  Returns:   workers_status (str): JSON-formatted workers status.  Raises:   HTTPException: if no worker is found.  # noqa: E501
@@ -390,13 +394,13 @@ def get_workers_status_with_http_info(self, days : Optional[Any] = None, all_fie
         >>> result = thread.get()
 
         :param days:
-        :type days: object
+        :type days: int
         :param all_fields:
-        :type all_fields: object
+        :type all_fields: bool
         :param async_req: Whether to execute the request asynchronously.
         :type async_req: bool, optional
         :param _preload_content: if False, the ApiResponse.data will
-                                 be set to none and raw_data will store the 
+                                 be set to none and raw_data will store the
                                  HTTP response body without reading/decoding.
                                  Default is True.
         :type _preload_content: bool, optional
diff --git a/turbinia/api/client/turbinia_api_lib/api_client.py b/turbinia/api/client/turbinia_api_lib/api_client.py
index e3b3e1bee..435c1ea36 100644
--- a/turbinia/api/client/turbinia_api_lib/api_client.py
+++ b/turbinia/api/client/turbinia_api_lib/api_client.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import atexit
@@ -31,7 +31,7 @@
 from turbinia_api_lib.exceptions import ApiValueError, ApiException
 
 
-class ApiClient(object):
+class ApiClient:
     """Generic API client for OpenAPI client library builds.
 
     OpenAPI generic API client. This client handles the client-
@@ -63,7 +63,7 @@ class ApiClient(object):
     _pool = None
 
     def __init__(self, configuration=None, header_name=None, header_value=None,
-                 cookie=None, pool_threads=1):
+                 cookie=None, pool_threads=1) -> None:
         # use default configuration if none is provided
         if configuration is None:
             configuration = Configuration.get_default()
@@ -226,6 +226,9 @@ def __call_api(
         # data needs deserialization or returns HTTP data (deserialized) only
         if _preload_content or _return_http_data_only:
           response_type = response_types_map.get(str(response_data.status), None)
+          if not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599:
+              # if not found, look for '1XX', '2XX', etc.
+              response_type = response_types_map.get(str(response_data.status)[0] + "XX", None)
 
           if response_type == "bytearray":
               response_data.data = response_data.data
@@ -326,7 +329,7 @@ def __deserialize(self, data, klass):
         if data is None:
             return None
 
-        if type(klass) == str:
+        if isinstance(klass, str):
             if klass.startswith('List['):
                 sub_kls = re.match(r'List\[(.*)]', klass).group(1)
                 return [self.__deserialize(sub_data, sub_kls)
diff --git a/turbinia/api/client/turbinia_api_lib/api_response.py b/turbinia/api/client/turbinia_api_lib/api_response.py
index d81c2ff58..a0b62b952 100644
--- a/turbinia/api/client/turbinia_api_lib/api_response.py
+++ b/turbinia/api/client/turbinia_api_lib/api_response.py
@@ -18,7 +18,7 @@ def __init__(self,
                  status_code=None,
                  headers=None,
                  data=None,
-                 raw_data=None):
+                 raw_data=None) -> None:
         self.status_code = status_code
         self.headers = headers
         self.data = data
diff --git a/turbinia/api/client/turbinia_api_lib/apis/__init__.py b/turbinia/api/client/turbinia_api_lib/apis/__init__.py
index 3d882a496..7840f7726 100644
--- a/turbinia/api/client/turbinia_api_lib/apis/__init__.py
+++ b/turbinia/api/client/turbinia_api_lib/apis/__init__.py
@@ -1,22 +1,3 @@
-
-# flake8: noqa
-
-# Import all APIs into this package.
-# If you have many APIs here with many many models used in each API this may
-# raise a `RecursionError`.
-# In order to avoid this, import only the API that you directly need like:
-#
-#   from turbinia_api_lib.api.turbinia_configuration_api import TurbiniaConfigurationApi
-#
-# or import this package, but before doing it, use:
-#
-#   import sys
-#   sys.setrecursionlimit(n)
-
-# Import APIs into API package:
-from turbinia_api_lib.api.turbinia_configuration_api import TurbiniaConfigurationApi
-from turbinia_api_lib.api.turbinia_jobs_api import TurbiniaJobsApi
-from turbinia_api_lib.api.turbinia_logs_api import TurbiniaLogsApi
-from turbinia_api_lib.api.turbinia_request_results_api import TurbiniaRequestResultsApi
-from turbinia_api_lib.api.turbinia_requests_api import TurbiniaRequestsApi
-from turbinia_api_lib.api.turbinia_tasks_api import TurbiniaTasksApi
+# do not import all endpoints into this module because that uses a lot of memory and stack frames
+# if you need the ability to import all endpoints then import them from
+# tags, paths, or path_to_api, or tag_to_api
\ No newline at end of file
diff --git a/turbinia/api/client/turbinia_api_lib/apis/path_to_api.py b/turbinia/api/client/turbinia_api_lib/apis/path_to_api.py
new file mode 100644
index 000000000..c5019cd27
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/path_to_api.py
@@ -0,0 +1,68 @@
+import typing_extensions
+
+from turbinia_api_lib.paths import PathValues
+from turbinia_api_lib.apis.paths.api_config_ import ApiConfig
+from turbinia_api_lib.apis.paths.api_config_request_options import ApiConfigRequestOptions
+from turbinia_api_lib.apis.paths.api_evidence_query import ApiEvidenceQuery
+from turbinia_api_lib.apis.paths.api_evidence_summary import ApiEvidenceSummary
+from turbinia_api_lib.apis.paths.api_evidence_types import ApiEvidenceTypes
+from turbinia_api_lib.apis.paths.api_evidence_types_evidence_type import ApiEvidenceTypesEvidenceType
+from turbinia_api_lib.apis.paths.api_evidence_upload import ApiEvidenceUpload
+from turbinia_api_lib.apis.paths.api_evidence_evidence_id import ApiEvidenceEvidenceId
+from turbinia_api_lib.apis.paths.api_jobs_ import ApiJobs
+from turbinia_api_lib.apis.paths.api_logs_query import ApiLogsQuery
+from turbinia_api_lib.apis.paths.api_request_ import ApiRequest
+from turbinia_api_lib.apis.paths.api_request_summary import ApiRequestSummary
+from turbinia_api_lib.apis.paths.api_request_request_id import ApiRequestRequestId
+from turbinia_api_lib.apis.paths.api_result_request_request_id import ApiResultRequestRequestId
+from turbinia_api_lib.apis.paths.api_result_task_task_id import ApiResultTaskTaskId
+from turbinia_api_lib.apis.paths.api_task_statistics import ApiTaskStatistics
+from turbinia_api_lib.apis.paths.api_task_workers import ApiTaskWorkers
+from turbinia_api_lib.apis.paths.api_task_task_id import ApiTaskTaskId
+
+PathToApi = typing_extensions.TypedDict(
+    'PathToApi',
+    {
+        PathValues.API_CONFIG_: ApiConfig,
+        PathValues.API_CONFIG_REQUEST_OPTIONS: ApiConfigRequestOptions,
+        PathValues.API_EVIDENCE_QUERY: ApiEvidenceQuery,
+        PathValues.API_EVIDENCE_SUMMARY: ApiEvidenceSummary,
+        PathValues.API_EVIDENCE_TYPES: ApiEvidenceTypes,
+        PathValues.API_EVIDENCE_TYPES_EVIDENCE_TYPE: ApiEvidenceTypesEvidenceType,
+        PathValues.API_EVIDENCE_UPLOAD: ApiEvidenceUpload,
+        PathValues.API_EVIDENCE_EVIDENCE_ID: ApiEvidenceEvidenceId,
+        PathValues.API_JOBS_: ApiJobs,
+        PathValues.API_LOGS_QUERY: ApiLogsQuery,
+        PathValues.API_REQUEST_: ApiRequest,
+        PathValues.API_REQUEST_SUMMARY: ApiRequestSummary,
+        PathValues.API_REQUEST_REQUEST_ID: ApiRequestRequestId,
+        PathValues.API_RESULT_REQUEST_REQUEST_ID: ApiResultRequestRequestId,
+        PathValues.API_RESULT_TASK_TASK_ID: ApiResultTaskTaskId,
+        PathValues.API_TASK_STATISTICS: ApiTaskStatistics,
+        PathValues.API_TASK_WORKERS: ApiTaskWorkers,
+        PathValues.API_TASK_TASK_ID: ApiTaskTaskId,
+    }
+)
+
+path_to_api = PathToApi(
+    {
+        PathValues.API_CONFIG_: ApiConfig,
+        PathValues.API_CONFIG_REQUEST_OPTIONS: ApiConfigRequestOptions,
+        PathValues.API_EVIDENCE_QUERY: ApiEvidenceQuery,
+        PathValues.API_EVIDENCE_SUMMARY: ApiEvidenceSummary,
+        PathValues.API_EVIDENCE_TYPES: ApiEvidenceTypes,
+        PathValues.API_EVIDENCE_TYPES_EVIDENCE_TYPE: ApiEvidenceTypesEvidenceType,
+        PathValues.API_EVIDENCE_UPLOAD: ApiEvidenceUpload,
+        PathValues.API_EVIDENCE_EVIDENCE_ID: ApiEvidenceEvidenceId,
+        PathValues.API_JOBS_: ApiJobs,
+        PathValues.API_LOGS_QUERY: ApiLogsQuery,
+        PathValues.API_REQUEST_: ApiRequest,
+        PathValues.API_REQUEST_SUMMARY: ApiRequestSummary,
+        PathValues.API_REQUEST_REQUEST_ID: ApiRequestRequestId,
+        PathValues.API_RESULT_REQUEST_REQUEST_ID: ApiResultRequestRequestId,
+        PathValues.API_RESULT_TASK_TASK_ID: ApiResultTaskTaskId,
+        PathValues.API_TASK_STATISTICS: ApiTaskStatistics,
+        PathValues.API_TASK_WORKERS: ApiTaskWorkers,
+        PathValues.API_TASK_TASK_ID: ApiTaskTaskId,
+    }
+)
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/__init__.py b/turbinia/api/client/turbinia_api_lib/apis/paths/__init__.py
new file mode 100644
index 000000000..d1ead46b3
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/__init__.py
@@ -0,0 +1,3 @@
+# do not import all endpoints into this module because that uses a lot of memory and stack frames
+# if you need the ability to import all endpoints from this module, import them with
+# from turbinia_api_lib.apis.path_to_api import path_to_api
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_config_.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_config_.py
new file mode 100644
index 000000000..19759c5f3
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_config_.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_config_.get import ApiForget
+
+
+class ApiConfig(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_config_request_options.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_config_request_options.py
new file mode 100644
index 000000000..205b4ce97
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_config_request_options.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_config_request_options.get import ApiForget
+
+
+class ApiConfigRequestOptions(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_evidence_id.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_evidence_id.py
new file mode 100644
index 000000000..6273dd215
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_evidence_id.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_evidence_evidence_id.get import ApiForget
+
+
+class ApiEvidenceEvidenceId(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_query.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_query.py
new file mode 100644
index 000000000..0ab0f06cc
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_query.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_evidence_query.get import ApiForget
+
+
+class ApiEvidenceQuery(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_summary.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_summary.py
new file mode 100644
index 000000000..628fb44bd
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_summary.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_evidence_summary.get import ApiForget
+
+
+class ApiEvidenceSummary(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_types.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_types.py
new file mode 100644
index 000000000..55bd14f5b
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_types.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_evidence_types.get import ApiForget
+
+
+class ApiEvidenceTypes(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_types_evidence_type.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_types_evidence_type.py
new file mode 100644
index 000000000..33c77ff9d
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_types_evidence_type.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_evidence_types_evidence_type.get import ApiForget
+
+
+class ApiEvidenceTypesEvidenceType(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_upload.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_upload.py
new file mode 100644
index 000000000..43603d613
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_evidence_upload.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_evidence_upload.post import ApiForpost
+
+
+class ApiEvidenceUpload(
+    ApiForpost,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_jobs_.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_jobs_.py
new file mode 100644
index 000000000..35ca9d8cd
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_jobs_.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_jobs_.get import ApiForget
+
+
+class ApiJobs(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_logs_query.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_logs_query.py
new file mode 100644
index 000000000..fd7565c4a
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_logs_query.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_logs_query.get import ApiForget
+
+
+class ApiLogsQuery(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_.py
new file mode 100644
index 000000000..4398b0718
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_request_.post import ApiForpost
+
+
+class ApiRequest(
+    ApiForpost,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_request_id.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_request_id.py
new file mode 100644
index 000000000..79c221e86
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_request_id.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_request_request_id.get import ApiForget
+
+
+class ApiRequestRequestId(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_summary.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_summary.py
new file mode 100644
index 000000000..c1c4b0848
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_request_summary.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_request_summary.get import ApiForget
+
+
+class ApiRequestSummary(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_result_request_request_id.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_result_request_request_id.py
new file mode 100644
index 000000000..d3e911f0b
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_result_request_request_id.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_result_request_request_id.get import ApiForget
+
+
+class ApiResultRequestRequestId(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_result_task_task_id.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_result_task_task_id.py
new file mode 100644
index 000000000..705119be1
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_result_task_task_id.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_result_task_task_id.get import ApiForget
+
+
+class ApiResultTaskTaskId(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_statistics.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_statistics.py
new file mode 100644
index 000000000..218e4e27b
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_statistics.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_task_statistics.get import ApiForget
+
+
+class ApiTaskStatistics(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_task_id.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_task_id.py
new file mode 100644
index 000000000..be568df8c
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_task_id.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_task_task_id.get import ApiForget
+
+
+class ApiTaskTaskId(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_workers.py b/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_workers.py
new file mode 100644
index 000000000..d4d5d5d5d
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/paths/api_task_workers.py
@@ -0,0 +1,7 @@
+from turbinia_api_lib.paths.api_task_workers.get import ApiForget
+
+
+class ApiTaskWorkers(
+    ApiForget,
+):
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tag_to_api.py b/turbinia/api/client/turbinia_api_lib/apis/tag_to_api.py
new file mode 100644
index 000000000..7934b7c0f
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tag_to_api.py
@@ -0,0 +1,35 @@
+import typing_extensions
+
+from turbinia_api_lib.apis.tags import TagValues
+from turbinia_api_lib.apis.tags.turbinia_configuration_api import TurbiniaConfigurationApi
+from turbinia_api_lib.apis.tags.turbinia_evidence_api import TurbiniaEvidenceApi
+from turbinia_api_lib.apis.tags.turbinia_jobs_api import TurbiniaJobsApi
+from turbinia_api_lib.apis.tags.turbinia_logs_api import TurbiniaLogsApi
+from turbinia_api_lib.apis.tags.turbinia_request_results_api import TurbiniaRequestResultsApi
+from turbinia_api_lib.apis.tags.turbinia_requests_api import TurbiniaRequestsApi
+from turbinia_api_lib.apis.tags.turbinia_tasks_api import TurbiniaTasksApi
+
+TagToApi = typing_extensions.TypedDict(
+    'TagToApi',
+    {
+        TagValues.TURBINIA_CONFIGURATION: TurbiniaConfigurationApi,
+        TagValues.TURBINIA_EVIDENCE: TurbiniaEvidenceApi,
+        TagValues.TURBINIA_JOBS: TurbiniaJobsApi,
+        TagValues.TURBINIA_LOGS: TurbiniaLogsApi,
+        TagValues.TURBINIA_REQUEST_RESULTS: TurbiniaRequestResultsApi,
+        TagValues.TURBINIA_REQUESTS: TurbiniaRequestsApi,
+        TagValues.TURBINIA_TASKS: TurbiniaTasksApi,
+    }
+)
+
+tag_to_api = TagToApi(
+    {
+        TagValues.TURBINIA_CONFIGURATION: TurbiniaConfigurationApi,
+        TagValues.TURBINIA_EVIDENCE: TurbiniaEvidenceApi,
+        TagValues.TURBINIA_JOBS: TurbiniaJobsApi,
+        TagValues.TURBINIA_LOGS: TurbiniaLogsApi,
+        TagValues.TURBINIA_REQUEST_RESULTS: TurbiniaRequestResultsApi,
+        TagValues.TURBINIA_REQUESTS: TurbiniaRequestsApi,
+        TagValues.TURBINIA_TASKS: TurbiniaTasksApi,
+    }
+)
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/__init__.py b/turbinia/api/client/turbinia_api_lib/apis/tags/__init__.py
new file mode 100644
index 000000000..097040cbb
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/__init__.py
@@ -0,0 +1,15 @@
+# do not import all endpoints into this module because that uses a lot of memory and stack frames
+# if you need the ability to import all endpoints from this module, import them with
+# from turbinia_api_lib.apis.tag_to_api import tag_to_api
+
+import enum
+
+
+class TagValues(str, enum.Enum):
+    TURBINIA_CONFIGURATION = "Turbinia Configuration"
+    TURBINIA_EVIDENCE = "Turbinia Evidence"
+    TURBINIA_JOBS = "Turbinia Jobs"
+    TURBINIA_LOGS = "Turbinia Logs"
+    TURBINIA_REQUEST_RESULTS = "Turbinia Request Results"
+    TURBINIA_REQUESTS = "Turbinia Requests"
+    TURBINIA_TASKS = "Turbinia Tasks"
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_configuration_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_configuration_api.py
new file mode 100644
index 000000000..5c2f969b5
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_configuration_api.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_config_request_options.get import GetRequestOptions
+from turbinia_api_lib.paths.api_config_.get import ReadConfig
+
+
+class TurbiniaConfigurationApi(
+    GetRequestOptions,
+    ReadConfig,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_evidence_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_evidence_api.py
new file mode 100644
index 000000000..fa8b19d5d
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_evidence_api.py
@@ -0,0 +1,33 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_evidence_types_evidence_type.get import GetEvidenceAttributes
+from turbinia_api_lib.paths.api_evidence_evidence_id.get import GetEvidenceById
+from turbinia_api_lib.paths.api_evidence_summary.get import GetEvidenceSummary
+from turbinia_api_lib.paths.api_evidence_types.get import GetEvidenceTypes
+from turbinia_api_lib.paths.api_evidence_query.get import QueryEvidence
+from turbinia_api_lib.paths.api_evidence_upload.post import UploadEvidence
+
+
+class TurbiniaEvidenceApi(
+    GetEvidenceAttributes,
+    GetEvidenceById,
+    GetEvidenceSummary,
+    GetEvidenceTypes,
+    QueryEvidence,
+    UploadEvidence,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_jobs_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_jobs_api.py
new file mode 100644
index 000000000..620921102
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_jobs_api.py
@@ -0,0 +1,23 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_jobs_.get import ReadJobs
+
+
+class TurbiniaJobsApi(
+    ReadJobs,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_logs_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_logs_api.py
new file mode 100644
index 000000000..9f1a243c7
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_logs_api.py
@@ -0,0 +1,23 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_logs_query.get import GetLogs
+
+
+class TurbiniaLogsApi(
+    GetLogs,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_request_results_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_request_results_api.py
new file mode 100644
index 000000000..cfdf99b77
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_request_results_api.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_result_request_request_id.get import GetRequestOutput
+from turbinia_api_lib.paths.api_result_task_task_id.get import GetTaskOutput
+
+
+class TurbiniaRequestResultsApi(
+    GetRequestOutput,
+    GetTaskOutput,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_requests_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_requests_api.py
new file mode 100644
index 000000000..7c3de522d
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_requests_api.py
@@ -0,0 +1,27 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_request_.post import CreateRequest
+from turbinia_api_lib.paths.api_request_request_id.get import GetRequestStatus
+from turbinia_api_lib.paths.api_request_summary.get import GetRequestsSummary
+
+
+class TurbiniaRequestsApi(
+    CreateRequest,
+    GetRequestStatus,
+    GetRequestsSummary,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_tasks_api.py b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_tasks_api.py
new file mode 100644
index 000000000..6faea7c20
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/apis/tags/turbinia_tasks_api.py
@@ -0,0 +1,27 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from turbinia_api_lib.paths.api_task_statistics.get import GetTaskStatistics
+from turbinia_api_lib.paths.api_task_task_id.get import GetTaskStatus
+from turbinia_api_lib.paths.api_task_workers.get import GetWorkersStatus
+
+
+class TurbiniaTasksApi(
+    GetTaskStatistics,
+    GetTaskStatus,
+    GetWorkersStatus,
+):
+    """NOTE: This class is auto generated by OpenAPI Generator
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+    pass
diff --git a/turbinia/api/client/turbinia_api_lib/configuration.py b/turbinia/api/client/turbinia_api_lib/configuration.py
index fda853b5c..c8a2fa296 100644
--- a/turbinia/api/client/turbinia_api_lib/configuration.py
+++ b/turbinia/api/client/turbinia_api_lib/configuration.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import copy
@@ -19,7 +19,6 @@
 import urllib3
 
 import http.client as httplib
-from turbinia_api_lib.exceptions import ApiValueError
 
 JSON_SCHEMA_VALIDATION_KEYWORDS = {
     'multipleOf', 'maximum', 'exclusiveMaximum',
@@ -27,7 +26,7 @@
     'minLength', 'pattern', 'maxItems', 'minItems'
 }
 
-class Configuration(object):
+class Configuration:
     """This class contains various settings of the API client.
 
     :param host: Base url.
@@ -49,7 +48,8 @@ class Configuration(object):
       configuration.
     :param server_operation_variables: Mapping from operation ID to a mapping with
       string values to replace variables in templated server configuration.
-      The validation of enums is performed for variables with defined enum values before.
+      The validation of enums is performed for variables with defined enum
+      values before.
     :param ssl_ca_cert: str - the path to a file of concatenated CA certificates
       in PEM format.
 
@@ -65,7 +65,7 @@ def __init__(self, host=None,
                  server_index=None, server_variables=None,
                  server_operation_index=None, server_operation_variables=None,
                  ssl_ca_cert=None,
-                 ):
+                 ) -> None:
         """Constructor
         """
         self._base_path = "http://localhost" if host is None else host
diff --git a/turbinia/api/client/turbinia_api_lib/exceptions.py b/turbinia/api/client/turbinia_api_lib/exceptions.py
index f8a90f5f2..8525fb875 100644
--- a/turbinia/api/client/turbinia_api_lib/exceptions.py
+++ b/turbinia/api/client/turbinia_api_lib/exceptions.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 class OpenApiException(Exception):
@@ -18,7 +18,7 @@ class OpenApiException(Exception):
 
 class ApiTypeError(OpenApiException, TypeError):
     def __init__(self, msg, path_to_item=None, valid_classes=None,
-                 key_type=None):
+                 key_type=None) -> None:
         """ Raises an exception for TypeErrors
 
         Args:
@@ -46,7 +46,7 @@ def __init__(self, msg, path_to_item=None, valid_classes=None,
 
 
 class ApiValueError(OpenApiException, ValueError):
-    def __init__(self, msg, path_to_item=None):
+    def __init__(self, msg, path_to_item=None) -> None:
         """
         Args:
             msg (str): the exception message
@@ -64,7 +64,7 @@ def __init__(self, msg, path_to_item=None):
 
 
 class ApiAttributeError(OpenApiException, AttributeError):
-    def __init__(self, msg, path_to_item=None):
+    def __init__(self, msg, path_to_item=None) -> None:
         """
         Raised when an attribute reference or assignment fails.
 
@@ -83,7 +83,7 @@ def __init__(self, msg, path_to_item=None):
 
 
 class ApiKeyError(OpenApiException, KeyError):
-    def __init__(self, msg, path_to_item=None):
+    def __init__(self, msg, path_to_item=None) -> None:
         """
         Args:
             msg (str): the exception message
@@ -101,7 +101,7 @@ def __init__(self, msg, path_to_item=None):
 
 class ApiException(OpenApiException):
 
-    def __init__(self, status=None, reason=None, http_resp=None):
+    def __init__(self, status=None, reason=None, http_resp=None) -> None:
         if http_resp:
             self.status = http_resp.status
             self.reason = http_resp.reason
@@ -128,30 +128,30 @@ def __str__(self):
 
 class BadRequestException(ApiException):
 
-    def __init__(self, status=None, reason=None, http_resp=None):
+    def __init__(self, status=None, reason=None, http_resp=None) -> None:
         super(BadRequestException, self).__init__(status, reason, http_resp)
 
 class NotFoundException(ApiException):
 
-    def __init__(self, status=None, reason=None, http_resp=None):
+    def __init__(self, status=None, reason=None, http_resp=None) -> None:
         super(NotFoundException, self).__init__(status, reason, http_resp)
 
 
 class UnauthorizedException(ApiException):
 
-    def __init__(self, status=None, reason=None, http_resp=None):
+    def __init__(self, status=None, reason=None, http_resp=None) -> None:
         super(UnauthorizedException, self).__init__(status, reason, http_resp)
 
 
 class ForbiddenException(ApiException):
 
-    def __init__(self, status=None, reason=None, http_resp=None):
+    def __init__(self, status=None, reason=None, http_resp=None) -> None:
         super(ForbiddenException, self).__init__(status, reason, http_resp)
 
 
 class ServiceException(ApiException):
 
-    def __init__(self, status=None, reason=None, http_resp=None):
+    def __init__(self, status=None, reason=None, http_resp=None) -> None:
         super(ServiceException, self).__init__(status, reason, http_resp)
 
 
diff --git a/turbinia/api/client/turbinia_api_lib/model/base_request_options.py b/turbinia/api/client/turbinia_api_lib/model/base_request_options.py
index b4bb306e1..d9192b9ce 100644
--- a/turbinia/api/client/turbinia_api_lib/model/base_request_options.py
+++ b/turbinia/api/client/turbinia_api_lib/model/base_request_options.py
@@ -1,303 +1,246 @@
+# coding: utf-8
+
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
 
     The version of the OpenAPI document: 1.0.0
     Generated by: https://openapi-generator.tech
 """
 
-
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
 import re  # noqa: F401
-import sys  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
 
-from turbinia_api_lib.model_utils import (  # noqa: F401
-    ApiTypeError,
-    ModelComposed,
-    ModelNormal,
-    ModelSimple,
-    cached_property,
-    change_keys_js_to_python,
-    convert_js_args_to_python_args,
-    date,
-    datetime,
-    file_type,
-    none_type,
-    validate_get_composed_info,
-    OpenApiModel
-)
-from turbinia_api_lib.exceptions import ApiAttributeError
+import frozendict  # noqa: F401
 
+from turbinia_api_lib import schemas  # noqa: F401
 
 
-class BaseRequestOptions(ModelNormal):
+class BaseRequestOptions(
+    schemas.DictSchema
+):
     """NOTE: This class is auto generated by OpenAPI Generator.
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
 
-    Attributes:
-      allowed_values (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          with a capitalized key describing the allowed value and an allowed
-          value. These dicts store the allowed enum values.
-      attribute_map (dict): The key is attribute name
-          and the value is json key in definition.
-      discriminator_value_class_map (dict): A dict to go from the discriminator
-          variable value to the discriminator class name.
-      validations (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          that stores validations for max_length, min_length, max_items,
-          min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
-          inclusive_minimum, and regex.
-      additional_properties_type (tuple): A tuple of classes accepted
-          as additional properties values.
+    Base Request Options class to be extended by other option types. 
     """
 
-    allowed_values = {
-    }
-
-    validations = {
-    }
-
-    @cached_property
-    def additional_properties_type():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
-        """
-        return (bool, date, datetime, dict, float, int, list, str, none_type,)  # noqa: E501
-
-    _nullable = False
-
-    @cached_property
-    def openapi_types():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
-
-        Returns
-            openapi_types (dict): The key is attribute name
-                and the value is attribute type.
-        """
-        return {
-            'filter_patterns': ([str],),  # noqa: E501
-            'group_id': (str,),  # noqa: E501
-            'jobs_allowlist': ([str],),  # noqa: E501
-            'jobs_denylist': ([str],),  # noqa: E501
-            'reason': (str,),  # noqa: E501
-            'recipe_data': (str,),  # noqa: E501
-            'recipe_name': (str,),  # noqa: E501
-            'request_id': (str,),  # noqa: E501
-            'requester': (str,),  # noqa: E501
-            'sketch_id': (int,),  # noqa: E501
-            'yara_rules': (str,),  # noqa: E501
-        }
-
-    @cached_property
-    def discriminator():
-        return None
-
-
-    attribute_map = {
-        'filter_patterns': 'filter_patterns',  # noqa: E501
-        'group_id': 'group_id',  # noqa: E501
-        'jobs_allowlist': 'jobs_allowlist',  # noqa: E501
-        'jobs_denylist': 'jobs_denylist',  # noqa: E501
-        'reason': 'reason',  # noqa: E501
-        'recipe_data': 'recipe_data',  # noqa: E501
-        'recipe_name': 'recipe_name',  # noqa: E501
-        'request_id': 'request_id',  # noqa: E501
-        'requester': 'requester',  # noqa: E501
-        'sketch_id': 'sketch_id',  # noqa: E501
-        'yara_rules': 'yara_rules',  # noqa: E501
-    }
-
-    read_only_vars = {
-    }
-
-    _composed_schemas = {}
-
-    @classmethod
-    @convert_js_args_to_python_args
-    def _from_openapi_data(cls, *args, **kwargs):  # noqa: E501
-        """BaseRequestOptions - a model defined in OpenAPI
 
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-            filter_patterns ([str]): [optional]  # noqa: E501
-            group_id (str): [optional]  # noqa: E501
-            jobs_allowlist ([str]): [optional]  # noqa: E501
-            jobs_denylist ([str]): [optional]  # noqa: E501
-            reason (str): [optional]  # noqa: E501
-            recipe_data (str): [optional]  # noqa: E501
-            recipe_name (str): [optional]  # noqa: E501
-            request_id (str): [optional]  # noqa: E501
-            requester (str): [optional]  # noqa: E501
-            sketch_id (int): [optional]  # noqa: E501
-            yara_rules (str): [optional]  # noqa: E501
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', True)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        self = super(OpenApiModel, cls).__new__(cls)
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
+    class MetaOapg:
+        
+        class properties:
+            
+            
+            class filter_patterns(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    items = schemas.StrSchema
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, str, ]], typing.List[typing.Union[MetaOapg.items, str, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'filter_patterns':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
                     )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-        return self
-
-    required_properties = set([
-        '_data_store',
-        '_check_type',
-        '_spec_property_naming',
-        '_path_to_item',
-        '_configuration',
-        '_visited_composed_classes',
-    ])
-
-    @convert_js_args_to_python_args
-    def __init__(self, *args, **kwargs):  # noqa: E501
-        """BaseRequestOptions - a model defined in OpenAPI
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-            filter_patterns ([str]): [optional]  # noqa: E501
-            group_id (str): [optional]  # noqa: E501
-            jobs_allowlist ([str]): [optional]  # noqa: E501
-            jobs_denylist ([str]): [optional]  # noqa: E501
-            reason (str): [optional]  # noqa: E501
-            recipe_data (str): [optional]  # noqa: E501
-            recipe_name (str): [optional]  # noqa: E501
-            request_id (str): [optional]  # noqa: E501
-            requester (str): [optional]  # noqa: E501
-            sketch_id (int): [optional]  # noqa: E501
-            yara_rules (str): [optional]  # noqa: E501
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', False)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            group_id = schemas.StrSchema
+            
+            
+            class jobs_allowlist(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    items = schemas.StrSchema
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, str, ]], typing.List[typing.Union[MetaOapg.items, str, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'jobs_allowlist':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
                     )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-            if var_name in self.read_only_vars:
-                raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
-                                     f"class with read only attributes.")
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            
+            
+            class jobs_denylist(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    items = schemas.StrSchema
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, str, ]], typing.List[typing.Union[MetaOapg.items, str, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'jobs_denylist':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
+                    )
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            reason = schemas.StrSchema
+            recipe_data = schemas.StrSchema
+            recipe_name = schemas.StrSchema
+            request_id = schemas.StrSchema
+            requester = schemas.StrSchema
+            sketch_id = schemas.IntSchema
+            yara_rules = schemas.StrSchema
+            __annotations__ = {
+                "filter_patterns": filter_patterns,
+                "group_id": group_id,
+                "jobs_allowlist": jobs_allowlist,
+                "jobs_denylist": jobs_denylist,
+                "reason": reason,
+                "recipe_data": recipe_data,
+                "recipe_name": recipe_name,
+                "request_id": request_id,
+                "requester": requester,
+                "sketch_id": sketch_id,
+                "yara_rules": yara_rules,
+            }
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["filter_patterns"]) -> MetaOapg.properties.filter_patterns: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["group_id"]) -> MetaOapg.properties.group_id: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["jobs_allowlist"]) -> MetaOapg.properties.jobs_allowlist: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["jobs_denylist"]) -> MetaOapg.properties.jobs_denylist: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["reason"]) -> MetaOapg.properties.reason: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["recipe_data"]) -> MetaOapg.properties.recipe_data: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["recipe_name"]) -> MetaOapg.properties.recipe_name: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["request_id"]) -> MetaOapg.properties.request_id: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["requester"]) -> MetaOapg.properties.requester: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["sketch_id"]) -> MetaOapg.properties.sketch_id: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["yara_rules"]) -> MetaOapg.properties.yara_rules: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["filter_patterns", "group_id", "jobs_allowlist", "jobs_denylist", "reason", "recipe_data", "recipe_name", "request_id", "requester", "sketch_id", "yara_rules", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["filter_patterns"]) -> typing.Union[MetaOapg.properties.filter_patterns, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["group_id"]) -> typing.Union[MetaOapg.properties.group_id, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["jobs_allowlist"]) -> typing.Union[MetaOapg.properties.jobs_allowlist, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["jobs_denylist"]) -> typing.Union[MetaOapg.properties.jobs_denylist, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["reason"]) -> typing.Union[MetaOapg.properties.reason, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["recipe_data"]) -> typing.Union[MetaOapg.properties.recipe_data, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["recipe_name"]) -> typing.Union[MetaOapg.properties.recipe_name, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["request_id"]) -> typing.Union[MetaOapg.properties.request_id, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["requester"]) -> typing.Union[MetaOapg.properties.requester, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["sketch_id"]) -> typing.Union[MetaOapg.properties.sketch_id, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["yara_rules"]) -> typing.Union[MetaOapg.properties.yara_rules, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["filter_patterns", "group_id", "jobs_allowlist", "jobs_denylist", "reason", "recipe_data", "recipe_name", "request_id", "requester", "sketch_id", "yara_rules", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        filter_patterns: typing.Union[MetaOapg.properties.filter_patterns, list, tuple, schemas.Unset] = schemas.unset,
+        group_id: typing.Union[MetaOapg.properties.group_id, str, schemas.Unset] = schemas.unset,
+        jobs_allowlist: typing.Union[MetaOapg.properties.jobs_allowlist, list, tuple, schemas.Unset] = schemas.unset,
+        jobs_denylist: typing.Union[MetaOapg.properties.jobs_denylist, list, tuple, schemas.Unset] = schemas.unset,
+        reason: typing.Union[MetaOapg.properties.reason, str, schemas.Unset] = schemas.unset,
+        recipe_data: typing.Union[MetaOapg.properties.recipe_data, str, schemas.Unset] = schemas.unset,
+        recipe_name: typing.Union[MetaOapg.properties.recipe_name, str, schemas.Unset] = schemas.unset,
+        request_id: typing.Union[MetaOapg.properties.request_id, str, schemas.Unset] = schemas.unset,
+        requester: typing.Union[MetaOapg.properties.requester, str, schemas.Unset] = schemas.unset,
+        sketch_id: typing.Union[MetaOapg.properties.sketch_id, decimal.Decimal, int, schemas.Unset] = schemas.unset,
+        yara_rules: typing.Union[MetaOapg.properties.yara_rules, str, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'BaseRequestOptions':
+        return super().__new__(
+            cls,
+            *_args,
+            filter_patterns=filter_patterns,
+            group_id=group_id,
+            jobs_allowlist=jobs_allowlist,
+            jobs_denylist=jobs_denylist,
+            reason=reason,
+            recipe_data=recipe_data,
+            recipe_name=recipe_name,
+            request_id=request_id,
+            requester=requester,
+            sketch_id=sketch_id,
+            yara_rules=yara_rules,
+            _configuration=_configuration,
+            **kwargs,
+        )
diff --git a/turbinia/api/client/turbinia_api_lib/model/base_request_options.pyi b/turbinia/api/client/turbinia_api_lib/model/base_request_options.pyi
new file mode 100644
index 000000000..d9192b9ce
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/model/base_request_options.pyi
@@ -0,0 +1,246 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
+import re  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
+
+import frozendict  # noqa: F401
+
+from turbinia_api_lib import schemas  # noqa: F401
+
+
+class BaseRequestOptions(
+    schemas.DictSchema
+):
+    """NOTE: This class is auto generated by OpenAPI Generator.
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+
+    Base Request Options class to be extended by other option types. 
+    """
+
+
+    class MetaOapg:
+        
+        class properties:
+            
+            
+            class filter_patterns(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    items = schemas.StrSchema
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, str, ]], typing.List[typing.Union[MetaOapg.items, str, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'filter_patterns':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
+                    )
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            group_id = schemas.StrSchema
+            
+            
+            class jobs_allowlist(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    items = schemas.StrSchema
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, str, ]], typing.List[typing.Union[MetaOapg.items, str, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'jobs_allowlist':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
+                    )
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            
+            
+            class jobs_denylist(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    items = schemas.StrSchema
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, str, ]], typing.List[typing.Union[MetaOapg.items, str, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'jobs_denylist':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
+                    )
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            reason = schemas.StrSchema
+            recipe_data = schemas.StrSchema
+            recipe_name = schemas.StrSchema
+            request_id = schemas.StrSchema
+            requester = schemas.StrSchema
+            sketch_id = schemas.IntSchema
+            yara_rules = schemas.StrSchema
+            __annotations__ = {
+                "filter_patterns": filter_patterns,
+                "group_id": group_id,
+                "jobs_allowlist": jobs_allowlist,
+                "jobs_denylist": jobs_denylist,
+                "reason": reason,
+                "recipe_data": recipe_data,
+                "recipe_name": recipe_name,
+                "request_id": request_id,
+                "requester": requester,
+                "sketch_id": sketch_id,
+                "yara_rules": yara_rules,
+            }
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["filter_patterns"]) -> MetaOapg.properties.filter_patterns: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["group_id"]) -> MetaOapg.properties.group_id: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["jobs_allowlist"]) -> MetaOapg.properties.jobs_allowlist: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["jobs_denylist"]) -> MetaOapg.properties.jobs_denylist: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["reason"]) -> MetaOapg.properties.reason: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["recipe_data"]) -> MetaOapg.properties.recipe_data: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["recipe_name"]) -> MetaOapg.properties.recipe_name: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["request_id"]) -> MetaOapg.properties.request_id: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["requester"]) -> MetaOapg.properties.requester: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["sketch_id"]) -> MetaOapg.properties.sketch_id: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["yara_rules"]) -> MetaOapg.properties.yara_rules: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["filter_patterns", "group_id", "jobs_allowlist", "jobs_denylist", "reason", "recipe_data", "recipe_name", "request_id", "requester", "sketch_id", "yara_rules", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["filter_patterns"]) -> typing.Union[MetaOapg.properties.filter_patterns, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["group_id"]) -> typing.Union[MetaOapg.properties.group_id, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["jobs_allowlist"]) -> typing.Union[MetaOapg.properties.jobs_allowlist, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["jobs_denylist"]) -> typing.Union[MetaOapg.properties.jobs_denylist, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["reason"]) -> typing.Union[MetaOapg.properties.reason, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["recipe_data"]) -> typing.Union[MetaOapg.properties.recipe_data, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["recipe_name"]) -> typing.Union[MetaOapg.properties.recipe_name, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["request_id"]) -> typing.Union[MetaOapg.properties.request_id, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["requester"]) -> typing.Union[MetaOapg.properties.requester, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["sketch_id"]) -> typing.Union[MetaOapg.properties.sketch_id, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["yara_rules"]) -> typing.Union[MetaOapg.properties.yara_rules, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["filter_patterns", "group_id", "jobs_allowlist", "jobs_denylist", "reason", "recipe_data", "recipe_name", "request_id", "requester", "sketch_id", "yara_rules", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        filter_patterns: typing.Union[MetaOapg.properties.filter_patterns, list, tuple, schemas.Unset] = schemas.unset,
+        group_id: typing.Union[MetaOapg.properties.group_id, str, schemas.Unset] = schemas.unset,
+        jobs_allowlist: typing.Union[MetaOapg.properties.jobs_allowlist, list, tuple, schemas.Unset] = schemas.unset,
+        jobs_denylist: typing.Union[MetaOapg.properties.jobs_denylist, list, tuple, schemas.Unset] = schemas.unset,
+        reason: typing.Union[MetaOapg.properties.reason, str, schemas.Unset] = schemas.unset,
+        recipe_data: typing.Union[MetaOapg.properties.recipe_data, str, schemas.Unset] = schemas.unset,
+        recipe_name: typing.Union[MetaOapg.properties.recipe_name, str, schemas.Unset] = schemas.unset,
+        request_id: typing.Union[MetaOapg.properties.request_id, str, schemas.Unset] = schemas.unset,
+        requester: typing.Union[MetaOapg.properties.requester, str, schemas.Unset] = schemas.unset,
+        sketch_id: typing.Union[MetaOapg.properties.sketch_id, decimal.Decimal, int, schemas.Unset] = schemas.unset,
+        yara_rules: typing.Union[MetaOapg.properties.yara_rules, str, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'BaseRequestOptions':
+        return super().__new__(
+            cls,
+            *_args,
+            filter_patterns=filter_patterns,
+            group_id=group_id,
+            jobs_allowlist=jobs_allowlist,
+            jobs_denylist=jobs_denylist,
+            reason=reason,
+            recipe_data=recipe_data,
+            recipe_name=recipe_name,
+            request_id=request_id,
+            requester=requester,
+            sketch_id=sketch_id,
+            yara_rules=yara_rules,
+            _configuration=_configuration,
+            **kwargs,
+        )
diff --git a/turbinia/api/client/turbinia_api_lib/model/complete_turbinia_stats.py b/turbinia/api/client/turbinia_api_lib/model/complete_turbinia_stats.py
new file mode 100644
index 000000000..0e12473d9
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/model/complete_turbinia_stats.py
@@ -0,0 +1,140 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
+import re  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
+
+import frozendict  # noqa: F401
+
+from turbinia_api_lib import schemas  # noqa: F401
+
+
+class CompleteTurbiniaStats(
+    schemas.DictSchema
+):
+    """NOTE: This class is auto generated by OpenAPI Generator.
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+
+    Statistics for different groups of tasks.
+    """
+
+
+    class MetaOapg:
+        
+        class properties:
+            all_tasks = schemas.DictSchema
+            failed_tasks = schemas.DictSchema
+            requests = schemas.DictSchema
+            successful_tasks = schemas.DictSchema
+            tasks_per_type = schemas.DictSchema
+            tasks_per_user = schemas.DictSchema
+            tasks_per_worker = schemas.DictSchema
+            __annotations__ = {
+                "all_tasks": all_tasks,
+                "failed_tasks": failed_tasks,
+                "requests": requests,
+                "successful_tasks": successful_tasks,
+                "tasks_per_type": tasks_per_type,
+                "tasks_per_user": tasks_per_user,
+                "tasks_per_worker": tasks_per_worker,
+            }
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["all_tasks"]) -> MetaOapg.properties.all_tasks: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["failed_tasks"]) -> MetaOapg.properties.failed_tasks: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["requests"]) -> MetaOapg.properties.requests: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["successful_tasks"]) -> MetaOapg.properties.successful_tasks: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["tasks_per_type"]) -> MetaOapg.properties.tasks_per_type: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["tasks_per_user"]) -> MetaOapg.properties.tasks_per_user: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["tasks_per_worker"]) -> MetaOapg.properties.tasks_per_worker: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["all_tasks", "failed_tasks", "requests", "successful_tasks", "tasks_per_type", "tasks_per_user", "tasks_per_worker", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["all_tasks"]) -> typing.Union[MetaOapg.properties.all_tasks, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["failed_tasks"]) -> typing.Union[MetaOapg.properties.failed_tasks, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["requests"]) -> typing.Union[MetaOapg.properties.requests, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["successful_tasks"]) -> typing.Union[MetaOapg.properties.successful_tasks, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["tasks_per_type"]) -> typing.Union[MetaOapg.properties.tasks_per_type, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["tasks_per_user"]) -> typing.Union[MetaOapg.properties.tasks_per_user, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["tasks_per_worker"]) -> typing.Union[MetaOapg.properties.tasks_per_worker, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["all_tasks", "failed_tasks", "requests", "successful_tasks", "tasks_per_type", "tasks_per_user", "tasks_per_worker", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        all_tasks: typing.Union[MetaOapg.properties.all_tasks, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        failed_tasks: typing.Union[MetaOapg.properties.failed_tasks, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        requests: typing.Union[MetaOapg.properties.requests, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        successful_tasks: typing.Union[MetaOapg.properties.successful_tasks, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        tasks_per_type: typing.Union[MetaOapg.properties.tasks_per_type, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        tasks_per_user: typing.Union[MetaOapg.properties.tasks_per_user, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        tasks_per_worker: typing.Union[MetaOapg.properties.tasks_per_worker, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'CompleteTurbiniaStats':
+        return super().__new__(
+            cls,
+            *_args,
+            all_tasks=all_tasks,
+            failed_tasks=failed_tasks,
+            requests=requests,
+            successful_tasks=successful_tasks,
+            tasks_per_type=tasks_per_type,
+            tasks_per_user=tasks_per_user,
+            tasks_per_worker=tasks_per_worker,
+            _configuration=_configuration,
+            **kwargs,
+        )
diff --git a/turbinia/api/client/turbinia_api_lib/model/complete_turbinia_stats.pyi b/turbinia/api/client/turbinia_api_lib/model/complete_turbinia_stats.pyi
new file mode 100644
index 000000000..0e12473d9
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/model/complete_turbinia_stats.pyi
@@ -0,0 +1,140 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
+import re  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
+
+import frozendict  # noqa: F401
+
+from turbinia_api_lib import schemas  # noqa: F401
+
+
+class CompleteTurbiniaStats(
+    schemas.DictSchema
+):
+    """NOTE: This class is auto generated by OpenAPI Generator.
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+
+    Statistics for different groups of tasks.
+    """
+
+
+    class MetaOapg:
+        
+        class properties:
+            all_tasks = schemas.DictSchema
+            failed_tasks = schemas.DictSchema
+            requests = schemas.DictSchema
+            successful_tasks = schemas.DictSchema
+            tasks_per_type = schemas.DictSchema
+            tasks_per_user = schemas.DictSchema
+            tasks_per_worker = schemas.DictSchema
+            __annotations__ = {
+                "all_tasks": all_tasks,
+                "failed_tasks": failed_tasks,
+                "requests": requests,
+                "successful_tasks": successful_tasks,
+                "tasks_per_type": tasks_per_type,
+                "tasks_per_user": tasks_per_user,
+                "tasks_per_worker": tasks_per_worker,
+            }
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["all_tasks"]) -> MetaOapg.properties.all_tasks: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["failed_tasks"]) -> MetaOapg.properties.failed_tasks: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["requests"]) -> MetaOapg.properties.requests: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["successful_tasks"]) -> MetaOapg.properties.successful_tasks: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["tasks_per_type"]) -> MetaOapg.properties.tasks_per_type: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["tasks_per_user"]) -> MetaOapg.properties.tasks_per_user: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["tasks_per_worker"]) -> MetaOapg.properties.tasks_per_worker: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["all_tasks", "failed_tasks", "requests", "successful_tasks", "tasks_per_type", "tasks_per_user", "tasks_per_worker", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["all_tasks"]) -> typing.Union[MetaOapg.properties.all_tasks, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["failed_tasks"]) -> typing.Union[MetaOapg.properties.failed_tasks, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["requests"]) -> typing.Union[MetaOapg.properties.requests, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["successful_tasks"]) -> typing.Union[MetaOapg.properties.successful_tasks, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["tasks_per_type"]) -> typing.Union[MetaOapg.properties.tasks_per_type, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["tasks_per_user"]) -> typing.Union[MetaOapg.properties.tasks_per_user, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["tasks_per_worker"]) -> typing.Union[MetaOapg.properties.tasks_per_worker, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["all_tasks", "failed_tasks", "requests", "successful_tasks", "tasks_per_type", "tasks_per_user", "tasks_per_worker", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        all_tasks: typing.Union[MetaOapg.properties.all_tasks, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        failed_tasks: typing.Union[MetaOapg.properties.failed_tasks, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        requests: typing.Union[MetaOapg.properties.requests, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        successful_tasks: typing.Union[MetaOapg.properties.successful_tasks, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        tasks_per_type: typing.Union[MetaOapg.properties.tasks_per_type, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        tasks_per_user: typing.Union[MetaOapg.properties.tasks_per_user, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        tasks_per_worker: typing.Union[MetaOapg.properties.tasks_per_worker, dict, frozendict.frozendict, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'CompleteTurbiniaStats':
+        return super().__new__(
+            cls,
+            *_args,
+            all_tasks=all_tasks,
+            failed_tasks=failed_tasks,
+            requests=requests,
+            successful_tasks=successful_tasks,
+            tasks_per_type=tasks_per_type,
+            tasks_per_user=tasks_per_user,
+            tasks_per_worker=tasks_per_worker,
+            _configuration=_configuration,
+            **kwargs,
+        )
diff --git a/turbinia/api/client/turbinia_api_lib/model/http_validation_error.py b/turbinia/api/client/turbinia_api_lib/model/http_validation_error.py
index 34dabfe98..1ad73989f 100644
--- a/turbinia/api/client/turbinia_api_lib/model/http_validation_error.py
+++ b/turbinia/api/client/turbinia_api_lib/model/http_validation_error.py
@@ -1,269 +1,105 @@
+# coding: utf-8
+
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
 
     The version of the OpenAPI document: 1.0.0
     Generated by: https://openapi-generator.tech
 """
 
-
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
 import re  # noqa: F401
-import sys  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
 
-from turbinia_api_lib.model_utils import (  # noqa: F401
-    ApiTypeError,
-    ModelComposed,
-    ModelNormal,
-    ModelSimple,
-    cached_property,
-    change_keys_js_to_python,
-    convert_js_args_to_python_args,
-    date,
-    datetime,
-    file_type,
-    none_type,
-    validate_get_composed_info,
-    OpenApiModel
-)
-from turbinia_api_lib.exceptions import ApiAttributeError
+import frozendict  # noqa: F401
 
+from turbinia_api_lib import schemas  # noqa: F401
 
-def lazy_import():
-    from turbinia_api_lib.model.validation_error import ValidationError
-    globals()['ValidationError'] = ValidationError
 
-
-class HTTPValidationError(ModelNormal):
+class HTTPValidationError(
+    schemas.DictSchema
+):
     """NOTE: This class is auto generated by OpenAPI Generator.
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
-
-    Attributes:
-      allowed_values (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          with a capitalized key describing the allowed value and an allowed
-          value. These dicts store the allowed enum values.
-      attribute_map (dict): The key is attribute name
-          and the value is json key in definition.
-      discriminator_value_class_map (dict): A dict to go from the discriminator
-          variable value to the discriminator class name.
-      validations (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          that stores validations for max_length, min_length, max_items,
-          min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
-          inclusive_minimum, and regex.
-      additional_properties_type (tuple): A tuple of classes accepted
-          as additional properties values.
     """
 
-    allowed_values = {
-    }
-
-    validations = {
-    }
-
-    @cached_property
-    def additional_properties_type():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
-        """
-        lazy_import()
-        return (bool, date, datetime, dict, float, int, list, str, none_type,)  # noqa: E501
-
-    _nullable = False
-
-    @cached_property
-    def openapi_types():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
-
-        Returns
-            openapi_types (dict): The key is attribute name
-                and the value is attribute type.
-        """
-        lazy_import()
-        return {
-            'detail': ([ValidationError],),  # noqa: E501
-        }
-
-    @cached_property
-    def discriminator():
-        return None
-
-
-    attribute_map = {
-        'detail': 'detail',  # noqa: E501
-    }
-
-    read_only_vars = {
-    }
-
-    _composed_schemas = {}
 
-    @classmethod
-    @convert_js_args_to_python_args
-    def _from_openapi_data(cls, *args, **kwargs):  # noqa: E501
-        """HTTPValidationError - a model defined in OpenAPI
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-            detail ([ValidationError]): [optional]  # noqa: E501
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', True)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        self = super(OpenApiModel, cls).__new__(cls)
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
-                    )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-        return self
-
-    required_properties = set([
-        '_data_store',
-        '_check_type',
-        '_spec_property_naming',
-        '_path_to_item',
-        '_configuration',
-        '_visited_composed_classes',
-    ])
-
-    @convert_js_args_to_python_args
-    def __init__(self, *args, **kwargs):  # noqa: E501
-        """HTTPValidationError - a model defined in OpenAPI
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-            detail ([ValidationError]): [optional]  # noqa: E501
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', False)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
+    class MetaOapg:
+        
+        class properties:
+            
+            
+            class detail(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    
+                    @staticmethod
+                    def items() -> typing.Type['ValidationError']:
+                        return ValidationError
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple['ValidationError'], typing.List['ValidationError']],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'detail':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
                     )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-            if var_name in self.read_only_vars:
-                raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
-                                     f"class with read only attributes.")
+            
+                def __getitem__(self, i: int) -> 'ValidationError':
+                    return super().__getitem__(i)
+            __annotations__ = {
+                "detail": detail,
+            }
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["detail"]) -> MetaOapg.properties.detail: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["detail", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["detail"]) -> typing.Union[MetaOapg.properties.detail, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["detail", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        detail: typing.Union[MetaOapg.properties.detail, list, tuple, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'HTTPValidationError':
+        return super().__new__(
+            cls,
+            *_args,
+            detail=detail,
+            _configuration=_configuration,
+            **kwargs,
+        )
+
+from turbinia_api_lib.model.validation_error import ValidationError
diff --git a/turbinia/api/client/turbinia_api_lib/model/http_validation_error.pyi b/turbinia/api/client/turbinia_api_lib/model/http_validation_error.pyi
new file mode 100644
index 000000000..1ad73989f
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/model/http_validation_error.pyi
@@ -0,0 +1,105 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
+import re  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
+
+import frozendict  # noqa: F401
+
+from turbinia_api_lib import schemas  # noqa: F401
+
+
+class HTTPValidationError(
+    schemas.DictSchema
+):
+    """NOTE: This class is auto generated by OpenAPI Generator.
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+
+
+    class MetaOapg:
+        
+        class properties:
+            
+            
+            class detail(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    
+                    @staticmethod
+                    def items() -> typing.Type['ValidationError']:
+                        return ValidationError
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple['ValidationError'], typing.List['ValidationError']],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'detail':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
+                    )
+            
+                def __getitem__(self, i: int) -> 'ValidationError':
+                    return super().__getitem__(i)
+            __annotations__ = {
+                "detail": detail,
+            }
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["detail"]) -> MetaOapg.properties.detail: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["detail", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["detail"]) -> typing.Union[MetaOapg.properties.detail, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["detail", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        detail: typing.Union[MetaOapg.properties.detail, list, tuple, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'HTTPValidationError':
+        return super().__new__(
+            cls,
+            *_args,
+            detail=detail,
+            _configuration=_configuration,
+            **kwargs,
+        )
+
+from turbinia_api_lib.model.validation_error import ValidationError
diff --git a/turbinia/api/client/turbinia_api_lib/model/request.py b/turbinia/api/client/turbinia_api_lib/model/request.py
index df37375a7..0a1b05f45 100644
--- a/turbinia/api/client/turbinia_api_lib/model/request.py
+++ b/turbinia/api/client/turbinia_api_lib/model/request.py
@@ -1,285 +1,112 @@
+# coding: utf-8
+
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
 
     The version of the OpenAPI document: 1.0.0
     Generated by: https://openapi-generator.tech
 """
 
-
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
 import re  # noqa: F401
-import sys  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
 
-from turbinia_api_lib.model_utils import (  # noqa: F401
-    ApiTypeError,
-    ModelComposed,
-    ModelNormal,
-    ModelSimple,
-    cached_property,
-    change_keys_js_to_python,
-    convert_js_args_to_python_args,
-    date,
-    datetime,
-    file_type,
-    none_type,
-    validate_get_composed_info,
-    OpenApiModel
-)
-from turbinia_api_lib.exceptions import ApiAttributeError
+import frozendict  # noqa: F401
 
+from turbinia_api_lib import schemas  # noqa: F401
 
-def lazy_import():
-    from turbinia_api_lib.model.base_request_options import BaseRequestOptions
-    globals()['BaseRequestOptions'] = BaseRequestOptions
 
-
-class Request(ModelNormal):
+class Request(
+    schemas.DictSchema
+):
     """NOTE: This class is auto generated by OpenAPI Generator.
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
 
-    Attributes:
-      allowed_values (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          with a capitalized key describing the allowed value and an allowed
-          value. These dicts store the allowed enum values.
-      attribute_map (dict): The key is attribute name
-          and the value is json key in definition.
-      discriminator_value_class_map (dict): A dict to go from the discriminator
-          variable value to the discriminator class name.
-      validations (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          that stores validations for max_length, min_length, max_items,
-          min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
-          inclusive_minimum, and regex.
-      additional_properties_type (tuple): A tuple of classes accepted
-          as additional properties values.
+    Base request object. 
     """
 
-    allowed_values = {
-    }
-
-    validations = {
-    }
-
-    @cached_property
-    def additional_properties_type():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
-        """
-        lazy_import()
-        return (bool, date, datetime, dict, float, int, list, str, none_type,)  # noqa: E501
-
-    _nullable = False
-
-    @cached_property
-    def openapi_types():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
 
-        Returns
-            openapi_types (dict): The key is attribute name
-                and the value is attribute type.
-        """
-        lazy_import()
-        return {
-            'evidence': ({str: (bool, date, datetime, dict, float, int, list, str, none_type)},),  # noqa: E501
-            'request_options': (BaseRequestOptions,),  # noqa: E501
-            'description': (str,),  # noqa: E501
+    class MetaOapg:
+        required = {
+            "request_options",
+            "evidence",
         }
-
-    @cached_property
-    def discriminator():
-        return None
-
-
-    attribute_map = {
-        'evidence': 'evidence',  # noqa: E501
-        'request_options': 'request_options',  # noqa: E501
-        'description': 'description',  # noqa: E501
-    }
-
-    read_only_vars = {
-    }
-
-    _composed_schemas = {}
-
-    @classmethod
-    @convert_js_args_to_python_args
-    def _from_openapi_data(cls, evidence, request_options, *args, **kwargs):  # noqa: E501
-        """Request - a model defined in OpenAPI
-
-        Args:
-            evidence ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}):
-            request_options (BaseRequestOptions):
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-            description (str): [optional] if omitted the server will use the default value of "Turbinia request object"  # noqa: E501
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', True)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        self = super(OpenApiModel, cls).__new__(cls)
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
-                    )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        self.evidence = evidence
-        self.request_options = request_options
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-        return self
-
-    required_properties = set([
-        '_data_store',
-        '_check_type',
-        '_spec_property_naming',
-        '_path_to_item',
-        '_configuration',
-        '_visited_composed_classes',
-    ])
-
-    @convert_js_args_to_python_args
-    def __init__(self, evidence, request_options, *args, **kwargs):  # noqa: E501
-        """Request - a model defined in OpenAPI
-
-        Args:
-            evidence ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}):
-            request_options (BaseRequestOptions):
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-            description (str): [optional] if omitted the server will use the default value of "Turbinia request object"  # noqa: E501
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', False)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
-                    )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        self.evidence = evidence
-        self.request_options = request_options
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-            if var_name in self.read_only_vars:
-                raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
-                                     f"class with read only attributes.")
+        
+        class properties:
+            evidence = schemas.DictSchema
+        
+            @staticmethod
+            def request_options() -> typing.Type['BaseRequestOptions']:
+                return BaseRequestOptions
+            description = schemas.StrSchema
+            __annotations__ = {
+                "evidence": evidence,
+                "request_options": request_options,
+                "description": description,
+            }
+    
+    request_options: 'BaseRequestOptions'
+    evidence: MetaOapg.properties.evidence
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["evidence"]) -> MetaOapg.properties.evidence: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["request_options"]) -> 'BaseRequestOptions': ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["description"]) -> MetaOapg.properties.description: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["evidence", "request_options", "description", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["evidence"]) -> MetaOapg.properties.evidence: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["request_options"]) -> 'BaseRequestOptions': ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["description"]) -> typing.Union[MetaOapg.properties.description, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["evidence", "request_options", "description", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        request_options: 'BaseRequestOptions',
+        evidence: typing.Union[MetaOapg.properties.evidence, dict, frozendict.frozendict, ],
+        description: typing.Union[MetaOapg.properties.description, str, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'Request':
+        return super().__new__(
+            cls,
+            *_args,
+            request_options=request_options,
+            evidence=evidence,
+            description=description,
+            _configuration=_configuration,
+            **kwargs,
+        )
+
+from turbinia_api_lib.model.base_request_options import BaseRequestOptions
diff --git a/turbinia/api/client/turbinia_api_lib/model/request.pyi b/turbinia/api/client/turbinia_api_lib/model/request.pyi
new file mode 100644
index 000000000..0a1b05f45
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/model/request.pyi
@@ -0,0 +1,112 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
+import re  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
+
+import frozendict  # noqa: F401
+
+from turbinia_api_lib import schemas  # noqa: F401
+
+
+class Request(
+    schemas.DictSchema
+):
+    """NOTE: This class is auto generated by OpenAPI Generator.
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+
+    Base request object. 
+    """
+
+
+    class MetaOapg:
+        required = {
+            "request_options",
+            "evidence",
+        }
+        
+        class properties:
+            evidence = schemas.DictSchema
+        
+            @staticmethod
+            def request_options() -> typing.Type['BaseRequestOptions']:
+                return BaseRequestOptions
+            description = schemas.StrSchema
+            __annotations__ = {
+                "evidence": evidence,
+                "request_options": request_options,
+                "description": description,
+            }
+    
+    request_options: 'BaseRequestOptions'
+    evidence: MetaOapg.properties.evidence
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["evidence"]) -> MetaOapg.properties.evidence: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["request_options"]) -> 'BaseRequestOptions': ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["description"]) -> MetaOapg.properties.description: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["evidence", "request_options", "description", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["evidence"]) -> MetaOapg.properties.evidence: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["request_options"]) -> 'BaseRequestOptions': ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["description"]) -> typing.Union[MetaOapg.properties.description, schemas.Unset]: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["evidence", "request_options", "description", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        request_options: 'BaseRequestOptions',
+        evidence: typing.Union[MetaOapg.properties.evidence, dict, frozendict.frozendict, ],
+        description: typing.Union[MetaOapg.properties.description, str, schemas.Unset] = schemas.unset,
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'Request':
+        return super().__new__(
+            cls,
+            *_args,
+            request_options=request_options,
+            evidence=evidence,
+            description=description,
+            _configuration=_configuration,
+            **kwargs,
+        )
+
+from turbinia_api_lib.model.base_request_options import BaseRequestOptions
diff --git a/turbinia/api/client/turbinia_api_lib/model/validation_error.py b/turbinia/api/client/turbinia_api_lib/model/validation_error.py
index 0b38e7e31..8935cbb7c 100644
--- a/turbinia/api/client/turbinia_api_lib/model/validation_error.py
+++ b/turbinia/api/client/turbinia_api_lib/model/validation_error.py
@@ -1,287 +1,167 @@
+# coding: utf-8
+
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
 
     The version of the OpenAPI document: 1.0.0
     Generated by: https://openapi-generator.tech
 """
 
-
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
 import re  # noqa: F401
-import sys  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
 
-from turbinia_api_lib.model_utils import (  # noqa: F401
-    ApiTypeError,
-    ModelComposed,
-    ModelNormal,
-    ModelSimple,
-    cached_property,
-    change_keys_js_to_python,
-    convert_js_args_to_python_args,
-    date,
-    datetime,
-    file_type,
-    none_type,
-    validate_get_composed_info,
-    OpenApiModel
-)
-from turbinia_api_lib.exceptions import ApiAttributeError
+import frozendict  # noqa: F401
 
+from turbinia_api_lib import schemas  # noqa: F401
 
-def lazy_import():
-    from turbinia_api_lib.model.validation_error_loc_inner import ValidationErrorLocInner
-    globals()['ValidationErrorLocInner'] = ValidationErrorLocInner
 
-
-class ValidationError(ModelNormal):
+class ValidationError(
+    schemas.DictSchema
+):
     """NOTE: This class is auto generated by OpenAPI Generator.
     Ref: https://openapi-generator.tech
 
     Do not edit the class manually.
-
-    Attributes:
-      allowed_values (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          with a capitalized key describing the allowed value and an allowed
-          value. These dicts store the allowed enum values.
-      attribute_map (dict): The key is attribute name
-          and the value is json key in definition.
-      discriminator_value_class_map (dict): A dict to go from the discriminator
-          variable value to the discriminator class name.
-      validations (dict): The key is the tuple path to the attribute
-          and the for var_name this is (var_name,). The value is a dict
-          that stores validations for max_length, min_length, max_items,
-          min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum,
-          inclusive_minimum, and regex.
-      additional_properties_type (tuple): A tuple of classes accepted
-          as additional properties values.
     """
 
-    allowed_values = {
-    }
-
-    validations = {
-    }
-
-    @cached_property
-    def additional_properties_type():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
-        """
-        lazy_import()
-        return (bool, date, datetime, dict, float, int, list, str, none_type,)  # noqa: E501
-
-    _nullable = False
-
-    @cached_property
-    def openapi_types():
-        """
-        This must be a method because a model may have properties that are
-        of type self, this must run after the class is loaded
 
-        Returns
-            openapi_types (dict): The key is attribute name
-                and the value is attribute type.
-        """
-        lazy_import()
-        return {
-            'loc': ([ValidationErrorLocInner],),  # noqa: E501
-            'msg': (str,),  # noqa: E501
-            'type': (str,),  # noqa: E501
+    class MetaOapg:
+        required = {
+            "msg",
+            "loc",
+            "type",
         }
-
-    @cached_property
-    def discriminator():
-        return None
-
-
-    attribute_map = {
-        'loc': 'loc',  # noqa: E501
-        'msg': 'msg',  # noqa: E501
-        'type': 'type',  # noqa: E501
-    }
-
-    read_only_vars = {
-    }
-
-    _composed_schemas = {}
-
-    @classmethod
-    @convert_js_args_to_python_args
-    def _from_openapi_data(cls, loc, msg, type, *args, **kwargs):  # noqa: E501
-        """ValidationError - a model defined in OpenAPI
-
-        Args:
-            loc ([ValidationErrorLocInner]):
-            msg (str):
-            type (str):
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', True)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        self = super(OpenApiModel, cls).__new__(cls)
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
+        
+        class properties:
+            
+            
+            class loc(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    
+                    
+                    class items(
+                        schemas.ComposedSchema,
+                    ):
+                    
+                    
+                        class MetaOapg:
+                            any_of_0 = schemas.StrSchema
+                            any_of_1 = schemas.IntSchema
+                            
+                            @classmethod
+                            @functools.lru_cache()
+                            def any_of(cls):
+                                # we need this here to make our import statements work
+                                # we must store _composed_schemas in here so the code is only run
+                                # when we invoke this method. If we kept this at the class
+                                # level we would get an error because the class level
+                                # code would be run when this module is imported, and these composed
+                                # classes don't exist yet because their module has not finished
+                                # loading
+                                return [
+                                    cls.any_of_0,
+                                    cls.any_of_1,
+                                ]
+                    
+                    
+                        def __new__(
+                            cls,
+                            *_args: typing.Union[dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ],
+                            _configuration: typing.Optional[schemas.Configuration] = None,
+                            **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+                        ) -> 'items':
+                            return super().__new__(
+                                cls,
+                                *_args,
+                                _configuration=_configuration,
+                                **kwargs,
+                            )
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ]], typing.List[typing.Union[MetaOapg.items, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'loc':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
                     )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        self.loc = loc
-        self.msg = msg
-        self.type = type
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-        return self
-
-    required_properties = set([
-        '_data_store',
-        '_check_type',
-        '_spec_property_naming',
-        '_path_to_item',
-        '_configuration',
-        '_visited_composed_classes',
-    ])
-
-    @convert_js_args_to_python_args
-    def __init__(self, loc, msg, type, *args, **kwargs):  # noqa: E501
-        """ValidationError - a model defined in OpenAPI
-
-        Args:
-            loc ([ValidationErrorLocInner]):
-            msg (str):
-            type (str):
-
-        Keyword Args:
-            _check_type (bool): if True, values for parameters in openapi_types
-                                will be type checked and a TypeError will be
-                                raised if the wrong type is input.
-                                Defaults to True
-            _path_to_item (tuple/list): This is a list of keys or values to
-                                drill down to the model in received_data
-                                when deserializing a response
-            _spec_property_naming (bool): True if the variable names in the input data
-                                are serialized names, as specified in the OpenAPI document.
-                                False if the variable names in the input data
-                                are pythonic names, e.g. snake case (default)
-            _configuration (Configuration): the instance to use when
-                                deserializing a file_type parameter.
-                                If passed, type conversion is attempted
-                                If omitted no type conversion is done.
-            _visited_composed_classes (tuple): This stores a tuple of
-                                classes that we have traveled through so that
-                                if we see that class again we will not use its
-                                discriminator again.
-                                When traveling through a discriminator, the
-                                composed schema that is
-                                is traveled through is added to this set.
-                                For example if Animal has a discriminator
-                                petType and we pass in "Dog", and the class Dog
-                                allOf includes Animal, we move through Animal
-                                once using the discriminator, and pick Dog.
-                                Then in Dog, we will make an instance of the
-                                Animal class but this time we won't travel
-                                through its discriminator because we passed in
-                                _visited_composed_classes = (Animal,)
-        """
-
-        _check_type = kwargs.pop('_check_type', True)
-        _spec_property_naming = kwargs.pop('_spec_property_naming', False)
-        _path_to_item = kwargs.pop('_path_to_item', ())
-        _configuration = kwargs.pop('_configuration', None)
-        _visited_composed_classes = kwargs.pop('_visited_composed_classes', ())
-
-        if args:
-            for arg in args:
-                if isinstance(arg, dict):
-                    kwargs.update(arg)
-                else:
-                    raise ApiTypeError(
-                        "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % (
-                            args,
-                            self.__class__.__name__,
-                        ),
-                        path_to_item=_path_to_item,
-                        valid_classes=(self.__class__,),
-                    )
-
-        self._data_store = {}
-        self._check_type = _check_type
-        self._spec_property_naming = _spec_property_naming
-        self._path_to_item = _path_to_item
-        self._configuration = _configuration
-        self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
-
-        self.loc = loc
-        self.msg = msg
-        self.type = type
-        for var_name, var_value in kwargs.items():
-            if var_name not in self.attribute_map and \
-                        self._configuration is not None and \
-                        self._configuration.discard_unknown_keys and \
-                        self.additional_properties_type is None:
-                # discard variable.
-                continue
-            setattr(self, var_name, var_value)
-            if var_name in self.read_only_vars:
-                raise ApiAttributeError(f"`{var_name}` is a read-only attribute. Use `from_openapi_data` to instantiate "
-                                     f"class with read only attributes.")
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            msg = schemas.StrSchema
+            type = schemas.StrSchema
+            __annotations__ = {
+                "loc": loc,
+                "msg": msg,
+                "type": type,
+            }
+    
+    msg: MetaOapg.properties.msg
+    loc: MetaOapg.properties.loc
+    type: MetaOapg.properties.type
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["loc"]) -> MetaOapg.properties.loc: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["msg"]) -> MetaOapg.properties.msg: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["type"]) -> MetaOapg.properties.type: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["loc", "msg", "type", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["loc"]) -> MetaOapg.properties.loc: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["msg"]) -> MetaOapg.properties.msg: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["type"]) -> MetaOapg.properties.type: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["loc", "msg", "type", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        msg: typing.Union[MetaOapg.properties.msg, str, ],
+        loc: typing.Union[MetaOapg.properties.loc, list, tuple, ],
+        type: typing.Union[MetaOapg.properties.type, str, ],
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'ValidationError':
+        return super().__new__(
+            cls,
+            *_args,
+            msg=msg,
+            loc=loc,
+            type=type,
+            _configuration=_configuration,
+            **kwargs,
+        )
diff --git a/turbinia/api/client/turbinia_api_lib/model/validation_error.pyi b/turbinia/api/client/turbinia_api_lib/model/validation_error.pyi
new file mode 100644
index 000000000..8935cbb7c
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/model/validation_error.pyi
@@ -0,0 +1,167 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from datetime import date, datetime  # noqa: F401
+import decimal  # noqa: F401
+import functools  # noqa: F401
+import io  # noqa: F401
+import re  # noqa: F401
+import typing  # noqa: F401
+import typing_extensions  # noqa: F401
+import uuid  # noqa: F401
+
+import frozendict  # noqa: F401
+
+from turbinia_api_lib import schemas  # noqa: F401
+
+
+class ValidationError(
+    schemas.DictSchema
+):
+    """NOTE: This class is auto generated by OpenAPI Generator.
+    Ref: https://openapi-generator.tech
+
+    Do not edit the class manually.
+    """
+
+
+    class MetaOapg:
+        required = {
+            "msg",
+            "loc",
+            "type",
+        }
+        
+        class properties:
+            
+            
+            class loc(
+                schemas.ListSchema
+            ):
+            
+            
+                class MetaOapg:
+                    
+                    
+                    class items(
+                        schemas.ComposedSchema,
+                    ):
+                    
+                    
+                        class MetaOapg:
+                            any_of_0 = schemas.StrSchema
+                            any_of_1 = schemas.IntSchema
+                            
+                            @classmethod
+                            @functools.lru_cache()
+                            def any_of(cls):
+                                # we need this here to make our import statements work
+                                # we must store _composed_schemas in here so the code is only run
+                                # when we invoke this method. If we kept this at the class
+                                # level we would get an error because the class level
+                                # code would be run when this module is imported, and these composed
+                                # classes don't exist yet because their module has not finished
+                                # loading
+                                return [
+                                    cls.any_of_0,
+                                    cls.any_of_1,
+                                ]
+                    
+                    
+                        def __new__(
+                            cls,
+                            *_args: typing.Union[dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ],
+                            _configuration: typing.Optional[schemas.Configuration] = None,
+                            **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+                        ) -> 'items':
+                            return super().__new__(
+                                cls,
+                                *_args,
+                                _configuration=_configuration,
+                                **kwargs,
+                            )
+            
+                def __new__(
+                    cls,
+                    _arg: typing.Union[typing.Tuple[typing.Union[MetaOapg.items, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ]], typing.List[typing.Union[MetaOapg.items, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, bool, None, list, tuple, bytes, io.FileIO, io.BufferedReader, ]]],
+                    _configuration: typing.Optional[schemas.Configuration] = None,
+                ) -> 'loc':
+                    return super().__new__(
+                        cls,
+                        _arg,
+                        _configuration=_configuration,
+                    )
+            
+                def __getitem__(self, i: int) -> MetaOapg.items:
+                    return super().__getitem__(i)
+            msg = schemas.StrSchema
+            type = schemas.StrSchema
+            __annotations__ = {
+                "loc": loc,
+                "msg": msg,
+                "type": type,
+            }
+    
+    msg: MetaOapg.properties.msg
+    loc: MetaOapg.properties.loc
+    type: MetaOapg.properties.type
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["loc"]) -> MetaOapg.properties.loc: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["msg"]) -> MetaOapg.properties.msg: ...
+    
+    @typing.overload
+    def __getitem__(self, name: typing_extensions.Literal["type"]) -> MetaOapg.properties.type: ...
+    
+    @typing.overload
+    def __getitem__(self, name: str) -> schemas.UnsetAnyTypeSchema: ...
+    
+    def __getitem__(self, name: typing.Union[typing_extensions.Literal["loc", "msg", "type", ], str]):
+        # dict_instance[name] accessor
+        return super().__getitem__(name)
+    
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["loc"]) -> MetaOapg.properties.loc: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["msg"]) -> MetaOapg.properties.msg: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: typing_extensions.Literal["type"]) -> MetaOapg.properties.type: ...
+    
+    @typing.overload
+    def get_item_oapg(self, name: str) -> typing.Union[schemas.UnsetAnyTypeSchema, schemas.Unset]: ...
+    
+    def get_item_oapg(self, name: typing.Union[typing_extensions.Literal["loc", "msg", "type", ], str]):
+        return super().get_item_oapg(name)
+    
+
+    def __new__(
+        cls,
+        *_args: typing.Union[dict, frozendict.frozendict, ],
+        msg: typing.Union[MetaOapg.properties.msg, str, ],
+        loc: typing.Union[MetaOapg.properties.loc, list, tuple, ],
+        type: typing.Union[MetaOapg.properties.type, str, ],
+        _configuration: typing.Optional[schemas.Configuration] = None,
+        **kwargs: typing.Union[schemas.AnyTypeSchema, dict, frozendict.frozendict, str, date, datetime, uuid.UUID, int, float, decimal.Decimal, None, list, tuple, bytes],
+    ) -> 'ValidationError':
+        return super().__new__(
+            cls,
+            *_args,
+            msg=msg,
+            loc=loc,
+            type=type,
+            _configuration=_configuration,
+            **kwargs,
+        )
diff --git a/turbinia/api/client/turbinia_api_lib/models/__init__.py b/turbinia/api/client/turbinia_api_lib/models/__init__.py
index 905318b61..e22c1e8f8 100644
--- a/turbinia/api/client/turbinia_api_lib/models/__init__.py
+++ b/turbinia/api/client/turbinia_api_lib/models/__init__.py
@@ -4,18 +4,19 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 # import models into model package
 from turbinia_api_lib.models.base_request_options import BaseRequestOptions
 from turbinia_api_lib.models.complete_turbinia_stats import CompleteTurbiniaStats
 from turbinia_api_lib.models.http_validation_error import HTTPValidationError
+from turbinia_api_lib.models.location_inner import LocationInner
 from turbinia_api_lib.models.request import Request
 from turbinia_api_lib.models.validation_error import ValidationError
diff --git a/turbinia/api/client/turbinia_api_lib/models/base_request_options.py b/turbinia/api/client/turbinia_api_lib/models/base_request_options.py
index 36dc65fe0..51fcd86d7 100644
--- a/turbinia/api/client/turbinia_api_lib/models/base_request_options.py
+++ b/turbinia/api/client/turbinia_api_lib/models/base_request_options.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 from __future__ import annotations
@@ -18,24 +18,24 @@
 import json
 
 
-from typing import Any, Optional
-from pydantic import BaseModel
+from typing import List, Optional
+from pydantic import BaseModel, StrictInt, StrictStr, conlist
 
 class BaseRequestOptions(BaseModel):
     """
-    Base Request Options class to be extended by other option types. 
+    Base Request Options class to be extended by other option types.   # noqa: E501
     """
-    filter_patterns: Optional[Any] = None
-    group_id: Optional[Any] = None
-    jobs_allowlist: Optional[Any] = None
-    jobs_denylist: Optional[Any] = None
-    reason: Optional[Any] = None
-    recipe_data: Optional[Any] = None
-    recipe_name: Optional[Any] = None
-    request_id: Optional[Any] = None
-    requester: Optional[Any] = None
-    sketch_id: Optional[Any] = None
-    yara_rules: Optional[Any] = None
+    filter_patterns: Optional[conlist(StrictStr)] = None
+    group_id: Optional[StrictStr] = None
+    jobs_allowlist: Optional[conlist(StrictStr)] = None
+    jobs_denylist: Optional[conlist(StrictStr)] = None
+    reason: Optional[StrictStr] = None
+    recipe_data: Optional[StrictStr] = None
+    recipe_name: Optional[StrictStr] = None
+    request_id: Optional[StrictStr] = None
+    requester: Optional[StrictStr] = None
+    sketch_id: Optional[StrictInt] = None
+    yara_rules: Optional[StrictStr] = None
     __properties = ["filter_patterns", "group_id", "jobs_allowlist", "jobs_denylist", "reason", "recipe_data", "recipe_name", "request_id", "requester", "sketch_id", "yara_rules"]
 
     class Config:
@@ -62,61 +62,6 @@ def to_dict(self):
                           exclude={
                           },
                           exclude_none=True)
-        # set to None if filter_patterns (nullable) is None
-        # and __fields_set__ contains the field
-        if self.filter_patterns is None and "filter_patterns" in self.__fields_set__:
-            _dict['filter_patterns'] = None
-
-        # set to None if group_id (nullable) is None
-        # and __fields_set__ contains the field
-        if self.group_id is None and "group_id" in self.__fields_set__:
-            _dict['group_id'] = None
-
-        # set to None if jobs_allowlist (nullable) is None
-        # and __fields_set__ contains the field
-        if self.jobs_allowlist is None and "jobs_allowlist" in self.__fields_set__:
-            _dict['jobs_allowlist'] = None
-
-        # set to None if jobs_denylist (nullable) is None
-        # and __fields_set__ contains the field
-        if self.jobs_denylist is None and "jobs_denylist" in self.__fields_set__:
-            _dict['jobs_denylist'] = None
-
-        # set to None if reason (nullable) is None
-        # and __fields_set__ contains the field
-        if self.reason is None and "reason" in self.__fields_set__:
-            _dict['reason'] = None
-
-        # set to None if recipe_data (nullable) is None
-        # and __fields_set__ contains the field
-        if self.recipe_data is None and "recipe_data" in self.__fields_set__:
-            _dict['recipe_data'] = None
-
-        # set to None if recipe_name (nullable) is None
-        # and __fields_set__ contains the field
-        if self.recipe_name is None and "recipe_name" in self.__fields_set__:
-            _dict['recipe_name'] = None
-
-        # set to None if request_id (nullable) is None
-        # and __fields_set__ contains the field
-        if self.request_id is None and "request_id" in self.__fields_set__:
-            _dict['request_id'] = None
-
-        # set to None if requester (nullable) is None
-        # and __fields_set__ contains the field
-        if self.requester is None and "requester" in self.__fields_set__:
-            _dict['requester'] = None
-
-        # set to None if sketch_id (nullable) is None
-        # and __fields_set__ contains the field
-        if self.sketch_id is None and "sketch_id" in self.__fields_set__:
-            _dict['sketch_id'] = None
-
-        # set to None if yara_rules (nullable) is None
-        # and __fields_set__ contains the field
-        if self.yara_rules is None and "yara_rules" in self.__fields_set__:
-            _dict['yara_rules'] = None
-
         return _dict
 
     @classmethod
@@ -143,3 +88,4 @@ def from_dict(cls, obj: dict) -> BaseRequestOptions:
         })
         return _obj
 
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/body_upload_evidence_api_evidence_upload_post.py b/turbinia/api/client/turbinia_api_lib/models/body_upload_evidence_api_evidence_upload_post.py
new file mode 100644
index 000000000..7a9eaf1ee
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/models/body_upload_evidence_api_evidence_upload_post.py
@@ -0,0 +1,90 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia API server
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+    Do not edit the class manually.
+"""  # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re  # noqa: F401
+import json
+
+
+from typing import Any, Optional
+from pydantic import BaseModel, Field
+
+class BodyUploadEvidenceApiEvidenceUploadPost(BaseModel):
+    """
+    BodyUploadEvidenceApiEvidenceUploadPost
+    """
+    calculate_hash: Optional[Any] = None
+    files: Optional[Any] = Field(...)
+    ticket_id: Optional[Any] = Field(...)
+    __properties = ["calculate_hash", "files", "ticket_id"]
+
+    class Config:
+        """Pydantic configuration"""
+        allow_population_by_field_name = True
+        validate_assignment = True
+
+    def to_str(self) -> str:
+        """Returns the string representation of the model using alias"""
+        return pprint.pformat(self.dict(by_alias=True))
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the model using alias"""
+        return json.dumps(self.to_dict())
+
+    @classmethod
+    def from_json(cls, json_str: str) -> BodyUploadEvidenceApiEvidenceUploadPost:
+        """Create an instance of BodyUploadEvidenceApiEvidenceUploadPost from a JSON string"""
+        return cls.from_dict(json.loads(json_str))
+
+    def to_dict(self):
+        """Returns the dictionary representation of the model using alias"""
+        _dict = self.dict(by_alias=True,
+                          exclude={
+                          },
+                          exclude_none=True)
+        # set to None if calculate_hash (nullable) is None
+        # and __fields_set__ contains the field
+        if self.calculate_hash is None and "calculate_hash" in self.__fields_set__:
+            _dict['calculate_hash'] = None
+
+        # set to None if files (nullable) is None
+        # and __fields_set__ contains the field
+        if self.files is None and "files" in self.__fields_set__:
+            _dict['files'] = None
+
+        # set to None if ticket_id (nullable) is None
+        # and __fields_set__ contains the field
+        if self.ticket_id is None and "ticket_id" in self.__fields_set__:
+            _dict['ticket_id'] = None
+
+        return _dict
+
+    @classmethod
+    def from_dict(cls, obj: dict) -> BodyUploadEvidenceApiEvidenceUploadPost:
+        """Create an instance of BodyUploadEvidenceApiEvidenceUploadPost from a dict"""
+        if obj is None:
+            return None
+
+        if not isinstance(obj, dict):
+            return BodyUploadEvidenceApiEvidenceUploadPost.parse_obj(obj)
+
+        _obj = BodyUploadEvidenceApiEvidenceUploadPost.parse_obj({
+            "calculate_hash": obj.get("calculate_hash"),
+            "files": obj.get("files"),
+            "ticket_id": obj.get("ticket_id")
+        })
+        return _obj
+
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/complete_turbinia_stats.py b/turbinia/api/client/turbinia_api_lib/models/complete_turbinia_stats.py
index 7960b7c5b..8da619655 100644
--- a/turbinia/api/client/turbinia_api_lib/models/complete_turbinia_stats.py
+++ b/turbinia/api/client/turbinia_api_lib/models/complete_turbinia_stats.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 from __future__ import annotations
@@ -18,20 +18,20 @@
 import json
 
 
-from typing import Any, Optional
-from pydantic import BaseModel, Field
+from typing import Any, Dict, Optional
+from pydantic import BaseModel
 
 class CompleteTurbiniaStats(BaseModel):
     """
-    Statistics for different groups of tasks.
+    Statistics for different groups of tasks.  # noqa: E501
     """
-    all_tasks: Optional[Any] = Field(...)
-    failed_tasks: Optional[Any] = Field(...)
-    requests: Optional[Any] = Field(...)
-    successful_tasks: Optional[Any] = Field(...)
-    tasks_per_type: Optional[Any] = Field(...)
-    tasks_per_user: Optional[Any] = Field(...)
-    tasks_per_worker: Optional[Any] = Field(...)
+    all_tasks: Optional[Dict[str, Any]] = None
+    failed_tasks: Optional[Dict[str, Any]] = None
+    requests: Optional[Dict[str, Any]] = None
+    successful_tasks: Optional[Dict[str, Any]] = None
+    tasks_per_type: Optional[Dict[str, Any]] = None
+    tasks_per_user: Optional[Dict[str, Any]] = None
+    tasks_per_worker: Optional[Dict[str, Any]] = None
     __properties = ["all_tasks", "failed_tasks", "requests", "successful_tasks", "tasks_per_type", "tasks_per_user", "tasks_per_worker"]
 
     class Config:
@@ -58,41 +58,6 @@ def to_dict(self):
                           exclude={
                           },
                           exclude_none=True)
-        # set to None if all_tasks (nullable) is None
-        # and __fields_set__ contains the field
-        if self.all_tasks is None and "all_tasks" in self.__fields_set__:
-            _dict['all_tasks'] = None
-
-        # set to None if failed_tasks (nullable) is None
-        # and __fields_set__ contains the field
-        if self.failed_tasks is None and "failed_tasks" in self.__fields_set__:
-            _dict['failed_tasks'] = None
-
-        # set to None if requests (nullable) is None
-        # and __fields_set__ contains the field
-        if self.requests is None and "requests" in self.__fields_set__:
-            _dict['requests'] = None
-
-        # set to None if successful_tasks (nullable) is None
-        # and __fields_set__ contains the field
-        if self.successful_tasks is None and "successful_tasks" in self.__fields_set__:
-            _dict['successful_tasks'] = None
-
-        # set to None if tasks_per_type (nullable) is None
-        # and __fields_set__ contains the field
-        if self.tasks_per_type is None and "tasks_per_type" in self.__fields_set__:
-            _dict['tasks_per_type'] = None
-
-        # set to None if tasks_per_user (nullable) is None
-        # and __fields_set__ contains the field
-        if self.tasks_per_user is None and "tasks_per_user" in self.__fields_set__:
-            _dict['tasks_per_user'] = None
-
-        # set to None if tasks_per_worker (nullable) is None
-        # and __fields_set__ contains the field
-        if self.tasks_per_worker is None and "tasks_per_worker" in self.__fields_set__:
-            _dict['tasks_per_worker'] = None
-
         return _dict
 
     @classmethod
@@ -115,3 +80,4 @@ def from_dict(cls, obj: dict) -> CompleteTurbiniaStats:
         })
         return _obj
 
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/http_validation_error.py b/turbinia/api/client/turbinia_api_lib/models/http_validation_error.py
index 5c458ac5f..aa2f6024c 100644
--- a/turbinia/api/client/turbinia_api_lib/models/http_validation_error.py
+++ b/turbinia/api/client/turbinia_api_lib/models/http_validation_error.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 from __future__ import annotations
@@ -18,14 +18,15 @@
 import json
 
 
-from typing import Any, Optional
-from pydantic import BaseModel
+from typing import List, Optional
+from pydantic import BaseModel, conlist
+from turbinia_api_lib.models.validation_error import ValidationError
 
 class HTTPValidationError(BaseModel):
     """
     HTTPValidationError
     """
-    detail: Optional[Any] = None
+    detail: Optional[conlist(ValidationError)] = None
     __properties = ["detail"]
 
     class Config:
@@ -52,11 +53,13 @@ def to_dict(self):
                           exclude={
                           },
                           exclude_none=True)
-        # set to None if detail (nullable) is None
-        # and __fields_set__ contains the field
-        if self.detail is None and "detail" in self.__fields_set__:
-            _dict['detail'] = None
-
+        # override the default output from pydantic by calling `to_dict()` of each item in detail (list)
+        _items = []
+        if self.detail:
+            for _item in self.detail:
+                if _item:
+                    _items.append(_item.to_dict())
+            _dict['detail'] = _items
         return _dict
 
     @classmethod
@@ -69,7 +72,8 @@ def from_dict(cls, obj: dict) -> HTTPValidationError:
             return HTTPValidationError.parse_obj(obj)
 
         _obj = HTTPValidationError.parse_obj({
-            "detail": obj.get("detail")
+            "detail": [ValidationError.from_dict(_item) for _item in obj.get("detail")] if obj.get("detail") is not None else None
         })
         return _obj
 
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/location_inner.py b/turbinia/api/client/turbinia_api_lib/models/location_inner.py
new file mode 100644
index 000000000..40d11a88f
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/models/location_inner.py
@@ -0,0 +1,138 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+    Do not edit the class manually.
+"""  # noqa: E501
+
+
+from __future__ import annotations
+from inspect import getfullargspec
+import json
+import pprint
+import re  # noqa: F401
+
+from typing import Optional
+from pydantic import BaseModel, Field, StrictInt, StrictStr, ValidationError, validator
+from typing import Union, Any, List, TYPE_CHECKING
+from pydantic import StrictStr, Field
+
+LOCATIONINNER_ANY_OF_SCHEMAS = ["int", "str"]
+
+class LocationInner(BaseModel):
+    """
+    LocationInner
+    """
+
+    # data type: str
+    anyof_schema_1_validator: Optional[StrictStr] = None
+    # data type: int
+    anyof_schema_2_validator: Optional[StrictInt] = None
+    if TYPE_CHECKING:
+        actual_instance: Union[int, str]
+    else:
+        actual_instance: Any
+    any_of_schemas: List[str] = Field(LOCATIONINNER_ANY_OF_SCHEMAS, const=True)
+
+    class Config:
+        validate_assignment = True
+
+    def __init__(self, *args, **kwargs) -> None:
+        if args:
+            if len(args) > 1:
+                raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
+            if kwargs:
+                raise ValueError("If a position argument is used, keyword arguments cannot be used.")
+            super().__init__(actual_instance=args[0])
+        else:
+            super().__init__(**kwargs)
+
+    @validator('actual_instance')
+    def actual_instance_must_validate_anyof(cls, v):
+        instance = LocationInner.construct()
+        error_messages = []
+        # validate data type: str
+        try:
+            instance.anyof_schema_1_validator = v
+            return v
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+        # validate data type: int
+        try:
+            instance.anyof_schema_2_validator = v
+            return v
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+        if error_messages:
+            # no match
+            raise ValueError("No match found when setting the actual_instance in LocationInner with anyOf schemas: int, str. Details: " + ", ".join(error_messages))
+        else:
+            return v
+
+    @classmethod
+    def from_dict(cls, obj: dict) -> LocationInner:
+        return cls.from_json(json.dumps(obj))
+
+    @classmethod
+    def from_json(cls, json_str: str) -> LocationInner:
+        """Returns the object represented by the json string"""
+        instance = LocationInner.construct()
+        error_messages = []
+        # deserialize data into str
+        try:
+            # validation
+            instance.anyof_schema_1_validator = json.loads(json_str)
+            # assign value to actual_instance
+            instance.actual_instance = instance.anyof_schema_1_validator
+            return instance
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+        # deserialize data into int
+        try:
+            # validation
+            instance.anyof_schema_2_validator = json.loads(json_str)
+            # assign value to actual_instance
+            instance.actual_instance = instance.anyof_schema_2_validator
+            return instance
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+
+        if error_messages:
+            # no match
+            raise ValueError("No match found when deserializing the JSON string into LocationInner with anyOf schemas: int, str. Details: " + ", ".join(error_messages))
+        else:
+            return instance
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the actual instance"""
+        if self.actual_instance is None:
+            return "null"
+
+        to_json = getattr(self.actual_instance, "to_json", None)
+        if callable(to_json):
+            return self.actual_instance.to_json()
+        else:
+            return json.dumps(self.actual_instance)
+
+    def to_dict(self) -> dict:
+        """Returns the dict representation of the actual instance"""
+        if self.actual_instance is None:
+            return "null"
+
+        to_json = getattr(self.actual_instance, "to_json", None)
+        if callable(to_json):
+            return self.actual_instance.to_dict()
+        else:
+            return json.dumps(self.actual_instance)
+
+    def to_str(self) -> str:
+        """Returns the string representation of the actual instance"""
+        return pprint.pformat(self.dict())
+
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/request.py b/turbinia/api/client/turbinia_api_lib/models/request.py
index 3b3e2b18f..91adb99e7 100644
--- a/turbinia/api/client/turbinia_api_lib/models/request.py
+++ b/turbinia/api/client/turbinia_api_lib/models/request.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 from __future__ import annotations
@@ -18,16 +18,16 @@
 import json
 
 
-from typing import Any, Optional
-from pydantic import BaseModel, Field
+from typing import Any, Dict, Optional
+from pydantic import BaseModel, Field, StrictStr
 from turbinia_api_lib.models.base_request_options import BaseRequestOptions
 
 class Request(BaseModel):
     """
-    Base request object. 
+    Base request object.   # noqa: E501
     """
-    description: Optional[Any] = None
-    evidence: Optional[Any] = Field(...)
+    description: Optional[StrictStr] = 'Turbinia request object'
+    evidence: Dict[str, Any] = Field(...)
     request_options: BaseRequestOptions = Field(...)
     __properties = ["description", "evidence", "request_options"]
 
@@ -58,16 +58,6 @@ def to_dict(self):
         # override the default output from pydantic by calling `to_dict()` of request_options
         if self.request_options:
             _dict['request_options'] = self.request_options.to_dict()
-        # set to None if description (nullable) is None
-        # and __fields_set__ contains the field
-        if self.description is None and "description" in self.__fields_set__:
-            _dict['description'] = None
-
-        # set to None if evidence (nullable) is None
-        # and __fields_set__ contains the field
-        if self.evidence is None and "evidence" in self.__fields_set__:
-            _dict['evidence'] = None
-
         return _dict
 
     @classmethod
@@ -80,9 +70,10 @@ def from_dict(cls, obj: dict) -> Request:
             return Request.parse_obj(obj)
 
         _obj = Request.parse_obj({
-            "description": obj.get("description"),
+            "description": obj.get("description") if obj.get("description") is not None else 'Turbinia request object',
             "evidence": obj.get("evidence"),
             "request_options": BaseRequestOptions.from_dict(obj.get("request_options")) if obj.get("request_options") is not None else None
         })
         return _obj
 
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/validation_error.py b/turbinia/api/client/turbinia_api_lib/models/validation_error.py
index 05d373d8f..9c513201e 100644
--- a/turbinia/api/client/turbinia_api_lib/models/validation_error.py
+++ b/turbinia/api/client/turbinia_api_lib/models/validation_error.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 from __future__ import annotations
@@ -18,16 +18,17 @@
 import json
 
 
-from typing import Any, Optional
-from pydantic import BaseModel, Field
+from typing import List
+from pydantic import BaseModel, Field, StrictStr, conlist
+from turbinia_api_lib.models.location_inner import LocationInner
 
 class ValidationError(BaseModel):
     """
     ValidationError
     """
-    loc: Optional[Any] = Field(...)
-    msg: Optional[Any] = Field(...)
-    type: Optional[Any] = Field(...)
+    loc: conlist(LocationInner) = Field(...)
+    msg: StrictStr = Field(...)
+    type: StrictStr = Field(...)
     __properties = ["loc", "msg", "type"]
 
     class Config:
@@ -54,21 +55,13 @@ def to_dict(self):
                           exclude={
                           },
                           exclude_none=True)
-        # set to None if loc (nullable) is None
-        # and __fields_set__ contains the field
-        if self.loc is None and "loc" in self.__fields_set__:
-            _dict['loc'] = None
-
-        # set to None if msg (nullable) is None
-        # and __fields_set__ contains the field
-        if self.msg is None and "msg" in self.__fields_set__:
-            _dict['msg'] = None
-
-        # set to None if type (nullable) is None
-        # and __fields_set__ contains the field
-        if self.type is None and "type" in self.__fields_set__:
-            _dict['type'] = None
-
+        # override the default output from pydantic by calling `to_dict()` of each item in loc (list)
+        _items = []
+        if self.loc:
+            for _item in self.loc:
+                if _item:
+                    _items.append(_item.to_dict())
+            _dict['loc'] = _items
         return _dict
 
     @classmethod
@@ -81,9 +74,10 @@ def from_dict(cls, obj: dict) -> ValidationError:
             return ValidationError.parse_obj(obj)
 
         _obj = ValidationError.parse_obj({
-            "loc": obj.get("loc"),
+            "loc": [LocationInner.from_dict(_item) for _item in obj.get("loc")] if obj.get("loc") is not None else None,
             "msg": obj.get("msg"),
             "type": obj.get("type")
         })
         return _obj
 
+
diff --git a/turbinia/api/client/turbinia_api_lib/models/validation_error_loc_inner.py b/turbinia/api/client/turbinia_api_lib/models/validation_error_loc_inner.py
new file mode 100644
index 000000000..ab45d7e1b
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/models/validation_error_loc_inner.py
@@ -0,0 +1,138 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia API server
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+    Do not edit the class manually.
+"""  # noqa: E501
+
+
+from __future__ import annotations
+from inspect import getfullargspec
+import json
+import pprint
+import re  # noqa: F401
+
+from typing import Optional
+from pydantic import BaseModel, Field, StrictInt, StrictStr, ValidationError, validator
+from typing import Union, Any, List, TYPE_CHECKING
+from pydantic import StrictStr, Field
+
+VALIDATIONERRORLOCINNER_ANY_OF_SCHEMAS = ["int", "str"]
+
+class ValidationErrorLocInner(BaseModel):
+    """
+    ValidationErrorLocInner
+    """
+
+    # data type: str
+    anyof_schema_1_validator: Optional[StrictStr] = None
+    # data type: int
+    anyof_schema_2_validator: Optional[StrictInt] = None
+    if TYPE_CHECKING:
+        actual_instance: Union[int, str]
+    else:
+        actual_instance: Any
+    any_of_schemas: List[str] = Field(VALIDATIONERRORLOCINNER_ANY_OF_SCHEMAS, const=True)
+
+    class Config:
+        validate_assignment = True
+
+    def __init__(self, *args, **kwargs) -> None:
+        if args:
+            if len(args) > 1:
+                raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
+            if kwargs:
+                raise ValueError("If a position argument is used, keyword arguments cannot be used.")
+            super().__init__(actual_instance=args[0])
+        else:
+            super().__init__(**kwargs)
+
+    @validator('actual_instance')
+    def actual_instance_must_validate_anyof(cls, v):
+        instance = ValidationErrorLocInner.construct()
+        error_messages = []
+        # validate data type: str
+        try:
+            instance.anyof_schema_1_validator = v
+            return v
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+        # validate data type: int
+        try:
+            instance.anyof_schema_2_validator = v
+            return v
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+        if error_messages:
+            # no match
+            raise ValueError("No match found when setting the actual_instance in ValidationErrorLocInner with anyOf schemas: int, str. Details: " + ", ".join(error_messages))
+        else:
+            return v
+
+    @classmethod
+    def from_dict(cls, obj: dict) -> ValidationErrorLocInner:
+        return cls.from_json(json.dumps(obj))
+
+    @classmethod
+    def from_json(cls, json_str: str) -> ValidationErrorLocInner:
+        """Returns the object represented by the json string"""
+        instance = ValidationErrorLocInner.construct()
+        error_messages = []
+        # deserialize data into str
+        try:
+            # validation
+            instance.anyof_schema_1_validator = json.loads(json_str)
+            # assign value to actual_instance
+            instance.actual_instance = instance.anyof_schema_1_validator
+            return instance
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+        # deserialize data into int
+        try:
+            # validation
+            instance.anyof_schema_2_validator = json.loads(json_str)
+            # assign value to actual_instance
+            instance.actual_instance = instance.anyof_schema_2_validator
+            return instance
+        except (ValidationError, ValueError) as e:
+            error_messages.append(str(e))
+
+        if error_messages:
+            # no match
+            raise ValueError("No match found when deserializing the JSON string into ValidationErrorLocInner with anyOf schemas: int, str. Details: " + ", ".join(error_messages))
+        else:
+            return instance
+
+    def to_json(self) -> str:
+        """Returns the JSON representation of the actual instance"""
+        if self.actual_instance is None:
+            return "null"
+
+        to_json = getattr(self.actual_instance, "to_json", None)
+        if callable(to_json):
+            return self.actual_instance.to_json()
+        else:
+            return json.dumps(self.actual_instance)
+
+    def to_dict(self) -> dict:
+        """Returns the dict representation of the actual instance"""
+        if self.actual_instance is None:
+            return "null"
+
+        to_json = getattr(self.actual_instance, "to_json", None)
+        if callable(to_json):
+            return self.actual_instance.to_dict()
+        else:
+            return json.dumps(self.actual_instance)
+
+    def to_str(self) -> str:
+        """Returns the string representation of the actual instance"""
+        return pprint.pformat(self.dict())
+
+
diff --git a/turbinia/api/client/turbinia_api_lib/rest.py b/turbinia/api/client/turbinia_api_lib/rest.py
index c5ee0d3cf..e7a0a66d4 100644
--- a/turbinia/api/client/turbinia_api_lib/rest.py
+++ b/turbinia/api/client/turbinia_api_lib/rest.py
@@ -3,13 +3,13 @@
 """
     Turbinia API Server
 
-    Turbinia API server  # noqa: E501
+    Turbinia is an open-source framework for deploying, managing, and running distributed forensic workloads
 
     The version of the OpenAPI document: 1.0.0
     Generated by OpenAPI Generator (https://openapi-generator.tech)
 
     Do not edit the class manually.
-"""
+"""  # noqa: E501
 
 
 import io
@@ -29,7 +29,7 @@
 
 class RESTResponse(io.IOBase):
 
-    def __init__(self, resp):
+    def __init__(self, resp) -> None:
         self.urllib3_response = resp
         self.status = resp.status
         self.reason = resp.reason
@@ -44,9 +44,9 @@ def getheader(self, name, default=None):
         return self.urllib3_response.headers.get(name, default)
 
 
-class RESTClientObject(object):
+class RESTClientObject:
 
-    def __init__(self, configuration, pools_size=4, maxsize=None):
+    def __init__(self, configuration, pools_size=4, maxsize=None) -> None:
         # urllib3.PoolManager will pass all kw parameters to connectionpool
         # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75  # noqa: E501
         # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680  # noqa: E501
diff --git a/turbinia/api/client/turbinia_api_lib/schemas.py b/turbinia/api/client/turbinia_api_lib/schemas.py
new file mode 100644
index 000000000..0c693fda8
--- /dev/null
+++ b/turbinia/api/client/turbinia_api_lib/schemas.py
@@ -0,0 +1,2475 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+from collections import defaultdict
+from datetime import date, datetime, timedelta  # noqa: F401
+import functools
+import decimal
+import io
+import re
+import types
+import typing
+import uuid
+
+from dateutil.parser.isoparser import isoparser, _takes_ascii
+import frozendict
+
+from turbinia_api_lib.exceptions import (
+    ApiTypeError,
+    ApiValueError,
+)
+from turbinia_api_lib.configuration import (
+    Configuration,
+)
+
+
+class Unset(object):
+    """
+    An instance of this class is set as the default value for object type(dict) properties that are optional
+    When a property has an unset value, that property will not be assigned in the dict
+    """
+    pass
+
+unset = Unset()
+
+none_type = type(None)
+file_type = io.IOBase
+
+
+class FileIO(io.FileIO):
+    """
+    A class for storing files
+    Note: this class is not immutable
+    """
+
+    def __new__(cls, _arg: typing.Union[io.FileIO, io.BufferedReader]):
+        if isinstance(_arg, (io.FileIO, io.BufferedReader)):
+            if _arg.closed:
+                raise ApiValueError('Invalid file state; file is closed and must be open')
+            _arg.close()
+            inst = super(FileIO, cls).__new__(cls, _arg.name)
+            super(FileIO, inst).__init__(_arg.name)
+            return inst
+        raise ApiValueError('FileIO must be passed _arg which contains the open file')
+
+    def __init__(self, _arg: typing.Union[io.FileIO, io.BufferedReader]):
+        pass
+
+
+def update(d: dict, u: dict):
+    """
+    Adds u to d
+    Where each dict is defaultdict(set)
+    """
+    if not u:
+        return d
+    for k, v in u.items():
+        if k not in d:
+            d[k] = v
+        else:
+            d[k] = d[k] | v
+
+
+class ValidationMetadata(frozendict.frozendict):
+    """
+    A class storing metadata that is needed to validate OpenApi Schema payloads
+    """
+    def __new__(
+        cls,
+        path_to_item: typing.Tuple[typing.Union[str, int], ...] = tuple(['args[0]']),
+        from_server: bool = False,
+        configuration: typing.Optional[Configuration] = None,
+        seen_classes: typing.FrozenSet[typing.Type] = frozenset(),
+        validated_path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Type]] = frozendict.frozendict()
+    ):
+        """
+        Args:
+            path_to_item: the path to the current data being instantiated.
+                For {'a': [1]} if the code is handling, 1, then the path is ('args[0]', 'a', 0)
+                This changes from location to location
+            from_server: whether or not this data came form the server
+                True when receiving server data
+                False when instantiating model with client side data not form the server
+                This does not change from location to location
+            configuration: the Configuration instance to use
+                This is needed because in Configuration:
+                - one can disable validation checking
+                This does not change from location to location
+            seen_classes: when deserializing data that matches multiple schemas, this is used to store
+                the schemas that have been traversed. This is used to stop processing when a cycle is seen.
+                This changes from location to location
+            validated_path_to_schemas: stores the already validated schema classes for a given path location
+                This does not change from location to location
+        """
+        return super().__new__(
+            cls,
+            path_to_item=path_to_item,
+            from_server=from_server,
+            configuration=configuration,
+            seen_classes=seen_classes,
+            validated_path_to_schemas=validated_path_to_schemas
+        )
+
+    def validation_ran_earlier(self, cls: type) -> bool:
+        validated_schemas = self.validated_path_to_schemas.get(self.path_to_item, set())
+        validation_ran_earlier = validated_schemas and cls in validated_schemas
+        if validation_ran_earlier:
+            return True
+        if cls in self.seen_classes:
+            return True
+        return False
+
+    @property
+    def path_to_item(self) -> typing.Tuple[typing.Union[str, int], ...]:
+        return self.get('path_to_item')
+
+    @property
+    def from_server(self) -> bool:
+        return self.get('from_server')
+
+    @property
+    def configuration(self) -> typing.Optional[Configuration]:
+        return self.get('configuration')
+
+    @property
+    def seen_classes(self) -> typing.FrozenSet[typing.Type]:
+        return self.get('seen_classes')
+
+    @property
+    def validated_path_to_schemas(self) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Type]]:
+        return self.get('validated_path_to_schemas')
+
+
+def add_deeper_validated_schemas(validation_metadata: ValidationMetadata, path_to_schemas: dict):
+    # this is called if validation_ran_earlier and current and deeper locations need to be added
+    current_path_to_item = validation_metadata.path_to_item
+    other_path_to_schemas = {}
+    for path_to_item, schemas in validation_metadata.validated_path_to_schemas.items():
+        if len(path_to_item) < len(current_path_to_item):
+            continue
+        path_begins_with_current_path = path_to_item[:len(current_path_to_item)] == current_path_to_item
+        if path_begins_with_current_path:
+            other_path_to_schemas[path_to_item] = schemas
+    update(path_to_schemas, other_path_to_schemas)
+
+
+class Singleton:
+    """
+    Enums and singletons are the same
+    The same instance is returned for a given key of (cls, _arg)
+    """
+    _instances = {}
+
+    def __new__(cls, _arg: typing.Any, **kwargs):
+        """
+        cls base classes: BoolClass, NoneClass, str, decimal.Decimal
+        The 3rd key is used in the tuple below for a corner case where an enum contains integer 1
+        However 1.0  can also be ingested into that enum schema because 1.0 == 1 and
+        Decimal('1.0') == Decimal('1')
+        But if we omitted the 3rd value in the key, then Decimal('1.0') would be stored as Decimal('1')
+        and json serializing that instance would be '1' rather than the expected '1.0'
+        Adding the 3rd value, the str of _arg ensures that 1.0 -> Decimal('1.0') which is serialized as 1.0
+        """
+        key = (cls, _arg, str(_arg))
+        if key not in cls._instances:
+            if isinstance(_arg, (none_type, bool, BoolClass, NoneClass)):
+                inst = super().__new__(cls)
+                cls._instances[key] = inst
+            else:
+                cls._instances[key] = super().__new__(cls, _arg)
+        return cls._instances[key]
+
+    def __repr__(self):
+        if isinstance(self, NoneClass):
+            return f'<{self.__class__.__name__}: None>'
+        elif isinstance(self, BoolClass):
+            if bool(self):
+                return f'<{self.__class__.__name__}: True>'
+            return f'<{self.__class__.__name__}: False>'
+        return f'<{self.__class__.__name__}: {super().__repr__()}>'
+
+
+class classproperty:
+
+    def __init__(self, fget):
+        self.fget = fget
+
+    def __get__(self, owner_self, owner_cls):
+        return self.fget(owner_cls)
+
+
+class NoneClass(Singleton):
+    @classproperty
+    def NONE(cls):
+        return cls(None)
+
+    def __bool__(self) -> bool:
+        return False
+
+
+class BoolClass(Singleton):
+    @classproperty
+    def TRUE(cls):
+        return cls(True)
+
+    @classproperty
+    def FALSE(cls):
+        return cls(False)
+
+    @functools.lru_cache()
+    def __bool__(self) -> bool:
+        for key, instance in self._instances.items():
+            if self is instance:
+                return bool(key[1])
+        raise ValueError('Unable to find the boolean value of this instance')
+
+
+class MetaOapgTyped:
+    exclusive_maximum: typing.Union[int, float]
+    inclusive_maximum: typing.Union[int, float]
+    exclusive_minimum: typing.Union[int, float]
+    inclusive_minimum: typing.Union[int, float]
+    max_items: int
+    min_items: int
+    discriminator: typing.Dict[str, typing.Dict[str, typing.Type['Schema']]]
+
+
+    class properties:
+        # to hold object properties
+        pass
+
+    additional_properties: typing.Optional[typing.Type['Schema']]
+    max_properties: int
+    min_properties: int
+    all_of: typing.List[typing.Type['Schema']]
+    one_of: typing.List[typing.Type['Schema']]
+    any_of: typing.List[typing.Type['Schema']]
+    not_schema: typing.Type['Schema']
+    max_length: int
+    min_length: int
+    items: typing.Type['Schema']
+
+
+class Schema:
+    """
+    the base class of all swagger/openapi schemas/models
+    """
+    __inheritable_primitive_types_set = {decimal.Decimal, str, tuple, frozendict.frozendict, FileIO, bytes, BoolClass, NoneClass}
+    _types: typing.Set[typing.Type]
+    MetaOapg = MetaOapgTyped
+
+    @staticmethod
+    def __get_valid_classes_phrase(input_classes):
+        """Returns a string phrase describing what types are allowed"""
+        all_classes = list(input_classes)
+        all_classes = sorted(all_classes, key=lambda cls: cls.__name__)
+        all_class_names = [cls.__name__ for cls in all_classes]
+        if len(all_class_names) == 1:
+            return "is {0}".format(all_class_names[0])
+        return "is one of [{0}]".format(", ".join(all_class_names))
+
+    @staticmethod
+    def _get_class_oapg(item_cls: typing.Union[types.FunctionType, staticmethod, typing.Type['Schema']]) -> typing.Type['Schema']:
+        if isinstance(item_cls, types.FunctionType):
+            # referenced schema
+            return item_cls()
+        elif isinstance(item_cls, staticmethod):
+            # referenced schema
+            return item_cls.__func__()
+        return item_cls
+
+    @classmethod
+    def __type_error_message(
+        cls, var_value=None, var_name=None, valid_classes=None, key_type=None
+    ):
+        """
+        Keyword Args:
+            var_value (any): the variable which has the type_error
+            var_name (str): the name of the variable which has the typ error
+            valid_classes (tuple): the accepted classes for current_item's
+                                      value
+            key_type (bool): False if our value is a value in a dict
+                             True if it is a key in a dict
+                             False if our item is an item in a tuple
+        """
+        key_or_value = "value"
+        if key_type:
+            key_or_value = "key"
+        valid_classes_phrase = cls.__get_valid_classes_phrase(valid_classes)
+        msg = "Invalid type. Required {1} type {2} and " "passed type was {3}".format(
+            var_name,
+            key_or_value,
+            valid_classes_phrase,
+            type(var_value).__name__,
+        )
+        return msg
+
+    @classmethod
+    def __get_type_error(cls, var_value, path_to_item, valid_classes, key_type=False):
+        error_msg = cls.__type_error_message(
+            var_name=path_to_item[-1],
+            var_value=var_value,
+            valid_classes=valid_classes,
+            key_type=key_type,
+        )
+        return ApiTypeError(
+            error_msg,
+            path_to_item=path_to_item,
+            valid_classes=valid_classes,
+            key_type=key_type,
+        )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
+        """
+        Schema _validate_oapg
+        All keyword validation except for type checking was done in calling stack frames
+        If those validations passed, the validated classes are collected in path_to_schemas
+
+        Returns:
+            path_to_schemas: a map of path to schemas
+
+        Raises:
+            ApiValueError: when a string can't be converted into a date or datetime and it must be one of those classes
+            ApiTypeError: when the input type is not in the list of allowed spec types
+        """
+        base_class = type(arg)
+        if base_class not in cls._types:
+            raise cls.__get_type_error(
+                arg,
+                validation_metadata.path_to_item,
+                cls._types,
+                key_type=False,
+            )
+
+        path_to_schemas = {validation_metadata.path_to_item: set()}
+        path_to_schemas[validation_metadata.path_to_item].add(cls)
+        path_to_schemas[validation_metadata.path_to_item].add(base_class)
+        return path_to_schemas
+
+    @staticmethod
+    def _process_schema_classes_oapg(
+        schema_classes: typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]
+    ):
+        """
+        Processes and mutates schema_classes
+        If a SomeSchema is a subclass of DictSchema then remove DictSchema because it is already included
+        """
+        if len(schema_classes) < 2:
+            return
+        if len(schema_classes) > 2 and UnsetAnyTypeSchema in schema_classes:
+            schema_classes.remove(UnsetAnyTypeSchema)
+        x_schema = schema_type_classes & schema_classes
+        if not x_schema:
+            return
+        x_schema = x_schema.pop()
+        if any(c is not x_schema and issubclass(c, x_schema) for c in schema_classes):
+            # needed to not have a mro error in get_new_class
+            schema_classes.remove(x_schema)
+
+    @classmethod
+    def __get_new_cls(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata
+    ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type['Schema']]:
+        """
+        Make a new dynamic class and return an instance of that class
+        We are making an instance of cls, but instead of making cls
+        make a new class, new_cls
+        which includes dynamic bases including cls
+        return an instance of that new class
+
+        Dict property + List Item Assignment Use cases:
+        1. value is NOT an instance of the required schema class
+            the value is validated by _validate_oapg
+            _validate_oapg returns a key value pair
+            where the key is the path to the item, and the value will be the required manufactured class
+            made out of the matching schemas
+        2. value is an instance of the correct schema type
+            the value is NOT validated by _validate_oapg, _validate_oapg only checks that the instance is of the correct schema type
+            for this value, _validate_oapg does NOT return an entry for it in _path_to_schemas
+            and in list/dict _get_items_oapg,_get_properties_oapg the value will be directly assigned
+            because value is of the correct type, and validation was run earlier when the instance was created
+        """
+        _path_to_schemas = {}
+        if validation_metadata.validation_ran_earlier(cls):
+            add_deeper_validated_schemas(validation_metadata, _path_to_schemas)
+        else:
+            other_path_to_schemas = cls._validate_oapg(arg, validation_metadata=validation_metadata)
+            update(_path_to_schemas, other_path_to_schemas)
+        # loop through it make a new class for each entry
+        # do not modify the returned result because it is cached and we would be modifying the cached value
+        path_to_schemas = {}
+        for path, schema_classes in _path_to_schemas.items():
+            """
+            Use cases
+            1. N number of schema classes + enum + type != bool/None, classes in path_to_schemas: tuple/frozendict.frozendict/str/Decimal/bytes/FileIo
+                needs Singleton added
+            2. N number of schema classes + enum + type == bool/None, classes in path_to_schemas: BoolClass/NoneClass
+                Singleton already added
+            3. N number of schema classes, classes in path_to_schemas: BoolClass/NoneClass/tuple/frozendict.frozendict/str/Decimal/bytes/FileIo
+            """
+            cls._process_schema_classes_oapg(schema_classes)
+            enum_schema = any(
+                issubclass(this_cls, EnumBase) for this_cls in schema_classes)
+            inheritable_primitive_type = schema_classes.intersection(cls.__inheritable_primitive_types_set)
+            chosen_schema_classes = schema_classes - inheritable_primitive_type
+            suffix = tuple(inheritable_primitive_type)
+            if enum_schema and suffix[0] not in {NoneClass, BoolClass}:
+                suffix = (Singleton,) + suffix
+
+            used_classes = tuple(sorted(chosen_schema_classes, key=lambda a_cls: a_cls.__name__)) + suffix
+            mfg_cls = get_new_class(class_name='DynamicSchema', bases=used_classes)
+            path_to_schemas[path] = mfg_cls
+
+        return path_to_schemas
+
+    @classmethod
+    def _get_new_instance_without_conversion_oapg(
+        cls,
+        arg: typing.Any,
+        path_to_item: typing.Tuple[typing.Union[str, int], ...],
+        path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type['Schema']]
+    ):
+        # We have a Dynamic class and we are making an instance of it
+        if issubclass(cls, frozendict.frozendict) and issubclass(cls, DictBase):
+            properties = cls._get_properties_oapg(arg, path_to_item, path_to_schemas)
+            return super(Schema, cls).__new__(cls, properties)
+        elif issubclass(cls, tuple) and issubclass(cls, ListBase):
+            items = cls._get_items_oapg(arg, path_to_item, path_to_schemas)
+            return super(Schema, cls).__new__(cls, items)
+        """
+        str = openapi str, date, and datetime
+        decimal.Decimal = openapi int and float
+        FileIO = openapi binary type and the user inputs a file
+        bytes = openapi binary type and the user inputs bytes
+        """
+        return super(Schema, cls).__new__(cls, arg)
+
+    @classmethod
+    def from_openapi_data_oapg(
+        cls,
+        arg: typing.Union[
+            str,
+            date,
+            datetime,
+            int,
+            float,
+            decimal.Decimal,
+            bool,
+            None,
+            'Schema',
+            dict,
+            frozendict.frozendict,
+            tuple,
+            list,
+            io.FileIO,
+            io.BufferedReader,
+            bytes
+        ],
+        _configuration: typing.Optional[Configuration]
+    ):
+        """
+        Schema from_openapi_data_oapg
+        """
+        from_server = True
+        validated_path_to_schemas = {}
+        arg = cast_to_allowed_types(arg, from_server, validated_path_to_schemas)
+        validation_metadata = ValidationMetadata(
+            from_server=from_server, configuration=_configuration, validated_path_to_schemas=validated_path_to_schemas)
+        path_to_schemas = cls.__get_new_cls(arg, validation_metadata)
+        new_cls = path_to_schemas[validation_metadata.path_to_item]
+        new_inst = new_cls._get_new_instance_without_conversion_oapg(
+            arg,
+            validation_metadata.path_to_item,
+            path_to_schemas
+        )
+        return new_inst
+
+    @staticmethod
+    def __get_input_dict(*args, **kwargs) -> frozendict.frozendict:
+        input_dict = {}
+        if args and isinstance(args[0], (dict, frozendict.frozendict)):
+            input_dict.update(args[0])
+        if kwargs:
+            input_dict.update(kwargs)
+        return frozendict.frozendict(input_dict)
+
+    @staticmethod
+    def __remove_unsets(kwargs):
+        return {key: val for key, val in kwargs.items() if val is not unset}
+
+    def __new__(cls, *_args: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema'], _configuration: typing.Optional[Configuration] = None, **kwargs: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema', Unset]):
+        """
+        Schema __new__
+
+        Args:
+            _args (int/float/decimal.Decimal/str/list/tuple/dict/frozendict.frozendict/bool/None): the value
+            kwargs (str, int/float/decimal.Decimal/str/list/tuple/dict/frozendict.frozendict/bool/None): dict values
+            _configuration: contains the Configuration that enables json schema validation keywords
+                like minItems, minLength etc
+
+        Note: double underscores are used here because pycharm thinks that these variables
+        are instance properties if they are named normally :(
+        """
+        __kwargs = cls.__remove_unsets(kwargs)
+        if not _args and not __kwargs:
+            raise TypeError(
+                'No input given. args or kwargs must be given.'
+            )
+        if not __kwargs and _args and not isinstance(_args[0], dict):
+            __arg = _args[0]
+        else:
+            __arg = cls.__get_input_dict(*_args, **__kwargs)
+        __from_server = False
+        __validated_path_to_schemas = {}
+        __arg = cast_to_allowed_types(
+            __arg, __from_server, __validated_path_to_schemas)
+        __validation_metadata = ValidationMetadata(
+            configuration=_configuration, from_server=__from_server, validated_path_to_schemas=__validated_path_to_schemas)
+        __path_to_schemas = cls.__get_new_cls(__arg, __validation_metadata)
+        __new_cls = __path_to_schemas[__validation_metadata.path_to_item]
+        return __new_cls._get_new_instance_without_conversion_oapg(
+            __arg,
+            __validation_metadata.path_to_item,
+            __path_to_schemas
+        )
+
+    def __init__(
+        self,
+        *_args: typing.Union[
+            dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema'],
+        _configuration: typing.Optional[Configuration] = None,
+        **kwargs: typing.Union[
+            dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, 'Schema', Unset
+        ]
+    ):
+        """
+        this is needed to fix 'Unexpected argument' warning in pycharm
+        this code does nothing because all Schema instances are immutable
+        this means that all input data is passed into and used in new, and after the new instance is made
+        no new attributes are assigned and init is not used
+        """
+        pass
+
+"""
+import itertools
+data_types = ('None', 'FrozenDict', 'Tuple', 'Str', 'Decimal', 'Bool')
+type_to_cls = {
+    'None': 'NoneClass',
+    'FrozenDict': 'frozendict.frozendict',
+    'Tuple': 'tuple',
+    'Str': 'str',
+    'Decimal': 'decimal.Decimal',
+    'Bool': 'BoolClass'
+}
+cls_tuples = [v for v in itertools.combinations(data_types, 5)]
+typed_classes = [f"class {''.join(cls_tuple)}Mixin({', '.join(type_to_cls[typ] for typ in cls_tuple)}):\n    pass" for cls_tuple in cls_tuples]
+for cls in typed_classes:
+    print(cls)
+object_classes = [f"{''.join(cls_tuple)}Mixin = object" for cls_tuple in cls_tuples]
+for cls in object_classes:
+    print(cls)
+"""
+if typing.TYPE_CHECKING:
+    # qty 1
+    NoneMixin = NoneClass
+    FrozenDictMixin = frozendict.frozendict
+    TupleMixin = tuple
+    StrMixin = str
+    DecimalMixin = decimal.Decimal
+    BoolMixin = BoolClass
+    BytesMixin = bytes
+    FileMixin = FileIO
+    # qty 2
+    class BinaryMixin(bytes, FileIO):
+        pass
+    class NoneFrozenDictMixin(NoneClass, frozendict.frozendict):
+        pass
+    class NoneTupleMixin(NoneClass, tuple):
+        pass
+    class NoneStrMixin(NoneClass, str):
+        pass
+    class NoneDecimalMixin(NoneClass, decimal.Decimal):
+        pass
+    class NoneBoolMixin(NoneClass, BoolClass):
+        pass
+    class FrozenDictTupleMixin(frozendict.frozendict, tuple):
+        pass
+    class FrozenDictStrMixin(frozendict.frozendict, str):
+        pass
+    class FrozenDictDecimalMixin(frozendict.frozendict, decimal.Decimal):
+        pass
+    class FrozenDictBoolMixin(frozendict.frozendict, BoolClass):
+        pass
+    class TupleStrMixin(tuple, str):
+        pass
+    class TupleDecimalMixin(tuple, decimal.Decimal):
+        pass
+    class TupleBoolMixin(tuple, BoolClass):
+        pass
+    class StrDecimalMixin(str, decimal.Decimal):
+        pass
+    class StrBoolMixin(str, BoolClass):
+        pass
+    class DecimalBoolMixin(decimal.Decimal, BoolClass):
+        pass
+    # qty 3
+    class NoneFrozenDictTupleMixin(NoneClass, frozendict.frozendict, tuple):
+        pass
+    class NoneFrozenDictStrMixin(NoneClass, frozendict.frozendict, str):
+        pass
+    class NoneFrozenDictDecimalMixin(NoneClass, frozendict.frozendict, decimal.Decimal):
+        pass
+    class NoneFrozenDictBoolMixin(NoneClass, frozendict.frozendict, BoolClass):
+        pass
+    class NoneTupleStrMixin(NoneClass, tuple, str):
+        pass
+    class NoneTupleDecimalMixin(NoneClass, tuple, decimal.Decimal):
+        pass
+    class NoneTupleBoolMixin(NoneClass, tuple, BoolClass):
+        pass
+    class NoneStrDecimalMixin(NoneClass, str, decimal.Decimal):
+        pass
+    class NoneStrBoolMixin(NoneClass, str, BoolClass):
+        pass
+    class NoneDecimalBoolMixin(NoneClass, decimal.Decimal, BoolClass):
+        pass
+    class FrozenDictTupleStrMixin(frozendict.frozendict, tuple, str):
+        pass
+    class FrozenDictTupleDecimalMixin(frozendict.frozendict, tuple, decimal.Decimal):
+        pass
+    class FrozenDictTupleBoolMixin(frozendict.frozendict, tuple, BoolClass):
+        pass
+    class FrozenDictStrDecimalMixin(frozendict.frozendict, str, decimal.Decimal):
+        pass
+    class FrozenDictStrBoolMixin(frozendict.frozendict, str, BoolClass):
+        pass
+    class FrozenDictDecimalBoolMixin(frozendict.frozendict, decimal.Decimal, BoolClass):
+        pass
+    class TupleStrDecimalMixin(tuple, str, decimal.Decimal):
+        pass
+    class TupleStrBoolMixin(tuple, str, BoolClass):
+        pass
+    class TupleDecimalBoolMixin(tuple, decimal.Decimal, BoolClass):
+        pass
+    class StrDecimalBoolMixin(str, decimal.Decimal, BoolClass):
+        pass
+    # qty 4
+    class NoneFrozenDictTupleStrMixin(NoneClass, frozendict.frozendict, tuple, str):
+        pass
+    class NoneFrozenDictTupleDecimalMixin(NoneClass, frozendict.frozendict, tuple, decimal.Decimal):
+        pass
+    class NoneFrozenDictTupleBoolMixin(NoneClass, frozendict.frozendict, tuple, BoolClass):
+        pass
+    class NoneFrozenDictStrDecimalMixin(NoneClass, frozendict.frozendict, str, decimal.Decimal):
+        pass
+    class NoneFrozenDictStrBoolMixin(NoneClass, frozendict.frozendict, str, BoolClass):
+        pass
+    class NoneFrozenDictDecimalBoolMixin(NoneClass, frozendict.frozendict, decimal.Decimal, BoolClass):
+        pass
+    class NoneTupleStrDecimalMixin(NoneClass, tuple, str, decimal.Decimal):
+        pass
+    class NoneTupleStrBoolMixin(NoneClass, tuple, str, BoolClass):
+        pass
+    class NoneTupleDecimalBoolMixin(NoneClass, tuple, decimal.Decimal, BoolClass):
+        pass
+    class NoneStrDecimalBoolMixin(NoneClass, str, decimal.Decimal, BoolClass):
+        pass
+    class FrozenDictTupleStrDecimalMixin(frozendict.frozendict, tuple, str, decimal.Decimal):
+        pass
+    class FrozenDictTupleStrBoolMixin(frozendict.frozendict, tuple, str, BoolClass):
+        pass
+    class FrozenDictTupleDecimalBoolMixin(frozendict.frozendict, tuple, decimal.Decimal, BoolClass):
+        pass
+    class FrozenDictStrDecimalBoolMixin(frozendict.frozendict, str, decimal.Decimal, BoolClass):
+        pass
+    class TupleStrDecimalBoolMixin(tuple, str, decimal.Decimal, BoolClass):
+        pass
+    # qty 5
+    class NoneFrozenDictTupleStrDecimalMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal):
+        pass
+    class NoneFrozenDictTupleStrBoolMixin(NoneClass, frozendict.frozendict, tuple, str, BoolClass):
+        pass
+    class NoneFrozenDictTupleDecimalBoolMixin(NoneClass, frozendict.frozendict, tuple, decimal.Decimal, BoolClass):
+        pass
+    class NoneFrozenDictStrDecimalBoolMixin(NoneClass, frozendict.frozendict, str, decimal.Decimal, BoolClass):
+        pass
+    class NoneTupleStrDecimalBoolMixin(NoneClass, tuple, str, decimal.Decimal, BoolClass):
+        pass
+    class FrozenDictTupleStrDecimalBoolMixin(frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass):
+        pass
+    # qty 6
+    class NoneFrozenDictTupleStrDecimalBoolMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass):
+        pass
+    # qty 8
+    class NoneFrozenDictTupleStrDecimalBoolFileBytesMixin(NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, FileIO, bytes):
+        pass
+else:
+    # qty 1
+    class NoneMixin:
+        _types = {NoneClass}
+    class FrozenDictMixin:
+        _types = {frozendict.frozendict}
+    class TupleMixin:
+        _types = {tuple}
+    class StrMixin:
+        _types = {str}
+    class DecimalMixin:
+        _types = {decimal.Decimal}
+    class BoolMixin:
+        _types = {BoolClass}
+    class BytesMixin:
+        _types = {bytes}
+    class FileMixin:
+        _types = {FileIO}
+    # qty 2
+    class BinaryMixin:
+        _types = {bytes, FileIO}
+    class NoneFrozenDictMixin:
+        _types = {NoneClass, frozendict.frozendict}
+    class NoneTupleMixin:
+        _types = {NoneClass, tuple}
+    class NoneStrMixin:
+        _types = {NoneClass, str}
+    class NoneDecimalMixin:
+        _types = {NoneClass, decimal.Decimal}
+    class NoneBoolMixin:
+        _types = {NoneClass, BoolClass}
+    class FrozenDictTupleMixin:
+        _types = {frozendict.frozendict, tuple}
+    class FrozenDictStrMixin:
+        _types = {frozendict.frozendict, str}
+    class FrozenDictDecimalMixin:
+        _types = {frozendict.frozendict, decimal.Decimal}
+    class FrozenDictBoolMixin:
+        _types = {frozendict.frozendict, BoolClass}
+    class TupleStrMixin:
+        _types = {tuple, str}
+    class TupleDecimalMixin:
+        _types = {tuple, decimal.Decimal}
+    class TupleBoolMixin:
+        _types = {tuple, BoolClass}
+    class StrDecimalMixin:
+        _types = {str, decimal.Decimal}
+    class StrBoolMixin:
+        _types = {str, BoolClass}
+    class DecimalBoolMixin:
+        _types = {decimal.Decimal, BoolClass}
+    # qty 3
+    class NoneFrozenDictTupleMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple}
+    class NoneFrozenDictStrMixin:
+        _types = {NoneClass, frozendict.frozendict, str}
+    class NoneFrozenDictDecimalMixin:
+        _types = {NoneClass, frozendict.frozendict, decimal.Decimal}
+    class NoneFrozenDictBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, BoolClass}
+    class NoneTupleStrMixin:
+        _types = {NoneClass, tuple, str}
+    class NoneTupleDecimalMixin:
+        _types = {NoneClass, tuple, decimal.Decimal}
+    class NoneTupleBoolMixin:
+        _types = {NoneClass, tuple, BoolClass}
+    class NoneStrDecimalMixin:
+        _types = {NoneClass, str, decimal.Decimal}
+    class NoneStrBoolMixin:
+        _types = {NoneClass, str, BoolClass}
+    class NoneDecimalBoolMixin:
+        _types = {NoneClass, decimal.Decimal, BoolClass}
+    class FrozenDictTupleStrMixin:
+        _types = {frozendict.frozendict, tuple, str}
+    class FrozenDictTupleDecimalMixin:
+        _types = {frozendict.frozendict, tuple, decimal.Decimal}
+    class FrozenDictTupleBoolMixin:
+        _types = {frozendict.frozendict, tuple, BoolClass}
+    class FrozenDictStrDecimalMixin:
+        _types = {frozendict.frozendict, str, decimal.Decimal}
+    class FrozenDictStrBoolMixin:
+        _types = {frozendict.frozendict, str, BoolClass}
+    class FrozenDictDecimalBoolMixin:
+        _types = {frozendict.frozendict, decimal.Decimal, BoolClass}
+    class TupleStrDecimalMixin:
+        _types = {tuple, str, decimal.Decimal}
+    class TupleStrBoolMixin:
+        _types = {tuple, str, BoolClass}
+    class TupleDecimalBoolMixin:
+        _types = {tuple, decimal.Decimal, BoolClass}
+    class StrDecimalBoolMixin:
+        _types = {str, decimal.Decimal, BoolClass}
+    # qty 4
+    class NoneFrozenDictTupleStrMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, str}
+    class NoneFrozenDictTupleDecimalMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, decimal.Decimal}
+    class NoneFrozenDictTupleBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, BoolClass}
+    class NoneFrozenDictStrDecimalMixin:
+        _types = {NoneClass, frozendict.frozendict, str, decimal.Decimal}
+    class NoneFrozenDictStrBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, str, BoolClass}
+    class NoneFrozenDictDecimalBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, decimal.Decimal, BoolClass}
+    class NoneTupleStrDecimalMixin:
+        _types = {NoneClass, tuple, str, decimal.Decimal}
+    class NoneTupleStrBoolMixin:
+        _types = {NoneClass, tuple, str, BoolClass}
+    class NoneTupleDecimalBoolMixin:
+        _types = {NoneClass, tuple, decimal.Decimal, BoolClass}
+    class NoneStrDecimalBoolMixin:
+        _types = {NoneClass, str, decimal.Decimal, BoolClass}
+    class FrozenDictTupleStrDecimalMixin:
+        _types = {frozendict.frozendict, tuple, str, decimal.Decimal}
+    class FrozenDictTupleStrBoolMixin:
+        _types = {frozendict.frozendict, tuple, str, BoolClass}
+    class FrozenDictTupleDecimalBoolMixin:
+        _types = {frozendict.frozendict, tuple, decimal.Decimal, BoolClass}
+    class FrozenDictStrDecimalBoolMixin:
+        _types = {frozendict.frozendict, str, decimal.Decimal, BoolClass}
+    class TupleStrDecimalBoolMixin:
+        _types = {tuple, str, decimal.Decimal, BoolClass}
+    # qty 5
+    class NoneFrozenDictTupleStrDecimalMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal}
+    class NoneFrozenDictTupleStrBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, str, BoolClass}
+    class NoneFrozenDictTupleDecimalBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, decimal.Decimal, BoolClass}
+    class NoneFrozenDictStrDecimalBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, str, decimal.Decimal, BoolClass}
+    class NoneTupleStrDecimalBoolMixin:
+        _types = {NoneClass, tuple, str, decimal.Decimal, BoolClass}
+    class FrozenDictTupleStrDecimalBoolMixin:
+        _types = {frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass}
+    # qty 6
+    class NoneFrozenDictTupleStrDecimalBoolMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass}
+    # qty 8
+    class NoneFrozenDictTupleStrDecimalBoolFileBytesMixin:
+        _types = {NoneClass, frozendict.frozendict, tuple, str, decimal.Decimal, BoolClass, FileIO, bytes}
+
+
+class ValidatorBase:
+    @staticmethod
+    def _is_json_validation_enabled_oapg(schema_keyword, configuration=None):
+        """Returns true if JSON schema validation is enabled for the specified
+        validation keyword. This can be used to skip JSON schema structural validation
+        as requested in the configuration.
+        Note: the suffix _oapg stands for openapi python (experimental) generator and
+        it has been added to prevent collisions with other methods and properties
+
+        Args:
+            schema_keyword (string): the name of a JSON schema validation keyword.
+            configuration (Configuration): the configuration class.
+        """
+
+        return (configuration is None or
+            not hasattr(configuration, '_disabled_client_side_validations') or
+            schema_keyword not in configuration._disabled_client_side_validations)
+
+    @staticmethod
+    def _raise_validation_error_message_oapg(value, constraint_msg, constraint_value, path_to_item, additional_txt=""):
+        raise ApiValueError(
+            "Invalid value `{value}`, {constraint_msg} `{constraint_value}`{additional_txt} at {path_to_item}".format(
+                value=value,
+                constraint_msg=constraint_msg,
+                constraint_value=constraint_value,
+                additional_txt=additional_txt,
+                path_to_item=path_to_item,
+            )
+        )
+
+
+class EnumBase:
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
+        """
+        EnumBase _validate_oapg
+        Validates that arg is in the enum's allowed values
+        """
+        try:
+            cls.MetaOapg.enum_value_to_name[arg]
+        except KeyError:
+            raise ApiValueError("Invalid value {} passed in to {}, allowed_values={}".format(arg, cls, cls.MetaOapg.enum_value_to_name.keys()))
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class BoolBase:
+    def is_true_oapg(self) -> bool:
+        """
+        A replacement for x is True
+        True if the instance is a BoolClass True Singleton
+        """
+        if not issubclass(self.__class__, BoolClass):
+            return False
+        return bool(self)
+
+    def is_false_oapg(self) -> bool:
+        """
+        A replacement for x is False
+        True if the instance is a BoolClass False Singleton
+        """
+        if not issubclass(self.__class__, BoolClass):
+            return False
+        return bool(self) is False
+
+
+class NoneBase:
+    def is_none_oapg(self) -> bool:
+        """
+        A replacement for x is None
+        True if the instance is a NoneClass None Singleton
+        """
+        if issubclass(self.__class__, NoneClass):
+            return True
+        return False
+
+
+class StrBase(ValidatorBase):
+    MetaOapg: MetaOapgTyped
+
+    @property
+    def as_str_oapg(self) -> str:
+        return self
+
+    @property
+    def as_date_oapg(self) -> date:
+        raise Exception('not implemented')
+
+    @property
+    def as_datetime_oapg(self) -> datetime:
+        raise Exception('not implemented')
+
+    @property
+    def as_decimal_oapg(self) -> decimal.Decimal:
+        raise Exception('not implemented')
+
+    @property
+    def as_uuid_oapg(self) -> uuid.UUID:
+        raise Exception('not implemented')
+
+    @classmethod
+    def __check_str_validations(
+        cls,
+        arg: str,
+        validation_metadata: ValidationMetadata
+    ):
+        if not hasattr(cls, 'MetaOapg'):
+            return
+        if (cls._is_json_validation_enabled_oapg('maxLength', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'max_length') and
+                len(arg) > cls.MetaOapg.max_length):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="length must be less than or equal to",
+                constraint_value=cls.MetaOapg.max_length,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('minLength', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'min_length') and
+                len(arg) < cls.MetaOapg.min_length):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="length must be greater than or equal to",
+                constraint_value=cls.MetaOapg.min_length,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('pattern', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'regex')):
+            for regex_dict in cls.MetaOapg.regex:
+                flags = regex_dict.get('flags', 0)
+                if not re.search(regex_dict['pattern'], arg, flags=flags):
+                    if flags != 0:
+                        # Don't print the regex flags if the flags are not
+                        # specified in the OAS document.
+                        cls._raise_validation_error_message_oapg(
+                            value=arg,
+                            constraint_msg="must match regular expression",
+                            constraint_value=regex_dict['pattern'],
+                            path_to_item=validation_metadata.path_to_item,
+                            additional_txt=" with flags=`{}`".format(flags)
+                        )
+                    cls._raise_validation_error_message_oapg(
+                        value=arg,
+                        constraint_msg="must match regular expression",
+                        constraint_value=regex_dict['pattern'],
+                        path_to_item=validation_metadata.path_to_item
+                    )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
+        """
+        StrBase _validate_oapg
+        Validates that validations pass
+        """
+        if isinstance(arg, str):
+            cls.__check_str_validations(arg, validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class UUIDBase:
+    @property
+    @functools.lru_cache()
+    def as_uuid_oapg(self) -> uuid.UUID:
+        return uuid.UUID(self)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[str], validation_metadata: ValidationMetadata):
+        if isinstance(arg, str):
+            try:
+                uuid.UUID(arg)
+                return True
+            except ValueError:
+                raise ApiValueError(
+                    "Invalid value '{}' for type UUID at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: typing.Optional[ValidationMetadata] = None,
+    ):
+        """
+        UUIDBase _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class CustomIsoparser(isoparser):
+
+    @_takes_ascii
+    def parse_isodatetime(self, dt_str):
+        components, pos = self._parse_isodate(dt_str)
+        if len(dt_str) > pos:
+            if self._sep is None or dt_str[pos:pos + 1] == self._sep:
+                components += self._parse_isotime(dt_str[pos + 1:])
+            else:
+                raise ValueError('String contains unknown ISO components')
+
+        if len(components) > 3 and components[3] == 24:
+            components[3] = 0
+            return datetime(*components) + timedelta(days=1)
+
+        if len(components) <= 3:
+            raise ValueError('Value is not a datetime')
+
+        return datetime(*components)
+
+    @_takes_ascii
+    def parse_isodate(self, datestr):
+        components, pos = self._parse_isodate(datestr)
+
+        if len(datestr) > pos:
+            raise ValueError('String contains invalid time components')
+
+        if len(components) > 3:
+            raise ValueError('String contains invalid time components')
+
+        return date(*components)
+
+
+DEFAULT_ISOPARSER = CustomIsoparser()
+
+
+class DateBase:
+    @property
+    @functools.lru_cache()
+    def as_date_oapg(self) -> date:
+        return DEFAULT_ISOPARSER.parse_isodate(self)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[str], validation_metadata: ValidationMetadata):
+        if isinstance(arg, str):
+            try:
+                DEFAULT_ISOPARSER.parse_isodate(arg)
+                return True
+            except ValueError:
+                raise ApiValueError(
+                    "Value does not conform to the required ISO-8601 date format. "
+                    "Invalid value '{}' for type date at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: typing.Optional[ValidationMetadata] = None,
+    ):
+        """
+        DateBase _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class DateTimeBase:
+    @property
+    @functools.lru_cache()
+    def as_datetime_oapg(self) -> datetime:
+        return DEFAULT_ISOPARSER.parse_isodatetime(self)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[str], validation_metadata: ValidationMetadata):
+        if isinstance(arg, str):
+            try:
+                DEFAULT_ISOPARSER.parse_isodatetime(arg)
+                return True
+            except ValueError:
+                raise ApiValueError(
+                    "Value does not conform to the required ISO-8601 datetime format. "
+                    "Invalid value '{}' for type datetime at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        DateTimeBase _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class DecimalBase:
+    """
+    A class for storing decimals that are sent over the wire as strings
+    These schemas must remain based on StrBase rather than NumberBase
+    because picking base classes must be deterministic
+    """
+
+    @property
+    @functools.lru_cache()
+    def as_decimal_oapg(self) -> decimal.Decimal:
+        return decimal.Decimal(self)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[str], validation_metadata: ValidationMetadata):
+        if isinstance(arg, str):
+            try:
+                decimal.Decimal(arg)
+                return True
+            except decimal.InvalidOperation:
+                raise ApiValueError(
+                    "Value cannot be converted to a decimal. "
+                    "Invalid value '{}' for type decimal at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        DecimalBase _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class NumberBase(ValidatorBase):
+    MetaOapg: MetaOapgTyped
+
+    @property
+    def as_int_oapg(self) -> int:
+        try:
+            return self._as_int
+        except AttributeError:
+            """
+            Note: for some numbers like 9.0 they could be represented as an
+            integer but our code chooses to store them as
+            >>> Decimal('9.0').as_tuple()
+            DecimalTuple(sign=0, digits=(9, 0), exponent=-1)
+            so we can tell that the value came from a float and convert it back to a float
+            during later serialization
+            """
+            if self.as_tuple().exponent < 0:
+                # this could be represented as an integer but should be represented as a float
+                # because that's what it was serialized from
+                raise ApiValueError(f'{self} is not an integer')
+            self._as_int = int(self)
+            return self._as_int
+
+    @property
+    def as_float_oapg(self) -> float:
+        try:
+            return self._as_float
+        except AttributeError:
+            if self.as_tuple().exponent >= 0:
+                raise ApiValueError(f'{self} is not a float')
+            self._as_float = float(self)
+            return self._as_float
+
+    @classmethod
+    def __check_numeric_validations(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata
+    ):
+        if not hasattr(cls, 'MetaOapg'):
+            return
+        if cls._is_json_validation_enabled_oapg('multipleOf',
+                                      validation_metadata.configuration) and hasattr(cls.MetaOapg, 'multiple_of'):
+            multiple_of_value = cls.MetaOapg.multiple_of
+            if (not (float(arg) / multiple_of_value).is_integer()):
+                # Note 'multipleOf' will be as good as the floating point arithmetic.
+                cls._raise_validation_error_message_oapg(
+                    value=arg,
+                    constraint_msg="value must be a multiple of",
+                    constraint_value=multiple_of_value,
+                    path_to_item=validation_metadata.path_to_item
+                )
+
+        checking_max_or_min_values = any(
+            hasattr(cls.MetaOapg, validation_key) for validation_key in {
+                'exclusive_maximum',
+                'inclusive_maximum',
+                'exclusive_minimum',
+                'inclusive_minimum',
+            }
+        )
+        if not checking_max_or_min_values:
+            return
+
+        if (cls._is_json_validation_enabled_oapg('exclusiveMaximum', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'exclusive_maximum') and
+                arg >= cls.MetaOapg.exclusive_maximum):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="must be a value less than",
+                constraint_value=cls.MetaOapg.exclusive_maximum,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('maximum', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'inclusive_maximum') and
+                arg > cls.MetaOapg.inclusive_maximum):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="must be a value less than or equal to",
+                constraint_value=cls.MetaOapg.inclusive_maximum,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('exclusiveMinimum', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'exclusive_minimum') and
+                arg <= cls.MetaOapg.exclusive_minimum):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="must be a value greater than",
+                constraint_value=cls.MetaOapg.exclusive_maximum,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('minimum', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'inclusive_minimum') and
+                arg < cls.MetaOapg.inclusive_minimum):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="must be a value greater than or equal to",
+                constraint_value=cls.MetaOapg.inclusive_minimum,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
+        """
+        NumberBase _validate_oapg
+        Validates that validations pass
+        """
+        if isinstance(arg, decimal.Decimal):
+            cls.__check_numeric_validations(arg, validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class ListBase(ValidatorBase):
+    MetaOapg: MetaOapgTyped
+
+    @classmethod
+    def __validate_items(cls, list_items, validation_metadata: ValidationMetadata):
+        """
+        Ensures that:
+        - values passed in for items are valid
+        Exceptions will be raised if:
+        - invalid arguments were passed in
+
+        Args:
+            list_items: the input list of items
+
+        Raises:
+            ApiTypeError - for missing required arguments, or for invalid properties
+        """
+
+        # if we have definitions for an items schema, use it
+        # otherwise accept anything
+        item_cls = getattr(cls.MetaOapg, 'items', UnsetAnyTypeSchema)
+        item_cls = cls._get_class_oapg(item_cls)
+        path_to_schemas = {}
+        for i, value in enumerate(list_items):
+            item_validation_metadata = ValidationMetadata(
+                from_server=validation_metadata.from_server,
+                configuration=validation_metadata.configuration,
+                path_to_item=validation_metadata.path_to_item+(i,),
+                validated_path_to_schemas=validation_metadata.validated_path_to_schemas
+            )
+            if item_validation_metadata.validation_ran_earlier(item_cls):
+                add_deeper_validated_schemas(item_validation_metadata, path_to_schemas)
+                continue
+            other_path_to_schemas = item_cls._validate_oapg(
+                value, validation_metadata=item_validation_metadata)
+            update(path_to_schemas, other_path_to_schemas)
+        return path_to_schemas
+
+    @classmethod
+    def __check_tuple_validations(
+            cls, arg,
+            validation_metadata: ValidationMetadata):
+        if not hasattr(cls, 'MetaOapg'):
+            return
+        if (cls._is_json_validation_enabled_oapg('maxItems', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'max_items') and
+                len(arg) > cls.MetaOapg.max_items):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="number of items must be less than or equal to",
+                constraint_value=cls.MetaOapg.max_items,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('minItems', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'min_items') and
+                len(arg) < cls.MetaOapg.min_items):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="number of items must be greater than or equal to",
+                constraint_value=cls.MetaOapg.min_items,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('uniqueItems', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'unique_items') and cls.MetaOapg.unique_items and arg):
+            unique_items = set(arg)
+            if len(arg) > len(unique_items):
+                cls._raise_validation_error_message_oapg(
+                    value=arg,
+                    constraint_msg="duplicate items were found, and the tuple must not contain duplicates because",
+                    constraint_value='unique_items==True',
+                    path_to_item=validation_metadata.path_to_item
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        ListBase _validate_oapg
+        We return dynamic classes of different bases depending upon the inputs
+        This makes it so:
+        - the returned instance is always a subclass of our defining schema
+            - this allows us to check type based on whether an instance is a subclass of a schema
+        - the returned instance is a serializable type (except for None, True, and False) which are enums
+
+        Returns:
+            new_cls (type): the new class
+
+        Raises:
+            ApiValueError: when a string can't be converted into a date or datetime and it must be one of those classes
+            ApiTypeError: when the input type is not in the list of allowed spec types
+        """
+        if isinstance(arg, tuple):
+            cls.__check_tuple_validations(arg, validation_metadata)
+        _path_to_schemas = super()._validate_oapg(arg, validation_metadata=validation_metadata)
+        if not isinstance(arg, tuple):
+            return _path_to_schemas
+        updated_vm = ValidationMetadata(
+            configuration=validation_metadata.configuration,
+            from_server=validation_metadata.from_server,
+            path_to_item=validation_metadata.path_to_item,
+            seen_classes=validation_metadata.seen_classes | frozenset({cls}),
+            validated_path_to_schemas=validation_metadata.validated_path_to_schemas
+        )
+        other_path_to_schemas = cls.__validate_items(arg, validation_metadata=updated_vm)
+        update(_path_to_schemas, other_path_to_schemas)
+        return _path_to_schemas
+
+    @classmethod
+    def _get_items_oapg(
+        cls: 'Schema',
+        arg: typing.List[typing.Any],
+        path_to_item: typing.Tuple[typing.Union[str, int], ...],
+        path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type['Schema']]
+    ):
+        '''
+        ListBase _get_items_oapg
+        '''
+        cast_items = []
+
+        for i, value in enumerate(arg):
+            item_path_to_item = path_to_item + (i,)
+            item_cls = path_to_schemas[item_path_to_item]
+            new_value = item_cls._get_new_instance_without_conversion_oapg(
+                value,
+                item_path_to_item,
+                path_to_schemas
+            )
+            cast_items.append(new_value)
+
+        return cast_items
+
+
+class Discriminable:
+    MetaOapg: MetaOapgTyped
+
+    @classmethod
+    def _ensure_discriminator_value_present_oapg(cls, disc_property_name: str, validation_metadata: ValidationMetadata, *args):
+        if not args or args and disc_property_name not in args[0]:
+            # The input data does not contain the discriminator property
+            raise ApiValueError(
+                "Cannot deserialize input data due to missing discriminator. "
+                "The discriminator property '{}' is missing at path: {}".format(disc_property_name, validation_metadata.path_to_item)
+            )
+
+    @classmethod
+    def get_discriminated_class_oapg(cls, disc_property_name: str, disc_payload_value: str):
+        """
+        Used in schemas with discriminators
+        """
+        if not hasattr(cls.MetaOapg, 'discriminator'):
+            return None
+        disc = cls.MetaOapg.discriminator()
+        if disc_property_name not in disc:
+            return None
+        discriminated_cls = disc[disc_property_name].get(disc_payload_value)
+        if discriminated_cls is not None:
+            return discriminated_cls
+        if not hasattr(cls, 'MetaOapg'):
+            return None
+        elif not (
+            hasattr(cls.MetaOapg, 'all_of') or
+            hasattr(cls.MetaOapg, 'one_of') or
+            hasattr(cls.MetaOapg, 'any_of')
+        ):
+            return None
+        # TODO stop traveling if a cycle is hit
+        if hasattr(cls.MetaOapg, 'all_of'):
+            for allof_cls in cls.MetaOapg.all_of():
+                discriminated_cls = allof_cls.get_discriminated_class_oapg(
+                    disc_property_name=disc_property_name, disc_payload_value=disc_payload_value)
+                if discriminated_cls is not None:
+                    return discriminated_cls
+        if hasattr(cls.MetaOapg, 'one_of'):
+            for oneof_cls in cls.MetaOapg.one_of():
+                discriminated_cls = oneof_cls.get_discriminated_class_oapg(
+                    disc_property_name=disc_property_name, disc_payload_value=disc_payload_value)
+                if discriminated_cls is not None:
+                    return discriminated_cls
+        if hasattr(cls.MetaOapg, 'any_of'):
+            for anyof_cls in cls.MetaOapg.any_of():
+                discriminated_cls = anyof_cls.get_discriminated_class_oapg(
+                    disc_property_name=disc_property_name, disc_payload_value=disc_payload_value)
+                if discriminated_cls is not None:
+                    return discriminated_cls
+        return None
+
+
+class DictBase(Discriminable, ValidatorBase):
+
+    @classmethod
+    def __validate_arg_presence(cls, arg):
+        """
+        Ensures that:
+        - all required arguments are passed in
+        - the input variable names are valid
+            - present in properties or
+            - accepted because additionalProperties exists
+        Exceptions will be raised if:
+        - invalid arguments were passed in
+            - a var_name is invalid if additional_properties == NotAnyTypeSchema
+            and var_name not in properties.__annotations__
+        - required properties were not passed in
+
+        Args:
+            arg: the input dict
+
+        Raises:
+            ApiTypeError - for missing required arguments, or for invalid properties
+        """
+        seen_required_properties = set()
+        invalid_arguments = []
+        required_property_names = getattr(cls.MetaOapg, 'required', set())
+        additional_properties = getattr(cls.MetaOapg, 'additional_properties', UnsetAnyTypeSchema)
+        properties = getattr(cls.MetaOapg, 'properties', {})
+        property_annotations = getattr(properties, '__annotations__', {})
+        for property_name in arg:
+            if property_name in required_property_names:
+                seen_required_properties.add(property_name)
+            elif property_name in property_annotations:
+                continue
+            elif additional_properties is not NotAnyTypeSchema:
+                continue
+            else:
+                invalid_arguments.append(property_name)
+        missing_required_arguments = list(required_property_names - seen_required_properties)
+        if missing_required_arguments:
+            missing_required_arguments.sort()
+            raise ApiTypeError(
+                "{} is missing {} required argument{}: {}".format(
+                    cls.__name__,
+                    len(missing_required_arguments),
+                    "s" if len(missing_required_arguments) > 1 else "",
+                    missing_required_arguments
+                )
+            )
+        if invalid_arguments:
+            invalid_arguments.sort()
+            raise ApiTypeError(
+                "{} was passed {} invalid argument{}: {}".format(
+                    cls.__name__,
+                    len(invalid_arguments),
+                    "s" if len(invalid_arguments) > 1 else "",
+                    invalid_arguments
+                )
+            )
+
+    @classmethod
+    def __validate_args(cls, arg, validation_metadata: ValidationMetadata):
+        """
+        Ensures that:
+        - values passed in for properties are valid
+        Exceptions will be raised if:
+        - invalid arguments were passed in
+
+        Args:
+            arg: the input dict
+
+        Raises:
+            ApiTypeError - for missing required arguments, or for invalid properties
+        """
+        path_to_schemas = {}
+        additional_properties = getattr(cls.MetaOapg, 'additional_properties', UnsetAnyTypeSchema)
+        properties = getattr(cls.MetaOapg, 'properties', {})
+        property_annotations = getattr(properties, '__annotations__', {})
+        for property_name, value in arg.items():
+            path_to_item = validation_metadata.path_to_item+(property_name,)
+            if property_name in property_annotations:
+                schema = property_annotations[property_name]
+            elif additional_properties is not NotAnyTypeSchema:
+                if additional_properties is UnsetAnyTypeSchema:
+                    """
+                    If additionalProperties is unset and this path_to_item does not yet have
+                    any validations on it, validate it.
+                    If it already has validations on it, skip this validation.
+                    """
+                    if path_to_item in path_to_schemas:
+                        continue
+                schema = additional_properties
+            else:
+                raise ApiTypeError('Unable to find schema for value={} in class={} at path_to_item={}'.format(
+                    value, cls, validation_metadata.path_to_item+(property_name,)
+                ))
+            schema = cls._get_class_oapg(schema)
+            arg_validation_metadata = ValidationMetadata(
+                from_server=validation_metadata.from_server,
+                configuration=validation_metadata.configuration,
+                path_to_item=path_to_item,
+                validated_path_to_schemas=validation_metadata.validated_path_to_schemas
+            )
+            if arg_validation_metadata.validation_ran_earlier(schema):
+                add_deeper_validated_schemas(arg_validation_metadata, path_to_schemas)
+                continue
+            other_path_to_schemas = schema._validate_oapg(value, validation_metadata=arg_validation_metadata)
+            update(path_to_schemas, other_path_to_schemas)
+        return path_to_schemas
+
+    @classmethod
+    def __check_dict_validations(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata
+    ):
+        if not hasattr(cls, 'MetaOapg'):
+            return
+        if (cls._is_json_validation_enabled_oapg('maxProperties', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'max_properties') and
+                len(arg) > cls.MetaOapg.max_properties):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="number of properties must be less than or equal to",
+                constraint_value=cls.MetaOapg.max_properties,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+        if (cls._is_json_validation_enabled_oapg('minProperties', validation_metadata.configuration) and
+                hasattr(cls.MetaOapg, 'min_properties') and
+                len(arg) < cls.MetaOapg.min_properties):
+            cls._raise_validation_error_message_oapg(
+                value=arg,
+                constraint_msg="number of properties must be greater than or equal to",
+                constraint_value=cls.MetaOapg.min_properties,
+                path_to_item=validation_metadata.path_to_item
+            )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        DictBase _validate_oapg
+        We return dynamic classes of different bases depending upon the inputs
+        This makes it so:
+        - the returned instance is always a subclass of our defining schema
+            - this allows us to check type based on whether an instance is a subclass of a schema
+        - the returned instance is a serializable type (except for None, True, and False) which are enums
+
+        Returns:
+            new_cls (type): the new class
+
+        Raises:
+            ApiValueError: when a string can't be converted into a date or datetime and it must be one of those classes
+            ApiTypeError: when the input type is not in the list of allowed spec types
+        """
+        if isinstance(arg, frozendict.frozendict):
+            cls.__check_dict_validations(arg, validation_metadata)
+        _path_to_schemas = super()._validate_oapg(arg, validation_metadata=validation_metadata)
+        if not isinstance(arg, frozendict.frozendict):
+            return _path_to_schemas
+        cls.__validate_arg_presence(arg)
+        other_path_to_schemas = cls.__validate_args(arg, validation_metadata=validation_metadata)
+        update(_path_to_schemas, other_path_to_schemas)
+        try:
+            discriminator = cls.MetaOapg.discriminator()
+        except AttributeError:
+            return _path_to_schemas
+        # discriminator exists
+        disc_prop_name = list(discriminator.keys())[0]
+        cls._ensure_discriminator_value_present_oapg(disc_prop_name, validation_metadata, arg)
+        discriminated_cls = cls.get_discriminated_class_oapg(
+            disc_property_name=disc_prop_name, disc_payload_value=arg[disc_prop_name])
+        if discriminated_cls is None:
+            raise ApiValueError(
+                "Invalid discriminator value was passed in to {}.{} Only the values {} are allowed at {}".format(
+                    cls.__name__,
+                    disc_prop_name,
+                    list(discriminator[disc_prop_name].keys()),
+                    validation_metadata.path_to_item + (disc_prop_name,)
+                )
+            )
+        updated_vm = ValidationMetadata(
+            configuration=validation_metadata.configuration,
+            from_server=validation_metadata.from_server,
+            path_to_item=validation_metadata.path_to_item,
+            seen_classes=validation_metadata.seen_classes | frozenset({cls}),
+            validated_path_to_schemas=validation_metadata.validated_path_to_schemas
+        )
+        if updated_vm.validation_ran_earlier(discriminated_cls):
+            add_deeper_validated_schemas(updated_vm, _path_to_schemas)
+            return _path_to_schemas
+        other_path_to_schemas = discriminated_cls._validate_oapg(arg, validation_metadata=updated_vm)
+        update(_path_to_schemas, other_path_to_schemas)
+        return _path_to_schemas
+
+    @classmethod
+    def _get_properties_oapg(
+        cls,
+        arg: typing.Dict[str, typing.Any],
+        path_to_item: typing.Tuple[typing.Union[str, int], ...],
+        path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Type['Schema']]
+    ):
+        """
+        DictBase _get_properties_oapg, this is how properties are set
+        These values already passed validation
+        """
+        dict_items = {}
+
+        for property_name_js, value in arg.items():
+            property_path_to_item = path_to_item + (property_name_js,)
+            property_cls = path_to_schemas[property_path_to_item]
+            new_value = property_cls._get_new_instance_without_conversion_oapg(
+                value,
+                property_path_to_item,
+                path_to_schemas
+            )
+            dict_items[property_name_js] = new_value
+
+        return dict_items
+
+    def __setattr__(self, name: str, value: typing.Any):
+        if not isinstance(self, FileIO):
+            raise AttributeError('property setting not supported on immutable instances')
+
+    def __getattr__(self, name: str):
+        """
+        for instance.name access
+        Properties are only type hinted for required properties
+        so that hasattr(instance, 'optionalProp') is False when that key is not present
+        """
+        if not isinstance(self, frozendict.frozendict):
+            return super().__getattr__(name)
+        if name not in self.__class__.__annotations__:
+            raise AttributeError(f"{self} has no attribute '{name}'")
+        try:
+            value = self[name]
+            return value
+        except KeyError as ex:
+            raise AttributeError(str(ex))
+
+    def __getitem__(self, name: str):
+        """
+        dict_instance[name] accessor
+        key errors thrown
+        """
+        if not isinstance(self, frozendict.frozendict):
+            return super().__getattr__(name)
+        return super().__getitem__(name)
+
+    def get_item_oapg(self, name: str) -> typing.Union['AnyTypeSchema', Unset]:
+        # dict_instance[name] accessor
+        if not isinstance(self, frozendict.frozendict):
+            raise NotImplementedError()
+        try:
+            return super().__getitem__(name)
+        except KeyError:
+            return unset
+
+
+def cast_to_allowed_types(
+    arg: typing.Union[str, date, datetime, uuid.UUID, decimal.Decimal, int, float, None, dict, frozendict.frozendict, list, tuple, bytes, Schema, io.FileIO, io.BufferedReader],
+    from_server: bool,
+    validated_path_to_schemas: typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]],
+    path_to_item: typing.Tuple[typing.Union[str, int], ...] = tuple(['args[0]']),
+) -> typing.Union[frozendict.frozendict, tuple, decimal.Decimal, str, bytes, BoolClass, NoneClass, FileIO]:
+    """
+    Casts the input payload arg into the allowed types
+    The input validated_path_to_schemas is mutated by running this function
+
+    When from_server is False then
+    - date/datetime is cast to str
+    - int/float is cast to Decimal
+
+    If a Schema instance is passed in it is converted back to a primitive instance because
+    One may need to validate that data to the original Schema class AND additional different classes
+    those additional classes will need to be added to the new manufactured class for that payload
+    If the code didn't do this and kept the payload as a Schema instance it would fail to validate to other
+    Schema classes and the code wouldn't be able to mfg a new class that includes all valid schemas
+    TODO: store the validated schema classes in validation_metadata
+
+    Args:
+        arg: the payload
+        from_server: whether this payload came from the server or not
+        validated_path_to_schemas: a dict that stores the validated classes at any path location in the payload
+    """
+    if isinstance(arg, Schema):
+        # store the already run validations
+        schema_classes = set()
+        for cls in arg.__class__.__bases__:
+            if cls is Singleton:
+                # Skip Singleton
+                continue
+            schema_classes.add(cls)
+        validated_path_to_schemas[path_to_item] = schema_classes
+
+    type_error = ApiTypeError(f"Invalid type. Required value type is str and passed type was {type(arg)} at {path_to_item}")
+    if isinstance(arg, str):
+        return str(arg)
+    elif isinstance(arg, (dict, frozendict.frozendict)):
+        return frozendict.frozendict({key: cast_to_allowed_types(val, from_server, validated_path_to_schemas, path_to_item + (key,)) for key, val in arg.items()})
+    elif isinstance(arg, (bool, BoolClass)):
+        """
+        this check must come before isinstance(arg, (int, float))
+        because isinstance(True, int) is True
+        """
+        if arg:
+            return BoolClass.TRUE
+        return BoolClass.FALSE
+    elif isinstance(arg, int):
+        return decimal.Decimal(arg)
+    elif isinstance(arg, float):
+        decimal_from_float = decimal.Decimal(arg)
+        if decimal_from_float.as_integer_ratio()[1] == 1:
+            # 9.0 -> Decimal('9.0')
+            # 3.4028234663852886e+38 -> Decimal('340282346638528859811704183484516925440.0')
+            return decimal.Decimal(str(decimal_from_float)+'.0')
+        return decimal_from_float
+    elif isinstance(arg, (tuple, list)):
+        return tuple([cast_to_allowed_types(item, from_server, validated_path_to_schemas, path_to_item + (i,)) for i, item in enumerate(arg)])
+    elif isinstance(arg, (none_type, NoneClass)):
+        return NoneClass.NONE
+    elif isinstance(arg, (date, datetime)):
+        if not from_server:
+            return arg.isoformat()
+        raise type_error
+    elif isinstance(arg, uuid.UUID):
+        if not from_server:
+            return str(arg)
+        raise type_error
+    elif isinstance(arg, decimal.Decimal):
+        return decimal.Decimal(arg)
+    elif isinstance(arg, bytes):
+        return bytes(arg)
+    elif isinstance(arg, (io.FileIO, io.BufferedReader)):
+        return FileIO(arg)
+    raise ValueError('Invalid type passed in got input={} type={}'.format(arg, type(arg)))
+
+
+class ComposedBase(Discriminable):
+
+    @classmethod
+    def __get_allof_classes(cls, arg, validation_metadata: ValidationMetadata):
+        path_to_schemas = defaultdict(set)
+        for allof_cls in cls.MetaOapg.all_of():
+            if validation_metadata.validation_ran_earlier(allof_cls):
+                add_deeper_validated_schemas(validation_metadata, path_to_schemas)
+                continue
+            other_path_to_schemas = allof_cls._validate_oapg(arg, validation_metadata=validation_metadata)
+            update(path_to_schemas, other_path_to_schemas)
+        return path_to_schemas
+
+    @classmethod
+    def __get_oneof_class(
+        cls,
+        arg,
+        discriminated_cls,
+        validation_metadata: ValidationMetadata,
+    ):
+        oneof_classes = []
+        path_to_schemas = defaultdict(set)
+        for oneof_cls in cls.MetaOapg.one_of():
+            if oneof_cls in path_to_schemas[validation_metadata.path_to_item]:
+                oneof_classes.append(oneof_cls)
+                continue
+            if validation_metadata.validation_ran_earlier(oneof_cls):
+                oneof_classes.append(oneof_cls)
+                add_deeper_validated_schemas(validation_metadata, path_to_schemas)
+                continue
+            try:
+                path_to_schemas = oneof_cls._validate_oapg(arg, validation_metadata=validation_metadata)
+            except (ApiValueError, ApiTypeError) as ex:
+                if discriminated_cls is not None and oneof_cls is discriminated_cls:
+                    raise ex
+                continue
+            oneof_classes.append(oneof_cls)
+        if not oneof_classes:
+            raise ApiValueError(
+                "Invalid inputs given to generate an instance of {}. None "
+                "of the oneOf schemas matched the input data.".format(cls)
+            )
+        elif len(oneof_classes) > 1:
+            raise ApiValueError(
+                "Invalid inputs given to generate an instance of {}. Multiple "
+                "oneOf schemas {} matched the inputs, but a max of one is allowed.".format(cls, oneof_classes)
+            )
+        # exactly one class matches
+        return path_to_schemas
+
+    @classmethod
+    def __get_anyof_classes(
+        cls,
+        arg,
+        discriminated_cls,
+        validation_metadata: ValidationMetadata
+    ):
+        anyof_classes = []
+        path_to_schemas = defaultdict(set)
+        for anyof_cls in cls.MetaOapg.any_of():
+            if validation_metadata.validation_ran_earlier(anyof_cls):
+                anyof_classes.append(anyof_cls)
+                add_deeper_validated_schemas(validation_metadata, path_to_schemas)
+                continue
+
+            try:
+                other_path_to_schemas = anyof_cls._validate_oapg(arg, validation_metadata=validation_metadata)
+            except (ApiValueError, ApiTypeError) as ex:
+                if discriminated_cls is not None and anyof_cls is discriminated_cls:
+                    raise ex
+                continue
+            anyof_classes.append(anyof_cls)
+            update(path_to_schemas, other_path_to_schemas)
+        if not anyof_classes:
+            raise ApiValueError(
+                "Invalid inputs given to generate an instance of {}. None "
+                "of the anyOf schemas matched the input data.".format(cls)
+            )
+        return path_to_schemas
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ) -> typing.Dict[typing.Tuple[typing.Union[str, int], ...], typing.Set[typing.Union['Schema', str, decimal.Decimal, BoolClass, NoneClass, frozendict.frozendict, tuple]]]:
+        """
+        ComposedBase _validate_oapg
+        We return dynamic classes of different bases depending upon the inputs
+        This makes it so:
+        - the returned instance is always a subclass of our defining schema
+            - this allows us to check type based on whether an instance is a subclass of a schema
+        - the returned instance is a serializable type (except for None, True, and False) which are enums
+
+        Returns:
+            new_cls (type): the new class
+
+        Raises:
+            ApiValueError: when a string can't be converted into a date or datetime and it must be one of those classes
+            ApiTypeError: when the input type is not in the list of allowed spec types
+        """
+        # validation checking on types, validations, and enums
+        path_to_schemas = super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+        updated_vm = ValidationMetadata(
+            configuration=validation_metadata.configuration,
+            from_server=validation_metadata.from_server,
+            path_to_item=validation_metadata.path_to_item,
+            seen_classes=validation_metadata.seen_classes | frozenset({cls}),
+            validated_path_to_schemas=validation_metadata.validated_path_to_schemas
+        )
+
+        # process composed schema
+        discriminator = None
+        if hasattr(cls, 'MetaOapg') and hasattr(cls.MetaOapg, 'discriminator'):
+            discriminator = cls.MetaOapg.discriminator()
+        discriminated_cls = None
+        if discriminator and arg and isinstance(arg, frozendict.frozendict):
+            disc_property_name = list(discriminator.keys())[0]
+            cls._ensure_discriminator_value_present_oapg(disc_property_name, updated_vm, arg)
+            # get discriminated_cls by looking at the dict in the current class
+            discriminated_cls = cls.get_discriminated_class_oapg(
+                disc_property_name=disc_property_name, disc_payload_value=arg[disc_property_name])
+            if discriminated_cls is None:
+                raise ApiValueError(
+                    "Invalid discriminator value '{}' was passed in to {}.{} Only the values {} are allowed at {}".format(
+                        arg[disc_property_name],
+                        cls.__name__,
+                        disc_property_name,
+                        list(discriminator[disc_property_name].keys()),
+                        updated_vm.path_to_item + (disc_property_name,)
+                    )
+                )
+
+        if hasattr(cls, 'MetaOapg') and hasattr(cls.MetaOapg, 'all_of'):
+            other_path_to_schemas = cls.__get_allof_classes(arg, validation_metadata=updated_vm)
+            update(path_to_schemas, other_path_to_schemas)
+        if hasattr(cls, 'MetaOapg') and hasattr(cls.MetaOapg, 'one_of'):
+            other_path_to_schemas = cls.__get_oneof_class(
+                arg,
+                discriminated_cls=discriminated_cls,
+                validation_metadata=updated_vm
+            )
+            update(path_to_schemas, other_path_to_schemas)
+        if hasattr(cls, 'MetaOapg') and hasattr(cls.MetaOapg, 'any_of'):
+            other_path_to_schemas = cls.__get_anyof_classes(
+                arg,
+                discriminated_cls=discriminated_cls,
+                validation_metadata=updated_vm
+            )
+            update(path_to_schemas, other_path_to_schemas)
+        not_cls = None
+        if hasattr(cls, 'MetaOapg') and hasattr(cls.MetaOapg, 'not_schema'):
+            not_cls = cls.MetaOapg.not_schema
+            not_cls = cls._get_class_oapg(not_cls)
+        if not_cls:
+            other_path_to_schemas = None
+            not_exception = ApiValueError(
+                "Invalid value '{}' was passed in to {}. Value is invalid because it is disallowed by {}".format(
+                    arg,
+                    cls.__name__,
+                    not_cls.__name__,
+                )
+            )
+            if updated_vm.validation_ran_earlier(not_cls):
+                raise not_exception
+
+            try:
+                other_path_to_schemas = not_cls._validate_oapg(arg, validation_metadata=updated_vm)
+            except (ApiValueError, ApiTypeError):
+                pass
+            if other_path_to_schemas:
+                raise not_exception
+
+        if discriminated_cls is not None and not updated_vm.validation_ran_earlier(discriminated_cls):
+            # TODO use an exception from this package here
+            add_deeper_validated_schemas(updated_vm, path_to_schemas)
+            assert discriminated_cls in path_to_schemas[updated_vm.path_to_item]
+        return path_to_schemas
+
+
+# DictBase, ListBase, NumberBase, StrBase, BoolBase, NoneBase
+class ComposedSchema(
+    ComposedBase,
+    DictBase,
+    ListBase,
+    NumberBase,
+    StrBase,
+    BoolBase,
+    NoneBase,
+    Schema,
+    NoneFrozenDictTupleStrDecimalBoolMixin
+):
+    @classmethod
+    def from_openapi_data_oapg(cls, *args: typing.Any, _configuration: typing.Optional[Configuration] = None, **kwargs):
+        if not args:
+            if not kwargs:
+                raise ApiTypeError('{} is missing required input data in args or kwargs'.format(cls.__name__))
+            args = (kwargs, )
+        return super().from_openapi_data_oapg(args[0], _configuration=_configuration)
+
+
+class ListSchema(
+    ListBase,
+    Schema,
+    TupleMixin
+):
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: typing.List[typing.Any], _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, _arg: typing.Union[typing.List[typing.Any], typing.Tuple[typing.Any]], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class NoneSchema(
+    NoneBase,
+    Schema,
+    NoneMixin
+):
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: None, _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, _arg: None, **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class NumberSchema(
+    NumberBase,
+    Schema,
+    DecimalMixin
+):
+    """
+    This is used for type: number with no format
+    Both integers AND floats are accepted
+    """
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: typing.Union[int, float], _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, _arg: typing.Union[decimal.Decimal, int, float], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class IntBase:
+    @property
+    def as_int_oapg(self) -> int:
+        try:
+            return self._as_int
+        except AttributeError:
+            self._as_int = int(self)
+            return self._as_int
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[decimal.Decimal], validation_metadata: ValidationMetadata):
+        if isinstance(arg, decimal.Decimal):
+
+            denominator = arg.as_integer_ratio()[-1]
+            if denominator != 1:
+                raise ApiValueError(
+                    "Invalid value '{}' for type integer at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        IntBase _validate_oapg
+        TODO what about types = (int, number) -> IntBase, NumberBase? We could drop int and keep number only
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class IntSchema(IntBase, NumberSchema):
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: int, _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, _arg: typing.Union[decimal.Decimal, int], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class Int32Base:
+    __inclusive_minimum = decimal.Decimal(-2147483648)
+    __inclusive_maximum = decimal.Decimal(2147483647)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[decimal.Decimal], validation_metadata: ValidationMetadata):
+        if isinstance(arg, decimal.Decimal) and arg.as_tuple().exponent == 0:
+            if not cls.__inclusive_minimum <= arg <= cls.__inclusive_maximum:
+                raise ApiValueError(
+                    "Invalid value '{}' for type int32 at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        Int32Base _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class Int32Schema(
+    Int32Base,
+    IntSchema
+):
+    pass
+
+
+class Int64Base:
+    __inclusive_minimum = decimal.Decimal(-9223372036854775808)
+    __inclusive_maximum = decimal.Decimal(9223372036854775807)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[decimal.Decimal], validation_metadata: ValidationMetadata):
+        if isinstance(arg, decimal.Decimal) and arg.as_tuple().exponent == 0:
+            if not cls.__inclusive_minimum <= arg <= cls.__inclusive_maximum:
+                raise ApiValueError(
+                    "Invalid value '{}' for type int64 at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        Int64Base _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class Int64Schema(
+    Int64Base,
+    IntSchema
+):
+    pass
+
+
+class Float32Base:
+    __inclusive_minimum = decimal.Decimal(-3.4028234663852886e+38)
+    __inclusive_maximum = decimal.Decimal(3.4028234663852886e+38)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[decimal.Decimal], validation_metadata: ValidationMetadata):
+        if isinstance(arg, decimal.Decimal):
+            if not cls.__inclusive_minimum <= arg <= cls.__inclusive_maximum:
+                raise ApiValueError(
+                    "Invalid value '{}' for type float at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        Float32Base _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+
+class Float32Schema(
+    Float32Base,
+    NumberSchema
+):
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: float, _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+
+class Float64Base:
+    __inclusive_minimum = decimal.Decimal(-1.7976931348623157E+308)
+    __inclusive_maximum = decimal.Decimal(1.7976931348623157E+308)
+
+    @classmethod
+    def __validate_format(cls, arg: typing.Optional[decimal.Decimal], validation_metadata: ValidationMetadata):
+        if isinstance(arg, decimal.Decimal):
+            if not cls.__inclusive_minimum <= arg <= cls.__inclusive_maximum:
+                raise ApiValueError(
+                    "Invalid value '{}' for type double at {}".format(arg, validation_metadata.path_to_item)
+                )
+
+    @classmethod
+    def _validate_oapg(
+        cls,
+        arg,
+        validation_metadata: ValidationMetadata,
+    ):
+        """
+        Float64Base _validate_oapg
+        """
+        cls.__validate_format(arg, validation_metadata=validation_metadata)
+        return super()._validate_oapg(arg, validation_metadata=validation_metadata)
+
+class Float64Schema(
+    Float64Base,
+    NumberSchema
+):
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: float, _configuration: typing.Optional[Configuration] = None):
+        # todo check format
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+
+class StrSchema(
+    StrBase,
+    Schema,
+    StrMixin
+):
+    """
+    date + datetime string types must inherit from this class
+    That is because one can validate a str payload as both:
+    - type: string (format unset)
+    - type: string, format: date
+    """
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: str, _configuration: typing.Optional[Configuration] = None) -> 'StrSchema':
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, _arg: typing.Union[str, date, datetime, uuid.UUID], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class UUIDSchema(UUIDBase, StrSchema):
+
+    def __new__(cls, _arg: typing.Union[str, uuid.UUID], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class DateSchema(DateBase, StrSchema):
+
+    def __new__(cls, _arg: typing.Union[str, date], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class DateTimeSchema(DateTimeBase, StrSchema):
+
+    def __new__(cls, _arg: typing.Union[str, datetime], **kwargs: Configuration):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class DecimalSchema(DecimalBase, StrSchema):
+
+    def __new__(cls, _arg: str, **kwargs: Configuration):
+        """
+        Note: Decimals may not be passed in because cast_to_allowed_types is only invoked once for payloads
+        which can be simple (str) or complex (dicts or lists with nested values)
+        Because casting is only done once and recursively casts all values prior to validation then for a potential
+        client side Decimal input if Decimal was accepted as an input in DecimalSchema then one would not know
+        if one was using it for a StrSchema (where it should be cast to str) or one is using it for NumberSchema
+        where it should stay as Decimal.
+        """
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class BytesSchema(
+    Schema,
+    BytesMixin
+):
+    """
+    this class will subclass bytes and is immutable
+    """
+    def __new__(cls, _arg: bytes, **kwargs: Configuration):
+        return super(Schema, cls).__new__(cls, _arg)
+
+
+class FileSchema(
+    Schema,
+    FileMixin
+):
+    """
+    This class is NOT immutable
+    Dynamic classes are built using it for example when AnyType allows in binary data
+    Al other schema classes ARE immutable
+    If one wanted to make this immutable one could make this a DictSchema with required properties:
+    - data = BytesSchema (which would be an immutable bytes based schema)
+    - file_name = StrSchema
+    and cast_to_allowed_types would convert bytes and file instances into dicts containing data + file_name
+    The downside would be that data would be stored in memory which one may not want to do for very large files
+
+    The developer is responsible for closing this file and deleting it
+
+    This class was kept as mutable:
+    - to allow file reading and writing to disk
+    - to be able to preserve file name info
+    """
+
+    def __new__(cls, _arg: typing.Union[io.FileIO, io.BufferedReader], **kwargs: Configuration):
+        return super(Schema, cls).__new__(cls, _arg)
+
+
+class BinaryBase:
+    pass
+
+
+class BinarySchema(
+    ComposedBase,
+    BinaryBase,
+    Schema,
+    BinaryMixin
+):
+    class MetaOapg:
+        @staticmethod
+        def one_of():
+            return [
+                BytesSchema,
+                FileSchema,
+            ]
+
+    def __new__(cls, _arg: typing.Union[io.FileIO, io.BufferedReader, bytes], **kwargs: Configuration):
+        return super().__new__(cls, _arg)
+
+
+class BoolSchema(
+    BoolBase,
+    Schema,
+    BoolMixin
+):
+
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: bool, _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, _arg: bool, **kwargs: ValidationMetadata):
+        return super().__new__(cls, _arg, **kwargs)
+
+
+class AnyTypeSchema(
+    DictBase,
+    ListBase,
+    NumberBase,
+    StrBase,
+    BoolBase,
+    NoneBase,
+    Schema,
+    NoneFrozenDictTupleStrDecimalBoolFileBytesMixin
+):
+    # Python representation of a schema defined as true or {}
+    pass
+
+
+class UnsetAnyTypeSchema(AnyTypeSchema):
+    # Used when additionalProperties/items was not explicitly defined and a defining schema is needed
+    pass
+
+
+class NotAnyTypeSchema(
+    ComposedSchema,
+):
+    """
+    Python representation of a schema defined as false or {'not': {}}
+    Does not allow inputs in of AnyType
+    Note: validations on this class are never run because the code knows that no inputs will ever validate
+    """
+
+    class MetaOapg:
+        not_schema = AnyTypeSchema
+
+    def __new__(
+        cls,
+        *_args,
+        _configuration: typing.Optional[Configuration] = None,
+    ) -> 'NotAnyTypeSchema':
+        return super().__new__(
+            cls,
+            *_args,
+            _configuration=_configuration,
+        )
+
+
+class DictSchema(
+    DictBase,
+    Schema,
+    FrozenDictMixin
+):
+    @classmethod
+    def from_openapi_data_oapg(cls, arg: typing.Dict[str, typing.Any], _configuration: typing.Optional[Configuration] = None):
+        return super().from_openapi_data_oapg(arg, _configuration=_configuration)
+
+    def __new__(cls, *_args: typing.Union[dict, frozendict.frozendict], **kwargs: typing.Union[dict, frozendict.frozendict, list, tuple, decimal.Decimal, float, int, str, date, datetime, bool, None, bytes, Schema, Unset, ValidationMetadata]):
+        return super().__new__(cls, *_args, **kwargs)
+
+
+schema_type_classes = {NoneSchema, DictSchema, ListSchema, NumberSchema, StrSchema, BoolSchema, AnyTypeSchema}
+
+
+@functools.lru_cache()
+def get_new_class(
+    class_name: str,
+    bases: typing.Tuple[typing.Type[typing.Union[Schema, typing.Any]], ...]
+) -> typing.Type[Schema]:
+    """
+    Returns a new class that is made with the subclass bases
+    """
+    new_cls: typing.Type[Schema] = type(class_name, bases, {})
+    return new_cls
+
+
+LOG_CACHE_USAGE = False
+
+
+def log_cache_usage(cache_fn):
+    if LOG_CACHE_USAGE:
+        print(cache_fn.__name__, cache_fn.cache_info())
\ No newline at end of file
diff --git a/turbinia/api/openapi.yaml b/turbinia/api/openapi.yaml
index 5323dca47..952595e88 100644
--- a/turbinia/api/openapi.yaml
+++ b/turbinia/api/openapi.yaml
@@ -11,69 +11,47 @@ components:
           scopes: {}
   schemas:
     BaseRequestOptions:
-      description: "Base Request Options class to be extended by other option types. "
+      description: 'Base Request Options class to be extended by other option types. '
       properties:
         filter_patterns:
-          anyOf:
-            - items:
-                type: string
-              type: array
-            - type: "null"
+          items:
+            type: string
           title: Filter Patterns
+          type: array
         group_id:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Group Id
+          type: string
         jobs_allowlist:
-          anyOf:
-            - items:
-                type: string
-              type: array
-            - type: "null"
+          items:
+            type: string
           title: Jobs Allowlist
+          type: array
         jobs_denylist:
-          anyOf:
-            - items:
-                type: string
-              type: array
-            - type: "null"
+          items:
+            type: string
           title: Jobs Denylist
+          type: array
         reason:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Reason
+          type: string
         recipe_data:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Recipe Data
+          type: string
         recipe_name:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Recipe Name
+          type: string
         request_id:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Request Id
+          type: string
         requester:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Requester
+          type: string
         sketch_id:
-          anyOf:
-            - type: integer
-            - type: "null"
           title: Sketch Id
+          type: integer
         yara_rules:
-          anyOf:
-            - type: string
-            - type: "null"
           title: Yara Rules
+          type: string
       title: BaseRequestOptions
       type: object
     Body_upload_evidence_api_evidence_upload_post:
@@ -92,8 +70,8 @@ components:
           title: Ticket Id
           type: string
       required:
-        - ticket_id
-        - files
+      - ticket_id
+      - files
       title: Body_upload_evidence_api_evidence_upload_post
       type: object
     CompleteTurbiniaStats:
@@ -127,42 +105,32 @@ components:
           default: {}
           title: Tasks Per Worker
           type: object
-      required:
-        - all_tasks
-        - successful_tasks
-        - failed_tasks
-        - requests
-        - tasks_per_type
-        - tasks_per_worker
-        - tasks_per_user
       title: CompleteTurbiniaStats
       type: object
     HTTPValidationError:
       properties:
         detail:
           items:
-            $ref: "#/components/schemas/ValidationError"
+            $ref: '#/components/schemas/ValidationError'
           title: Detail
           type: array
       title: HTTPValidationError
       type: object
     Request:
-      description: "Base request object. "
+      description: 'Base request object. '
       properties:
         description:
-          anyOf:
-            - type: string
-            - type: "null"
           default: Turbinia request object
           title: Description
+          type: string
         evidence:
           title: Evidence
           type: object
         request_options:
-          $ref: "#/components/schemas/BaseRequestOptions"
+          $ref: '#/components/schemas/BaseRequestOptions'
       required:
-        - evidence
-        - request_options
+      - evidence
+      - request_options
       title: Request
       type: object
     ValidationError:
@@ -170,8 +138,8 @@ components:
         loc:
           items:
             anyOf:
-              - type: string
-              - type: integer
+            - type: string
+            - type: integer
           title: Location
           type: array
         msg:
@@ -181,50 +149,50 @@ components:
           title: Error Type
           type: string
       required:
-        - loc
-        - msg
-        - type
+      - loc
+      - msg
+      - type
       title: ValidationError
       type: object
 info:
-  description: Turbinia API server
+  description: Turbinia is an open-source framework for deploying, managing, and running
+    distributed forensic workloads
   license:
     name: Apache License 2.0
     url: https://www.apache.org/licenses/LICENSE-2.0.html
   title: Turbinia API Server
   version: 1.0.0
-openapi: 3.1.0
+openapi: 3.0.2
 paths:
   /api/config/:
     get:
       description: Retrieve turbinia config.
       operationId: read_config
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
       summary: Read Config
       tags:
-        - Turbinia Configuration
+      - Turbinia Configuration
   /api/config/request_options:
     get:
       description: Returns a list BaseRequestOptions attributes.
       operationId: get_request_options
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
       summary: Get Request Options
       tags:
-        - Turbinia Configuration
+      - Turbinia Configuration
   /api/evidence/query:
     get:
-      description:
-        "Queries evidence in Redis that have the specified attribute value.\n\
+      description: "Queries evidence in Redis that have the specified attribute value.\n\
         \nArgs:\n  attribute_name (str): Name of attribute to be queried.\n  attribute_value\
         \ (str): Value the attribute must have.\n  output Optional(str): Sets how\
         \ the evidence found will be output.\n\nReturns:\n  summary (dict): Summary\
@@ -232,176 +200,173 @@ paths:
         \ evidence is found."
       operationId: query_evidence
       parameters:
-        - in: query
-          name: attribute_name
-          required: false
-          schema:
-            default: request_id
-            enum:
-              - _name
-              - cloud_only
-              - context_dependent
-              - copyable
-              - creation_time
-              - description
-              - has_child_evidence
-              - last_update
-              - local_path
-              - mount_path
-              - parent_evidence
-              - request_id
-              - resource_id
-              - resource_tracked
-              - save_metadata
-              - saved_path
-              - saved_path_type
-              - size
-              - source
-              - source_path
-              - type
-              - tasks
-            title: Attribute Name
-            type: string
-        - in: query
-          name: attribute_value
-          required: true
-          schema:
-            title: Attribute Value
-            type: string
-        - in: query
-          name: output
-          required: false
-          schema:
-            default: keys
-            enum:
-              - keys
-              - content
-              - count
-            title: Output
-            type: string
+      - in: query
+        name: attribute_name
+        required: false
+        schema:
+          default: request_id
+          enum:
+          - _name
+          - cloud_only
+          - context_dependent
+          - copyable
+          - creation_time
+          - description
+          - has_child_evidence
+          - last_update
+          - local_path
+          - mount_path
+          - parent_evidence
+          - request_id
+          - resource_id
+          - resource_tracked
+          - save_metadata
+          - saved_path
+          - saved_path_type
+          - size
+          - source
+          - source_path
+          - type
+          - tasks
+          title: Attribute Name
+          type: string
+      - in: query
+        name: attribute_value
+        required: true
+        schema:
+          title: Attribute Value
+          type: string
+      - in: query
+        name: output
+        required: false
+        schema:
+          default: keys
+          enum:
+          - keys
+          - content
+          - count
+          title: Output
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Query Evidence
       tags:
-        - Turbinia Evidence
+      - Turbinia Evidence
   /api/evidence/summary:
     get:
-      description:
-        "Retrieves a summary of all evidences in Redis.\n\nArgs:\n  group\
+      description: "Retrieves a summary of all evidences in Redis.\n\nArgs:\n  group\
         \ Optional(str): Attribute used to group summary.\n  output Optional(str):\
         \ Sets how the evidence found will be output. \n\nReturns:\n  summary (dict):\
         \ Summary of all evidences and their content.\n\nRaises:\n  HTTPException:\
         \ if there are no evidences."
       operationId: get_evidence_summary
       parameters:
-        - in: query
-          name: group
-          required: false
-          schema:
-            enum:
-              - _name
-              - cloud_only
-              - context_dependent
-              - copyable
-              - creation_time
-              - description
-              - has_child_evidence
-              - last_update
-              - local_path
-              - mount_path
-              - parent_evidence
-              - request_id
-              - resource_id
-              - resource_tracked
-              - save_metadata
-              - saved_path
-              - saved_path_type
-              - size
-              - source
-              - source_path
-              - type
-            title: Group
-            type: string
-        - in: query
-          name: output
-          required: false
-          schema:
-            default: keys
-            enum:
-              - keys
-              - content
-              - count
-            title: Output
-            type: string
+      - in: query
+        name: group
+        required: false
+        schema:
+          enum:
+          - _name
+          - cloud_only
+          - context_dependent
+          - copyable
+          - creation_time
+          - description
+          - has_child_evidence
+          - last_update
+          - local_path
+          - mount_path
+          - parent_evidence
+          - request_id
+          - resource_id
+          - resource_tracked
+          - save_metadata
+          - saved_path
+          - saved_path_type
+          - size
+          - source
+          - source_path
+          - type
+          title: Group
+          type: string
+      - in: query
+        name: output
+        required: false
+        schema:
+          default: keys
+          enum:
+          - keys
+          - content
+          - count
+          title: Output
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Evidence Summary
       tags:
-        - Turbinia Evidence
+      - Turbinia Evidence
   /api/evidence/types:
     get:
       description: Returns supported Evidence object types and required parameters.
       operationId: get_evidence_types
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
       summary: Get Evidence Types
       tags:
-        - Turbinia Evidence
+      - Turbinia Evidence
   /api/evidence/types/{evidence_type}:
     get:
-      description:
-        "Returns supported required parameters for evidence type.\n\nArgs:\n\
+      description: "Returns supported required parameters for evidence type.\n\nArgs:\n\
         \  evidence_type (str): Name of evidence type."
       operationId: get_evidence_attributes
       parameters:
-        - in: path
-          name: evidence_type
-          required: true
-          schema:
-            title: Evidence Type
+      - in: path
+        name: evidence_type
+        required: true
+        schema:
+          title: Evidence Type
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Evidence Attributes
       tags:
-        - Turbinia Evidence
+      - Turbinia Evidence
   /api/evidence/upload:
     post:
-      description:
-        "Upload evidence file to server for processing.\n\nArgs:\n  ticket_id\
+      description: "Upload evidence file to server for processing.\n\nArgs:\n  ticket_id\
         \ (str): ID of the ticket, which will be the name of the folder \n    where\
         \ the evidence will be saved.\n  calculate_hash (bool): Boolean defining if\
         \ the hash of the evidence should\n    be calculated.\n  file (List[UploadFile]):\
@@ -413,94 +378,92 @@ paths:
         content:
           multipart/form-data:
             schema:
-              $ref: "#/components/schemas/Body_upload_evidence_api_evidence_upload_post"
+              $ref: '#/components/schemas/Body_upload_evidence_api_evidence_upload_post'
         required: true
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Upload Evidence
       tags:
-        - Turbinia Evidence
+      - Turbinia Evidence
   /api/evidence/{evidence_id}:
     get:
-      description:
-        "Retrieves an evidence in Redis by using its UUID.\n\nArgs:\n \
+      description: "Retrieves an evidence in Redis by using its UUID.\n\nArgs:\n \
         \ evidence_id (str): The UUID of the evidence.\n\nRaises:\n  HTTPException:\
         \ if the evidence is not found.\n\nReturns:\n  Dictionary of the stored evidence"
       operationId: get_evidence_by_id
       parameters:
-        - in: path
-          name: evidence_id
-          required: true
-          schema:
-            title: Evidence Id
+      - in: path
+        name: evidence_id
+        required: true
+        schema:
+          title: Evidence Id
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Evidence By Id
       tags:
-        - Turbinia Evidence
+      - Turbinia Evidence
   /api/jobs/:
     get:
       description: Return enabled jobs from the current Turbinia config.
       operationId: read_jobs
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
       summary: Read Jobs
       tags:
-        - Turbinia Jobs
+      - Turbinia Jobs
   /api/logs/{query}:
     get:
       description: Retrieve log data.
       operationId: get_logs
       parameters:
-        - in: path
-          name: query
-          required: true
-          schema:
-            title: Query
-            type: string
+      - in: path
+        name: query
+        required: true
+        schema:
+          title: Query
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Logs
       tags:
-        - Turbinia Logs
+      - Turbinia Logs
   /api/request/:
     post:
-      description:
-        "Create a new Turbinia request.\n\nArgs:\n  request (Request):\
+      description: "Create a new Turbinia request.\n\nArgs:\n  request (Request):\
         \ FastAPI request object.\n  req (turbinia.api.schema.request): JSON object\
         \ from the HTTP POST data\n      matching the schema defined for a Turbinia\
         \ Request. The schema is used\n      by pydantic for field validation.\n\n\
@@ -511,237 +474,233 @@ paths:
         content:
           application/json:
             schema:
-              $ref: "#/components/schemas/Request"
+              $ref: '#/components/schemas/Request'
         required: true
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Create Request
       tags:
-        - Turbinia Requests
+      - Turbinia Requests
   /api/request/summary:
     get:
-      description:
-        "Retrieves a summary of all Turbinia requests.\n\nThe response\
+      description: "Retrieves a summary of all Turbinia requests.\n\nThe response\
         \ is validated against the RequestSummary model.\n\nRaises:\n  HTTPException:\
         \ if another exception is caught."
       operationId: get_requests_summary
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
       summary: Get Requests Summary
       tags:
-        - Turbinia Requests
+      - Turbinia Requests
   /api/request/{request_id}:
     get:
-      description:
-        "Retrieves status for a Turbinia Request.\n\nArgs:\n  request (Request):\
+      description: "Retrieves status for a Turbinia Request.\n\nArgs:\n  request (Request):\
         \ FastAPI request object.\n  request_id (str): A Turbinia request identifier.\n\
         \nRaises:\n  HTTPException: if another exception is caught."
       operationId: get_request_status
       parameters:
-        - in: path
-          name: request_id
-          required: true
-          schema:
-            title: Request Id
-            type: string
+      - in: path
+        name: request_id
+        required: true
+        schema:
+          title: Request Id
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Request Status
       tags:
-        - Turbinia Requests
+      - Turbinia Requests
   /api/result/request/{request_id}:
     get:
       description: Retrieve request output.
       operationId: get_request_output
       parameters:
-        - in: path
-          name: request_id
-          required: true
-          schema:
-            title: Request Id
-            type: string
+      - in: path
+        name: request_id
+        required: true
+        schema:
+          title: Request Id
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/octet-stream:
               schema:
                 format: binary
                 type: string
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Request Output
       tags:
-        - Turbinia Request Results
+      - Turbinia Request Results
   /api/result/task/{task_id}:
     get:
       description: Retrieves a task's output files.
       operationId: get_task_output
       parameters:
-        - in: path
-          name: task_id
-          required: true
-          schema:
-            title: Task Id
-            type: string
+      - in: path
+        name: task_id
+        required: true
+        schema:
+          title: Task Id
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/octet-stream:
               schema:
                 format: binary
                 type: string
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Task Output
       tags:
-        - Turbinia Request Results
+      - Turbinia Request Results
   /api/task/statistics:
     get:
-      description:
-        "Retrieves  statistics for Turbinia execution.\n\nArgs:\n  days\
+      description: "Retrieves  statistics for Turbinia execution.\n\nArgs:\n  days\
         \ (int): The number of days we want history for.\n  task_id (string): The\
         \ Id of the task.\n  request_id (string): The Id of the request we want tasks\
         \ for.\n  user (string): The user of the request we want tasks for.\n\nReturns:\n\
         \  statistics (str): JSON-formatted task statistics report."
       operationId: get_task_statistics
       parameters:
-        - in: query
-          name: days
-          required: false
-          schema:
-            title: Days
-            type: integer
-        - in: query
-          name: task_id
-          required: false
-          schema:
-            title: Task Id
-            type: string
-        - in: query
-          name: request_id
-          required: false
-          schema:
-            title: Request Id
-            type: string
-        - in: query
-          name: user
-          required: false
-          schema:
-            title: User
-            type: string
+      - in: query
+        name: days
+        required: false
+        schema:
+          title: Days
+          type: integer
+      - in: query
+        name: task_id
+        required: false
+        schema:
+          title: Task Id
+          type: string
+      - in: query
+        name: request_id
+        required: false
+        schema:
+          title: Request Id
+          type: string
+      - in: query
+        name: user
+        required: false
+        schema:
+          title: User
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/CompleteTurbiniaStats"
+                $ref: '#/components/schemas/CompleteTurbiniaStats'
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Task Statistics
       tags:
-        - Turbinia Tasks
+      - Turbinia Tasks
   /api/task/workers:
     get:
-      description:
-        "Retrieves the workers status.\n\nArgs:\n  days (int): The UUID\
+      description: "Retrieves the workers status.\n\nArgs:\n  days (int): The UUID\
         \ of the evidence.\n  all_fields (bool): Returns all status fields if set\
         \ to true.\n\nReturns:\n  workers_status (str): JSON-formatted workers status.\n\
         \nRaises:\n  HTTPException: if no worker is found."
       operationId: get_workers_status
       parameters:
-        - in: query
-          name: days
-          required: false
-          schema:
-            default: 7
-            title: Days
-            type: integer
-        - in: query
-          name: all_fields
-          required: false
-          schema:
-            default: false
-            title: All Fields
-            type: boolean
+      - in: query
+        name: days
+        required: false
+        schema:
+          default: 7
+          title: Days
+          type: integer
+      - in: query
+        name: all_fields
+        required: false
+        schema:
+          default: false
+          title: All Fields
+          type: boolean
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Workers Status
       tags:
-        - Turbinia Tasks
+      - Turbinia Tasks
   /api/task/{task_id}:
     get:
       description: Retrieve task information.
       operationId: get_task_status
       parameters:
-        - in: path
-          name: task_id
-          required: true
-          schema:
-            title: Task Id
-            type: string
+      - in: path
+        name: task_id
+        required: true
+        schema:
+          title: Task Id
+          type: string
       responses:
-        "200":
+        '200':
           content:
             application/json:
               schema: {}
           description: Successful Response
-        "422":
+        '422':
           content:
             application/json:
               schema:
-                $ref: "#/components/schemas/HTTPValidationError"
+                $ref: '#/components/schemas/HTTPValidationError'
           description: Validation Error
       summary: Get Task Status
       tags:
-        - Turbinia Tasks
+      - Turbinia Tasks
 security:
   - oAuth2: []
diff --git a/turbinia/api/routes/request.py b/turbinia/api/routes/request.py
index 16c62cb28..b6141a85b 100644
--- a/turbinia/api/routes/request.py
+++ b/turbinia/api/routes/request.py
@@ -31,7 +31,7 @@
 
 log = logging.getLogger('turbinia')
 
-router = APIRouter(prefix="/request", tags=["Turbinia Requests"])
+router = APIRouter(prefix='/request', tags=['Turbinia Requests'])
 
 
 @router.get('/summary')
@@ -48,7 +48,7 @@ async def get_requests_summary(request: Request):
     if not requests_summary.get_requests_summary():
       return JSONResponse(
           content={'detail': 'Request summary is empty'}, status_code=200)
-    response_json = requests_summary.model_dump_json()
+    response_json = requests_summary.json()
     response = OrderedDict(sorted(json.loads(response_json).items()))
     return JSONResponse(
         status_code=200, content=response, media_type='application/json')
@@ -78,7 +78,7 @@ async def get_request_status(request: Request, request_id: str):
       raise HTTPException(
           status_code=404,
           detail='Request ID not found or the request had no associated tasks.')
-    response_json = request_out.model_dump_json()
+    response_json = request_out.json()
     response = OrderedDict(sorted(json.loads(response_json).items()))
     return JSONResponse(
         status_code=200, content=response, media_type='application/json')


Test patch:
diff --git a/turbinia/api/client/test/test_body_upload_evidence_api_evidence_upload_post.py b/turbinia/api/client/test/test_body_upload_evidence_api_evidence_upload_post.py
new file mode 100644
index 000000000..e752e54dd
--- /dev/null
+++ b/turbinia/api/client/test/test_body_upload_evidence_api_evidence_upload_post.py
@@ -0,0 +1,58 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia API server
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+    Do not edit the class manually.
+"""  # noqa: E501
+
+
+import unittest
+import datetime
+
+import turbinia_api_lib
+from turbinia_api_lib.models.body_upload_evidence_api_evidence_upload_post import BodyUploadEvidenceApiEvidenceUploadPost  # noqa: E501
+from turbinia_api_lib.rest import ApiException
+
+class TestBodyUploadEvidenceApiEvidenceUploadPost(unittest.TestCase):
+    """BodyUploadEvidenceApiEvidenceUploadPost unit test stubs"""
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def make_instance(self, include_optional):
+        """Test BodyUploadEvidenceApiEvidenceUploadPost
+            include_option is a boolean, when False only required
+            params are included, when True both required and
+            optional params are included """
+        # uncomment below to create an instance of `BodyUploadEvidenceApiEvidenceUploadPost`
+        """
+        model = turbinia_api_lib.models.body_upload_evidence_api_evidence_upload_post.BodyUploadEvidenceApiEvidenceUploadPost()  # noqa: E501
+        if include_optional :
+            return BodyUploadEvidenceApiEvidenceUploadPost(
+                calculate_hash = None, 
+                files = None, 
+                ticket_id = None
+            )
+        else :
+            return BodyUploadEvidenceApiEvidenceUploadPost(
+                files = None,
+                ticket_id = None,
+        )
+        """
+
+    def testBodyUploadEvidenceApiEvidenceUploadPost(self):
+        """Test BodyUploadEvidenceApiEvidenceUploadPost"""
+        # inst_req_only = self.make_instance(include_optional=False)
+        # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_location_inner.py b/turbinia/api/client/test/test_location_inner.py
new file mode 100644
index 000000000..8c845e04b
--- /dev/null
+++ b/turbinia/api/client/test/test_location_inner.py
@@ -0,0 +1,51 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+    Do not edit the class manually.
+"""  # noqa: E501
+
+
+import unittest
+import datetime
+
+from turbinia_api_lib.models.location_inner import LocationInner  # noqa: E501
+
+class TestLocationInner(unittest.TestCase):
+    """LocationInner unit test stubs"""
+
+    def setUp(self):
+        pass
+
+    def tearDown(self):
+        pass
+
+    def make_instance(self, include_optional) -> LocationInner:
+        """Test LocationInner
+            include_option is a boolean, when False only required
+            params are included, when True both required and
+            optional params are included """
+        # uncomment below to create an instance of `LocationInner`
+        """
+        model = LocationInner()  # noqa: E501
+        if include_optional:
+            return LocationInner(
+            )
+        else:
+            return LocationInner(
+        )
+        """
+
+    def testLocationInner(self):
+        """Test LocationInner"""
+        # inst_req_only = self.make_instance(include_optional=False)
+        # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_models/__init__.py b/turbinia/api/client/test/test_models/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_models/test_base_request_options.py b/turbinia/api/client/test/test_models/test_base_request_options.py
new file mode 100644
index 000000000..745ef6f17
--- /dev/null
+++ b/turbinia/api/client/test/test_models/test_base_request_options.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+
+import turbinia_api_lib
+from turbinia_api_lib.model.base_request_options import BaseRequestOptions
+from turbinia_api_lib import configuration
+
+
+class TestBaseRequestOptions(unittest.TestCase):
+    """BaseRequestOptions unit test stubs"""
+    _configuration = configuration.Configuration()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_models/test_complete_turbinia_stats.py b/turbinia/api/client/test/test_models/test_complete_turbinia_stats.py
new file mode 100644
index 000000000..3bbb25c16
--- /dev/null
+++ b/turbinia/api/client/test/test_models/test_complete_turbinia_stats.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+
+import turbinia_api_lib
+from turbinia_api_lib.model.complete_turbinia_stats import CompleteTurbiniaStats
+from turbinia_api_lib import configuration
+
+
+class TestCompleteTurbiniaStats(unittest.TestCase):
+    """CompleteTurbiniaStats unit test stubs"""
+    _configuration = configuration.Configuration()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_models/test_http_validation_error.py b/turbinia/api/client/test/test_models/test_http_validation_error.py
new file mode 100644
index 000000000..086b4888f
--- /dev/null
+++ b/turbinia/api/client/test/test_models/test_http_validation_error.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+
+import turbinia_api_lib
+from turbinia_api_lib.model.http_validation_error import HTTPValidationError
+from turbinia_api_lib import configuration
+
+
+class TestHTTPValidationError(unittest.TestCase):
+    """HTTPValidationError unit test stubs"""
+    _configuration = configuration.Configuration()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_models/test_request.py b/turbinia/api/client/test/test_models/test_request.py
new file mode 100644
index 000000000..790833f50
--- /dev/null
+++ b/turbinia/api/client/test/test_models/test_request.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+
+import turbinia_api_lib
+from turbinia_api_lib.model.request import Request
+from turbinia_api_lib import configuration
+
+
+class TestRequest(unittest.TestCase):
+    """Request unit test stubs"""
+    _configuration = configuration.Configuration()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_models/test_validation_error.py b/turbinia/api/client/test/test_models/test_validation_error.py
new file mode 100644
index 000000000..415c9b755
--- /dev/null
+++ b/turbinia/api/client/test/test_models/test_validation_error.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+"""
+    Turbinia API Server
+
+    Turbinia is an open-source framework for deploying,managing, and running distributed forensic workloads  # noqa: E501
+
+    The version of the OpenAPI document: 1.0.0
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+
+import turbinia_api_lib
+from turbinia_api_lib.model.validation_error import ValidationError
+from turbinia_api_lib import configuration
+
+
+class TestValidationError(unittest.TestCase):
+    """ValidationError unit test stubs"""
+    _configuration = configuration.Configuration()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/__init__.py b/turbinia/api/client/test/test_paths/__init__.py
new file mode 100644
index 000000000..1309632d3
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/__init__.py
@@ -0,0 +1,68 @@
+import json
+import typing
+
+import urllib3
+from urllib3._collections import HTTPHeaderDict
+
+
+class ApiTestMixin:
+    json_content_type = 'application/json'
+    user_agent = 'OpenAPI-Generator/1.0.0/python'
+
+    @classmethod
+    def assert_pool_manager_request_called_with(
+        cls,
+        mock_request,
+        url: str,
+        method: str = 'POST',
+        body: typing.Optional[bytes] = None,
+        content_type: typing.Optional[str] = None,
+        accept_content_type: typing.Optional[str] = None,
+        stream: bool = False,
+    ):
+        headers = {
+            'User-Agent': cls.user_agent
+        }
+        if accept_content_type:
+            headers['Accept'] = accept_content_type
+        if content_type:
+            headers['Content-Type'] = content_type
+        kwargs = dict(
+            headers=HTTPHeaderDict(headers),
+            preload_content=not stream,
+            timeout=None,
+        )
+        if content_type and method != 'GET':
+            kwargs['body'] = body
+        mock_request.assert_called_with(
+            method,
+            url,
+            **kwargs
+        )
+
+    @staticmethod
+    def headers_for_content_type(content_type: str) -> typing.Dict[str, str]:
+        return {'content-type': content_type}
+
+    @classmethod
+    def response(
+        cls,
+        body: typing.Union[str, bytes],
+        status: int = 200,
+        content_type: str = json_content_type,
+        headers: typing.Optional[typing.Dict[str, str]] = None,
+        preload_content: bool = True
+    ) -> urllib3.HTTPResponse:
+        if headers is None:
+            headers = {}
+        headers.update(cls.headers_for_content_type(content_type))
+        return urllib3.HTTPResponse(
+            body,
+            headers=headers,
+            status=status,
+            preload_content=preload_content
+        )
+
+    @staticmethod
+    def json_bytes(in_data: typing.Any) -> bytes:
+        return json.dumps(in_data, separators=(",", ":"), ensure_ascii=False).encode('utf-8')
diff --git a/turbinia/api/client/test/test_paths/test_api_config_/__init__.py b/turbinia/api/client/test/test_paths/test_api_config_/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_config_/test_get.py b/turbinia/api/client/test/test_paths/test_api_config_/test_get.py
new file mode 100644
index 000000000..9d02211de
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_config_/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_config_ import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiConfig(ApiTestMixin, unittest.TestCase):
+    """
+    ApiConfig unit test stubs
+        Read Config  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_config_request_options/__init__.py b/turbinia/api/client/test/test_paths/test_api_config_request_options/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_config_request_options/test_get.py b/turbinia/api/client/test/test_paths/test_api_config_request_options/test_get.py
new file mode 100644
index 000000000..f8b00522c
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_config_request_options/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_config_request_options import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiConfigRequestOptions(ApiTestMixin, unittest.TestCase):
+    """
+    ApiConfigRequestOptions unit test stubs
+        Get Request Options  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_evidence_id/__init__.py b/turbinia/api/client/test/test_paths/test_api_evidence_evidence_id/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_evidence_id/test_get.py b/turbinia/api/client/test/test_paths/test_api_evidence_evidence_id/test_get.py
new file mode 100644
index 000000000..71508ee56
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_evidence_evidence_id/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_evidence_evidence_id import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiEvidenceEvidenceId(ApiTestMixin, unittest.TestCase):
+    """
+    ApiEvidenceEvidenceId unit test stubs
+        Get Evidence By Id  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_query/__init__.py b/turbinia/api/client/test/test_paths/test_api_evidence_query/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_query/test_get.py b/turbinia/api/client/test/test_paths/test_api_evidence_query/test_get.py
new file mode 100644
index 000000000..15e621417
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_evidence_query/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_evidence_query import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiEvidenceQuery(ApiTestMixin, unittest.TestCase):
+    """
+    ApiEvidenceQuery unit test stubs
+        Query Evidence  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_summary/__init__.py b/turbinia/api/client/test/test_paths/test_api_evidence_summary/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_summary/test_get.py b/turbinia/api/client/test/test_paths/test_api_evidence_summary/test_get.py
new file mode 100644
index 000000000..8a431584b
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_evidence_summary/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_evidence_summary import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiEvidenceSummary(ApiTestMixin, unittest.TestCase):
+    """
+    ApiEvidenceSummary unit test stubs
+        Get Evidence Summary  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_types/__init__.py b/turbinia/api/client/test/test_paths/test_api_evidence_types/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_types/test_get.py b/turbinia/api/client/test/test_paths/test_api_evidence_types/test_get.py
new file mode 100644
index 000000000..589936139
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_evidence_types/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_evidence_types import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiEvidenceTypes(ApiTestMixin, unittest.TestCase):
+    """
+    ApiEvidenceTypes unit test stubs
+        Get Evidence Types  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_types_evidence_type/__init__.py b/turbinia/api/client/test/test_paths/test_api_evidence_types_evidence_type/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_types_evidence_type/test_get.py b/turbinia/api/client/test/test_paths/test_api_evidence_types_evidence_type/test_get.py
new file mode 100644
index 000000000..c7ae46f8b
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_evidence_types_evidence_type/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_evidence_types_evidence_type import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiEvidenceTypesEvidenceType(ApiTestMixin, unittest.TestCase):
+    """
+    ApiEvidenceTypesEvidenceType unit test stubs
+        Get Evidence Attributes  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_upload/__init__.py b/turbinia/api/client/test/test_paths/test_api_evidence_upload/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_evidence_upload/test_post.py b/turbinia/api/client/test/test_paths/test_api_evidence_upload/test_post.py
new file mode 100644
index 000000000..6e519a392
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_evidence_upload/test_post.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_evidence_upload import post  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiEvidenceUpload(ApiTestMixin, unittest.TestCase):
+    """
+    ApiEvidenceUpload unit test stubs
+        Upload Evidence  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = post.ApiForpost(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_jobs_/__init__.py b/turbinia/api/client/test/test_paths/test_api_jobs_/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_jobs_/test_get.py b/turbinia/api/client/test/test_paths/test_api_jobs_/test_get.py
new file mode 100644
index 000000000..1e9bb98b3
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_jobs_/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_jobs_ import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiJobs(ApiTestMixin, unittest.TestCase):
+    """
+    ApiJobs unit test stubs
+        Read Jobs  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_logs_query/__init__.py b/turbinia/api/client/test/test_paths/test_api_logs_query/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_logs_query/test_get.py b/turbinia/api/client/test/test_paths/test_api_logs_query/test_get.py
new file mode 100644
index 000000000..2e59c8e3c
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_logs_query/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_logs_query import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiLogsQuery(ApiTestMixin, unittest.TestCase):
+    """
+    ApiLogsQuery unit test stubs
+        Get Logs  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_request_/__init__.py b/turbinia/api/client/test/test_paths/test_api_request_/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_request_/test_post.py b/turbinia/api/client/test/test_paths/test_api_request_/test_post.py
new file mode 100644
index 000000000..94a26f5bb
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_request_/test_post.py
@@ -0,0 +1,43 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_request_ import post  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiRequest(ApiTestMixin, unittest.TestCase):
+    """
+    ApiRequest unit test stubs
+        Create Request  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = post.ApiForpost(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_request_request_id/__init__.py b/turbinia/api/client/test/test_paths/test_api_request_request_id/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_request_request_id/test_get.py b/turbinia/api/client/test/test_paths/test_api_request_request_id/test_get.py
new file mode 100644
index 000000000..987fc9e43
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_request_request_id/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_request_request_id import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiRequestRequestId(ApiTestMixin, unittest.TestCase):
+    """
+    ApiRequestRequestId unit test stubs
+        Get Request Status  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_request_summary/__init__.py b/turbinia/api/client/test/test_paths/test_api_request_summary/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_request_summary/test_get.py b/turbinia/api/client/test/test_paths/test_api_request_summary/test_get.py
new file mode 100644
index 000000000..b7f258d6f
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_request_summary/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_request_summary import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiRequestSummary(ApiTestMixin, unittest.TestCase):
+    """
+    ApiRequestSummary unit test stubs
+        Get Requests Summary  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_result_request_request_id/__init__.py b/turbinia/api/client/test/test_paths/test_api_result_request_request_id/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_result_request_request_id/test_get.py b/turbinia/api/client/test/test_paths/test_api_result_request_request_id/test_get.py
new file mode 100644
index 000000000..22dbb9d9a
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_result_request_request_id/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_result_request_request_id import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiResultRequestRequestId(ApiTestMixin, unittest.TestCase):
+    """
+    ApiResultRequestRequestId unit test stubs
+        Get Request Output  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_result_task_task_id/__init__.py b/turbinia/api/client/test/test_paths/test_api_result_task_task_id/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_result_task_task_id/test_get.py b/turbinia/api/client/test/test_paths/test_api_result_task_task_id/test_get.py
new file mode 100644
index 000000000..520665bab
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_result_task_task_id/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_result_task_task_id import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiResultTaskTaskId(ApiTestMixin, unittest.TestCase):
+    """
+    ApiResultTaskTaskId unit test stubs
+        Get Task Output  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_task_statistics/__init__.py b/turbinia/api/client/test/test_paths/test_api_task_statistics/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_task_statistics/test_get.py b/turbinia/api/client/test/test_paths/test_api_task_statistics/test_get.py
new file mode 100644
index 000000000..ac13b17b4
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_task_statistics/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_task_statistics import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiTaskStatistics(ApiTestMixin, unittest.TestCase):
+    """
+    ApiTaskStatistics unit test stubs
+        Get Task Statistics  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_task_task_id/__init__.py b/turbinia/api/client/test/test_paths/test_api_task_task_id/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_task_task_id/test_get.py b/turbinia/api/client/test/test_paths/test_api_task_task_id/test_get.py
new file mode 100644
index 000000000..40d679dab
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_task_task_id/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_task_task_id import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiTaskTaskId(ApiTestMixin, unittest.TestCase):
+    """
+    ApiTaskTaskId unit test stubs
+        Get Task Status  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/turbinia/api/client/test/test_paths/test_api_task_workers/__init__.py b/turbinia/api/client/test/test_paths/test_api_task_workers/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/turbinia/api/client/test/test_paths/test_api_task_workers/test_get.py b/turbinia/api/client/test/test_paths/test_api_task_workers/test_get.py
new file mode 100644
index 000000000..84803385f
--- /dev/null
+++ b/turbinia/api/client/test/test_paths/test_api_task_workers/test_get.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+
+
+    Generated by: https://openapi-generator.tech
+"""
+
+import unittest
+from unittest.mock import patch
+
+import urllib3
+
+import turbinia_api_lib
+from turbinia_api_lib.paths.api_task_workers import get  # noqa: E501
+from turbinia_api_lib import configuration, schemas, api_client
+
+from .. import ApiTestMixin
+
+
+class TestApiTaskWorkers(ApiTestMixin, unittest.TestCase):
+    """
+    ApiTaskWorkers unit test stubs
+        Get Workers Status  # noqa: E501
+    """
+    _configuration = configuration.Configuration()
+
+    def setUp(self):
+        used_api_client = api_client.ApiClient(configuration=self._configuration)
+        self.api = get.ApiForget(api_client=used_api_client)  # noqa: E501
+
+    def tearDown(self):
+        pass
+
+    response_status = 200
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()